diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index b39cfde0..9b5ad7b8 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -17,23 +17,19 @@ jobs: matrix: version: - '1' # Leave this line unchanged. '1' will automatically expand to the latest stable 1.x release of Julia. + #- 'nightly' os: - ubuntu-latest + - macOS-latest + - windows-latest arch: - x64 steps: - uses: actions/checkout@v2 - - uses: julia-actions/setup-julia@v1 + - uses: julia-actions/setup-julia@latest with: version: ${{ matrix.version }} arch: ${{ matrix.arch }} - - name: Add General - shell: julia --color=yes {0} - run: | - using Pkg - Pkg.Registry.add(RegistrySpec(url="https://github.com/JuliaRegistries/General")) - env: - JULIA_PKG_USE_CLI_GIT: 'true' - - uses: julia-actions/julia-runtest@v1 + - uses: julia-actions/julia-runtest@latest env: JULIA_PKG_USE_CLI_GIT: 'true' diff --git a/Project.toml b/Project.toml index fa247721..02e5175a 100644 --- a/Project.toml +++ b/Project.toml @@ -1,32 +1,34 @@ name = "AcousticAnalogies" uuid = "e71b3392-1e0c-4536-b366-2bd1fce6fba0" -authors = ["Ingraham, Daniel James (GRC-LTV0) "] -version = "0.7.2" +authors = ["Ingraham, Daniel James (GRC-LTV0) and contributors"] +version = "0.8.0" [deps] AcousticMetrics = "046f749b-9c1e-43ca-86bc-6902340f753e" CCBlade = "e1828068-15df-11e9-03e4-ef195ea46fa4" CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" -ConcreteStructs = "2569d6c7-a4a2-43d3-a901-331e8e4be471" DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" FLOWMath = "6cb5d3fb-0fe8-4cc2-bd89-9fe0b19a99d3" +FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b" FlexiMaps = "6394faf6-06db-4fa8-b750-35ccc60383f7" -Formatting = "59287772-0a20-5a39-b81b-1366585eb4c0" +Format = "1fa38f19-a742-5d3f-a2b9-30dd87b9d5f8" JuliennedArrays = "5cadff95-7770-533d-a838-a1bf817ee6e0" KinematicCoordinateTransformations = "730d3219-0a85-48f9-b699-9f31f8913d09" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +Meshes = "eacbb407-ea5a-433e-ab97-5258b1ca43fa" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" WriteVTK = "64499a7a-5c06-52f2-abe2-ccb03c286192" [compat] -AcousticMetrics = "0.6.0" +AcousticMetrics = "0.7.0" CCBlade = "0.2.4" -ConcreteStructs = "0.2.3" FLOWMath = "0.3.3" +FillArrays = "1.11.0" FlexiMaps = "0.1.18" -Formatting = "0.4.2" +Format = "1.3.7" JuliennedArrays = "0.4.0" KinematicCoordinateTransformations = "0.4.1" +Meshes = "0.46.0" StaticArrays = "1.5.19" WriteVTK = "1.17.1" julia = "1.9.1" diff --git a/README.md b/README.md index 50a46835..5267c4de 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ or [http://dx.doi.org/10.2514/1.C034048](http://dx.doi.org/10.2514/1.C034048) for details). + * Implementation of Brooks & Burley's rotor broadband noise prediction method [http://dx.doi.org/10.2514/6.2001-2210](http://dx.doi.org/10.2514/6.2001-2210). * Support for stationary or constant-velocity moving observers, with an explict calculation for the latter from D. Casalino [http://dx.doi.org/10.1016/S0022-460X(02)00986-0](http://dx.doi.org/10.1016/S0022-460X(02)00986-0). @@ -50,7 +51,6 @@ **Installation** ```julia-repl -] registry add git@github.com:dingraha/DanielIngrahamRegistry.git # Optional, but needed to resolve dependencies in the next step ] add AcousticAnalogies ``` diff --git a/docs/Project.toml b/docs/Project.toml index 75353c30..28de79fa 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -3,10 +3,13 @@ AcousticAnalogies = "e71b3392-1e0c-4536-b366-2bd1fce6fba0" AcousticMetrics = "046f749b-9c1e-43ca-86bc-6902340f753e" CCBlade = "e1828068-15df-11e9-03e4-ef195ea46fa4" ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4" +DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" FLOWMath = "6cb5d3fb-0fe8-4cc2-bd89-9fe0b19a99d3" +FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a" Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59" +JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819" KinematicCoordinateTransformations = "730d3219-0a85-48f9-b699-9f31f8913d09" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56" diff --git a/docs/make.jl b/docs/make.jl index ebf7db6e..ea4e2d8b 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -12,7 +12,13 @@ function doit() "WriteVTK.jl Support"=>"writevtk_support.md", "OpenFAST Example"=>"openfast_example.md", "API Reference"=>"api.md", - "Software Quality Assurance"=>"sqa.md"]) + "Software Quality Assurance"=>"sqa.md", + "BPM Airfoil Self-Noise Tests"=>"bpm_tests1.md", + "BPM Airfoil Self-Noise Tests, Cont."=>"bpm_tests2.md", + "BPM Airfoil Self-Noise Tests, Cont."=>"bpm_tests3.md", + "Ideally Twisted Rotor Tests"=>"itr_tests1.md", + "Ideally Twisted Rotor Tests, Cont."=>"itr_tests2.md", + ]) if IN_CI deploydocs(repo="github.com/OpenMDAO/AcousticAnalogies.jl.git", devbranch="main") diff --git a/docs/src/bpm_tests1.md b/docs/src/bpm_tests1.md new file mode 100644 index 00000000..0c3a834a --- /dev/null +++ b/docs/src/bpm_tests1.md @@ -0,0 +1,517 @@ +```@meta +CurrentModule = AADocs +``` +# Software Quality Assurance, Cont. + +## Brooks, Pope, and Marcolini Airfoil Self-Noise Tests +The [Brooks, Pope, and Marcolini (BPM) report on airfoil self-noise](https://ntrs.nasa.gov/citations/19890016302) forms the basis of the [Brooks and Burley broadband noise modeling approach](https://doi.org/10.2514/6.2001-2210) that is implemented in AcousticAnalogies.jl. + +### Boundary Layer Tests + +```@example bpm_bl_thickness +using AcousticAnalogies: AcousticAnalogies +using ColorSchemes: colorschemes +using DelimitedFiles: DelimitedFiles +# using FLOWMath: linear +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +colors = colorschemes[:tab10] +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="Re_c/10^6", ylabel="δ_0/c", + xscale=log10, yscale=log10, + xminorticksvisible=true, yminorticksvisible=true, + xminorticks=IntervalsBetween(9), yminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), yticks=LogTicks(IntegerTicks())) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure06-bl_thickness-tripped.csv") +bpm_tripped = DelimitedFiles.readdlm(fname, ',') +Re_c_1e6 = bpm_tripped[:, 1] +deltastar0_c = bpm_tripped[:, 2] +scatter!(ax1, Re_c_1e6, deltastar0_c, markersize=4, label="tripped, BPM report", color=colors[1]) + +Re_c_1e6_jl = range(minimum(Re_c_1e6), maximum(Re_c_1e6); length=50) +deltastar0_c_jl = AcousticAnalogies.bl_thickness_0.(Ref(AcousticAnalogies.TrippedN0012BoundaryLayer()), Re_c_1e6_jl.*1e6) +lines!(ax1, Re_c_1e6_jl, deltastar0_c_jl, label="tripped, Julia", color=colors[1]) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure06-bl_thickness-untripped.csv") +bpm_untripped = DelimitedFiles.readdlm(fname, ',') +Re_c_1e6 = bpm_untripped[:, 1] +deltastar0_c = bpm_untripped[:, 2] +scatter!(ax1, Re_c_1e6, deltastar0_c, markersize=4, label="untripped, BPM report", color=colors[2]) + +Re_c_1e6_jl = range(minimum(Re_c_1e6), maximum(Re_c_1e6); length=50) +deltastar0_c_jl = AcousticAnalogies.bl_thickness_0.(Ref(AcousticAnalogies.UntrippedN0012BoundaryLayer()), Re_c_1e6_jl.*1e6) +lines!(ax1, Re_c_1e6_jl, deltastar0_c_jl, label="untripped, Julia", color=colors[2]) + +xlims!(ax1, 0.04, 3) +ylims!(ax1, 0.01, 0.2) +axislegend(ax1) +save("19890016302-figure06-bl_thickness.png", fig) +``` +![](19890016302-figure06-bl_thickness.png) + +```@example bpm_disp_thickness +using AcousticAnalogies: AcousticAnalogies +using ColorSchemes: colorschemes +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +colors = colorschemes[:tab10] +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="Re_c/10^6", ylabel="δ_0^*/c", + xscale=log10, yscale=log10, + xminorticksvisible=true, yminorticksvisible=true, + xminorticks=IntervalsBetween(9), yminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), yticks=LogTicks(IntegerTicks())) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure06-disp_thickness-tripped.csv") +bpm_tripped = DelimitedFiles.readdlm(fname, ',') +Re_c_1e6 = bpm_tripped[:, 1] +deltastar0_c = bpm_tripped[:, 2] +scatter!(ax1, Re_c_1e6, deltastar0_c, markersize=4, label="tripped, BPM report", color=colors[1]) + +Re_c_1e6_jl = range(minimum(Re_c_1e6), maximum(Re_c_1e6); length=50) +deltastar0_c_jl = AcousticAnalogies.disp_thickness_0.(Ref(AcousticAnalogies.TrippedN0012BoundaryLayer()), Re_c_1e6_jl.*1e6) +lines!(ax1, Re_c_1e6_jl, deltastar0_c_jl, label="tripped, Julia", color=colors[1]) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure06-disp_thickness-untripped.csv") +bpm_untripped = DelimitedFiles.readdlm(fname, ',') +Re_c_1e6 = bpm_untripped[:, 1] +deltastar0_c = bpm_untripped[:, 2] +scatter!(ax1, Re_c_1e6, deltastar0_c, markersize=4, label="untripped, BPM report", color=colors[2]) + +Re_c_1e6_jl = range(minimum(Re_c_1e6), maximum(Re_c_1e6); length=50) +deltastar0_c_jl = AcousticAnalogies.disp_thickness_0.(Ref(AcousticAnalogies.UntrippedN0012BoundaryLayer()), Re_c_1e6_jl.*1e6) +lines!(ax1, Re_c_1e6_jl, deltastar0_c_jl, label="untripped, Julia", color=colors[2]) + +xlims!(ax1, 0.04, 3) +ylims!(ax1, 0.001, 0.03) +axislegend(ax1) +save("19890016302-figure06-disp_thickness.png", fig) +``` +![](19890016302-figure06-disp_thickness.png) + +```@example bpm_bl_thickness_tripped +using AcousticAnalogies: AcousticAnalogies +using ColorSchemes: colorschemes +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +colors = colorschemes[:tab10] +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="alpha, deg.", ylabel="δ/δ_0", + yscale=log10, + yminorticksvisible=true, + yminorticks=IntervalsBetween(9), + yticks=LogTicks(IntegerTicks()) + ) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure07-bl_thickness-pressure_side.csv") +bpm_pressure_side = DelimitedFiles.readdlm(fname, ',') +alpha_deg = bpm_pressure_side[:, 1] +delta_bpm = bpm_pressure_side[:, 2] +scatter!(ax1, alpha_deg, delta_bpm, color=colors[1], markersize=4, label="pressure side, BPM report") + +alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=50) +delta_jl = AcousticAnalogies._bl_thickness_p.(Ref(AcousticAnalogies.TrippedN0012BoundaryLayer()), alpha_deg_jl.*pi/180) +lines!(ax1, alpha_deg_jl, delta_jl; color=colors[1], label="pressure side, Julia") + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure07-bl_thickness-suction_side.csv") +bpm_suction_side = DelimitedFiles.readdlm(fname, ',') +alpha_deg = bpm_suction_side[:, 1] +delta_bpm = bpm_suction_side[:, 2] +scatter!(ax1, alpha_deg, delta_bpm, markersize=4, color=colors[2], label="suction side, BPM report") + +alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=50) +delta_jl = AcousticAnalogies._bl_thickness_s.(Ref(AcousticAnalogies.TrippedN0012BoundaryLayer()), alpha_deg_jl.*pi/180) +lines!(ax1, alpha_deg_jl, delta_jl; color=colors[2], label="suction side, Julia") + +xlims!(ax1, 0, 25) +ylims!(ax1, 0.2, 20) +axislegend(ax1, position=:lt) +save("19890016302-figure07-bl_thickness.png", fig) +``` +![](19890016302-figure07-bl_thickness.png) + +```@example bpm_disp_thickness_star_tripped +using AcousticAnalogies: AcousticAnalogies +using ColorSchemes: colorschemes +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +colors = colorschemes[:tab10] +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="alpha, deg.", ylabel="δ^*/δ_0^*", + yscale=log10, + yminorticksvisible=true, + yminorticks=IntervalsBetween(9), + yticks=LogTicks(IntegerTicks()) + ) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure07-pressure_side.csv") +bpm_pressure_side = DelimitedFiles.readdlm(fname, ',') +alpha_deg = bpm_pressure_side[:, 1] +deltastar_bpm = bpm_pressure_side[:, 2] +scatter!(ax1, alpha_deg, deltastar_bpm, color=colors[1], markersize=4, label="pressure side, BPM report") + +alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=50) +deltastar_jl = AcousticAnalogies._disp_thickness_p.(Ref(AcousticAnalogies.TrippedN0012BoundaryLayer()), alpha_deg_jl.*pi/180) +lines!(ax1, alpha_deg_jl, deltastar_jl; color=colors[1], label="pressure side, Julia") + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure07-suction_side.csv") +bpm_suction_side = DelimitedFiles.readdlm(fname, ',') +alpha_deg = bpm_suction_side[:, 1] +deltastar_bpm = bpm_suction_side[:, 2] +scatter!(ax1, alpha_deg, deltastar_bpm, markersize=4, color=colors[2], label="suction side, BPM report") + +alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=50) +deltastar_jl = AcousticAnalogies._disp_thickness_s.(Ref(AcousticAnalogies.TrippedN0012BoundaryLayer()), alpha_deg_jl.*pi/180) +lines!(ax1, alpha_deg_jl, deltastar_jl; color=colors[2], label="suction side, Julia") + +xlims!(ax1, 0, 25) +ylims!(ax1, 0.2, 200) +axislegend(ax1, position=:lt) +save("19890016302-figure07.png", fig) +``` +![](19890016302-figure07.png) + +```@example bpm_bl_thickness_untripped +using AcousticAnalogies: AcousticAnalogies +using ColorSchemes: colorschemes +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +colors = colorschemes[:tab10] +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="alpha, deg.", ylabel="δ/δ_0", + yscale=log10, + yminorticksvisible=true, + yminorticks=IntervalsBetween(9), + yticks=LogTicks(IntegerTicks()) + ) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure08-bl_thickness-pressure_side.csv") +bpm_pressure_side = DelimitedFiles.readdlm(fname, ',') +alpha_deg = bpm_pressure_side[:, 1] +deltastar_bpm = bpm_pressure_side[:, 2] +scatter!(ax1, alpha_deg, deltastar_bpm, color=colors[1], markersize=4, label="pressure side, BPM report") + +alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=50) +deltastar_jl = AcousticAnalogies._bl_thickness_p.(Ref(AcousticAnalogies.UntrippedN0012BoundaryLayer()), alpha_deg_jl.*pi/180) +lines!(ax1, alpha_deg_jl, deltastar_jl; color=colors[1], label="pressure side, Julia") + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure08-bl_thickness-suction_side.csv") +bpm_pressure_side = DelimitedFiles.readdlm(fname, ',') +alpha_deg = bpm_pressure_side[:, 1] +deltastar_bpm = bpm_pressure_side[:, 2] +scatter!(ax1, alpha_deg, deltastar_bpm, color=colors[2], markersize=4, label="suction side, BPM report") + +alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=50) +deltastar_jl = AcousticAnalogies._bl_thickness_s.(Ref(AcousticAnalogies.UntrippedN0012BoundaryLayer()), alpha_deg_jl.*pi/180) +lines!(ax1, alpha_deg_jl, deltastar_jl; color=colors[2], label="suction side, Julia") + +xlims!(ax1, 0, 25) +ylims!(ax1, 0.2, 40) +axislegend(ax1, position=:lt) +save("19890016302-figure08-bl_thickness.png", fig) +``` +![](19890016302-figure08-bl_thickness.png) + +```@example bpm_disp_thickness_star_untripped +using AcousticAnalogies: AcousticAnalogies +using ColorSchemes: colorschemes +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +colors = colorschemes[:tab10] +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="alpha, deg.", ylabel="δ^*/δ_0^*", + yscale=log10, + yminorticksvisible=true, + yminorticks=IntervalsBetween(9), + yticks=LogTicks(IntegerTicks()) + ) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure08-pressure_side.csv") +bpm_pressure_side = DelimitedFiles.readdlm(fname, ',') +alpha_deg = bpm_pressure_side[:, 1] +deltastar_bpm = bpm_pressure_side[:, 2] +scatter!(ax1, alpha_deg, deltastar_bpm, color=colors[1], markersize=4, label="pressure side, BPM report") + +alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=50) +deltastar_jl = AcousticAnalogies._disp_thickness_p.(Ref(AcousticAnalogies.UntrippedN0012BoundaryLayer()), alpha_deg_jl.*pi/180) +lines!(ax1, alpha_deg_jl, deltastar_jl; color=colors[1], label="pressure side, Julia") + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure08-suction_side.csv") +bpm_suction_side = DelimitedFiles.readdlm(fname, ',') +alpha_deg = bpm_suction_side[:, 1] +deltastar_bpm = bpm_suction_side[:, 2] +scatter!(ax1, alpha_deg, deltastar_bpm, markersize=4, color=colors[2], label="suction side, BPM report") + +alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=50) +deltastar_jl = AcousticAnalogies._disp_thickness_s.(Ref(AcousticAnalogies.UntrippedN0012BoundaryLayer()), alpha_deg_jl.*pi/180) +lines!(ax1, alpha_deg_jl, deltastar_jl; color=colors[2], label="suction side, Julia") + +xlims!(ax1, 0, 25) +ylims!(ax1, 0.2, 200) +axislegend(ax1, position=:lt) +save("19890016302-figure08.png", fig) +``` +![](19890016302-figure08.png) + +### Turbulent Boundary Layer-Trailing Edge Shape Function Tests + +```@example bpm_K_1 +using AcousticAnalogies: AcousticAnalogies +using ColorSchemes: colorschemes +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +colors = colorschemes[:tab10] +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="Re_c", ylabel="Peak scaled SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks())) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure77.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +Re_c_bpm = bpm[:, 1] +K_1_bpm = bpm[:, 2] +scatter!(ax1, Re_c_bpm, K_1_bpm, color=colors[1], markersize=8, label="BPM report") + +Re_c_jl = range(minimum(Re_c_bpm), maximum(Re_c_bpm); length=50) +K_1_jl = AcousticAnalogies.K_1.(Re_c_jl) +lines!(ax1, Re_c_jl, K_1_jl, color=colors[1], label="Julia") + +xlims!(ax1, 10^4, 10^7) +ylims!(ax1, 110.0, 150.0) +axislegend(ax1, position=:lt) +save("19890016302-figure77.png", fig) +``` +![](19890016302-figure77.png) + +```@example bpm_A +using AcousticAnalogies: AcousticAnalogies +using ColorSchemes: colorschemes +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +colors = colorschemes[:tab10] +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="Strouhal number ratio, St/St_peak", ylabel="Function A level, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks())) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure78-A_min.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +St_St_peak_bpm = bpm[:, 1] +A = bpm[:, 2] +scatter!(ax1, St_St_peak_bpm, A, color=colors[1], markersize=8, label="A_min, BPM report") + +St_St_peak_jl = range(minimum(St_St_peak_bpm), maximum(St_St_peak_bpm); length=50) +A_jl = AcousticAnalogies.A.(St_St_peak_jl, 9.5e4) +lines!(ax1, St_St_peak_jl, A_jl, color=colors[1], label="A_min, Julia") + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure78-A_max.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +St_St_peak_bpm = bpm[:, 1] +A = bpm[:, 2] +scatter!(ax1, St_St_peak_bpm, A, color=colors[2], markersize=8, label="A_max, BPM report") + +St_St_peak_jl = range(minimum(St_St_peak_bpm), maximum(St_St_peak_bpm); length=50) +A_jl = AcousticAnalogies.A.(St_St_peak_jl, 8.58e5) +lines!(ax1, St_St_peak_jl, A_jl, color=colors[2], label="A_max, Julia") + +xlims!(ax1, 0.1, 20) +ylims!(ax1, -20.0, 0.0) +axislegend(ax1, position=:lt) +save("19890016302-figure78-A.png", fig) +``` +![](19890016302-figure78-A.png) + +```@example bpm_B +using AcousticAnalogies: AcousticAnalogies +using ColorSchemes: colorschemes +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +colors = colorschemes[:tab10] +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="Strouhal number ratio, St/St_peak", ylabel="Function B level, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks())) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure78-B_min.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +St_St_peak_bpm = bpm[:, 1] +B = bpm[:, 2] +scatter!(ax1, St_St_peak_bpm, B, color=colors[1], markersize=8, label="B_min, BPM report") + +St_St_peak_jl = range(0.5, 2; length=50) +B_jl = AcousticAnalogies.B.(St_St_peak_jl, 9.5e4) +lines!(ax1, St_St_peak_jl, B_jl, color=colors[1], label="B_min, Julia") + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure78-B_max.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +St_St_peak_bpm = bpm[:, 1] +B = bpm[:, 2] +scatter!(ax1, St_St_peak_bpm, B, color=colors[2], markersize=8, label="B_max, BPM report") + +St_St_peak_jl = range(0.2, 4; length=50) +B_jl = AcousticAnalogies.B.(St_St_peak_jl, 8.58e5) +lines!(ax1, St_St_peak_jl, B_jl, color=colors[2], label="B_max, Julia") + +xlims!(ax1, 0.1, 20) +ylims!(ax1, -20.0, 0.0) +axislegend(ax1, position=:lt) +save("19890016302-figure78-B.png", fig) +``` +![](19890016302-figure78-B.png) + +```@example bpm_St_2 +using AcousticAnalogies: AcousticAnalogies +using ColorSchemes: colorschemes +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +colors = colorschemes[:tab10] +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="Angle of attack α^*, deg", ylabel="Peak Strouhal number, St_peak", + yscale=log10, + yminorticksvisible=true, + yminorticks=IntervalsBetween(9), + yticks=LogTicks(IntegerTicks())) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure80-M0.093.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +alpha_deg = bpm[:, 1] +St_2 = bpm[:, 2] +scatter!(ax1, alpha_deg, St_2, color=colors[1], markersize=8, label="St_2 for M = 0.093, BPM") + +alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=50) +St_2_jl = AcousticAnalogies.St_2.(AcousticAnalogies.St_1(0.093), alpha_deg_jl.*pi/180) +lines!(ax1, alpha_deg_jl, St_2_jl, color=colors[1], label="St_2 for M = 0.093, Julia") + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure80-M0.209.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +alpha_deg = bpm[:, 1] +St_2 = bpm[:, 2] +scatter!(ax1, alpha_deg, St_2, color=colors[2], markersize=8, label="St_2 for M = 0.209, BPM") + +alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=50) +St_2_jl = AcousticAnalogies.St_2.(AcousticAnalogies.St_1(0.209), alpha_deg_jl.*pi/180) +lines!(ax1, alpha_deg_jl, St_2_jl, color=colors[2], label="St_2 for M = 0.209, Julia") + +xlims!(ax1, 0.0, 25.0) +ylims!(ax1, 0.01, 1) +axislegend(ax1, position=:lt) +save("19890016302-figure80.png", fig) +``` +![](19890016302-figure80.png) + +```@example bpm_K_2_K_1 +using AcousticAnalogies: AcousticAnalogies +using ColorSchemes: colorschemes +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +colors = colorschemes[:tab10] +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="Angle of attack α_*, deg", ylabel="Extracted scaled levels minus K_1, dB") + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure82-M0.093.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +alpha_deg = bpm[:, 1] +K_2_K_1 = bpm[:, 2] +scatter!(ax1, alpha_deg, K_2_K_1, color=colors[1], markersize=8, label="M = 0.093, BPM", marker='o') + +alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=200) +K_2_K_1_jl = AcousticAnalogies.K_2.(1e6, 0.093, alpha_deg_jl.*pi/180) .- AcousticAnalogies.K_1(1e6) +lines!(ax1, alpha_deg_jl, K_2_K_1_jl, color=colors[1], label="M = 0.093, Julia") + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure82-M0.116.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +alpha_deg = bpm[:, 1] +K_2_K_1 = bpm[:, 2] +scatter!(ax1, alpha_deg, K_2_K_1, color=colors[2], markersize=8, label="M = 0.116, BPM", marker='o') + +alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=200) +K_2_K_1_jl = AcousticAnalogies.K_2.(1e6, 0.116, alpha_deg_jl.*pi/180) .- AcousticAnalogies.K_1(1e6) +lines!(ax1, alpha_deg_jl, K_2_K_1_jl, color=colors[2], label="M = 0.116, Julia") + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure82-M0.163.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +alpha_deg = bpm[:, 1] +K_2_K_1 = bpm[:, 2] +scatter!(ax1, alpha_deg, K_2_K_1, color=colors[3], markersize=8, label="M = 0.163, BPM", marker='o') + +alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=200) +K_2_K_1_jl = AcousticAnalogies.K_2.(1e6, 0.163, alpha_deg_jl.*pi/180) .- AcousticAnalogies.K_1(1e6) +lines!(ax1, alpha_deg_jl, K_2_K_1_jl, color=colors[3], label="M = 0.163, Julia") + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure82-M0.209.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +alpha_deg = bpm[:, 1] +K_2_K_1 = bpm[:, 2] +scatter!(ax1, alpha_deg, K_2_K_1, color=colors[4], markersize=8, label="M = 0.209, BPM", marker='o') + +alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=200) +K_2_K_1_jl = AcousticAnalogies.K_2.(1e6, 0.209, alpha_deg_jl.*pi/180) .- AcousticAnalogies.K_1(1e6) +lines!(ax1, alpha_deg_jl, K_2_K_1_jl, color=colors[4], label="M = 0.209, Julia") + +xlims!(ax1, 0.0, 25.0) +ylims!(ax1, -20, 20) +axislegend(ax1, position=:lt) +save("19890016302-figure82.png", fig) +``` +![](19890016302-figure82.png) diff --git a/docs/src/bpm_tests2.md b/docs/src/bpm_tests2.md new file mode 100644 index 00000000..02c8e50a --- /dev/null +++ b/docs/src/bpm_tests2.md @@ -0,0 +1,471 @@ +```@meta +CurrentModule = AADocs +``` +# Software Quality Assurance, Cont. + +## Brooks, Pope, and Marcolini Airfoil Self-Noise Tests, Cont. + +### Laminar Boundary Layer-Vortex Shedding Tests + +```@example bpm_St_1_prime +using AcousticAnalogies: AcousticAnalogies +using ColorSchemes: colorschemes +using DelimitedFiles: DelimitedFiles +# using FLOWMath: linear +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +colors = colorschemes[:tab10] +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="Re_c", ylabel="Peak Strouhal number, St'_peak", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + yscale=log10, + yminorticksvisible=true, + yminorticks=IntervalsBetween(9), + yticks=LogTicks(IntegerTicks())) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure86-St_1_prime.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +Re_c_bpm = bpm[:, 1] +St_1_prime_bpm = bpm[:, 2] +scatter!(ax1, Re_c_bpm, St_1_prime_bpm, color=colors[1], markersize=4, label="BPM") + +Re_c_jl = 10.0.^(range(4, 7; length=100)) +St_1_prime_jl = AcousticAnalogies.St_1_prime.(Re_c_jl) +lines!(ax1, Re_c_jl, St_1_prime_jl, color=colors[1], label="Julia") + +xlims!(ax1, 1e4, 1e7) +ylims!(ax1, 0.01, 1) +axislegend(ax1, position=:lt) +save("19890016302-figure86.png", fig) +``` +![](19890016302-figure86.png) + +```@example bpm_lbl_vs_G1 +using AcousticAnalogies: AcousticAnalogies +using ColorSchemes: colorschemes +using DelimitedFiles: DelimitedFiles +# using FLOWMath: linear +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +colors = colorschemes[:tab10] +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="St'/St'_peak", ylabel="Function G_1 level, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks())) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure85-G1.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +e_bpm = bpm[:, 1] +G1_bpm = bpm[:, 2] +scatter!(ax1, e_bpm, G1_bpm, color=colors[1], markersize=4, label="BPM") + +e_jl = 10.0.^(range(-1, 1; length=101)) +G1_jl = AcousticAnalogies.G1.(e_jl) + +lines!(ax1, e_jl, G1_jl, color=colors[1], label="Julia") + +xlims!(ax1, 0.1, 10) +ylims!(ax1, -30, 0) +axislegend(ax1, position=:lt) +save("19890016302-figure85.png", fig) +``` +![](19890016302-figure85.png) + +```@example bpm_lbl_vs_St_peak_prime_alphastar +using AcousticAnalogies: AcousticAnalogies +using ColorSchemes: colorschemes +using DelimitedFiles: DelimitedFiles +# using FLOWMath: linear +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +colors = colorschemes[:tab10] +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="alpha^*, deg", ylabel="St'_peak/St'_1", + yscale=log10, + yminorticksvisible=true, + yminorticks=IntervalsBetween(9), + yticks=LogTicks(IntegerTicks())) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure87.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +alphastar_bpm = bpm[:, 1] +St_peak_ratio_bpm = bpm[:, 2] +scatter!(ax1, alphastar_bpm, St_peak_ratio_bpm, color=colors[1], markersize=4, label="BPM") + +St_1_prime = 0.25 # Just make up a value, since we're multiplying and then dividing by it anyway. +alphastar_jl = range(0.0*pi/180, 7.0*pi/180; length=21) +St_peak_ratio_jl = AcousticAnalogies.St_peak_prime.(St_1_prime, alphastar_jl)./St_1_prime +lines!(ax1, alphastar_jl.*180/pi, St_peak_ratio_jl, color=colors[1], label="Julia") + +xlims!(ax1, 0, 7) +ylims!(ax1, 0.5, 2) +axislegend(ax1, position=:lt) +save("19890016302-figure87.png", fig) +``` +![](19890016302-figure87.png) + +```@example bpm_lbl_vs_G2_alphastar +using AcousticAnalogies: AcousticAnalogies +using ColorSchemes: colorschemes +using DelimitedFiles: DelimitedFiles +# using FLOWMath: linear +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +colors = colorschemes[:tab10] +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="Re_c/Re_c0", ylabel="G2 + G3", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks())) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure88-G2-alpha0.csv") +alphastar = 0.0*pi/180 +bpm = DelimitedFiles.readdlm(fname, ',') +Re_c_bpm = bpm[:, 1] +G2_bpm = bpm[:, 2] +scatter!(ax1, Re_c_bpm, G2_bpm, color=colors[1], markersize=4, label="BPM - α^* = $(alphastar*180/pi)°") + +Re_c_jl = 10.0.^range(log10(first(Re_c_bpm)), log10(last(Re_c_bpm)), length=51) +Re_c0 = AcousticAnalogies.Re_c0(alphastar) +Re_ratio_jl = Re_c_jl./Re_c0 +# G2_jl = AcousticAnalogies.G2.(Re_ratio_jl) .+ 171.04 .- 3.03*(alphastar*180/pi) +G2_jl = AcousticAnalogies.G2.(Re_ratio_jl) .+ AcousticAnalogies.G3.(alphastar) +lines!(ax1, Re_c_jl, G2_jl, color=colors[1], label="Julia - α^* = $(alphastar*180/pi)°") + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure88-G2-alpha6.csv") +alphastar = 6.0*pi/180 +bpm = DelimitedFiles.readdlm(fname, ',') +Re_c_bpm = bpm[:, 1] +G2_bpm = bpm[:, 2] +scatter!(ax1, Re_c_bpm, G2_bpm, color=colors[2], markersize=4, label="BPM - α^* = $(alphastar*180/pi)°") + +Re_c_jl = 10.0.^range(log10(first(Re_c_bpm)), log10(last(Re_c_bpm)), length=51) +Re_c0 = AcousticAnalogies.Re_c0(alphastar) +Re_ratio_jl = Re_c_jl./Re_c0 +# G2_jl = AcousticAnalogies.G2.(Re_ratio_jl) .+ 171.04 .- 3.03*(alphastar*180/pi) +G2_jl = AcousticAnalogies.G2.(Re_ratio_jl) .+ AcousticAnalogies.G3.(alphastar) +lines!(ax1, Re_c_jl, G2_jl, color=colors[2], label="Julia - α^* = $(alphastar*180/pi)°") + +xlims!(ax1, 10^4, 10^7) +ylims!(ax1, 125, 175) +axislegend(ax1, position=:lt) +save("19890016302-figure88.png", fig) +``` +![](19890016302-figure88.png) + +```@example bpm_lbl_vs_G2 +using AcousticAnalogies: AcousticAnalogies +using ColorSchemes: colorschemes +using DelimitedFiles: DelimitedFiles +# using FLOWMath: linear +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +colors = colorschemes[:tab10] +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="Re_c/Re_c0", ylabel="G2", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks())) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure89.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +Re_ratio_bpm = bpm[:, 1] +G2_bpm = bpm[:, 2] +scatter!(ax1, Re_ratio_bpm, G2_bpm, color=colors[1], markersize=4, label="BPM") + +Re_ratio_jl = 10.0.^range(-1, 1, length=51) +G2_jl = AcousticAnalogies.G2.(Re_ratio_jl) +lines!(ax1, Re_ratio_jl, G2_jl, color=colors[1], label="Julia") + +xlims!(ax1, 0.1, 100) +ylims!(ax1, -45, 5) +axislegend(ax1, position=:lt) +save("19890016302-figure89.png", fig) +``` +![](19890016302-figure89.png) + +### Trailing Edge Bluntness-Vortex Shedding Tests + +```@example bpm_figure95 +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure95-0Psi.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +h_over_deltastar_0Psi = bpm[:, 1] +St_3prime_peak_0Psi = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure95-14Psi.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +h_over_deltastar_14Psi = bpm[:, 1] +St_3prime_peak_14Psi = bpm[:, 2] + +h_over_deltastar_jl = 10.0.^(range(-1, 1; length=51)) +St_3prime_peak_0Psi_jl = AcousticAnalogies.St_3prime_peak.(h_over_deltastar_jl, 0.0*pi/180) +St_3prime_peak_14Psi_jl = AcousticAnalogies.St_3prime_peak.(h_over_deltastar_jl, 14.0*pi/180) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="Thickness ratio, h/δ^*", ylabel="Peak Strouhal number, St'''_peak", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + yscale=log10, + yminorticksvisible=true, + yminorticks=IntervalsBetween(9), + yticks=LogTicks(IntegerTicks()), + title="Figure 95") + +scatter!(ax1, h_over_deltastar_0Psi, St_3prime_peak_0Psi; marker='o', label="Ψ = 0°, BPM") +lines!(ax1, h_over_deltastar_jl, St_3prime_peak_0Psi_jl; label="Ψ = 0°, Julia") + +scatter!(ax1, h_over_deltastar_14Psi, St_3prime_peak_14Psi; marker='o', label="Ψ = 14°, BPM") +lines!(ax1, h_over_deltastar_jl, St_3prime_peak_14Psi_jl; label="Ψ = 14°, Julia") + +xlims!(ax1, 0.2, 10.0) +ylims!(ax1, 0.05, 0.3) +axislegend(ax1, position=:rt) +save("19890016302-figure95.png", fig) +``` +![](19890016302-figure95.png) + +```@example bpm_figure96 +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure96-0Psi.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +h_over_deltastar_0Psi = bpm[:, 1] +G4_0Psi = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure96-14Psi.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +h_over_deltastar_14Psi = bpm[:, 1] +G4_14Psi = bpm[:, 2] + +h_over_deltastar_jl = 10.0.^(range(-1, 1; length=51)) +G4_0Psi_jl = AcousticAnalogies.G4.(h_over_deltastar_jl, 0.0*pi/180) +G4_14Psi_jl = AcousticAnalogies.G4.(h_over_deltastar_jl, 14.0*pi/180) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="Thickness ratio, h/δ^*", ylabel="Scaled peak SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 96") + +scatter!(ax1, h_over_deltastar_0Psi, G4_0Psi; marker='o', label="Ψ = 0°, BPM") +lines!(ax1, h_over_deltastar_jl, G4_0Psi_jl; label="Ψ = 0°, Julia") + +scatter!(ax1, h_over_deltastar_14Psi, G4_14Psi; marker='o', label="Ψ = 14°, BPM") +lines!(ax1, h_over_deltastar_jl, G4_14Psi_jl; label="Ψ = 14°, Julia") + +xlims!(ax1, 0.1, 10.0) +ylims!(ax1, 110, 180) +axislegend(ax1, position=:lt) +save("19890016302-figure96.png", fig) +``` +![](19890016302-figure96.png) + +```@example bpm_figure97a +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure97-Psi14-h_over_deltastar0p25.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +St_3prime_over_St_3prime_peak_0p25 = bpm[:, 1] +G5_14Psi_h_over_deltastar_avg0p25 = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure97-Psi14-h_over_deltastar0p43.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +St_3prime_over_St_3prime_peak_0p43 = bpm[:, 1] +G5_14Psi_h_over_deltastar_avg0p43 = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure97-Psi14-h_over_deltastar0p50.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +St_3prime_over_St_3prime_peak_0p50 = bpm[:, 1] +G5_14Psi_h_over_deltastar_avg0p50 = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure97-Psi14-h_over_deltastar0p54.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +St_3prime_over_St_3prime_peak_0p54 = bpm[:, 1] +G5_14Psi_h_over_deltastar_avg0p54 = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure97-Psi14-h_over_deltastar0p62.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +St_3prime_over_St_3prime_peak_0p62 = bpm[:, 1] +G5_14Psi_h_over_deltastar_avg0p62 = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure97-Psi14-h_over_deltastar1p20.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +St_3prime_over_St_3prime_peak_1p20 = bpm[:, 1] +G5_14Psi_h_over_deltastar_avg1p20 = bpm[:, 2] + +St_3prime_over_St_3prime_peak_jl = 10.0.^(range(-1, 10; length=1001)) +G5_14Psi_h_over_deltastar_avg0p25_jl = AcousticAnalogies.G5_Psi14.(0.25, St_3prime_over_St_3prime_peak_jl) +G5_14Psi_h_over_deltastar_avg0p43_jl = AcousticAnalogies.G5_Psi14.(0.43, St_3prime_over_St_3prime_peak_jl) +G5_14Psi_h_over_deltastar_avg0p50_jl = AcousticAnalogies.G5_Psi14.(0.50, St_3prime_over_St_3prime_peak_jl) +G5_14Psi_h_over_deltastar_avg0p54_jl = AcousticAnalogies.G5_Psi14.(0.54, St_3prime_over_St_3prime_peak_jl) +G5_14Psi_h_over_deltastar_avg0p62_jl = AcousticAnalogies.G5_Psi14.(0.62, St_3prime_over_St_3prime_peak_jl) +G5_14Psi_h_over_deltastar_avg1p20_jl = AcousticAnalogies.G5_Psi14.(1.20, St_3prime_over_St_3prime_peak_jl) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="Strouhal ratio, St'''/St'''_peak", ylabel="G_5, Ψ=14°", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 97a") + +scatter!(ax1, St_3prime_over_St_3prime_peak_0p25, G5_14Psi_h_over_deltastar_avg0p25; label="h/δ^* = 0.25, BPM", marker='o') +lines!(ax1, St_3prime_over_St_3prime_peak_jl, G5_14Psi_h_over_deltastar_avg0p25_jl; label="h/δ^* = 0.25, Julia") + +scatter!(ax1, St_3prime_over_St_3prime_peak_0p43, G5_14Psi_h_over_deltastar_avg0p43; label="h/δ^* = 0.43, BPM", marker='o') +lines!(ax1, St_3prime_over_St_3prime_peak_jl, G5_14Psi_h_over_deltastar_avg0p43_jl; label="h/δ^* = 0.43, Julia") + +scatter!(ax1, St_3prime_over_St_3prime_peak_0p50, G5_14Psi_h_over_deltastar_avg0p50; label="h/δ^* = 0.50, BPM", marker='o') +lines!(ax1, St_3prime_over_St_3prime_peak_jl, G5_14Psi_h_over_deltastar_avg0p50_jl; label="h/δ^* = 0.50, Julia") + +scatter!(ax1, St_3prime_over_St_3prime_peak_0p54, G5_14Psi_h_over_deltastar_avg0p54; label="h/δ^* = 0.54, BPM", marker='o') +lines!(ax1, St_3prime_over_St_3prime_peak_jl, G5_14Psi_h_over_deltastar_avg0p54_jl; label="h/δ^* = 0.54, Julia") + +scatter!(ax1, St_3prime_over_St_3prime_peak_0p62, G5_14Psi_h_over_deltastar_avg0p62; label="h/δ^* = 0.62, BPM", marker='o') +lines!(ax1, St_3prime_over_St_3prime_peak_jl, G5_14Psi_h_over_deltastar_avg0p62_jl; label="h/δ^* = 0.62, Julia") + +scatter!(ax1, St_3prime_over_St_3prime_peak_1p20, G5_14Psi_h_over_deltastar_avg1p20; label="h/δ^* = 1.20, BPM", marker='o') +lines!(ax1, St_3prime_over_St_3prime_peak_jl, G5_14Psi_h_over_deltastar_avg1p20_jl; label="h/δ^* = 1.20, Julia") + +xlims!(ax1, 0.1, 10.0) +ylims!(ax1, -30, 10) +axislegend(ax1, position=:rt) +save("19890016302-figure97a.png", fig) +``` +![](19890016302-figure97a.png) + +```@example bpm_figure97b +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure97-Psi0-h_over_deltastar0p25.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +St_3prime_over_St_3prime_peak_0p25 = bpm[:, 1] +G5_0Psi_h_over_deltastar_avg0p25 = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure97-Psi0-h_over_deltastar0p43.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +St_3prime_over_St_3prime_peak_0p43 = bpm[:, 1] +G5_0Psi_h_over_deltastar_avg0p43 = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure97-Psi0-h_over_deltastar0p50.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +St_3prime_over_St_3prime_peak_0p50 = bpm[:, 1] +G5_0Psi_h_over_deltastar_avg0p50 = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure97-Psi0-h_over_deltastar0p54.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +St_3prime_over_St_3prime_peak_0p54 = bpm[:, 1] +G5_0Psi_h_over_deltastar_avg0p54 = bpm[:, 2] + +# fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure97-Psi0-h_over_deltastar0p62.csv") +# bpm = DelimitedFiles.readdlm(fname, ',') +# St_3prime_over_St_3prime_peak_0p62 = bpm[:, 1] +# G5_0Psi_h_over_deltastar_avg0p62 = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure97-Psi0-h_over_deltastar1p20.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +St_3prime_over_St_3prime_peak_1p20 = bpm[:, 1] +G5_0Psi_h_over_deltastar_avg1p20 = bpm[:, 2] + +St_3prime_over_St_3prime_peak_jl = 10.0.^(range(-1, 10; length=1001)) +G5_0Psi_h_over_deltastar_avg0p25_jl = AcousticAnalogies.G5_Psi0.(0.25, St_3prime_over_St_3prime_peak_jl) +G5_0Psi_h_over_deltastar_avg0p43_jl = AcousticAnalogies.G5_Psi0.(0.43, St_3prime_over_St_3prime_peak_jl) +G5_0Psi_h_over_deltastar_avg0p50_jl = AcousticAnalogies.G5_Psi0.(0.50, St_3prime_over_St_3prime_peak_jl) +G5_0Psi_h_over_deltastar_avg0p54_jl = AcousticAnalogies.G5_Psi0.(0.54, St_3prime_over_St_3prime_peak_jl) +# G5_0Psi_h_over_deltastar_avg0p62_jl = AcousticAnalogies.G5_Psi0.(0.62, St_3prime_over_St_3prime_peak_jl) +G5_0Psi_h_over_deltastar_avg1p20_jl = AcousticAnalogies.G5_Psi0.(1.20, St_3prime_over_St_3prime_peak_jl) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="Strouhal ratio, St'''/St'''_peak", ylabel="G_5, Ψ=0°", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 97b") + +scatter!(ax1, St_3prime_over_St_3prime_peak_0p25, G5_0Psi_h_over_deltastar_avg0p25; label="h/δ^* = 0.25, BPM", marker='o') +lines!(ax1, St_3prime_over_St_3prime_peak_jl, G5_0Psi_h_over_deltastar_avg0p25_jl; label="h/δ^* = 0.25, Julia") + +scatter!(ax1, St_3prime_over_St_3prime_peak_0p43, G5_0Psi_h_over_deltastar_avg0p43; label="h/δ^* = 0.43, BPM", marker='o') +lines!(ax1, St_3prime_over_St_3prime_peak_jl, G5_0Psi_h_over_deltastar_avg0p43_jl; label="h/δ^* = 0.43, Julia") + +scatter!(ax1, St_3prime_over_St_3prime_peak_0p50, G5_0Psi_h_over_deltastar_avg0p50; label="h/δ^* = 0.50, BPM", marker='o') +lines!(ax1, St_3prime_over_St_3prime_peak_jl, G5_0Psi_h_over_deltastar_avg0p50_jl; label="h/δ^* = 0.50, Julia") + +scatter!(ax1, St_3prime_over_St_3prime_peak_0p54, G5_0Psi_h_over_deltastar_avg0p54; label="h/δ^* = 0.54, BPM", marker='o') +lines!(ax1, St_3prime_over_St_3prime_peak_jl, G5_0Psi_h_over_deltastar_avg0p54_jl; label="h/δ^* = 0.54, Julia") + +# scatter!(ax1, St_3prime_over_St_3prime_peak_0p62, G5_0Psi_h_over_deltastar_avg0p62; label="h/δ^* = 0.62, BPM", marker='o') +# lines!(ax1, St_3prime_over_St_3prime_peak_jl, G5_0Psi_h_over_deltastar_avg0p62_jl; label="h/δ^* = 0.62, Julia") + +scatter!(ax1, St_3prime_over_St_3prime_peak_1p20, G5_0Psi_h_over_deltastar_avg1p20; label="h/δ^* = 1.20, BPM", marker='o') +lines!(ax1, St_3prime_over_St_3prime_peak_jl, G5_0Psi_h_over_deltastar_avg1p20_jl; label="h/δ^* = 1.20, Julia") + +xlims!(ax1, 0.1, 10.0) +ylims!(ax1, -30, 10) +axislegend(ax1, position=:rt) +save("19890016302-figure97b.png", fig) +``` +![](19890016302-figure97b.png) + diff --git a/docs/src/bpm_tests3.md b/docs/src/bpm_tests3.md new file mode 100644 index 00000000..36ef6354 --- /dev/null +++ b/docs/src/bpm_tests3.md @@ -0,0 +1,1894 @@ +```@meta +CurrentModule = AADocs +``` +# Software Quality Assurance, Cont. + +## Brooks, Pope, and Marcolini Airfoil Self-Noise Tests, Cont. + +### Airfoil Self-Noise Predictions + +```@example bpm_figure11_a +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure11-a-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_s = bpm[:, 1] +SPL_s = bpm[:, 2] + +# At zero angle of attack the pressure and suction side predictions are the same. +f_p = f_s +SPL_p = SPL_s + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 30.48e-2 # chord in meters +U = 71.3 # freestream velocity in m/s +M = 0.209 # Mach number, corresponds to U = 71.3 m/s in BPM report +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +M_c = 0.8*M +alphastar = 0.0 +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl) + + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 11 (a) - U = $U m/s") +scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 40, 80) +axislegend(ax1, position=:rt) +save("19890016302-figure11-a.png", fig) +``` +![](19890016302-figure11-a.png) + +```@example bpm_figure11_b +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure11-b-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_s = bpm[:, 1] +SPL_s = bpm[:, 2] + +# At zero angle of attack the pressure and suction side predictions are the same. +f_p = f_s +SPL_p = SPL_s + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 30.48e-2 # chord in meters +U = 55.5 # freestream velocity in m/s +# M = 0.163 # Mach number, corresponds to U = 55.5 m/s in BPM report +M = U/340.46 +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +M_c = 0.8*M +D_h = AcousticAnalogies.Dbar_h(θ_e, Φ_e, M, M_c) +alphastar = 0.0 + +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 11 (b) - U = $U m/s") +scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 30, 70) +axislegend(ax1, position=:rt) +save("19890016302-figure11-b.png", fig) +``` +![](19890016302-figure11-b.png) + +```@example bpm_figure11_c +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure11-c-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_s = bpm[:, 1] +SPL_s = bpm[:, 2] + +# At zero angle of attack the pressure and suction side predictions are the same. +f_p = f_s +SPL_p = SPL_s + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 30.48e-2 # chord in meters +U = 39.6 # freestream velocity in m/s +# M = 0.116 # Mach number, corresponds to U = 36.6 m/s in BPM report +M = U/340.46 +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +M_c = 0.8*M +D_h = AcousticAnalogies.Dbar_h(θ_e, Φ_e, M, M_c) +alphastar = 0.0 + +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 11 (c) - U = $U m/s") +scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 20, 60) +axislegend(ax1, position=:rt) +save("19890016302-figure11-c.png", fig) +``` +![](19890016302-figure11-c.png) + +```@example bpm_figure11_d +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure11-d-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_s = bpm[:, 1] +SPL_s = bpm[:, 2] + +# At zero angle of attack the pressure and suction side predictions are the same. +f_p = f_s +SPL_p = SPL_s + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 30.48e-2 # chord in meters +U = 31.7 # freestream velocity in m/s +M = 0.093 # Mach number, corresponds to U = 31.7 m/s in BPM report +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +M_c = 0.8*M +D_h = AcousticAnalogies.Dbar_h(θ_e, Φ_e, M, M_c) +alphastar = 0.0 + +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 11 (d) - U = $U m/s") +scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 20, 60) +axislegend(ax1, position=:rt) +save("19890016302-figure11-d.png", fig) +``` +![](19890016302-figure11-d.png) + +```@example bpm_figure12_a +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure12-U71.3-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_s = bpm[:, 1] +SPL_s = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure12-U71.3-TBL-TE-pressure.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_p = bpm[:, 1] +SPL_p = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure12-U71.3-separation.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_alpha = bpm[:, 1] +SPL_alpha = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 30.48e-2 # chord in meters +U = 71.3 # freestream velocity in m/s +M = 0.209 # Mach number, corresponds to U = 71.3 m/s in BPM report +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +M_c = 0.8*M +alphastar = 1.5*pi/180 + +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 12 (a) - U = $U m/s") +scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") + +scatter!(ax1, f_alpha, SPL_alpha; marker='△', label="separation, BPM") +lines!(ax1, f_jl./1e3, SPL_alpha_jl; label="separation, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 40, 80) +axislegend(ax1, position=:rt) +save("19890016302-figure12-a.png", fig) +``` +![](19890016302-figure12-a.png) + +```@example bpm_figure12_b +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure12-b-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_s = bpm[:, 1] +SPL_s = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure12-b-TBL-TE-pressure.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_p = bpm[:, 1] +SPL_p = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure12-b-TBL-TE-separation.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_alpha = bpm[:, 1] +SPL_alpha = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 30.48e-2 # chord in meters +U = 39.6 # freestream velocity in m/s +M = 0.116 # Mach number, corresponds to U = 36.6 m/s in BPM report +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +M_c = 0.8*M +alphastar = 1.5*pi/180 + +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 12 (b) - U = $U m/s") +scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") + +scatter!(ax1, f_alpha, SPL_alpha; marker='△', label="separation, BPM") +lines!(ax1, f_jl./1e3, SPL_alpha_jl; label="separation, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 20, 60) +axislegend(ax1, position=:rt) +save("19890016302-figure12-b.png", fig) +``` +![](19890016302-figure12-b.png) + +```@example bpm_figure26_a +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure26-a-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_s = bpm[:, 1] +SPL_s = bpm[:, 2] + +# Pressure and suction sides are the same for zero angle of attack. +f_p = f_s +SPL_p = SPL_s + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 10.16e-2 # chord in meters +U = 71.3 # freestream velocity in m/s +M = 0.209 # Mach number, corresponds to U = 71.3 m/s in BPM report +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +M_c = 0.8*M +alphastar = 0.0*pi/180 + +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 26 (a) - U = $U m/s") +scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") + +# scatter!(ax1, f_alpha, SPL_alpha; marker='△', label="separation, BPM") +lines!(ax1, f_jl./1e3, SPL_alpha_jl; label="separation, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 40, 80) +axislegend(ax1, position=:rt) +save("19890016302-figure26-a.png", fig) +``` +![](19890016302-figure26-a.png) + +```@example bpm_figure26_b +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure26-b-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_s = bpm[:, 1] +SPL_s = bpm[:, 2] + +# Pressure and suction sides are the same for zero angle of attack. +f_p = f_s +SPL_p = SPL_s + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 10.16e-2 # chord in meters +U = 55.5 # freestream velocity in m/s +M = 0.163 # Mach number, corresponds to U = 55.5 m/s in BPM report +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +M_c = 0.8*M +alphastar = 0.0*pi/180 + +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 26 (b) - U = $U m/s") +scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") + +# scatter!(ax1, f_alpha, SPL_alpha; marker='△', label="separation, BPM") +lines!(ax1, f_jl./1e3, SPL_alpha_jl; label="separation, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 30, 70) +axislegend(ax1, position=:rt) +save("19890016302-figure26-b.png", fig) +``` +![](19890016302-figure26-b.png) + +```@example bpm_figure26_c +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure26-c-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_s = bpm[:, 1] +SPL_s = bpm[:, 2] + +# Pressure and suction sides are the same for zero angle of attack. +f_p = f_s +SPL_p = SPL_s + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 10.16e-2 # chord in meters +U = 39.6 # freestream velocity in m/s +M = 0.116 # Mach number, corresponds to U = 39.6 m/s in BPM report +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +M_c = 0.8*M +alphastar = 0.0*pi/180 + +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 26 (c) - U = $U m/s") +scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 20, 60) +axislegend(ax1, position=:rt) +save("19890016302-figure26-c.png", fig) +``` +![](19890016302-figure26-c.png) + +```@example bpm_figure26_d +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure26-d-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_s = bpm[:, 1] +SPL_s = bpm[:, 2] + +# Pressure and suction sides are the same for zero angle of attack. +f_p = f_s +SPL_p = SPL_s + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 10.16e-2 # chord in meters +U = 31.7 # freestream velocity in m/s +M = 0.093 # Mach number, corresponds to U = 31.7 m/s in BPM report +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +M_c = 0.8*M +alphastar = 0.0*pi/180 + +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 26 (d) - U = $U m/s") +scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") + +# scatter!(ax1, f_alpha, SPL_alpha; marker='△', label="separation, BPM") +lines!(ax1, f_jl./1e3, SPL_alpha_jl; label="separation, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 20, 60) +axislegend(ax1, position=:rt) +save("19890016302-figure26-d.png", fig) +``` +![](19890016302-figure26-d.png) + +```@example bpm_figure28_a +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure28-a-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_s = bpm[:, 1] +SPL_s = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure28-a-TBL-TE-pressure.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_p = bpm[:, 1] +SPL_p = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure28-a-separation.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_alpha = bpm[:, 1] +SPL_alpha = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 10.16e-2 # chord in meters +U = 71.3 # freestream velocity in m/s +M = 0.209 # Mach number, corresponds to U = 71.3 m/s in BPM report +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +M_c = 0.8*M +alphastar = 6.7*pi/180 + +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 28 (a) - U = $U m/s") +scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") + +scatter!(ax1, f_alpha, SPL_alpha; marker='△', label="separation, BPM") +lines!(ax1, f_jl./1e3, SPL_alpha_jl; label="separation, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 40, 80) +axislegend(ax1, position=:rt) +save("19890016302-figure28-a.png", fig) +``` +![](19890016302-figure28-a.png) + +```@example bpm_figure28_b +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure28-b-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_s = bpm[:, 1] +SPL_s = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure28-b-TBL-TE-pressure.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_p = bpm[:, 1] +SPL_p = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure28-b-separation.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_alpha = bpm[:, 1] +SPL_alpha = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 10.16e-2 # chord in meters +U = 55.5 # freestream velocity in m/s +M = 0.163 # Mach number, corresponds to U = 55.5 m/s in BPM report +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +M_c = 0.8*M +alphastar = 6.7*pi/180 + +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 28 (b) - U = $U m/s") +scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") + +scatter!(ax1, f_alpha, SPL_alpha; marker='△', label="separation, BPM") +lines!(ax1, f_jl./1e3, SPL_alpha_jl; label="separation, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 30, 70) +axislegend(ax1, position=:rt) +save("19890016302-figure28-b.png", fig) +``` +![](19890016302-figure28-b.png) + +```@example bpm_figure28_c +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure28-c-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_s = bpm[:, 1] +SPL_s = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure28-c-TBL-TE-pressure.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_p = bpm[:, 1] +SPL_p = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure28-c-separation.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_alpha = bpm[:, 1] +SPL_alpha = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 10.16e-2 # chord in meters +U = 39.6 # freestream velocity in m/s +M = 0.116 # Mach number, corresponds to U = 39.6 m/s in BPM report +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +M_c = 0.8*M +alphastar = 6.7*pi/180 + +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 28 (c) - U = $U m/s") +scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") + +scatter!(ax1, f_alpha, SPL_alpha; marker='△', label="separation, BPM") +lines!(ax1, f_jl./1e3, SPL_alpha_jl; label="separation, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 30, 70) +axislegend(ax1, position=:rt) +save("19890016302-figure28-c.png", fig) +``` +![](19890016302-figure28-c.png) + +```@example bpm_figure28_d +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure28-d-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_s = bpm[:, 1] +SPL_s = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure28-d-TBL-TE-pressure.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_p = bpm[:, 1] +SPL_p = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure28-d-separation.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_alpha = bpm[:, 1] +SPL_alpha = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 10.16e-2 # chord in meters +U = 31.7 # freestream velocity in m/s +M = 0.093 # mach number, corresponds to u = 31.7 m/s in bpm report +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +M_c = 0.8*M +alphastar = 6.7*pi/180 + +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="figure 28 (d) - U = $U m/s") +scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") + +scatter!(ax1, f_alpha, SPL_alpha; marker='△', label="separation, BPM") +lines!(ax1, f_jl./1e3, SPL_alpha_jl; label="separation, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 30, 70) +axislegend(ax1, position=:rt) +save("19890016302-figure28-d.png", fig) +``` +![](19890016302-figure28-d.png) + +```@example bpm_figure38_d +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure38-d-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_s = bpm[:, 1] +SPL_s = bpm[:, 2] + +# fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure38-d-TBL-TE-pressure.csv") +# bpm = DelimitedFiles.readdlm(fname, ',') +# f_p = bpm[:, 1] +# SPL_p = bpm[:, 2] +# +# fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure38-d-separation.csv") +# bpm = DelimitedFiles.readdlm(fname, ',') +# f_alpha = bpm[:, 1] +# SPL_alpha = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 2.54e-2 # chord in meters +U = 31.7 # freestream velocity in m/s +M = 0.093 # mach number, corresponds to u = 31.7 m/s in bpm report +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +M_c = 0.8*M +alphastar = 0.0*pi/180 + +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="figure 38 (d) - U = $U m/s") +scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +# scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +# lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") +# +# scatter!(ax1, f_alpha, SPL_alpha; marker='△', label="separation, BPM") +# lines!(ax1, f_jl./1e3, SPL_alpha_jl; label="separation, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 20, 60) +axislegend(ax1, position=:rt) +save("19890016302-figure38-d.png", fig) +``` +![](19890016302-figure38-d.png) + +```@example bpm_figure39_d +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure39-d-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_s = bpm[:, 1] +SPL_s = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure39-d-TBL-TE-pressure.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_p = bpm[:, 1] +SPL_p = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure39-d-separation.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_alpha = bpm[:, 1] +SPL_alpha = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 2.54e-2 # chord in meters +U = 31.7 # freestream velocity in m/s +M = 0.093 # mach number, corresponds to u = 31.7 m/s in bpm report +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +M_c = 0.8*M +alphastar = 4.8*pi/180 + +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="figure 39 (d) - U = $U m/s") +scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") + +scatter!(ax1, f_alpha, SPL_alpha; marker='△', label="separation, BPM") +lines!(ax1, f_jl./1e3, SPL_alpha_jl; label="separation, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 20, 60) +axislegend(ax1, position=:rt) +save("19890016302-figure39-d.png", fig) +``` +![](19890016302-figure39-d.png) + +```@example bpm_figure45_a +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure45-a-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_s = bpm[:, 1] +SPL_s = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure45-a-TBL-TE-pressure.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_p = bpm[:, 1] +SPL_p = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure45-a-separation.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_alpha = bpm[:, 1] +SPL_alpha = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure45-a-LBL-VS.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_lbl_vs = bpm[:, 1] +SPL_lbl_vs = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 30.48e-2 # chord in meters +U = 71.3 # freestream velocity in m/s +M = 0.209 # Mach number, corresponds to U = 71.3 m/s in BPM report +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +alphastar = 1.5*pi/180 + +bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_lbl_vs_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl; do_lblvs=true) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 45 (a) - U = $U m/s") +scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") + +scatter!(ax1, f_alpha, SPL_alpha; marker='△', label="separation, BPM") +lines!(ax1, f_jl./1e3, SPL_alpha_jl; label="separation, Julia") + +scatter!(ax1, f_lbl_vs, SPL_lbl_vs; marker='◇', label="LBL-VS, BPM") +scatterlines!(ax1, f_jl./1e3, SPL_lbl_vs_jl; marker='◇', label="LBL-VS, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 40, 80) +axislegend(ax1, position=:rt) +save("19890016302-figure45-a.png", fig) +``` +![](19890016302-figure45-a.png) + +```@example bpm_figure48_c +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure48-c-LBL-VS.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_lbl_vs = bpm[:, 1] +SPL_lbl_vs = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 22.86e-2 # chord in meters +U = 39.6 # freestream velocity in m/s +M = 0.116 # Mach number, corresponds to U = 39.6 m/s in BPM report +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +alphastar = 0.0*pi/180 + +bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_lbl_vs_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl; do_lblvs=true) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 48 (c) - U = $U m/s") + +scatter!(ax1, f_lbl_vs, SPL_lbl_vs; marker=:diamond, label="LBL-VS, BPM") +lines!(ax1, f_jl./1e3, SPL_lbl_vs_jl; label="LBL-VS, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 20, 60) +axislegend(ax1, position=:rt) +save("19890016302-figure48-c.png", fig) +``` +![](19890016302-figure48-c.png) + +```@example bpm_figure54_a +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure54-a-LBL-VS.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_lbl_vs = bpm[:, 1] +SPL_lbl_vs = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 15.24e-2 # chord in meters +U = 71.3 # freestream velocity in m/s +M = 0.209 # Mach number, corresponds to U = 71.3 m/s in BPM report +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +alphastar = 2.7*pi/180 + +bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_lbl_vs_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl; do_lblvs=true) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 54 (a) - U = $U m/s") + +scatter!(ax1, f_lbl_vs, SPL_lbl_vs; marker=:diamond, label="LBL-VS, BPM") +lines!(ax1, f_jl./1e3, SPL_lbl_vs_jl; label="LBL-VS, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 50, 90) +axislegend(ax1, position=:rt) +save("19890016302-figure54-a.png", fig) +``` +![](19890016302-figure54-a.png) + +```@example bpm_figure59_c +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure59-c-LBL-VS.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_lbl_vs = bpm[:, 1] +SPL_lbl_vs = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 10.16e-2 # chord in meters +U = 39.6 # freestream velocity in m/s +M = 0.116 # Mach number, corresponds to U = 39.6 m/s in BPM report +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +alphastar = 0.0*pi/180 + +bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_lbl_vs_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl; do_lblvs=true) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 59 (c) - U = $U m/s") + +scatter!(ax1, f_lbl_vs, SPL_lbl_vs; marker=:diamond, label="LBL-VS, BPM") +lines!(ax1, f_jl./1e3, SPL_lbl_vs_jl; label="LBL-VS, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 40, 80) +axislegend(ax1, position=:rt) +save("19890016302-figure59-c.png", fig) +``` +![](19890016302-figure59-c.png) + +```@example bpm_figure60_c +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure60-c-LBL-VS.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_lbl_vs = bpm[:, 1] +SPL_lbl_vs = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 10.16e-2 # chord in meters +U = 39.6 # freestream velocity in m/s +M = 0.116 # Mach number, corresponds to U = 39.6 m/s in BPM report +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +alphastar = 3.3*pi/180 + +bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_lbl_vs_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl; do_lblvs=true) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 60 (c) - U = $U m/s") + +scatter!(ax1, f_lbl_vs, SPL_lbl_vs; marker=:diamond, label="LBL-VS, BPM") +lines!(ax1, f_jl./1e3, SPL_lbl_vs_jl; label="LBL-VS, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 40, 80) +axislegend(ax1, position=:rt) +save("19890016302-figure60-c.png", fig) +``` +![](19890016302-figure60-c.png) + +```@example bpm_figure60_d +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure60-d-LBL-VS.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_lbl_vs = bpm[:, 1] +SPL_lbl_vs = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 10.16e-2 # chord in meters +U = 31.7 # freestream velocity in m/s +M = 0.093 # mach number, corresponds to u = 31.7 m/s in bpm report +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +alphastar = 3.3*pi/180 + +bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_lbl_vs_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl; do_lblvs=true) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 60 (d) - U = $U m/s") + +scatter!(ax1, f_lbl_vs, SPL_lbl_vs; marker=:diamond, label="LBL-VS, BPM") +lines!(ax1, f_jl./1e3, SPL_lbl_vs_jl; label="LBL-VS, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 40, 80) +axislegend(ax1, position=:rt) +save("19890016302-figure60-d.png", fig) +``` +![](19890016302-figure60-d.png) + +```@example bpm_figure65_d +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure65-d-LBL-VS.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_lbl_vs = bpm[:, 1] +SPL_lbl_vs = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 5.08e-2 # chord in meters +U = 31.7 # freestream velocity in m/s +M = 0.093 # mach number, corresponds to u = 31.7 m/s in bpm report +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +alphastar = 0.0*pi/180 + +bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_lbl_vs_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl; do_lblvs=true) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 65 (d) - U = $U m/s") + +scatter!(ax1, f_lbl_vs, SPL_lbl_vs; marker=:diamond, label="LBL-VS, BPM") +lines!(ax1, f_jl./1e3, SPL_lbl_vs_jl; label="LBL-VS, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 50, 90) +axislegend(ax1, position=:rt) +save("19890016302-figure65-d.png", fig) +``` +![](19890016302-figure65-d.png) + +```@example bpm_figure66_b +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure66-b-LBL-VS.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_lbl_vs = bpm[:, 1] +SPL_lbl_vs = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 5.08e-2 # chord in meters +U = 39.6 # freestream velocity in m/s +M = 0.116 # Mach number, corresponds to U = 39.6 m/s in BPM report +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +alphastar = 4.2*pi/180 + +bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_lbl_vs_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl; do_lblvs=true) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 66 (b) - U = $U m/s") + +scatter!(ax1, f_lbl_vs, SPL_lbl_vs; marker=:diamond, label="LBL-VS, BPM") +scatterlines!(ax1, f_jl./1e3, SPL_lbl_vs_jl; label="LBL-VS, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 30, 70) +axislegend(ax1, position=:rt) +save("19890016302-figure66-b.png", fig) +``` +![](19890016302-figure66-b.png) + +```@example bpm_figure69_a +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure69-a-separation.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_alpha = bpm[:, 1] +SPL_alpha = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 5.08e-2 # chord in meters +U = 71.3 # freestream velocity in m/s +M = 0.209 # Mach number, corresponds to U = 71.3 m/s in BPM report +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +M_c = 0.8*M +alphastar = 15.4*pi/180 + +bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl) + + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 69 (a) - U = $U m/s") +# scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +# scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") + +scatter!(ax1, f_alpha, SPL_alpha; marker='△', label="separation, BPM") +lines!(ax1, f_jl./1e3, SPL_alpha_jl; label="separation, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 60, 100) +axislegend(ax1, position=:rt) +save("19890016302-figure69-a.png", fig) +``` +![](19890016302-figure69-a.png) + +```@example bpm_figure69_b +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +# TBL-TE suction and pressure aren't significant sources for this case (deep stall). + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure69-b-separation.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_alpha = bpm[:, 1] +SPL_alpha = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 5.08e-2 # chord in meters +U = 39.6 # freestream velocity in m/s +M = 0.116 # Mach number, corresponds to U = 39.6 m/s in BPM report +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +M_c = 0.8*M +alphastar = 15.4*pi/180 + +bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 69 (b) - U = $U m/s") +# scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +# scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") + +scatter!(ax1, f_alpha, SPL_alpha; marker='△', label="separation, BPM") +lines!(ax1, f_jl./1e3, SPL_alpha_jl; label="separation, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 40, 80) +axislegend(ax1, position=:rt) +save("19890016302-figure69-b.png", fig) +``` +![](19890016302-figure69-b.png) + +```@example bpm_figure91 +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure91-tip.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_tip = bpm[:, 1] +SPL_tip = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 30.48e-2 # span in meters +chord = 15.24e-2 # chord in meters +speedofsound = 340.46 +U = 71.3 # freestream velocity in m/s +# M = 0.209 # Mach number, corresponds to U = 71.3 m/s in BPM report +M = U/speedofsound +M_c = 0.8*M +# speedofsound = U/M +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +alphastar = 10.8*pi/180 + +bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() +blade_tip = AcousticAnalogies.RoundedTip(AcousticAnalogies.BPMTipAlphaCorrection(), 0.0) +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_tip_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl; do_tip_vortex=true, blade_tip=blade_tip) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 91") +scatter!(ax1, f_tip, SPL_tip; marker='o', label="Tip, BPM") +lines!(ax1, f_jl./1e3, SPL_tip_jl; label="Tip, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 40, 90) +axislegend(ax1, position=:rt) +save("19890016302-figure91.png", fig) +``` +![](19890016302-figure91.png) + +```@example bpm_figure98_b +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +# Figures 98 a-d only differ in trailing edge bluntness, so the other sources are all the same. +# And TBL-TE is the only significant source, other than bluntness. +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure98-a-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_s = bpm[:, 1] +SPL_s = bpm[:, 2] + +# Suction and pressure are the same for zero angle of attack. +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure98-a-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_p = bpm[:, 1] +SPL_p = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure98-b-bluntness.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_teb_vs = bpm[:, 1] +SPL_teb_vs = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 60.96e-2 # chord in meters +U = 69.5 # freestream velocity in m/s +M = U/340.46 +h = 1.1e-3 # trailing edge bluntness in meters +Psi = 14*pi/180 # bluntness angle in radians +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +M_c = 0.8*M +alphastar = 0.0*pi/180 + +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_teb_vs_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl; do_tebvs=true, h=h, Psi=Psi) + + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 98 (b) - U = $U m/s") +scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") + +scatter!(ax1, f_teb_vs, SPL_teb_vs; marker='◺', label="Bluntness, BPM") +lines!(ax1, f_jl./1e3, SPL_teb_vs_jl; label="Bluntness, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 40, 80) +axislegend(ax1, position=:rt) +save("19890016302-figure98-b.png", fig) +``` +![](19890016302-figure98-b.png) + +```@example bpm_figure98_c +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +# Figures 98 a-d only differ in trailing edge bluntness, so the other sources are all the same. +# And TBL-TE is the only significant source, other than bluntness. +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure98-a-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_s = bpm[:, 1] +SPL_s = bpm[:, 2] + +# Suction and pressure are the same for zero angle of attack. +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure98-a-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_p = bpm[:, 1] +SPL_p = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure98-c-bluntness.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_teb_vs = bpm[:, 1] +SPL_teb_vs = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 60.96e-2 # chord in meters +U = 69.5 # freestream velocity in m/s +M = U/340.46 +h = 1.9e-3 # trailing edge bluntness in meters +Psi = 14*pi/180 # bluntness angle in radians +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +M_c = 0.8*M +alphastar = 0.0*pi/180 + +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_teb_vs_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl; do_tebvs=true, h=h, Psi=Psi) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 98 (c) - U = $U m/s") +scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") + +scatter!(ax1, f_teb_vs, SPL_teb_vs; marker='◺', label="Bluntness, BPM") +lines!(ax1, f_jl./1e3, SPL_teb_vs_jl; label="Bluntness, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 40, 80) +axislegend(ax1, position=:lt) +save("19890016302-figure98-c.png", fig) +``` +![](19890016302-figure98-c.png) + +```@example bpm_figure98_d +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +# Figures 98 a-d only differ in trailing edge bluntness, so the other sources are all the same. +# And TBL-TE is the only significant source, other than bluntness. +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure98-a-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_s = bpm[:, 1] +SPL_s = bpm[:, 2] + +# Suction and pressure are the same for zero angle of attack. +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure98-a-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_p = bpm[:, 1] +SPL_p = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure98-d-bluntness.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_teb_vs = bpm[:, 1] +SPL_teb_vs = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 60.96e-2 # chord in meters +U = 69.5 # freestream velocity in m/s +M = U/340.46 +h = 2.5e-3 # trailing edge bluntness in meters +Psi = 14*pi/180 # bluntness angle in radians +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +M_c = 0.8*M +alphastar = 0.0*pi/180 + +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_teb_vs_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl; do_tebvs=true, h=h, Psi=Psi) + + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 98 (d) - U = $U m/s") +scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") + +scatter!(ax1, f_teb_vs, SPL_teb_vs; marker='◺', label="Bluntness, BPM") +lines!(ax1, f_jl./1e3, SPL_teb_vs_jl; label="Bluntness, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 40, 80) +axislegend(ax1, position=:lt) +save("19890016302-figure98-d.png", fig) +``` +![](19890016302-figure98-d.png) + +```@example bpm_figure99_b +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +# Figures 99 a-d only differ in trailing edge bluntness, so the other sources are all the same. +# And TBL-TE is the only significant source, other than bluntness. +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure99-b-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_s = bpm[:, 1] +SPL_s = bpm[:, 2] + +# Suction and pressure are the same for zero angle of attack. +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure99-b-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_p = bpm[:, 1] +SPL_p = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure99-b-bluntness.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_teb_vs = bpm[:, 1] +SPL_teb_vs = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 60.96e-2 # chord in meters +U = 38.6 # freestream velocity in m/s +M = U/340.46 +h = 1.1e-3 # trailing edge bluntness in meters +Psi = 14*pi/180 # bluntness angle in radians +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +M_c = 0.8*M +alphastar = 0.0*pi/180 + +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_teb_vs_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl; do_tebvs=true, h=h, Psi=Psi) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 99 (b) - U = $U m/s") +scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") + +scatter!(ax1, f_teb_vs, SPL_teb_vs; marker='◺', label="Bluntness, BPM") +lines!(ax1, f_jl./1e3, SPL_teb_vs_jl; label="Bluntness, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 30, 70) +axislegend(ax1, position=:rt) +save("19890016302-figure99-b.png", fig) +``` +![](19890016302-figure99-b.png) + +```@example bpm_figure99_c +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +# Figures 99 a-d only differ in trailing edge bluntness, so the other sources are all the same. +# And TBL-TE is the only significant source, other than bluntness. +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure99-b-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_s = bpm[:, 1] +SPL_s = bpm[:, 2] + +# Suction and pressure are the same for zero angle of attack. +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure99-b-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_p = bpm[:, 1] +SPL_p = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure99-c-bluntness.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_teb_vs = bpm[:, 1] +SPL_teb_vs = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 60.96e-2 # chord in meters +U = 38.6 # freestream velocity in m/s +M = U/340.46 +h = 1.9e-3 # trailing edge bluntness in meters +Psi = 14*pi/180 # bluntness angle in radians +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +M_c = 0.8*M +alphastar = 0.0*pi/180 + +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_teb_vs_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl; do_tebvs=true, h=h, Psi=Psi) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 99 (c) - U = $U m/s") +scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") + +scatter!(ax1, f_teb_vs, SPL_teb_vs; marker='◺', label="Bluntness, BPM") +lines!(ax1, f_jl./1e3, SPL_teb_vs_jl; label="Bluntness, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 30, 70) +axislegend(ax1, position=:rt) +save("19890016302-figure99-c.png", fig) +``` +![](19890016302-figure99-c.png) + +```@example bpm_figure99_d +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: ExactThirdOctaveCenterBands +using DelimitedFiles: DelimitedFiles +using GLMakie + +# https://docs.makie.org/stable/examples/blocks/axis/index.html#logticks +struct IntegerTicks end +Makie.get_tickvalues(::IntegerTicks, vmin, vmax) = ceil(Int, vmin) : floor(Int, vmax) + +# Figures 99 a-d only differ in trailing edge bluntness, so the other sources are all the same. +# And TBL-TE is the only significant source, other than bluntness. +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure99-b-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_s = bpm[:, 1] +SPL_s = bpm[:, 2] + +# Suction and pressure are the same for zero angle of attack. +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure99-b-TBL-TE-suction.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_p = bpm[:, 1] +SPL_p = bpm[:, 2] + +fname = joinpath(@__DIR__, "..", "..", "test", "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure99-d-bluntness.csv") +bpm = DelimitedFiles.readdlm(fname, ',') +f_teb_vs = bpm[:, 1] +SPL_teb_vs = bpm[:, 2] + +nu = 1.4529e-5 # kinematic viscosity, m^2/s +L = 45.72e-2 # span in meters +chord = 60.96e-2 # chord in meters +U = 38.6 # freestream velocity in m/s +M = U/340.46 +h = 2.5e-3 # trailing edge bluntness in meters +Psi = 14*pi/180 # bluntness angle in radians +r_e = 1.22 # radiation distance in meters +θ_e = 90*pi/180 +Φ_e = 90*pi/180 +M_c = 0.8*M +alphastar = 0.0*pi/180 + +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() +f_jl, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_teb_vs_jl = AcousticAnalogies.calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl; do_tebvs=true, h=h, Psi=Psi) + +fig = Figure() +ax1 = fig[1, 1] = Axis(fig; xlabel="frequency, kHz", ylabel="SPL_1/3, dB", + xscale=log10, + xminorticksvisible=true, + xminorticks=IntervalsBetween(9), + xticks=LogTicks(IntegerTicks()), + title="Figure 99 (d) - U = $U m/s") +scatter!(ax1, f_s, SPL_s; marker='o', label="TBL-TE suction side, BPM") +lines!(ax1, f_jl./1e3, SPL_s_jl; label="TBL-TE suction side, Julia") + +scatter!(ax1, f_p, SPL_p; marker='□', label="TBL-TE pressure side, BPM") +lines!(ax1, f_jl./1e3, SPL_p_jl; label="TBL-TE pressure side, Julia") + +scatter!(ax1, f_teb_vs, SPL_teb_vs; marker='◺', label="Bluntness, BPM") +lines!(ax1, f_jl./1e3, SPL_teb_vs_jl; label="Bluntness, Julia") + +xlims!(ax1, 0.2, 20.0) +ylims!(ax1, 30, 70) +axislegend(ax1, position=:rt) +save("19890016302-figure99-d.png", fig) +``` +![](19890016302-figure99-d.png) diff --git a/docs/src/ccblade_example.md b/docs/src/ccblade_example.md index 8d2b1a82..98a97826 100644 --- a/docs/src/ccblade_example.md +++ b/docs/src/ccblade_example.md @@ -113,15 +113,16 @@ nothing # hide ![](ccblade_example-ccblade_loads.png) Now we can use the CCBlade.jl `structs` to create AcousticAnalogies.jl source -elements. The key function is [`source_elements_ccblade`](@ref): +elements. The key function is [`f1a_source_elements_ccblade`](@ref): ```@docs -source_elements_ccblade +f1a_source_elements_ccblade ``` So let's try that: ```@example first_example -using AcousticAnalogies: source_elements_ccblade, ConstVelocityAcousticObserver, f1a, combine, pressure_monopole, pressure_dipole +using AcousticAnalogies: f1a_source_elements_ccblade, ConstVelocityAcousticObserver, noise, combine, pressure_monopole, pressure_dipole bpp = 2*pi/omega/num_blades # blade passing period -ses = source_elements_ccblade(rotor, sections, ops, outs, [area_over_chord_squared], 4*bpp, 64) +positive_x_rotation = true +ses = f1a_source_elements_ccblade(rotor, sections, ops, outs, [area_over_chord_squared], 4*bpp, 64, positive_x_rotation) nothing # hide ``` @@ -134,7 +135,7 @@ using AcousticMetrics x_obs = [0.0, 2.3033, 2.6842] v_obs = [v, 0.0, 0.0] obs = ConstVelocityAcousticObserver(0.0, x_obs, v_obs) -apth = f1a.(ses, Ref(obs)) +apth = noise.(ses, Ref(obs)) apth_total = combine(apth, 2*bpp, 64) nothing # hide ``` diff --git a/docs/src/guided_example.md b/docs/src/guided_example.md index 2062aa24..5367736f 100644 --- a/docs/src/guided_example.md +++ b/docs/src/guided_example.md @@ -164,8 +164,8 @@ a rate of `omega` and moving forward at a speed of `v` defined above. Let's do that. We want one source element for each radial station along the blade at each `src_time` and each of the `num_blades` blades. Sounds kind of complicated, but luckily Julia's broadcasting makes this easy. What we'd like is an array `ses` -of `CompactSourceElement` types that has `size` `(num_src_times, num_radial, -num_blades)`, where `ses[i, j, k]` holds the `CompactSourceElement` at +of `CompactF1ASourceElement` types that has `size` `(num_src_times, num_radial, +num_blades)`, where `ses[i, j, k]` holds the `CompactF1ASourceElement` at `src_time[i]`, `radii[j]`, and blade number `k`. So let's reshape the input arrays to make that happen. @@ -184,7 +184,7 @@ Now, the last thing we need to think about is the coordinate system we're defining these quantities in. Again, right now we are in the blade-fixed frame, which means the coordinate system is rotating with the blades at a rate of `omega` and translating with a velocity `v` in the positive x direction. The -`CompactSourceElement` constructor we'll use allows us to specify each source +`CompactF1ASourceElement` constructor we'll use allows us to specify each source element's location in terms of `r` and `θ`, where `r` is the distance from the origin and `θ` is the polar angle from the positive y axis, rotating toward the positive `z` axis. So the `radii` and `θs` arrays are set up correctly. @@ -207,19 +207,19 @@ the `fc` array. So let's create all the source elements: ```@example first_example -ses = CompactSourceElement.(rho, c0, radii, θs, dradii, cs_area, -fn, 0.0, fc, src_times) +ses = CompactF1ASourceElement.(rho, c0, radii, θs, dradii, cs_area, -fn, 0.0, fc, src_times) size(ses) ``` The size of the source element array ended up like we wanted: `(num_src_times, num_radial, num_blades)`. ### The Global Reference Frame -At this point we have an array of `CompactSourceElement` that describes the what +At this point we have an array of `CompactF1ASourceElement` that describes the what each blade element "source" is doing from the perspective of the blade-fixed reference frame. But in order to perform the F1A calculation, we need to move the sources from the blade-fixed frame to the global reference frame, i.e., the one for which the fluid medium (air) appears to be stationary. This involves -just setting the position and loading components of each `CompactSourceElement` +just setting the position and loading components of each `CompactF1ASourceElement` to the correct values (`y0dot` through `y3dot` and `f0dot` and `f1dot`). This could be done manually, but it's easier to use the [KinematicCoordinateTransformations.jl](https://github.com/OpenMDAO/KinematicCoordinateTransformations.jl) @@ -280,7 +280,7 @@ the global reference frame. We could have created the source elements and transformed them all in one line, too, which is pretty slick: ```@example first_example -ses = AcousticAnalogies.CompactSourceElement.(rho, c0, radii, θs, dradii, cs_area, -fn, 0.0, fc, src_times) .|> trans +ses = AcousticAnalogies.CompactF1ASourceElement.(rho, c0, radii, θs, dradii, cs_area, -fn, 0.0, fc, src_times) .|> trans nothing # hide ``` @@ -321,11 +321,11 @@ nothing # hide We're finally ready to do the compact F1A calculation! ```@example first_example -apth = f1a.(ses, Ref(obs), obs_time) +apth = noise.(ses, Ref(obs), obs_time) nothing # hide ``` -When called this way (notice the `.` after `f1a`), the `f1a` routine returns an +When called this way (notice the `.` after `noise`), the `noise` routine returns an array of `F1AOutput` `struct`s, the same size as `ses` and `obs_time`. Each `F1AOutput` `struct` has three components: the observer time `t`, the thickness/monopole part of the acoustic pressure `p_m`, and the @@ -389,7 +389,7 @@ with the `F1AAcousticPressure` returned by `combine`: using AcousticMetrics # Calculate the overall sound pressure level from the acoustic pressure time history. oaspl_from_apth = AcousticMetrics.OASPL(apth_total) -# Calculate the narrowband spectrum. +# Calculate the narrowband spectrum of mean-squared pressure. nbs = AcousticMetrics.MSPSpectrumAmplitude(apth_total) # Calculate the OASPL from the NBS. oaspl_from_nbs = AcousticMetrics.OASPL(nbs) diff --git a/docs/src/index.md b/docs/src/index.md index 959e779b..ab017c47 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -36,6 +36,7 @@ CurrentModule = AADocs or [http://dx.doi.org/10.2514/1.C034048](http://dx.doi.org/10.2514/1.C034048) for details). + * Implementation of Brooks & Burley's rotor broadband noise prediction method [http://dx.doi.org/10.2514/6.2001-2210](http://dx.doi.org/10.2514/6.2001-2210). * Support for stationary or constant-velocity moving observers, with an explict calculation for the latter from D. Casalino [http://dx.doi.org/10.1016/S0022-460X(02)00986-0](http://dx.doi.org/10.1016/S0022-460X(02)00986-0). diff --git a/docs/src/itr_tests1.md b/docs/src/itr_tests1.md new file mode 100644 index 00000000..2b55f031 --- /dev/null +++ b/docs/src/itr_tests1.md @@ -0,0 +1,1011 @@ +```@meta +CurrentModule = AADocs +``` +# Software Quality Assurance, Cont. + +## BPM.jl Comparisons for the Pettingill et al. Ideally Twisted Rotor +See [here](http://dx.doi.org/10.2514/6.2021-1928) or [here](https://ntrs.nasa.gov/citations/20205003328) for details on the Ideally Twisted Rotor. + +### Figure 22b +```@example figure22b +using AcousticAnalogies +using AcousticMetrics: AcousticMetrics +using GLMakie +using KinematicCoordinateTransformations: compose, SteadyRotXTransformation, SteadyRotYTransformation, SteadyRotZTransformation, ConstantVelocityTransformation +using FileIO: load +using FLOWMath: Akima +using StaticArrays: @SVector + +# Copied from BPM.jl (would like to add BPM.jl as a dependency if it's registered in General some day). +# tip vortex noise correction data based on "Airfoil Tip Vortex Formation Noise" +const bm_tip_alpha_aspect_data = [2.0,2.67,4.0,6.0,12.0,24.0] +const bm_tip_alpha_aratio_data = [0.54,0.62,0.71,0.79,0.89,0.95] +const bm_tip_alpha_aspect_ratio_correction = Akima(bm_tip_alpha_aspect_data, bm_tip_alpha_aratio_data) + +function bm_tip_vortex_alpha_correction_nonsmooth(aspect_ratio) + # compute tip lift curve slope + if aspect_ratio < 2.0 + aratio = 0.5*one(aspect_ratio) + elseif 2.0 <= aspect_ratio <= 24.0 + aratio = bm_tip_alpha_aspect_ratio_correction(aspect_ratio) + elseif aspect_ratio > 24.0 + aratio = 1.0*one(aspect_ratio) + end + + return aratio +end + +struct BMTipAlphaCorrection{TCorrection} <: AbstractTipAlphaCorrection + correction::TCorrection + + function BMTipAlphaCorrection(aspect_ratio) + # correction = BPM._tip_vortex_alpha_correction_nonsmooth(aspect_ratio) + correction = bm_tip_vortex_alpha_correction_nonsmooth(aspect_ratio) + return new{typeof(correction)}(correction) + end +end + +function AcousticAnalogies.tip_vortex_alpha_correction(blade_tip::AbstractBladeTip{<:BMTipAlphaCorrection}, alphatip) + a0l = AcousticAnalogies.alpha_zerolift(blade_tip) + correction_factor = AcousticAnalogies.tip_alpha_correction(blade_tip).correction + return correction_factor * (alphatip - a0l) + a0l +end + +# Pettingill et al., "Acoustic And Performance Characteristics of an Ideally Twisted Rotor in Hover", 2021 +# Parameters from Table 1 +B = 4 # number of blades +Rtip = 0.1588 # meters +chord = 0.2*Rtip + +# Standard day: +Tamb = 15 + 273.15 # 15°C in Kelvin +pamb = 101325.0 # Pa +R = 287.052874 # J/(kg*K) +rho = pamb/(R*Tamb) +asound = sqrt(1.4*R*Tamb) +# Dynamic and kinematic viscosity +mu = rho*1.4502e-5 +nu = mu/rho + +# This is a hover case, so the freestream velocity should be zero. +# CCBlade.jl will run with a zero freestream, but I've found that it compares a bit better with experiment if I give it a small non-zero value. +Vinf = 0.001*asound + +# Figure 22 caption says Ω_c = 5465 RPM. +rpm = 5465.0 +omega = rpm * (2*pi/60) + +# Get "cell-centered" radial locations, and also the radial spacing. +num_radial = 50 +r_Rtip_ = range(0.2, 1.0; length=num_radial+1) +r_Rtip = 0.5 .* (r_Rtip_[2:end] .+ r_Rtip_[1:end-1]) +radii = r_Rtip .* Rtip +dradii = (r_Rtip_[2:end] .- r_Rtip_[1:end-1]) .* Rtip +Rhub = r_Rtip_[1]*Rtip + +# From Pettingill Equation (1), and value for Θ_tip in Table 1. +Θ_tip = 6.9 * pi/180 +twist = Θ_tip ./ (r_Rtip) + +# Need some aerodynamic quantities. +# Got these using CCBlade.jl: see `AcousticAnalogies.jl/test/gen_bpmjl_data/itr_with_bpmjl.jl`. +data_bpmjl = load(joinpath(@__DIR__, "..", "..", "test", "gen_bpmjl_data", "figure22b.jld2")) +# Angle of attack at each radial station, radians. +alpha = data_bpmjl["alpha"] +# Flow speed normal to span at each radial station, m/s. +U = data_bpmjl["U"] + +# In the Figure 22 caption, "for these predictions, bluntness thickness H was set to 0.8 mm and trailing edge angle Ψ was set to 16 degrees." +h = 0.8e-3 # meters +Psi = 16*pi/180 # radians + +# We'll run for 1 blade pass, 20 time steps per blade pass. +num_blade_pass = 1 +num_src_times_blade_pass = 20 +bpp = 1/(B/(2*pi)*omega) # 1/(B blade_passes/rev * 1 rev / (2*pi rad) * omega rad/s) +period_src = num_blade_pass*bpp +num_src_times = num_src_times_blade_pass * num_blade_pass +t0 = 0.0 +dt = period_src/num_src_times +src_times = t0 .+ (0:num_src_times-1).*dt + +# BPM.jl uses a different tip alpha correction which appears to require the blade aspect ratio. +# Need to find the blade aspect ratio of the ITR to apply the tip vortex angle of attack correction. +# The aspect ratio is defined as the blade tip radius divided by the average chord, but the chord is constant for this case. +aspect_ratio = Rtip / chord + +# Now we can create the tip object. +alpha0lift = 0.0 +blade_tip = AcousticAnalogies.FlatTip(BMTipAlphaCorrection(aspect_ratio), alpha0lift) + +# Start with a rotation about the negative x axis. +positive_x_rotation = false +rot_trans = SteadyRotXTransformation(t0, omega*ifelse(positive_x_rotation, 1, -1), 0) + +# Then translate along the positive x axis. +y0_hub = @SVector [0.0, 0.0, 0.0] # m +v0_hub = @SVector [Vinf, 0.0, 0.0] +const_vel_trans = ConstantVelocityTransformation(t0, y0_hub, v0_hub) + +# Then a 90° rotation about the negative z axis. +trans_z90deg = SteadyRotZTransformation(0.0, 0.0, -0.5*pi) + +# Then a 90° rotation about the negative y axis. +trans_y90deg = SteadyRotYTransformation(0.0, 0.0, -0.5*pi) + +# Put them all together: +trans = compose.(src_times, Ref(trans_y90deg), + compose.(src_times, Ref(trans_z90deg), + compose.(src_times, Ref(const_vel_trans), Ref(rot_trans)))) + +# Use the M_c = 0.8*M that BPM report and BPM.jl use. +U = @. 0.8*sqrt(Vinf^2 + (omega*radii)^2) + +# In the text describing Figure 22, "For these predictions, the trip flag was set to “tripped”, due to the rough surface quality of the blade." +# So we'll use a tripped boundary layer for all radial stations along the blade. +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() + +# Need to do the LBLVS with the untripped boundary layer to match what BPM.jl is doing. +# BPM.jl uses the untripped boundary layer properties for the laminar boundary layer-vortex shedding noise source, so do that here too. +bl_lblvs = AcousticAnalogies.UntrippedN0012BoundaryLayer() + +# Paper doesn't specify the microphone used for Figure 22, but earlier at the beginning of "C. Noise Characteristics and Trends" there is this: +# > For the purposes of this paper, presented acoustic spectra will correspond to an observer located −35° below the plane of the rotor (microphone 5). +# So I'll just assume that holds for Figure 22. +# The observer (microphone 5) is 35 deg behind/downstream of the rotor rotation plane. +r_obs = 2.27 # meters +theta_obs = -35*pi/180 +# So, the docstring for BPM.jl says that `V` argument is the wind velocity in the y direction. +# So I guess we should assume that the blades are rotating about the y axis. +# And if the freestream velocity is in the positive y axis, then, from the perspective of the fluid, the blades are translating in the negative y direction. +# And I want the observer to be downstream/behind the blades, so that would mean they would have a positive y position. +# So I want to rotate the observer around the positive x axis, so I'm going to switch the sign on `theta_obs`. +t0_obs = 0.0 +x0_obs = @SVector [0.0, r_obs*sin(-theta_obs), r_obs*cos(-theta_obs)] +# The observer is moving in the same direction as the blades, which is the negative y axis. +v_obs = @SVector [0.0, -Vinf, 0.0] +obs = AcousticAnalogies.ConstVelocityAcousticObserver(t0_obs, x0_obs, v_obs) + +# Azimuthal offset for each blade. +θs = (0:(B-1)) .* (2*pi/B) .* ifelse(positive_x_rotation, 1, -1) + +# Reshape the inputs to the source element constructors so that everything will line up with (num_times, num_radial, num_blades). +θs_rs = reshape(θs, 1, 1, :) +radii_rs = reshape(radii, 1, :, 1) +dradii_rs = reshape(dradii, 1, :, 1) +# chord_rs = reshape(chord, 1, :, 1) +twist_rs = reshape(twist, 1, :, 1) +# hs_rs = reshape(hs, 1, :, 1) +# Psis_rs = reshape(Psis, 1, :, 1) +Us_rs = reshape(U, 1, :, 1) +alphas_rs = reshape(alpha, 1, :, 1) +# bls_rs = reshape(bls, 1, :, 1) +# bls_untripped_rs = reshape(bls_untripped, 1, :, 1) + +# Separate things into tip and no-tip. +radii_rs_no_tip = @view radii_rs[:, begin:end-1, :] +dradii_rs_no_tip = @view dradii_rs[:, begin:end-1, :] +# chord_rs_no_tip = @view chord_rs[:, begin:end-1, :] +twist_rs_no_tip = @view twist_rs[:, begin:end-1, :] +# hs_rs_no_tip = @view hs_rs[:, begin:end-1, :] +# Psis_rs_no_tip = @view Psis_rs[:, begin:end-1, :] +Us_rs_no_tip = @view Us_rs[:, begin:end-1, :] +alphas_rs_no_tip = @view alphas_rs[:, begin:end-1, :] +# bls_rs_no_tip = @view bls_rs[:, begin:end-1, :] + +radii_rs_with_tip = @view radii_rs[:, end:end, :] +dradii_rs_with_tip = @view dradii_rs[:, end:end, :] +# chord_rs_with_tip = @view chord_rs[:, end:end, :] +twist_rs_with_tip = @view twist_rs[:, end:end, :] +# hs_rs_with_tip = @view hs_rs[:, end:end, :] +# Psis_rs_with_tip = @view Psis_rs[:, end:end, :] +Us_rs_with_tip = @view Us_rs[:, end:end, :] +alphas_rs_with_tip = @view alphas_rs[:, end:end, :] +# bls_rs_with_tip = @view bls_rs[:, end:end, :] + +direct = AcousticAnalogies.BPMDirectivity +use_UInduction = false +use_Doppler = false +mach_correction = AcousticAnalogies.NoMachCorrection +ses_no_tip = CombinedNoTipBroadbandSourceElement{direct,use_UInduction,mach_correction,use_Doppler}.(asound, nu, radii_rs_no_tip, θs_rs, dradii_rs_no_tip, chord, twist_rs_no_tip, h, Psi, Us_rs_no_tip, alphas_rs_no_tip, src_times, dt, Ref(bl), positive_x_rotation) .|> trans + +ses_with_tip = CombinedWithTipBroadbandSourceElement{direct,use_UInduction,mach_correction,use_Doppler}.(asound, nu, radii_rs_with_tip, θs_rs, dradii_rs_with_tip, chord, twist_rs_with_tip, h, Psi, Us_rs_with_tip, alphas_rs_with_tip, src_times, dt, Ref(bl), Ref(blade_tip), positive_x_rotation) .|> trans + +# Put the source elements together: +ses = cat(ses_no_tip, ses_with_tip; dims=2) + +# Need to do the LBLVS with the untripped boundary layer to match what BPM.jl is doing. +lblvs_ses = AcousticAnalogies.LBLVSSourceElement{direct,use_UInduction,use_Doppler}.(asound, nu, radii_rs, θs_rs, dradii_rs, chord, twist_rs, Us_rs, alphas_rs, src_times, dt, Ref(bl_lblvs), positive_x_rotation) .|> trans + +# Define the frequencies we'd like to evaluate. +# BPM.jl uses the approximate 1/3rd-octave bands. +freqs_obs = AcousticMetrics.ApproximateThirdOctaveCenterBands(100.0, 40000.0) +freqs_src = freqs_obs + +# Now do the noise prediction. +bpm_outs = AcousticAnalogies.noise.(ses, Ref(obs), Ref(freqs_src)) +pbs_lblvss = AcousticAnalogies.noise.(lblvs_ses, Ref(obs), Ref(freqs_src)) + +# Separate out each source. +pbs_tblte_ps = AcousticAnalogies.pbs_pressure.(bpm_outs) +pbs_tblte_ss = AcousticAnalogies.pbs_suction.(bpm_outs) +pbs_tblte_alphas = AcousticAnalogies.pbs_alpha.(bpm_outs) +pbs_tebs = AcousticAnalogies.pbs_teb.(bpm_outs) +pbs_tips = AcousticAnalogies.pbs_tip.(bpm_outs[:, end:end, :]) + +# Combine each noise prediction. +time_axis = 1 +pbs_pressure = AcousticMetrics.combine(pbs_tblte_ps, freqs_obs, time_axis) +pbs_suction = AcousticMetrics.combine(pbs_tblte_ss, freqs_obs, time_axis) +pbs_alpha = AcousticMetrics.combine(pbs_tblte_alphas, freqs_obs, time_axis) +pbs_teb = AcousticMetrics.combine(pbs_tebs, freqs_obs, time_axis) +pbs_tip = AcousticMetrics.combine(pbs_tips, freqs_obs, time_axis) +pbs_lblvs = AcousticMetrics.combine(pbs_lblvss, freqs_obs, time_axis) + +# Now I need to account for the fact that Figure 22b is actually comparing to narrowband experimental data with a frequency spacing of 20 Hz. +# So, to do that, I need to multiply the mean-squared pressure by Δf_nb/Δf_pbs, where `Δf_nb` is the 20 Hz narrowband and `Δf_pbs` is the bandwidth of each 1/3-octave proportional band. +# (Dividing the MSP by Δf_pbs aka the 1/3 octave spacing is like getting a power-spectral density, then multiplying by the narrowband spacing Δf_nb gives us the MSP associated with the narrowband.) +# I think the paper describes that, right? +# Right, here's something: +# +# > The current prediction method is limited to one-third octave bands, but it is compared to the narrowband experiment with Δf = 20 Hz. +# > This is done by dividing the energy from the one-third octave bands by the number of bands in Δf = 20 Hz. +# +# So, `Δf_pbs/Δf_nb` would represent the number of `Δf_nb`-width bands that could fit in a proportional band of bin width `Δf_pbs`. +# And then I'm dividing by that. +# So that seems like the right thing. +# So, first thing is to get the proportional band spacing. +freqs_l = AcousticMetrics.lower_bands(freqs_obs) +freqs_u = AcousticMetrics.upper_bands(freqs_obs) +df_pbs = freqs_u .- freqs_l +# Also need the experimental narrowband spacing. +df_nb = 20.0 +# Now multiply each by that. +nb_pressure = pbs_pressure .* df_nb ./ df_pbs +nb_suction = pbs_suction .* df_nb ./ df_pbs +nb_alpha = pbs_alpha .* df_nb ./ df_pbs +nb_teb = pbs_teb .* df_nb ./ df_pbs +nb_tip = pbs_tip .* df_nb ./ df_pbs +nb_lblvs_untripped = pbs_lblvs .* df_nb ./ df_pbs + +# Now I want the SPL, which should just be this: +pref = 20e-6 +spl_pressure = 10 .* log10.(nb_pressure./(pref^2)) +spl_suction = 10 .* log10.(nb_suction./(pref^2)) +spl_alpha = 10 .* log10.(nb_alpha./(pref^2)) +spl_teb = 10 .* log10.(nb_teb./(pref^2)) +spl_tip = 10 .* log10.(nb_tip./(pref^2)) +spl_lblvs_untripped = 10 .* log10.(nb_lblvs_untripped./(pref^2)) + +# Finally, let's get the BPM.jl predictions for this case, which we've run and saved previously in a JLD2/HDF5 file. +freq_bpmjl = data_bpmjl["freqs"] +spl_pressure_bpmjl = data_bpmjl["spl_nb_pressure"] +spl_suction_bpmjl = data_bpmjl["spl_nb_suction"] +spl_separation_bpmjl = data_bpmjl["spl_nb_separation"] +spl_lblvs_bpmjl = data_bpmjl["spl_nb_lblvs"] +spl_blunt_bpmjl = data_bpmjl["spl_nb_blunt"] +spl_tip_bpmjl = data_bpmjl["spl_nb_tip"] + +# Now let's plot. +fig = Figure() +ax1 = fig[2, 1] = Axis(fig, xlabel="frequency, Hz", ylabel="SPL (dB Ref: 20 μPa), Δf = 20 Hz", xscale=log10, xticks=[10^3, 10^4], xminorticksvisible=true, xminorgridvisible=true, xminorticks=IntervalsBetween(9), yticks=10:10:70)#, aspect=3) + +s_pressure = scatter!(ax1, freq_bpmjl, spl_pressure_bpmjl, color=:blue, marker=:rtriangle) +s_suction = scatter!(ax1, freq_bpmjl, spl_suction_bpmjl, color=:red, marker=:ltriangle) +s_separation = scatter!(ax1, freq_bpmjl, spl_separation_bpmjl, color=:yellow, marker=:diamond) +s_lblvs = scatter!(ax1, freq_bpmjl, spl_lblvs_bpmjl, color=:purple, marker=:rect) +s_blunt = scatter!(ax1, freq_bpmjl, spl_blunt_bpmjl, color=:green, marker=:star6) +s_tip = scatter!(ax1, freq_bpmjl, spl_tip_bpmjl, color=:cyan, marker=:circle) + +l_pressure = lines!(ax1, freqs_obs, spl_pressure, color=:blue) +l_suction = lines!(ax1, freqs_obs, spl_suction, color=:red) +l_alpha = lines!(ax1, freqs_obs, spl_alpha, color=:yellow) +l_lblvs = lines!(ax1, freqs_obs, spl_lblvs_untripped, color=:purple) +l_teb = lines!(ax1, freqs_obs, spl_teb, color=:green) +l_tip = lines!(ax1, freqs_obs, spl_tip, color=:cyan) + +xlims!(ax1, 2e2, 6e4) +ylims!(ax1, 10.0, 70.0) + +leg = Legend(fig[1, 1], [ + [s_pressure, l_pressure], + [s_suction, l_suction], + [s_separation, l_alpha], + [s_lblvs, l_lblvs], + [s_blunt, l_teb], + [s_tip, l_tip], + ], + [ + "TBLTE-Pressure", + "TBLTE-Suction", + "Separation", + "LBLVS", + "BVS", + "Tip", + ]; orientation=:horizontal, tellwidth=false, tellheight=true, nbanks=2) + +text!(ax1, 210, 62; text="markers: CCBlade.jl+BPM.jl\nlines: CCBlade.jl+AcousticAnalogies.jl") + +save("figure22b-spl-bpmjl.png", fig) +``` +![](figure22b-spl-bpmjl.png) + +### Figure 23c +```@example figure23c +using AcousticAnalogies +using AcousticMetrics: AcousticMetrics +using GLMakie +using KinematicCoordinateTransformations: compose, SteadyRotXTransformation, SteadyRotYTransformation, SteadyRotZTransformation, ConstantVelocityTransformation +using FileIO: load +using FLOWMath: Akima +using StaticArrays: @SVector + +# Copied from BPM.jl (would like to add BPM.jl as a dependency if it's registered in General some day). +# tip vortex noise correction data based on "Airfoil Tip Vortex Formation Noise" +const bm_tip_alpha_aspect_data = [2.0,2.67,4.0,6.0,12.0,24.0] +const bm_tip_alpha_aratio_data = [0.54,0.62,0.71,0.79,0.89,0.95] +const bm_tip_alpha_aspect_ratio_correction = Akima(bm_tip_alpha_aspect_data, bm_tip_alpha_aratio_data) + +function bm_tip_vortex_alpha_correction_nonsmooth(aspect_ratio) + # compute tip lift curve slope + if aspect_ratio < 2.0 + aratio = 0.5*one(aspect_ratio) + elseif 2.0 <= aspect_ratio <= 24.0 + aratio = bm_tip_alpha_aspect_ratio_correction(aspect_ratio) + elseif aspect_ratio > 24.0 + aratio = 1.0*one(aspect_ratio) + end + + return aratio +end + +struct BMTipAlphaCorrection{TCorrection} <: AbstractTipAlphaCorrection + correction::TCorrection + + function BMTipAlphaCorrection(aspect_ratio) + # correction = BPM._tip_vortex_alpha_correction_nonsmooth(aspect_ratio) + correction = bm_tip_vortex_alpha_correction_nonsmooth(aspect_ratio) + return new{typeof(correction)}(correction) + end +end + +function AcousticAnalogies.tip_vortex_alpha_correction(blade_tip::AbstractBladeTip{<:BMTipAlphaCorrection}, alphatip) + a0l = AcousticAnalogies.alpha_zerolift(blade_tip) + correction_factor = AcousticAnalogies.tip_alpha_correction(blade_tip).correction + return correction_factor * (alphatip - a0l) + a0l +end + +# Pettingill et al., "Acoustic And Performance Characteristics of an Ideally Twisted Rotor in Hover", 2021 +# Parameters from Table 1 +B = 4 # number of blades +Rtip = 0.1588 # meters +chord = 0.2*Rtip + +# Standard day: +Tamb = 15 + 273.15 # 15°C in Kelvin +pamb = 101325.0 # Pa +R = 287.052874 # J/(kg*K) +rho = pamb/(R*Tamb) +asound = sqrt(1.4*R*Tamb) +# Dynamic and kinematic viscosity +mu = rho*1.4502e-5 +nu = mu/rho + +# This is a hover case, so the freestream velocity should be zero. +# CCBlade.jl will run with a zero freestream, but I've found that it compares a bit better with experiment if I give it a small non-zero value. +Vinf = 0.001*asound + +# Figure 23 caption says Ω_c = 5510 RPM. +rpm = 5510.0 +omega = rpm * (2*pi/60) + +# Get "cell-centered" radial locations, and also the radial spacing. +num_radial = 50 +r_Rtip_ = range(0.2, 1.0; length=num_radial+1) +r_Rtip = 0.5 .* (r_Rtip_[2:end] .+ r_Rtip_[1:end-1]) +radii = r_Rtip .* Rtip +dradii = (r_Rtip_[2:end] .- r_Rtip_[1:end-1]) .* Rtip +Rhub = r_Rtip_[1]*Rtip + +# From Pettingill Equation (1), and value for Θ_tip in Table 1. +Θ_tip = 6.9 * pi/180 +twist = Θ_tip ./ (r_Rtip) + +# Need some aerodynamic quantities. +# Got these using CCBlade.jl: see `AcousticAnalogies.jl/test/gen_bpmjl_data/itr_with_bpmjl.jl`. +data_bpmjl = load(joinpath(@__DIR__, "..", "..", "test", "gen_bpmjl_data", "figure23c.jld2")) +# Angle of attack at each radial station, radians. +alpha = data_bpmjl["alpha"] +# Flow speed normal to span at each radial station, m/s. +U = data_bpmjl["U"] + +# In the Figure 23 caption, "for these predictions, bluntness thickness H was set to 0.5 mm and trailing edge angle Ψ was set to 14 degrees." +h = 0.5e-3 # meters +Psi = 14*pi/180 # radians + +# We'll run for 1 blade pass, 20 time steps per blade pass. +num_blade_pass = 1 +num_src_times_blade_pass = 20 +bpp = 1/(B/(2*pi)*omega) # 1/(B blade_passes/rev * 1 rev / (2*pi rad) * omega rad/s) +period_src = num_blade_pass*bpp +num_src_times = num_src_times_blade_pass * num_blade_pass +t0 = 0.0 +dt = period_src/num_src_times +src_times = t0 .+ (0:num_src_times-1).*dt + +# BPM.jl uses a different tip alpha correction which appears to require the blade aspect ratio. +# Need to find the blade aspect ratio of the ITR to apply the tip vortex angle of attack correction. +# The aspect ratio is defined as the blade tip radius divided by the average chord, but the chord is constant for this case. +aspect_ratio = Rtip / chord + +# Now we can create the tip object. +alpha0lift = 0.0 +blade_tip = AcousticAnalogies.FlatTip(BMTipAlphaCorrection(aspect_ratio), alpha0lift) + +# Start with a rotation about the negative x axis. +positive_x_rotation = false +rot_trans = SteadyRotXTransformation(t0, omega*ifelse(positive_x_rotation, 1, -1), 0) + +# Then translate along the positive x axis. +y0_hub = @SVector [0.0, 0.0, 0.0] # m +v0_hub = @SVector [Vinf, 0.0, 0.0] +const_vel_trans = ConstantVelocityTransformation(t0, y0_hub, v0_hub) + +# Then a 90° rotation about the negative z axis. +trans_z90deg = SteadyRotZTransformation(0.0, 0.0, -0.5*pi) + +# Then a 90° rotation about the negative y axis. +trans_y90deg = SteadyRotYTransformation(0.0, 0.0, -0.5*pi) + +# Put them all together: +trans = compose.(src_times, Ref(trans_y90deg), + compose.(src_times, Ref(trans_z90deg), + compose.(src_times, Ref(const_vel_trans), Ref(rot_trans)))) + +# Use the M_c = 0.8*M that BPM report and BPM.jl use. +U = @. 0.8*sqrt(Vinf^2 + (omega*radii)^2) + +# For the boundary layer we want to use untripped for the 95% of the blade from the hub to almost tip, and then tripped for the last 5% of the blade at the tip. +# First figure out how many of each we'll actually have with the `num_radial = 50` radial stations. +num_untripped = Int(round(0.95*num_radial)) +num_tripped = num_radial - num_untripped +# Now create a length-`num_radial` vector of untripped and then tripped boundary layer objects. +bls = vcat(fill(AcousticAnalogies.UntrippedN0012BoundaryLayer(), num_untripped), fill(AcousticAnalogies.TrippedN0012BoundaryLayer(), num_tripped)) + +# Now, the other trick: for this case, we're only going to include the LBLVS source where the local Reynolds number (with the chord as the length scale) is < 160000. +low_Re_c = 160000.0 +# So we need the Reynolds number for each section. +Re_c = U .* chord / nu +# Now we'll get a length-`num_radial` vector of Bools indicating if that criteria is satisfied or not. +lblvs_flags = Re_c .< low_Re_c + +# Also we'll always be using the untripped boundary layer for LBLVS, like BPM.jl does. +bl_lblvs = AcousticAnalogies.UntrippedN0012BoundaryLayer() + +# Paper doesn't specify the microphone used for Figure 23, but earlier at the beginning of "C. Noise Characteristics and Trends" there is this: +# > For the purposes of this paper, presented acoustic spectra will correspond to an observer located −35° below the plane of the rotor (microphone 5). +# So I'll just assume that holds for Figure 23. +# The observer (microphone 5) is 35 deg behind/downstream of the rotor rotation plane. +r_obs = 2.27 # meters +theta_obs = -35*pi/180 +# So, the docstring for BPM.jl says that `V` argument is the wind velocity in the y direction. +# So I guess we should assume that the blades are rotating about the y axis. +# And if the freestream velocity is in the positive y axis, then, from the perspective of the fluid, the blades are translating in the negative y direction. +# And I want the observer to be downstream/behind the blades, so that would mean they would have a positive y position. +# So I want to rotate the observer around the positive x axis, so I'm going to switch the sign on `theta_obs`. +t0_obs = 0.0 +x0_obs = @SVector [0.0, r_obs*sin(-theta_obs), r_obs*cos(-theta_obs)] +# The observer is moving in the same direction as the blades, which is the negative y axis. +v_obs = @SVector [0.0, -Vinf, 0.0] +obs = AcousticAnalogies.ConstVelocityAcousticObserver(t0_obs, x0_obs, v_obs) + +# Azimuthal offset for each blade. +θs = (0:(B-1)) .* (2*pi/B) .* ifelse(positive_x_rotation, 1, -1) + +# Reshape the inputs to the source element constructors so that everything will line up with (num_times, num_radial, num_blades). +θs_rs = reshape(θs, 1, 1, :) +radii_rs = reshape(radii, 1, :, 1) +dradii_rs = reshape(dradii, 1, :, 1) +# chord_rs = reshape(chord, 1, :, 1) +twist_rs = reshape(twist, 1, :, 1) +# hs_rs = reshape(hs, 1, :, 1) +# Psis_rs = reshape(Psis, 1, :, 1) +Us_rs = reshape(U, 1, :, 1) +alphas_rs = reshape(alpha, 1, :, 1) +bls_rs = reshape(bls, 1, :, 1) + +# Separate things into tip and no-tip. +radii_rs_no_tip = @view radii_rs[:, begin:end-1, :] +dradii_rs_no_tip = @view dradii_rs[:, begin:end-1, :] +twist_rs_no_tip = @view twist_rs[:, begin:end-1, :] +Us_rs_no_tip = @view Us_rs[:, begin:end-1, :] +alphas_rs_no_tip = @view alphas_rs[:, begin:end-1, :] +bls_rs_no_tip = @view bls_rs[:, begin:end-1, :] + +radii_rs_with_tip = @view radii_rs[:, end:end, :] +dradii_rs_with_tip = @view dradii_rs[:, end:end, :] +twist_rs_with_tip = @view twist_rs[:, end:end, :] +Us_rs_with_tip = @view Us_rs[:, end:end, :] +alphas_rs_with_tip = @view alphas_rs[:, end:end, :] +bls_rs_with_tip = @view bls_rs[:, end:end, :] + +direct = AcousticAnalogies.BPMDirectivity +use_UInduction = false +use_Doppler = false +mach_correction = AcousticAnalogies.NoMachCorrection +ses_no_tip = CombinedNoTipBroadbandSourceElement{direct,use_UInduction,mach_correction,use_Doppler}.(asound, nu, radii_rs_no_tip, θs_rs, dradii_rs_no_tip, chord, twist_rs_no_tip, h, Psi, Us_rs_no_tip, alphas_rs_no_tip, src_times, dt, bls_rs_no_tip, positive_x_rotation) .|> trans + +ses_with_tip = CombinedWithTipBroadbandSourceElement{direct,use_UInduction,mach_correction,use_Doppler}.(asound, nu, radii_rs_with_tip, θs_rs, dradii_rs_with_tip, chord, twist_rs_with_tip, h, Psi, Us_rs_with_tip, alphas_rs_with_tip, src_times, dt, bls_rs_with_tip, Ref(blade_tip), positive_x_rotation) .|> trans + +# Put the source elements together: +ses = cat(ses_no_tip, ses_with_tip; dims=2) + +# Need to do the LBLVS with the untripped boundary layer to match what BPM.jl is doing, and only where `lblvs_flags` is true. +# So extract the radial locations where that's true. +radii_lblvs = @view radii[lblvs_flags] +dradii_lblvs = @view dradii[lblvs_flags] +twist_lblvs = @view twist[lblvs_flags] +Us_lblvs = @view U[lblvs_flags] +alphas_lblvs = @view alpha[lblvs_flags] + +# Now do the usual reshaping. +radii_lblvs_rs = reshape(radii_lblvs, 1, :, 1) +dradii_lblvs_rs = reshape(dradii_lblvs, 1, :, 1) +twist_lblvs_rs = reshape(twist_lblvs, 1, :, 1) +Us_lblvs_rs = reshape(Us_lblvs, 1, :, 1) +alphas_lblvs_rs = reshape(alphas_lblvs, 1, :, 1) + +# Now we can construct the lblvs source elements. +lblvs_ses = AcousticAnalogies.LBLVSSourceElement{direct,use_UInduction,use_Doppler}.(asound, nu, radii_lblvs_rs, θs_rs, dradii_lblvs_rs, chord, twist_lblvs_rs, Us_lblvs_rs, alphas_lblvs_rs, src_times, dt, Ref(bl_lblvs), positive_x_rotation) .|> trans + +# Define the frequencies we'd like to evaluate. +# BPM.jl uses the approximate 1/3rd-octave bands. +freqs_obs = AcousticMetrics.ApproximateThirdOctaveCenterBands(100.0, 40000.0) +freqs_src = freqs_obs + +# Now do the noise prediction. +bpm_outs = AcousticAnalogies.noise.(ses, Ref(obs), Ref(freqs_src)) +pbs_lblvss = AcousticAnalogies.noise.(lblvs_ses, Ref(obs), Ref(freqs_src)) + +# Separate out each source. +pbs_tblte_ps = AcousticAnalogies.pbs_pressure.(bpm_outs) +pbs_tblte_ss = AcousticAnalogies.pbs_suction.(bpm_outs) +pbs_tblte_alphas = AcousticAnalogies.pbs_alpha.(bpm_outs) +pbs_tebs = AcousticAnalogies.pbs_teb.(bpm_outs) +pbs_tips = AcousticAnalogies.pbs_tip.(bpm_outs[:, end:end, :]) + +# Combine each noise prediction. +time_axis = 1 +pbs_pressure = AcousticMetrics.combine(pbs_tblte_ps, freqs_obs, time_axis) +pbs_suction = AcousticMetrics.combine(pbs_tblte_ss, freqs_obs, time_axis) +pbs_alpha = AcousticMetrics.combine(pbs_tblte_alphas, freqs_obs, time_axis) +pbs_teb = AcousticMetrics.combine(pbs_tebs, freqs_obs, time_axis) +pbs_tip = AcousticMetrics.combine(pbs_tips, freqs_obs, time_axis) +pbs_lblvs = AcousticMetrics.combine(pbs_lblvss, freqs_obs, time_axis) + +# Now I need to account for the fact that Figure 23c is actually comparing to narrowband experimental data with a frequency spacing of 20 Hz. +# So, to do that, I need to multiply the mean-squared pressure by Δf_nb/Δf_pbs, where `Δf_nb` is the 20 Hz narrowband and `Δf_pbs` is the bandwidth of each 1/3-octave proportional band. +# (Dividing the MSP by Δf_pbs aka the 1/3 octave spacing is like getting a power-spectral density, then multiplying by the narrowband spacing Δf_nb gives us the MSP associated with the narrowband.) +# I think the paper describes that, right? +# Right, here's something: +# +# > The current prediction method is limited to one-third octave bands, but it is compared to the narrowband experiment with Δf = 20 Hz. +# > This is done by dividing the energy from the one-third octave bands by the number of bands in Δf = 20 Hz. +# +# So, `Δf_pbs/Δf_nb` would represent the number of `Δf_nb`-width bands that could fit in a proportional band of bin width `Δf_pbs`. +# And then I'm dividing by that. +# So that seems like the right thing. +# So, first thing is to get the proportional band spacing. +freqs_l = AcousticMetrics.lower_bands(freqs_obs) +freqs_u = AcousticMetrics.upper_bands(freqs_obs) +df_pbs = freqs_u .- freqs_l +# Also need the experimental narrowband spacing. +df_nb = 20.0 +# Now multiply each by that. +nb_pressure = pbs_pressure .* df_nb ./ df_pbs +nb_suction = pbs_suction .* df_nb ./ df_pbs +nb_alpha = pbs_alpha .* df_nb ./ df_pbs +nb_teb = pbs_teb .* df_nb ./ df_pbs +nb_tip = pbs_tip .* df_nb ./ df_pbs +nb_lblvs_untripped = pbs_lblvs .* df_nb ./ df_pbs + +# Now I want the SPL, which should just be this: +pref = 20e-6 +spl_pressure = 10 .* log10.(nb_pressure./(pref^2)) +spl_suction = 10 .* log10.(nb_suction./(pref^2)) +spl_alpha = 10 .* log10.(nb_alpha./(pref^2)) +spl_teb = 10 .* log10.(nb_teb./(pref^2)) +spl_tip = 10 .* log10.(nb_tip./(pref^2)) +spl_lblvs_untripped = 10 .* log10.(nb_lblvs_untripped./(pref^2)) + +# Finally, let's get the BPM.jl predictions for this case, which we've run and saved previously in a JLD2/HDF5 file. +freq_bpmjl = data_bpmjl["freqs"] +spl_pressure_bpmjl = data_bpmjl["spl_nb_pressure"] +spl_suction_bpmjl = data_bpmjl["spl_nb_suction"] +spl_separation_bpmjl = data_bpmjl["spl_nb_separation"] +spl_lblvs_bpmjl = data_bpmjl["spl_nb_lblvs"] +spl_blunt_bpmjl = data_bpmjl["spl_nb_blunt"] +spl_tip_bpmjl = data_bpmjl["spl_nb_tip"] + +# Now let's plot. +fig = Figure() +ax1 = fig[2, 1] = Axis(fig, xlabel="frequency, Hz", ylabel="SPL (dB Ref: 20 μPa), Δf = 20 Hz", xscale=log10, xticks=[10^3, 10^4], xminorticksvisible=true, xminorgridvisible=true, xminorticks=IntervalsBetween(9), yticks=10:10:70)#, aspect=3) + +s_pressure = scatter!(ax1, freq_bpmjl, spl_pressure_bpmjl, color=:blue, marker=:rtriangle) +s_suction = scatter!(ax1, freq_bpmjl, spl_suction_bpmjl, color=:red, marker=:ltriangle) +s_separation = scatter!(ax1, freq_bpmjl, spl_separation_bpmjl, color=:yellow, marker=:diamond) +s_lblvs = scatter!(ax1, freq_bpmjl, spl_lblvs_bpmjl, color=:purple, marker=:rect) +s_blunt = scatter!(ax1, freq_bpmjl, spl_blunt_bpmjl, color=:green, marker=:star6) +s_tip = scatter!(ax1, freq_bpmjl, spl_tip_bpmjl, color=:cyan, marker=:circle) + +l_pressure = lines!(ax1, freqs_obs, spl_pressure, color=:blue) +l_suction = lines!(ax1, freqs_obs, spl_suction, color=:red) +l_alpha = lines!(ax1, freqs_obs, spl_alpha, color=:yellow) +l_lblvs = lines!(ax1, freqs_obs, spl_lblvs_untripped, color=:purple) +l_teb = lines!(ax1, freqs_obs, spl_teb, color=:green) +l_tip = lines!(ax1, freqs_obs, spl_tip, color=:cyan) + +xlims!(ax1, 2e2, 6e4) +ylims!(ax1, 10.0, 70.0) + +leg = Legend(fig[1, 1], [ + [s_pressure, l_pressure], + [s_suction, l_suction], + [s_separation, l_alpha], + [s_lblvs, l_lblvs], + [s_blunt, l_teb], + [s_tip, l_tip], + ], + [ + "TBLTE-Pressure", + "TBLTE-Suction", + "Separation", + "LBLVS", + "BVS", + "Tip", + ]; orientation=:horizontal, tellwidth=false, tellheight=true, nbanks=2) + +text!(ax1, 210, 62; text="markers: CCBlade.jl+BPM.jl\nlines: CCBlade.jl+AcousticAnalogies.jl") + +save("figure23c-spl-bpmjl.png", fig) +``` +![](figure23c-spl-bpmjl.png) + +### Figure 24b +```@example figure24b +using AcousticAnalogies +using AcousticMetrics: AcousticMetrics +using GLMakie +using KinematicCoordinateTransformations: compose, SteadyRotXTransformation, SteadyRotYTransformation, SteadyRotZTransformation, ConstantVelocityTransformation +using FileIO: load +using FLOWMath: Akima +using StaticArrays: @SVector + +# Copied from BPM.jl (would like to add BPM.jl as a dependency if it's registered in General some day). +# tip vortex noise correction data based on "Airfoil Tip Vortex Formation Noise" +const bm_tip_alpha_aspect_data = [2.0,2.67,4.0,6.0,12.0,24.0] +const bm_tip_alpha_aratio_data = [0.54,0.62,0.71,0.79,0.89,0.95] +const bm_tip_alpha_aspect_ratio_correction = Akima(bm_tip_alpha_aspect_data, bm_tip_alpha_aratio_data) + +function bm_tip_vortex_alpha_correction_nonsmooth(aspect_ratio) + # compute tip lift curve slope + if aspect_ratio < 2.0 + aratio = 0.5*one(aspect_ratio) + elseif 2.0 <= aspect_ratio <= 24.0 + aratio = bm_tip_alpha_aspect_ratio_correction(aspect_ratio) + elseif aspect_ratio > 24.0 + aratio = 1.0*one(aspect_ratio) + end + + return aratio +end + +struct BMTipAlphaCorrection{TCorrection} <: AbstractTipAlphaCorrection + correction::TCorrection + + function BMTipAlphaCorrection(aspect_ratio) + # correction = BPM._tip_vortex_alpha_correction_nonsmooth(aspect_ratio) + correction = bm_tip_vortex_alpha_correction_nonsmooth(aspect_ratio) + return new{typeof(correction)}(correction) + end +end + +function AcousticAnalogies.tip_vortex_alpha_correction(blade_tip::AbstractBladeTip{<:BMTipAlphaCorrection}, alphatip) + a0l = AcousticAnalogies.alpha_zerolift(blade_tip) + correction_factor = AcousticAnalogies.tip_alpha_correction(blade_tip).correction + return correction_factor * (alphatip - a0l) + a0l +end + +# Pettingill et al., "Acoustic And Performance Characteristics of an Ideally Twisted Rotor in Hover", 2021 +# Parameters from Table 1 +B = 4 # number of blades +Rtip = 0.1588 # meters +chord = 0.2*Rtip + +# Standard day: +Tamb = 15 + 273.15 # 15°C in Kelvin +pamb = 101325.0 # Pa +R = 287.052874 # J/(kg*K) +rho = pamb/(R*Tamb) +asound = sqrt(1.4*R*Tamb) +# Dynamic and kinematic viscosity +mu = rho*1.4502e-5 +nu = mu/rho + +# This is a hover case, so the freestream velocity should be zero. +# CCBlade.jl will run with a zero freestream, but I've found that it compares a bit better with experiment if I give it a small non-zero value. +Vinf = 0.001*asound + +# Figure 24 caption says Ω_c = 2938 RPM. +rpm = 2938.0 +omega = rpm * (2*pi/60) + +# Get "cell-centered" radial locations, and also the radial spacing. +num_radial = 50 +r_Rtip_ = range(0.2, 1.0; length=num_radial+1) +r_Rtip = 0.5 .* (r_Rtip_[2:end] .+ r_Rtip_[1:end-1]) +radii = r_Rtip .* Rtip +dradii = (r_Rtip_[2:end] .- r_Rtip_[1:end-1]) .* Rtip +Rhub = r_Rtip_[1]*Rtip + +# From Pettingill Equation (1), and value for Θ_tip in Table 1. +Θ_tip = 6.9 * pi/180 +twist = Θ_tip ./ (r_Rtip) + +# Need some aerodynamic quantities. +# Got these using CCBlade.jl: see `AcousticAnalogies.jl/test/gen_bpmjl_data/itr_with_bpmjl.jl`. +data_bpmjl = load(joinpath(@__DIR__, "..", "..", "test", "gen_bpmjl_data", "figure24b.jld2")) +# Angle of attack at each radial station, radians. +alpha = data_bpmjl["alpha"] +# Flow speed normal to span at each radial station, m/s. +U = data_bpmjl["U"] + +# In the Figure 24 caption, "for these predictions, bluntness thickness H was set to 0.5 mm and trailing edge angle Ψ was set to 14 degrees." +h = 0.5e-3 # meters +Psi = 14*pi/180 # radians + +# We'll run for 1 blade pass, 20 time steps per blade pass. +num_blade_pass = 1 +num_src_times_blade_pass = 20 + +# Get the time levels we'll run. +# First, get the blade passing period. +bpp = 1/(B/(2*pi)*omega) # 1/(B blade_passes/rev * 1 rev / (2*pi rad) * omega rad/s) + +# Now we can get the total period of source time we'll run over. +period_src = num_blade_pass*bpp +# And th number of source times. +num_src_times = num_src_times_blade_pass * num_blade_pass + +# We know the total time period and number of source times, so we can get the time step. +dt = period_src/num_src_times + +# We'll arbitrarily start at time 0.0 seconds. +t0 = 0.0 + +# And now we can finally get each source time. +src_times = t0 .+ (0:num_src_times-1).*dt + +# BPM.jl uses a different tip alpha correction which appears to require the blade aspect ratio. +# Need to find the blade aspect ratio of the ITR to apply the tip vortex angle of attack correction. +# The aspect ratio is defined as the blade tip radius divided by the average chord, but the chord is constant for this case. +aspect_ratio = Rtip / chord + +# Now we can create the tip object. +alpha0lift = 0.0 +blade_tip = AcousticAnalogies.FlatTip(BMTipAlphaCorrection(aspect_ratio), alpha0lift) + +# Start with a rotation about the negative x axis. +positive_x_rotation = false +rot_trans = SteadyRotXTransformation(t0, omega*ifelse(positive_x_rotation, 1, -1), 0) + +# Then translate along the positive x axis. +y0_hub = @SVector [0.0, 0.0, 0.0] # m +v0_hub = @SVector [Vinf, 0.0, 0.0] +const_vel_trans = ConstantVelocityTransformation(t0, y0_hub, v0_hub) + +# Then a 90° rotation about the negative z axis. +trans_z90deg = SteadyRotZTransformation(0.0, 0.0, -0.5*pi) + +# Then a 90° rotation about the negative y axis. +trans_y90deg = SteadyRotYTransformation(0.0, 0.0, -0.5*pi) + +# Put them all together: +trans = compose.(src_times, Ref(trans_y90deg), + compose.(src_times, Ref(trans_z90deg), + compose.(src_times, Ref(const_vel_trans), Ref(rot_trans)))) + +# Use the M_c = 0.8*M that BPM report and BPM.jl use. +U = @. 0.8*sqrt(Vinf^2 + (omega*radii)^2) + +# For the boundary layer we want to use untripped for the 95% of the blade from the hub to almost tip, and then tripped for the last 5% of the blade at the tip. +# First figure out how many of each we'll actually have with the `num_radial = 50` radial stations. +num_untripped = Int(round(0.95*num_radial)) +num_tripped = num_radial - num_untripped +# Now create a length-`num_radial` vector of untripped and then tripped boundary layer objects. +bls = vcat(fill(AcousticAnalogies.UntrippedN0012BoundaryLayer(), num_untripped), fill(AcousticAnalogies.TrippedN0012BoundaryLayer(), num_tripped)) + +# Also we'll always be using the untripped boundary layer for LBLVS, like BPM.jl does. +bl_lblvs = AcousticAnalogies.UntrippedN0012BoundaryLayer() + +# Paper doesn't specify the microphone used for Figure 24, but earlier at the beginning of "C. Noise Characteristics and Trends" there is this: +# > For the purposes of this paper, presented acoustic spectra will correspond to an observer located −35° below the plane of the rotor (microphone 5). +# So I'll just assume that holds for Figure 23. +# The observer (microphone 5) is 35 deg behind/downstream of the rotor rotation plane. +r_obs = 2.27 # meters +theta_obs = -35*pi/180 +# So, the docstring for BPM.jl says that `V` argument is the wind velocity in the y direction. +# So I guess we should assume that the blades are rotating about the y axis. +# And if the freestream velocity is in the positive y axis, then, from the perspective of the fluid, the blades are translating in the negative y direction. +# And I want the observer to be downstream/behind the blades, so that would mean they would have a positive y position. +# So I want to rotate the observer around the positive x axis, so I'm going to switch the sign on `theta_obs`. +t0_obs = 0.0 +x0_obs = @SVector [0.0, r_obs*sin(-theta_obs), r_obs*cos(-theta_obs)] +# The observer is moving in the same direction as the blades, which is the negative y axis. +v_obs = @SVector [0.0, -Vinf, 0.0] +obs = AcousticAnalogies.ConstVelocityAcousticObserver(t0_obs, x0_obs, v_obs) + +# Azimuthal offset for each blade. +θs = (0:(B-1)) .* (2*pi/B) .* ifelse(positive_x_rotation, 1, -1) + +# Reshape the inputs to the source element constructors so that everything will line up with (num_times, num_radial, num_blades). +θs_rs = reshape(θs, 1, 1, :) +radii_rs = reshape(radii, 1, :, 1) +dradii_rs = reshape(dradii, 1, :, 1) +# chord_rs = reshape(chord, 1, :, 1) +twist_rs = reshape(twist, 1, :, 1) +# hs_rs = reshape(hs, 1, :, 1) +# Psis_rs = reshape(Psis, 1, :, 1) +Us_rs = reshape(U, 1, :, 1) +alphas_rs = reshape(alpha, 1, :, 1) +bls_rs = reshape(bls, 1, :, 1) + +# Separate things into tip and no-tip. +radii_rs_no_tip = @view radii_rs[:, begin:end-1, :] +dradii_rs_no_tip = @view dradii_rs[:, begin:end-1, :] +twist_rs_no_tip = @view twist_rs[:, begin:end-1, :] +Us_rs_no_tip = @view Us_rs[:, begin:end-1, :] +alphas_rs_no_tip = @view alphas_rs[:, begin:end-1, :] +bls_rs_no_tip = @view bls_rs[:, begin:end-1, :] + +radii_rs_with_tip = @view radii_rs[:, end:end, :] +dradii_rs_with_tip = @view dradii_rs[:, end:end, :] +twist_rs_with_tip = @view twist_rs[:, end:end, :] +Us_rs_with_tip = @view Us_rs[:, end:end, :] +alphas_rs_with_tip = @view alphas_rs[:, end:end, :] +bls_rs_with_tip = @view bls_rs[:, end:end, :] + +# Use the directivity functions from the BPM report. +direct = AcousticAnalogies.BPMDirectivity + +# Don't include induction for the velocity scale U. +use_UInduction = false + +# Don't doppler-shift the source frequencies and source time steps to get observer frequencies & timesteps. +use_Doppler = false + +# Don't use the Prandtl-Glauret Mach number correction that Brooks & Burley recommend. +mach_correction = AcousticAnalogies.NoMachCorrection + +ses_no_tip = CombinedNoTipBroadbandSourceElement{direct,use_UInduction,mach_correction,use_Doppler}.(asound, nu, radii_rs_no_tip, θs_rs, dradii_rs_no_tip, chord, twist_rs_no_tip, h, Psi, Us_rs_no_tip, alphas_rs_no_tip, src_times, dt, bls_rs_no_tip, positive_x_rotation) .|> trans + +ses_with_tip = CombinedWithTipBroadbandSourceElement{direct,use_UInduction,mach_correction,use_Doppler}.(asound, nu, radii_rs_with_tip, θs_rs, dradii_rs_with_tip, chord, twist_rs_with_tip, h, Psi, Us_rs_with_tip, alphas_rs_with_tip, src_times, dt, bls_rs_with_tip, Ref(blade_tip), positive_x_rotation) .|> trans + +# Put the source elements together: +ses = cat(ses_no_tip, ses_with_tip; dims=2) + +# Need to do the LBLVS with the untripped boundary layer to match what BPM.jl is doing. +lblvs_ses = AcousticAnalogies.LBLVSSourceElement{direct,use_UInduction,use_Doppler}.(asound, nu, radii_rs, θs_rs, dradii_rs, chord, twist_rs, Us_rs, alphas_rs, src_times, dt, Ref(bl_lblvs), positive_x_rotation) .|> trans + +# Define the frequencies we'd like to evaluate. +# BPM.jl uses the approximate 1/3rd-octave bands. +freqs_obs = AcousticMetrics.ApproximateThirdOctaveCenterBands(100.0, 40000.0) +freqs_src = freqs_obs + +# Now do the noise prediction. +bpm_outs = AcousticAnalogies.noise.(ses, Ref(obs), Ref(freqs_src)) +pbs_lblvss = AcousticAnalogies.noise.(lblvs_ses, Ref(obs), Ref(freqs_src)) + +# Separate out each source. +pbs_tblte_ps = AcousticAnalogies.pbs_pressure.(bpm_outs) +pbs_tblte_ss = AcousticAnalogies.pbs_suction.(bpm_outs) +pbs_tblte_alphas = AcousticAnalogies.pbs_alpha.(bpm_outs) +pbs_tebs = AcousticAnalogies.pbs_teb.(bpm_outs) +pbs_tips = AcousticAnalogies.pbs_tip.(bpm_outs[:, end:end, :]) + +# Combine each noise prediction. +time_axis = 1 +pbs_pressure = AcousticMetrics.combine(pbs_tblte_ps, freqs_obs, time_axis) +pbs_suction = AcousticMetrics.combine(pbs_tblte_ss, freqs_obs, time_axis) +pbs_alpha = AcousticMetrics.combine(pbs_tblte_alphas, freqs_obs, time_axis) +pbs_teb = AcousticMetrics.combine(pbs_tebs, freqs_obs, time_axis) +pbs_tip = AcousticMetrics.combine(pbs_tips, freqs_obs, time_axis) +pbs_lblvs = AcousticMetrics.combine(pbs_lblvss, freqs_obs, time_axis) + +# Now I need to account for the fact that Figure 24b is actually comparing to narrowband experimental data with a frequency spacing of 20 Hz. +# So, to do that, I need to multiply the mean-squared pressure by Δf_nb/Δf_pbs, where `Δf_nb` is the 20 Hz narrowband and `Δf_pbs` is the bandwidth of each 1/3-octave proportional band. +# (Dividing the MSP by Δf_pbs aka the 1/3 octave spacing is like getting a power-spectral density, then multiplying by the narrowband spacing Δf_nb gives us the MSP associated with the narrowband.) +# I think the paper describes that, right? +# Right, here's something: +# +# > The current prediction method is limited to one-third octave bands, but it is compared to the narrowband experiment with Δf = 20 Hz. +# > This is done by dividing the energy from the one-third octave bands by the number of bands in Δf = 20 Hz. +# +# So, `Δf_pbs/Δf_nb` would represent the number of `Δf_nb`-width bands that could fit in a proportional band of bin width `Δf_pbs`. +# And then I'm dividing by that. +# So that seems like the right thing. +# So, first thing is to get the proportional band spacing. +freqs_l = AcousticMetrics.lower_bands(freqs_obs) +freqs_u = AcousticMetrics.upper_bands(freqs_obs) +df_pbs = freqs_u .- freqs_l +# Also need the experimental narrowband spacing. +df_nb = 20.0 +# Now multiply each by that. +nb_pressure = pbs_pressure .* df_nb ./ df_pbs +nb_suction = pbs_suction .* df_nb ./ df_pbs +nb_alpha = pbs_alpha .* df_nb ./ df_pbs +nb_teb = pbs_teb .* df_nb ./ df_pbs +nb_tip = pbs_tip .* df_nb ./ df_pbs +nb_lblvs_untripped = pbs_lblvs .* df_nb ./ df_pbs + +# Now I want the SPL, which should just be this: +pref = 20e-6 +spl_pressure = 10 .* log10.(nb_pressure./(pref^2)) +spl_suction = 10 .* log10.(nb_suction./(pref^2)) +spl_alpha = 10 .* log10.(nb_alpha./(pref^2)) +spl_teb = 10 .* log10.(nb_teb./(pref^2)) +spl_tip = 10 .* log10.(nb_tip./(pref^2)) +spl_lblvs_untripped = 10 .* log10.(nb_lblvs_untripped./(pref^2)) + +# Finally, let's get the BPM.jl predictions for this case, which we've run and saved previously in a JLD2/HDF5 file. +freq_bpmjl = data_bpmjl["freqs"] +spl_pressure_bpmjl = data_bpmjl["spl_nb_pressure"] +spl_suction_bpmjl = data_bpmjl["spl_nb_suction"] +spl_separation_bpmjl = data_bpmjl["spl_nb_separation"] +spl_lblvs_bpmjl = data_bpmjl["spl_nb_lblvs"] +spl_blunt_bpmjl = data_bpmjl["spl_nb_blunt"] +spl_tip_bpmjl = data_bpmjl["spl_nb_tip"] + +# Now let's plot. +fig = Figure() +ax1 = fig[2, 1] = Axis(fig, xlabel="frequency, Hz", ylabel="SPL (dB Ref: 20 μPa), Δf = 20 Hz", xscale=log10, xticks=[10^3, 10^4], xminorticksvisible=true, xminorgridvisible=true, xminorticks=IntervalsBetween(9), yticks=10:10:70)#, aspect=3) + +s_pressure = scatter!(ax1, freq_bpmjl, spl_pressure_bpmjl, color=:blue, marker=:rtriangle) +s_suction = scatter!(ax1, freq_bpmjl, spl_suction_bpmjl, color=:red, marker=:ltriangle) +s_separation = scatter!(ax1, freq_bpmjl, spl_separation_bpmjl, color=:yellow, marker=:diamond) +s_lblvs = scatter!(ax1, freq_bpmjl, spl_lblvs_bpmjl, color=:purple, marker=:rect) +s_blunt = scatter!(ax1, freq_bpmjl, spl_blunt_bpmjl, color=:green, marker=:star6) +s_tip = scatter!(ax1, freq_bpmjl, spl_tip_bpmjl, color=:cyan, marker=:circle) + +l_pressure = lines!(ax1, freqs_obs, spl_pressure, color=:blue) +l_suction = lines!(ax1, freqs_obs, spl_suction, color=:red) +l_alpha = lines!(ax1, freqs_obs, spl_alpha, color=:yellow) +l_lblvs = lines!(ax1, freqs_obs, spl_lblvs_untripped, color=:purple) +l_teb = lines!(ax1, freqs_obs, spl_teb, color=:green) +l_tip = lines!(ax1, freqs_obs, spl_tip, color=:cyan) + +xlims!(ax1, 2e2, 6e4) +ylims!(ax1, 0.0, 50.0) + +leg = Legend(fig[1, 1], [ + [s_pressure, l_pressure], + [s_suction, l_suction], + [s_separation, l_alpha], + [s_lblvs, l_lblvs], + [s_blunt, l_teb], + [s_tip, l_tip], + ], + [ + "TBLTE-Pressure", + "TBLTE-Suction", + "Separation", + "LBLVS", + "BVS", + "Tip", + ]; orientation=:horizontal, tellwidth=false, tellheight=true, nbanks=2) + +text!(ax1, 210, 44; text="markers: CCBlade.jl+BPM.jl\nlines: CCBlade.jl+AcousticAnalogies.jl") + +save("figure24b-spl-bpmjl.png", fig) +``` +![](figure24b-spl-bpmjl.png) diff --git a/docs/src/itr_tests2.md b/docs/src/itr_tests2.md new file mode 100644 index 00000000..45f3c2b8 --- /dev/null +++ b/docs/src/itr_tests2.md @@ -0,0 +1,901 @@ +```@meta +CurrentModule = AADocs +``` +# Software Quality Assurance, Cont. + +## PAS/ROTONET/BARC Comparisons for the Pettingill et al. Ideally Twisted Rotor +See [here](http://dx.doi.org/10.2514/6.2021-1928) or [here](https://ntrs.nasa.gov/citations/20205003328) for details on the Ideally Twisted Rotor. + +### Figure 22b +```@example figure22b +using AcousticAnalogies +using AcousticMetrics: AcousticMetrics +using DelimitedFiles: readdlm +using KinematicCoordinateTransformations: compose, SteadyRotXTransformation, ConstantVelocityTransformation +using FileIO: load +using GLMakie +using StaticArrays: @SVector + +# Pettingill et al., "Acoustic And Performance Characteristics of an Ideally Twisted Rotor in Hover", 2021 +# Parameters from Table 1 +B = 4 # number of blades +Rtip = 0.1588 # meters +chord = 0.2*Rtip + +# Standard day: +Tamb = 15 + 273.15 # 15°C in Kelvin +pamb = 101325.0 # Pa +R = 287.052874 # J/(kg*K) +rho = pamb/(R*Tamb) +asound = sqrt(1.4*R*Tamb) +# Dynamic and kinematic viscosity +mu = rho*1.4502e-5 +nu = mu/rho + +# This is a hover case, so the freestream velocity should be zero. +# CCBlade.jl will run with a zero freestream, but I've found that it compares a bit better with experiment if I give it a small non-zero value. +Vinf = 0.001*asound + +# Figure 22 caption says Ω_c = 5465 RPM. +rpm = 5465.0 +omega = rpm * (2*pi/60) + +# Get "cell-centered" radial locations, and also the radial spacing. +num_radial = 50 +r_Rtip_ = range(0.2, 1.0; length=num_radial+1) +r_Rtip = 0.5 .* (r_Rtip_[2:end] .+ r_Rtip_[1:end-1]) +radii = r_Rtip .* Rtip +dradii = (r_Rtip_[2:end] .- r_Rtip_[1:end-1]) .* Rtip +Rhub = r_Rtip_[1]*Rtip + +# From Pettingill Equation (1), and value for Θ_tip in Table 1. +Θ_tip = 6.9 * pi/180 +twist = Θ_tip ./ (r_Rtip) + +# Need some aerodynamic quantities. +# Got these using CCBlade.jl: see `AcousticAnalogies.jl/test/gen_bpmjl_data/itr_with_bpmjl.jl`. +data_ccblade = load(joinpath(@__DIR__, "..", "..", "test", "gen_bpmjl_data", "figure22b.jld2")) +# Angle of attack at each radial station, radians. +alpha = data_ccblade["alpha"] +# Flow speed normal to span at each radial station, m/s. +U = data_ccblade["U"] + +# In the text describing Figure 22, "For these predictions, the trip flag was set to “tripped”, due to the rough surface quality of the blade." +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() + +# But we're going to use the untripped boundary layer for the LBL-VS noise. +bl_lblvs = AcousticAnalogies.UntrippedN0012BoundaryLayer() + +# In the Figure 22 caption, "for these predictions, bluntness thickness H was set to 0.8 mm and trailing edge angle Ψ was set to 16 degrees." +h = 0.8e-3 # meters +Psi = 16*pi/180 # radians + +# We'll run for 1 blade pass, 20 time steps per blade pass. +num_blade_pass = 1 +num_src_times_blade_pass = 20 +bpp = 1/(B/(2*pi)*omega) # 1/(B blade_passes/rev * 1 rev / (2*pi rad) * omega rad/s) +period_src = num_blade_pass*bpp +num_src_times = num_src_times_blade_pass * num_blade_pass +t0 = 0.0 +dt = period_src/num_src_times +src_times = t0 .+ (0:num_src_times-1).*dt + +# I don't see any discussion for what type of tip was used for the tip vortex noise. +# The flat tip seems to match the PAS+ROTONET+BARC predictions well. +blade_tip = AcousticAnalogies.FlatTip() + +# Now let's define the coordinate system. +# I'm going to do my usual thing, which is to have the freestream velocity pointed in the negative x direction, and thus the blades will be translating in the positive x direction. +# And the blades will be rotating about the positive x axis at a rate of `omega`. +rot_trans = SteadyRotXTransformation(t0, omega, 0.0) + +# The hub/rotation axis of the blades will start at the origin at time `t0`, and translate in the positive x direction at a speed of `Vinf`. +y0_hub = @SVector [0.0, 0.0, 0.0] # m +v0_hub = @SVector [Vinf, 0.0, 0.0] # m/s +const_vel_trans = ConstantVelocityTransformation(t0, y0_hub, v0_hub) + +# Now I can put the two transformations together: +trans = compose.(src_times, Ref(const_vel_trans), Ref(rot_trans)) + +# Azimuthal offset for each blade. +θs = (0:(B-1)) .* (2*pi/B) + +# Paper doesn't specify the microphone used for Figure 22, but earlier at the beginning of "C. Noise Characteristics and Trends" there is this: +# > For the purposes of this paper, presented acoustic spectra will correspond to an observer located −35° below the plane of the rotor (microphone 5). +# So I'll just assume that holds for Figure 22. +# For the coordinate system, I'm doing my usual thing, which is to have the freestream velocity pointed in the negative x direction, and thus the blades will be translating in the positive x direction. +# The observer (microphone 5) is 35 deg behind/downstream of the rotor rotation plane, so this should be good. +# But it will of course be moving with the same freestream in the positive x direction. +r_obs = 2.27 # meters +theta_obs = -35*pi/180 +# The observer is moving in the positive x direction at Vinf, at the origin at time t0. +t0_obs = 0.0 +x0_obs = @SVector [r_obs*sin(theta_obs), r_obs*cos(theta_obs), 0.0] +v_obs = @SVector [Vinf, 0.0, 0.0] +obs = AcousticAnalogies.ConstVelocityAcousticObserver(t0_obs, x0_obs, v_obs) + +# Reshape the inputs to the source element constructors so that everything will line up with (num_times, num_radial, num_blades). +θs_rs = reshape(θs, 1, 1, :) +radii_rs = reshape(radii, 1, :, 1) +dradii_rs = reshape(dradii, 1, :, 1) +# chord_rs = reshape(chord, 1, :, 1) +twist_rs = reshape(twist, 1, :, 1) +# hs_rs = reshape(hs, 1, :, 1) +# Psis_rs = reshape(Psis, 1, :, 1) +Us_rs = reshape(U, 1, :, 1) +alphas_rs = reshape(alpha, 1, :, 1) +# bls_rs = reshape(bls, 1, :, 1) + +# Separate things into tip and no-tip. +radii_rs_no_tip = @view radii_rs[:, begin:end-1, :] +dradii_rs_no_tip = @view dradii_rs[:, begin:end-1, :] +# chord_rs_no_tip = @view chord_rs[:, begin:end-1, :] +twist_rs_no_tip = @view twist_rs[:, begin:end-1, :] +# hs_rs_no_tip = @view hs_rs[:, begin:end-1, :] +# Psis_rs_no_tip = @view Psis_rs[:, begin:end-1, :] +Us_rs_no_tip = @view Us_rs[:, begin:end-1, :] +alphas_rs_no_tip = @view alphas_rs[:, begin:end-1, :] + +radii_rs_with_tip = @view radii_rs[:, end:end, :] +dradii_rs_with_tip = @view dradii_rs[:, end:end, :] +# chord_rs_with_tip = @view chord_rs[:, end:end, :] +twist_rs_with_tip = @view twist_rs[:, end:end, :] +# hs_rs_with_tip = @view hs_rs[:, end:end, :] +# Psis_rs_with_tip = @view Psis_rs[:, end:end, :] +Us_rs_with_tip = @view Us_rs[:, end:end, :] +alphas_rs_with_tip = @view alphas_rs[:, end:end, :] + +positive_x_rotation = true +ses_no_tip = CombinedNoTipBroadbandSourceElement.(asound, nu, radii_rs_no_tip, θs_rs, dradii_rs_no_tip, chord, twist_rs_no_tip, h, Psi, Us_rs_no_tip, alphas_rs_no_tip, src_times, dt, Ref(bl), positive_x_rotation) .|> trans +ses_with_tip = CombinedWithTipBroadbandSourceElement.(asound, nu, radii_rs_with_tip, θs_rs, dradii_rs_with_tip, chord, twist_rs_with_tip, h, Psi, Us_rs_with_tip, alphas_rs_with_tip, src_times, dt, Ref(bl), Ref(blade_tip), positive_x_rotation) .|> trans + +# It's more convinient to cat all the sources together. +ses = cat(ses_no_tip, ses_with_tip; dims=2) + +# Do the LBLVS prediction with the untripped boundary layer. +ses_lblvs = LBLVSSourceElement.(asound, nu, radii_rs, θs_rs, dradii_rs, chord, twist_rs, Us_rs, alphas_rs, src_times, dt, Ref(bl_lblvs), positive_x_rotation) .|> trans + +# The predictions in Figure 22b appear to be on 1/3 octave, ranging from about 200 Hz to 60,000 Hz. +# But let's expand the range of source frequencies to account for Doppler shifting. +freqs_src = AcousticMetrics.ExactProportionalBands{3, :center}(10.0, 200000.0) +freqs_obs = AcousticMetrics.ExactProportionalBands{3, :center}(200.0, 60000.0) + +# Now we can do a noise prediction. +bpm_outs = AcousticAnalogies.noise.(ses, Ref(obs), Ref(freqs_src)) +pbs_lblvss = AcousticAnalogies.noise.(ses_lblvs, Ref(obs), Ref(freqs_src)) + +# This seperates out the noise prediction for each source-observer combination into the different sources. +pbs_tblte_ps = AcousticAnalogies.pbs_pressure.(bpm_outs) +pbs_tblte_ss = AcousticAnalogies.pbs_suction.(bpm_outs) +pbs_tblte_alphas = AcousticAnalogies.pbs_alpha.(bpm_outs) +# pbs_lblvss = AcousticAnalogies.pbs_lblvs.(bpm_outs) +pbs_tebs = AcousticAnalogies.pbs_teb.(bpm_outs) +pbs_tips = AcousticAnalogies.pbs_tip.(bpm_outs[:, end:end, :]) + +# Now, need to combine each broadband noise prediction. +# The time axis the axis over which the time varies for each source. +time_axis = 1 +pbs_pressure = AcousticMetrics.combine(pbs_tblte_ps, freqs_obs, time_axis) +pbs_suction = AcousticMetrics.combine(pbs_tblte_ss, freqs_obs, time_axis) +pbs_alpha = AcousticMetrics.combine(pbs_tblte_alphas, freqs_obs, time_axis) +pbs_lblvs = AcousticMetrics.combine(pbs_lblvss, freqs_obs, time_axis) +pbs_teb = AcousticMetrics.combine(pbs_tebs, freqs_obs, time_axis) +pbs_tip = AcousticMetrics.combine(pbs_tips, freqs_obs, time_axis) + +# Now I need to account for the fact that Figure 22b is actually comparing to narrowband experimental data with a frequency spacing of 20 Hz. +# So, to do that, I need to multiply the mean-squared pressure by Δf_nb/Δf_pbs, where `Δf_nb` is the 20 Hz narrowband and `Δf_pbs` is the bandwidth of each 1/3-octave proportional band. +# I think the paper describes that, right? +# Right, here's something: +# +# > The current prediction method is limited to one-third octave bands, but it is compared to the narrowband experiment with Δf = 20 Hz. +# > This is done by dividing the energy from the one-third octave bands by the number of bands in Δf = 20 Hz. +# +# So, `Δf_pbs/Δf_nb` would represent the number of `Δf_nb`-width bands that could fit in a proportional band of bin width `Δf_pbs`. +# And then I'm dividing by that. +# So that seems like the right thing. +# So, first thing is to get the proportional band spacing. +freqs_l = AcousticMetrics.lower_bands(freqs_obs) +freqs_u = AcousticMetrics.upper_bands(freqs_obs) +df_pbs = freqs_u .- freqs_l + +# Also need the experimental narrowband spacing. +df_nb = 20.0 +# Now multiply each by that. +nb_pressure = pbs_pressure .* df_nb ./ df_pbs +nb_suction = pbs_suction .* df_nb ./ df_pbs +nb_alpha = pbs_alpha .* df_nb ./ df_pbs +nb_lblvs = pbs_lblvs .* df_nb ./ df_pbs +nb_teb = pbs_teb .* df_nb ./ df_pbs +nb_tip = pbs_tip .* df_nb ./ df_pbs + +# Now I want the SPL, which should just be this: +pref = 20e-6 +spl_pressure = 10 .* log10.(nb_pressure./(pref^2)) +spl_suction = 10 .* log10.(nb_suction./(pref^2)) +spl_alpha = 10 .* log10.(nb_alpha./(pref^2)) +spl_lblvs = 10 .* log10.(nb_lblvs./(pref^2)) +spl_teb = 10 .* log10.(nb_teb./(pref^2)) +spl_tip = 10 .* log10.(nb_tip./(pref^2)) + +# Now I should be able to compare to the BARC data. +# Need to read it in first. +data_pressure_barc = readdlm(joinpath(@__DIR__, "..", "..", "test", "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure22b-TBL-TE-pressure-2.csv"), ',') +freq_pressure_barc = data_pressure_barc[:, 1] +spl_pressure_barc = data_pressure_barc[:, 2] + +data_suction_barc = readdlm(joinpath(@__DIR__, "..", "..", "test", "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure22b-TBL-TE-suction-2.csv"), ',') +freq_suction_barc = data_suction_barc[:, 1] +spl_suction_barc = data_suction_barc[:, 2] + +data_separation_barc = readdlm(joinpath(@__DIR__, "..", "..", "test", "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure22b-separation-2.csv"), ',') +freq_separation_barc = data_separation_barc[:, 1] +spl_separation_barc = data_separation_barc[:, 2] + +# data_lblvs_barc = readdlm(joinpath(@__DIR__, "..", "..", "test", "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure22b-LBLVS.csv"), ',') +# freq_lblvs_barc = data_lblvs_barc[:, 1] +# spl_lblvs_barc = data_lblvs_barc[:, 2] + +data_teb_barc = readdlm(joinpath(@__DIR__, "..", "..", "test", "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure22b-BVS.csv"), ',') +freq_teb_barc = data_teb_barc[:, 1] +spl_teb_barc = data_teb_barc[:, 2] + +data_tip_barc = readdlm(joinpath(@__DIR__, "..", "..", "test", "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure22b-tip_vortex_shedding.csv"), ',') +freq_tip_barc = data_tip_barc[:, 1] +spl_tip_barc = data_tip_barc[:, 2] + +# Now let's plot. +fig = Figure() +ax1 = fig[2, 1] = Axis(fig, xlabel="frequency, Hz", ylabel="SPL (dB Ref: 20 μPa), Δf = 20 Hz", xscale=log10, xticks=[10^3, 10^4], xminorticksvisible=true, xminorgridvisible=true, xminorticks=IntervalsBetween(9), yticks=10:10:70)#, aspect=3) + +s_pressure = scatter!(ax1, freq_pressure_barc, spl_pressure_barc, color=:blue, marker=:rtriangle) +s_suction = scatter!(ax1, freq_suction_barc, spl_suction_barc, color=:red, marker=:ltriangle) +s_separation = scatter!(ax1, freq_separation_barc, spl_separation_barc, color=:yellow, marker=:diamond) +# s_lblvs = scatter!(ax1, freq_lblvs_barc, spl_lblvs_barc, color=:purple, marker=:rect) +s_blunt = scatter!(ax1, freq_teb_barc, spl_teb_barc, color=:green, marker=:star6) +s_tip = scatter!(ax1, freq_tip_barc, spl_tip_barc, color=:cyan, marker=:circle) + +l_pressure = lines!(ax1, freqs_obs, spl_pressure, color=:blue) +l_suction = lines!(ax1, freqs_obs, spl_suction, color=:red) +l_alpha = lines!(ax1, freqs_obs, spl_alpha, color=:yellow) +# l_lblvs = lines!(ax1, freqs_obs, spl_lblvs, color=:purple) +l_teb = lines!(ax1, freqs_obs, spl_teb, color=:green) +l_tip = lines!(ax1, freqs_obs, spl_tip, color=:cyan) + +xlims!(ax1, 2e2, 6e4) +ylims!(ax1, 10.0, 70.0) + +leg = Legend(fig[1, 1], [ + [s_pressure, l_pressure], + [s_suction, l_suction], + [s_separation, l_alpha], + # [s_lblvs, l_lblvs], + [s_blunt, l_teb], + [s_tip, l_tip], + ], + [ + "TBLTE-Pressure", + "TBLTE-Suction", + "Separation", + # "LBLVS", + "BVS", + "Tip", + ]; orientation=:horizontal, tellwidth=false, tellheight=true, nbanks=2) + +text!(ax1, 210, 62; text="markers: CCBlade.jl+BPM.jl\nlines: CCBlade.jl+AcousticAnalogies.jl") + +save("figure22b-spl-barc.png", fig) +``` +![](figure22b-spl-barc.png) + +### Figure 23c +```@example figure23c +using AcousticAnalogies +using AcousticMetrics: AcousticMetrics +using DelimitedFiles: readdlm +using KinematicCoordinateTransformations: compose, SteadyRotXTransformation, ConstantVelocityTransformation +using FileIO: load +using GLMakie +using StaticArrays: @SVector + +# Pettingill et al., "Acoustic And Performance Characteristics of an Ideally Twisted Rotor in Hover", 2021 +# Parameters from Table 1 +B = 4 # number of blades +Rtip = 0.1588 # meters +chord = 0.2*Rtip + +# Standard day: +Tamb = 15 + 273.15 # 15°C in Kelvin +pamb = 101325.0 # Pa +R = 287.052874 # J/(kg*K) +rho = pamb/(R*Tamb) +asound = sqrt(1.4*R*Tamb) +# Dynamic and kinematic viscosity +mu = rho*1.4502e-5 +nu = mu/rho + +# This is a hover case, so the freestream velocity should be zero. +# CCBlade.jl will run with a zero freestream, but I've found that it compares a bit better with experiment if I give it a small non-zero value. +Vinf = 0.001*asound + +# Figure 23 caption says Ω_c = 5510 RPM. +rpm = 5510.0 +omega = rpm * (2*pi/60) + +# Get "cell-centered" radial locations, and also the radial spacing. +num_radial = 50 +r_Rtip_ = range(0.2, 1.0; length=num_radial+1) +r_Rtip = 0.5 .* (r_Rtip_[2:end] .+ r_Rtip_[1:end-1]) +radii = r_Rtip .* Rtip +dradii = (r_Rtip_[2:end] .- r_Rtip_[1:end-1]) .* Rtip +Rhub = r_Rtip_[1]*Rtip + +# From Pettingill Equation (1), and value for Θ_tip in Table 1. +Θ_tip = 6.9 * pi/180 +twist = Θ_tip ./ (r_Rtip) + +# Need some aerodynamic quantities. +# Got these using CCBlade.jl: see `AcousticAnalogies.jl/test/gen_bpmjl_data/itr_with_bpmjl.jl`. +data_ccblade = load(joinpath(@__DIR__, "..", "..", "test", "gen_bpmjl_data", "figure23c.jld2")) +# Angle of attack at each radial station, radians. +alpha = data_ccblade["alpha"] +# Flow speed normal to span at each radial station, m/s. +U = data_ccblade["U"] + +# So, for the boundary layer, we want to use untripped for the 95% of the blade from the hub to almost tip, and then tripped for the last 5% of the blade at the tip. +num_untripped = Int(round(0.95*num_radial)) +num_tripped = num_radial - num_untripped +bls_untripped = fill(AcousticAnalogies.UntrippedN0012BoundaryLayer(), num_untripped) +bls_tripped = fill(AcousticAnalogies.TrippedN0012BoundaryLayer(), num_tripped) +bls = vcat(bls_untripped, bls_tripped) + +# Now, the other trick: need to only include LBLVS noise for elements where the Reynolds number is < 160000. +# So, we need the Reynolds number for each section. +Re_c = @. U * chord / nu +# So now we want to extract the radial stations that meet that < 160000 condition. +low_Re_c = 160000 +mask_low_Re_c = Re_c .< low_Re_c + +# And we're also going to use the untripped boundary layer for the LBLVS source. +bl_lblvs = AcousticAnalogies.UntrippedN0012BoundaryLayer() + +# In the Figure 23 caption, "for these predictions, bluntness thickness H was set to 0.5 mm and trailing edge angle Ψ was set to 14 degrees." +h = 0.5e-3 # meters +Psi = 14*pi/180 # radians + +# We'll run for 1 blade pass, 20 time steps per blade pass. +num_blade_pass = 1 +num_src_times_blade_pass = 20 +bpp = 1/(B/(2*pi)*omega) # 1/(B blade_passes/rev * 1 rev / (2*pi rad) * omega rad/s) +period_src = num_blade_pass*bpp +num_src_times = num_src_times_blade_pass * num_blade_pass +t0 = 0.0 +dt = period_src/num_src_times +src_times = t0 .+ (0:num_src_times-1).*dt + +# I don't see any discussion for what type of tip was used for the tip vortex noise. +# The flat tip seems to match the PAS+ROTONET+BARC predictions well. +blade_tip = AcousticAnalogies.FlatTip() + +# Now let's define the coordinate system. +# I'm going to do my usual thing, which is to have the freestream velocity pointed in the negative x direction, and thus the blades will be translating in the positive x direction. +# And the blades will be rotating about the positive x axis at a rate of `omega`. +rot_trans = SteadyRotXTransformation(t0, omega, 0.0) + +# The hub/rotation axis of the blades will start at the origin at time `t0`, and translate in the positive x direction at a speed of `Vinf`. +y0_hub = @SVector [0.0, 0.0, 0.0] # m +v0_hub = @SVector [Vinf, 0.0, 0.0] # m/s +const_vel_trans = ConstantVelocityTransformation(t0, y0_hub, v0_hub) + +# Now I can put the two transformations together: +trans = compose.(src_times, Ref(const_vel_trans), Ref(rot_trans)) + +# Azimuthal offset for each blade. +θs = (0:(B-1)) .* (2*pi/B) + +# Paper doesn't specify the microphone used for Figure 22, but earlier at the beginning of "C. Noise Characteristics and Trends" there is this: +# > For the purposes of this paper, presented acoustic spectra will correspond to an observer located −35° below the plane of the rotor (microphone 5). +# So I'll just assume that holds for Figure 22. +# For the coordinate system, I'm doing my usual thing, which is to have the freestream velocity pointed in the negative x direction, and thus the blades will be translating in the positive x direction. +# The observer (microphone 5) is 35 deg behind/downstream of the rotor rotation plane, so this should be good. +# But it will of course be moving with the same freestream in the positive x direction. +r_obs = 2.27 # meters +theta_obs = -35*pi/180 +# The observer is moving in the positive x direction at Vinf, at the origin at time t0. +t0_obs = 0.0 +x0_obs = @SVector [r_obs*sin(theta_obs), r_obs*cos(theta_obs), 0.0] +v_obs = @SVector [Vinf, 0.0, 0.0] +obs = AcousticAnalogies.ConstVelocityAcousticObserver(t0_obs, x0_obs, v_obs) + +# Reshape the inputs to the source element constructors so that everything will line up with (num_times, num_radial, num_blades). +θs_rs = reshape(θs, 1, 1, :) +radii_rs = reshape(radii, 1, :, 1) +dradii_rs = reshape(dradii, 1, :, 1) +# chord_rs = reshape(chord, 1, :, 1) +twist_rs = reshape(twist, 1, :, 1) +# hs_rs = reshape(hs, 1, :, 1) +# Psis_rs = reshape(Psis, 1, :, 1) +Us_rs = reshape(U, 1, :, 1) +alphas_rs = reshape(alpha, 1, :, 1) +bls_rs = reshape(bls, 1, :, 1) + +# Separate things into tip and no-tip. +radii_rs_no_tip = @view radii_rs[:, begin:end-1, :] +dradii_rs_no_tip = @view dradii_rs[:, begin:end-1, :] +# chord_rs_no_tip = @view chord_rs[:, begin:end-1, :] +twist_rs_no_tip = @view twist_rs[:, begin:end-1, :] +# hs_rs_no_tip = @view hs_rs[:, begin:end-1, :] +# Psis_rs_no_tip = @view Psis_rs[:, begin:end-1, :] +Us_rs_no_tip = @view Us_rs[:, begin:end-1, :] +alphas_rs_no_tip = @view alphas_rs[:, begin:end-1, :] +bls_rs_no_tip = @view bls_rs[:, begin:end-1, :] + +radii_rs_with_tip = @view radii_rs[:, end:end, :] +dradii_rs_with_tip = @view dradii_rs[:, end:end, :] +# chord_rs_with_tip = @view chord_rs[:, end:end, :] +twist_rs_with_tip = @view twist_rs[:, end:end, :] +# hs_rs_with_tip = @view hs_rs[:, end:end, :] +# Psis_rs_with_tip = @view Psis_rs[:, end:end, :] +Us_rs_with_tip = @view Us_rs[:, end:end, :] +alphas_rs_with_tip = @view alphas_rs[:, end:end, :] +bls_rs_with_tip = @view bls_rs[:, end:end, :] + +positive_x_rotation = true +ses_no_tip = CombinedNoTipBroadbandSourceElement.(asound, nu, radii_rs_no_tip, θs_rs, dradii_rs_no_tip, chord, twist_rs_no_tip, h, Psi, Us_rs_no_tip, alphas_rs_no_tip, src_times, dt, bls_rs_no_tip, positive_x_rotation) .|> trans +ses_with_tip = CombinedWithTipBroadbandSourceElement.(asound, nu, radii_rs_with_tip, θs_rs, dradii_rs_with_tip, chord, twist_rs_with_tip, h, Psi, Us_rs_with_tip, alphas_rs_with_tip, src_times, dt, bls_rs_with_tip, Ref(blade_tip), positive_x_rotation) .|> trans + +# It's more convinient to cat all the sources together. +ses = cat(ses_no_tip, ses_with_tip; dims=2) + +# Need to do the LBLVS stuff separately. +# Grab the parts of the inputs that correspond to the low Reynolds number stations. +radii_lblvs = @view radii[mask_low_Re_c] +dradii_lblvs = @view dradii[mask_low_Re_c] +# chord_lblvs = @view chord[mask_low_Re_c] +twist_lblvs = @view twist[mask_low_Re_c] +# hs_lblvs = @view hs[mask_low_Re_c] +# Psis_lblvs = @view Psis[mask_low_Re_c] +Us_lblvs = @view U[mask_low_Re_c] +alphas_lblvs = @view alpha[mask_low_Re_c] + +# And do the reshaping. +radii_lblvs_rs = reshape(radii_lblvs, 1, :, 1) +dradii_lblvs_rs = reshape(dradii_lblvs, 1, :, 1) +# chord_lblvs_rs = reshape(chord_lblvs, 1, :, 1) +twist_lblvs_rs = reshape(twist_lblvs, 1, :, 1) +# hs_lblvs_rs = reshape(hs_lblvs, 1, :, 1) +# Psis_lblvs_rs = reshape(Psis_lblvs, 1, :, 1) +Us_lblvs_rs = reshape(Us_lblvs, 1, :, 1) +alphas_lblvs_rs = reshape(alphas_lblvs, 1, :, 1) + +# Now we can create the source elements. +ses_lblvs = LBLVSSourceElement.(asound, nu, radii_lblvs_rs, θs_rs, dradii_lblvs_rs, chord, twist_lblvs_rs, Us_lblvs_rs, alphas_lblvs_rs, src_times, dt, Ref(bl_lblvs), positive_x_rotation) .|> trans + +# Now we can create the source elements. +ses_lblvs = LBLVSSourceElement.(asound, nu, radii_lblvs_rs, θs_rs, dradii_lblvs_rs, chord, twist_lblvs_rs, Us_lblvs_rs, alphas_lblvs_rs, src_times, dt, Ref(bl_lblvs), positive_x_rotation) .|> trans + +# The predictions in Figure 23c appear to be on 1/3 octave, ranging from about 200 Hz to 60,000 Hz. +# But let's expand the range of source frequencies to account for Doppler shifting. +freqs_src = AcousticMetrics.ExactProportionalBands{3, :center}(10.0, 200000.0) +freqs_obs = AcousticMetrics.ExactProportionalBands{3, :center}(200.0, 60000.0) + +# Now we can do a noise prediction. +bpm_outs = AcousticAnalogies.noise.(ses, Ref(obs), Ref(freqs_src)) +pbs_lblvss = AcousticAnalogies.noise.(ses_lblvs, Ref(obs), Ref(freqs_src)) + +# This seperates out the noise prediction for each source-observer combination into the different sources. +pbs_tblte_ps = AcousticAnalogies.pbs_pressure.(bpm_outs) +pbs_tblte_ss = AcousticAnalogies.pbs_suction.(bpm_outs) +pbs_tblte_alphas = AcousticAnalogies.pbs_alpha.(bpm_outs) +pbs_tebs = AcousticAnalogies.pbs_teb.(bpm_outs) +pbs_tips = AcousticAnalogies.pbs_tip.(bpm_outs[:, end:end, :]) + +# Now, need to combine each broadband noise prediction. +# The time axis the axis over which the time varies for each source. +time_axis = 1 +pbs_pressure = AcousticMetrics.combine(pbs_tblte_ps, freqs_obs, time_axis) +pbs_suction = AcousticMetrics.combine(pbs_tblte_ss, freqs_obs, time_axis) +pbs_alpha = AcousticMetrics.combine(pbs_tblte_alphas, freqs_obs, time_axis) +pbs_teb = AcousticMetrics.combine(pbs_tebs, freqs_obs, time_axis) +pbs_tip = AcousticMetrics.combine(pbs_tips, freqs_obs, time_axis) +pbs_lblvs = AcousticMetrics.combine(pbs_lblvss, freqs_obs, time_axis) + +# Now I need to account for the fact that Figure 23c is actually comparing to narrowband experimental data with a frequency spacing of 20 Hz. +# So, to do that, I need to multiply the mean-squared pressure by Δf_nb/Δf_pbs, where `Δf_nb` is the 20 Hz narrowband and `Δf_pbs` is the bandwidth of each 1/3-octave proportional band. +# I think the paper describes that, right? +# Right, here's something: +# +# > The current prediction method is limited to one-third octave bands, but it is compared to the narrowband experiment with Δf = 20 Hz. +# > This is done by dividing the energy from the one-third octave bands by the number of bands in Δf = 20 Hz. +# +# So, `Δf_pbs/Δf_nb` would represent the number of `Δf_nb`-width bands that could fit in a proportional band of bin width `Δf_pbs`. +# And then I'm dividing by that. +# So that seems like the right thing. +# So, first thing is to get the proportional band spacing. +freqs_l = AcousticMetrics.lower_bands(freqs_obs) +freqs_u = AcousticMetrics.upper_bands(freqs_obs) +df_pbs = freqs_u .- freqs_l + +# Also need the experimental narrowband spacing. +df_nb = 20.0 +# Now multiply each by that. +nb_pressure = pbs_pressure .* df_nb ./ df_pbs +nb_suction = pbs_suction .* df_nb ./ df_pbs +nb_alpha = pbs_alpha .* df_nb ./ df_pbs +nb_lblvs = pbs_lblvs .* df_nb ./ df_pbs +nb_teb = pbs_teb .* df_nb ./ df_pbs +nb_tip = pbs_tip .* df_nb ./ df_pbs + +# Now I want the SPL, which should just be this: +pref = 20e-6 +spl_pressure = 10 .* log10.(nb_pressure./(pref^2)) +spl_suction = 10 .* log10.(nb_suction./(pref^2)) +spl_alpha = 10 .* log10.(nb_alpha./(pref^2)) +spl_lblvs = 10 .* log10.(nb_lblvs./(pref^2)) +spl_teb = 10 .* log10.(nb_teb./(pref^2)) +spl_tip = 10 .* log10.(nb_tip./(pref^2)) + +# Now I should be able to compare to the BARC data. +# Need to read it in first. +data_pressure_barc = readdlm(joinpath(@__DIR__, "..", "..", "test", "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure23c-TBL-TE-pressure.csv"), ',') +freq_pressure_barc = data_pressure_barc[:, 1] +spl_pressure_barc = data_pressure_barc[:, 2] + +data_suction_barc = readdlm(joinpath(@__DIR__, "..", "..", "test", "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure23c-TBL-TE-suction.csv"), ',') +freq_suction_barc = data_suction_barc[:, 1] +spl_suction_barc = data_suction_barc[:, 2] + +data_separation_barc = readdlm(joinpath(@__DIR__, "..", "..", "test", "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure23c-separation.csv"), ',') +freq_separation_barc = data_separation_barc[:, 1] +spl_separation_barc = data_separation_barc[:, 2] + +data_lblvs_barc = readdlm(joinpath(@__DIR__, "..", "..", "test", "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure23c-LBLVS.csv"), ',') +freq_lblvs_barc = data_lblvs_barc[:, 1] +spl_lblvs_barc = data_lblvs_barc[:, 2] + +data_teb_barc = readdlm(joinpath(@__DIR__, "..", "..", "test", "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure23c-BVS.csv"), ',') +freq_teb_barc = data_teb_barc[:, 1] +spl_teb_barc = data_teb_barc[:, 2] + +data_tip_barc = readdlm(joinpath(@__DIR__, "..", "..", "test", "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure23c-tip_vortex_shedding.csv"), ',') +freq_tip_barc = data_tip_barc[:, 1] +spl_tip_barc = data_tip_barc[:, 2] + +# Now let's plot. +fig = Figure() +ax1 = fig[2, 1] = Axis(fig, xlabel="frequency, Hz", ylabel="SPL (dB Ref: 20 μPa), Δf = 20 Hz", xscale=log10, xticks=[10^3, 10^4], xminorticksvisible=true, xminorgridvisible=true, xminorticks=IntervalsBetween(9), yticks=10:10:70)#, aspect=3) + +s_pressure = scatter!(ax1, freq_pressure_barc, spl_pressure_barc, color=:blue, marker=:rtriangle) +s_suction = scatter!(ax1, freq_suction_barc, spl_suction_barc, color=:red, marker=:ltriangle) +s_separation = scatter!(ax1, freq_separation_barc, spl_separation_barc, color=:yellow, marker=:diamond) +s_lblvs = scatter!(ax1, freq_lblvs_barc, spl_lblvs_barc, color=:purple, marker=:rect) +s_blunt = scatter!(ax1, freq_teb_barc, spl_teb_barc, color=:green, marker=:star6) +s_tip = scatter!(ax1, freq_tip_barc, spl_tip_barc, color=:cyan, marker=:circle) + +l_pressure = lines!(ax1, freqs_obs, spl_pressure, color=:blue) +l_suction = lines!(ax1, freqs_obs, spl_suction, color=:red) +l_alpha = lines!(ax1, freqs_obs, spl_alpha, color=:yellow) +l_lblvs = lines!(ax1, freqs_obs, spl_lblvs, color=:purple) +l_teb = lines!(ax1, freqs_obs, spl_teb, color=:green) +l_tip = lines!(ax1, freqs_obs, spl_tip, color=:cyan) + +xlims!(ax1, 2e2, 6e4) +ylims!(ax1, 10.0, 70.0) + +leg = Legend(fig[1, 1], [ + [s_pressure, l_pressure], + [s_suction, l_suction], + [s_separation, l_alpha], + [s_lblvs, l_lblvs], + [s_blunt, l_teb], + [s_tip, l_tip], + ], + [ + "TBLTE-Pressure", + "TBLTE-Suction", + "Separation", + "LBLVS", + "BVS", + "Tip", + ]; orientation=:horizontal, tellwidth=false, tellheight=true, nbanks=2) + +text!(ax1, 210, 62; text="markers: CCBlade.jl+BPM.jl\nlines: CCBlade.jl+AcousticAnalogies.jl") + +save("figure23c-spl-barc.png", fig) +``` +![](figure23c-spl-barc.png) + + +### Figure 24b +```@example figure24b +using AcousticAnalogies +using AcousticMetrics: AcousticMetrics +using DelimitedFiles: readdlm +using KinematicCoordinateTransformations: compose, SteadyRotXTransformation, ConstantVelocityTransformation +using FileIO: load +using GLMakie +using StaticArrays: @SVector + +# Pettingill et al., "Acoustic And Performance Characteristics of an Ideally Twisted Rotor in Hover", 2021 +# Parameters from Table 1 +B = 4 # number of blades +Rtip = 0.1588 # meters +chord = 0.2*Rtip + +# Standard day: +Tamb = 15 + 273.15 # 15°C in Kelvin +pamb = 101325.0 # Pa +R = 287.052874 # J/(kg*K) +rho = pamb/(R*Tamb) +asound = sqrt(1.4*R*Tamb) +# Dynamic and kinematic viscosity +mu = rho*1.4502e-5 +nu = mu/rho + +# This is a hover case, so the freestream velocity should be zero. +# CCBlade.jl will run with a zero freestream, but I've found that it compares a bit better with experiment if I give it a small non-zero value. +Vinf = 0.001*asound + +# Figure 24 caption says Ω_c = 2938 RPM. +rpm = 2938.0 +omega = rpm * (2*pi/60) + +# Get "cell-centered" radial locations, and also the radial spacing. +num_radial = 50 +r_Rtip_ = range(0.2, 1.0; length=num_radial+1) +r_Rtip = 0.5 .* (r_Rtip_[2:end] .+ r_Rtip_[1:end-1]) +radii = r_Rtip .* Rtip +dradii = (r_Rtip_[2:end] .- r_Rtip_[1:end-1]) .* Rtip +Rhub = r_Rtip_[1]*Rtip + +# From Pettingill Equation (1), and value for Θ_tip in Table 1. +Θ_tip = 6.9 * pi/180 +twist = Θ_tip ./ (r_Rtip) + +# Need some aerodynamic quantities. +# Got these using CCBlade.jl: see `AcousticAnalogies.jl/test/gen_bpmjl_data/itr_with_bpmjl.jl`. +data_ccblade = load(joinpath(@__DIR__, "..", "..", "test", "gen_bpmjl_data", "figure24b.jld2")) +# Angle of attack at each radial station, radians. +alpha = data_ccblade["alpha"] +# Flow speed normal to span at each radial station, m/s. +U = data_ccblade["U"] + +# In the Figure 24 caption, "for these predictions, bluntness thickness H was set to 0.5 mm and trailing edge angle Ψ was set to 14 degrees." +h = 0.5e-3 # meters +Psi = 14*pi/180 # radians + +# We'll run for 1 blade pass, 20 time steps per blade pass. +num_blade_pass = 1 +num_src_times_blade_pass = 20 + +# Get the time levels we'll run. +# First, get the blade passing period. +bpp = 1/(B/(2*pi)*omega) # 1/(B blade_passes/rev * 1 rev / (2*pi rad) * omega rad/s) + +# Now we can get the total period of source time we'll run over. +period_src = num_blade_pass*bpp + +# And the number of source times. +num_src_times = num_src_times_blade_pass * num_blade_pass + +# We know the total time period and number of source times, so we can get the time step. +dt = period_src/num_src_times + +# We'll arbitrarily start at time 0.0 seconds. +t0 = 0.0 + +# And now we can finally get each source time. +src_times = t0 .+ (0:num_src_times-1).*dt + +# Now let's define the coordinate system. +# I'm going to do my usual thing, which is to have the freestream velocity pointed in the negative x direction, and thus the blades will be translating in the positive x direction. +# And the blades will be rotating about the positive x axis at a rate of `omega`. +rot_trans = SteadyRotXTransformation(t0, omega, 0.0) + +# The hub/rotation axis of the blades will start at the origin at time `t0`, and translate in the positive x direction at a speed of `Vinf`. +y0_hub = @SVector [0.0, 0.0, 0.0] # m +v0_hub = @SVector [Vinf, 0.0, 0.0] # m/s +const_vel_trans = ConstantVelocityTransformation(t0, y0_hub, v0_hub) + +# Now I can put the two transformations together: +trans = compose.(src_times, Ref(const_vel_trans), Ref(rot_trans)) + +# Azimuthal offset for each blade. +θs = (0:(B-1)) .* (2*pi/B) + +# For the boundary layer we want to use untripped for the 95% of the blade from the hub to almost tip, and then tripped for the last 5% of the blade at the tip. +# First figure out how many of each we'll actually have with the `num_radial = 50` radial stations. +num_untripped = Int(round(0.95*num_radial)) +num_tripped = num_radial - num_untripped +# Now create a length-`num_radial` vector of untripped and then tripped boundary layer objects. +bls = vcat(fill(AcousticAnalogies.UntrippedN0012BoundaryLayer(), num_untripped), fill(AcousticAnalogies.TrippedN0012BoundaryLayer(), num_tripped)) + +# But we'll always use the untripped boundary layer with LBLVS. +bl_lblvs = AcousticAnalogies.UntrippedN0012BoundaryLayer() + +# I don't see any discussion for what type of tip was used for the tip vortex noise. +# The flat tip seems to match the PAS+ROTONET+BARC predictions well. +blade_tip = AcousticAnalogies.FlatTip() + +# Paper doesn't specify the microphone used for Figure 24, but earlier at the beginning of "C. Noise Characteristics and Trends" there is this: +# > For the purposes of this paper, presented acoustic spectra will correspond to an observer located −35° below the plane of the rotor (microphone 5). +# So I'll just assume that holds for Figure 24. +# For the coordinate system, I'm doing my usual thing, which is to have the freestream velocity pointed in the negative x direction, and thus the blades will be translating in the positive x direction. +# The observer (microphone 5) is 35 deg behind/downstream of the rotor rotation plane, so this should be good. +# But it will of course be moving with the same freestream in the positive x direction. +r_obs = 2.27 # meters +theta_obs = -35*pi/180 +# The observer is moving in the positive x direction at Vinf, at the origin at time t0. +t0_obs = 0.0 +x0_obs = @SVector [r_obs*sin(theta_obs), r_obs*cos(theta_obs), 0.0] +v_obs = @SVector [Vinf, 0.0, 0.0] +obs = AcousticAnalogies.ConstVelocityAcousticObserver(t0_obs, x0_obs, v_obs) + +# Reshape the inputs to the source element constructors so that everything will line up with (num_times, num_radial, num_blades). +θs_rs = reshape(θs, 1, 1, :) +radii_rs = reshape(radii, 1, :, 1) +dradii_rs = reshape(dradii, 1, :, 1) +# chord_rs = reshape(chord, 1, :, 1) +twist_rs = reshape(twist, 1, :, 1) +# hs_rs = reshape(hs, 1, :, 1) +# Psis_rs = reshape(Psis, 1, :, 1) +Us_rs = reshape(U, 1, :, 1) +alphas_rs = reshape(alpha, 1, :, 1) +bls_rs = reshape(bls, 1, :, 1) + +# Separate things into tip and no-tip. +radii_rs_no_tip = @view radii_rs[:, begin:end-1, :] +dradii_rs_no_tip = @view dradii_rs[:, begin:end-1, :] +twist_rs_no_tip = @view twist_rs[:, begin:end-1, :] +Us_rs_no_tip = @view Us_rs[:, begin:end-1, :] +alphas_rs_no_tip = @view alphas_rs[:, begin:end-1, :] +bls_rs_no_tip = @view bls_rs[:, begin:end-1, :] + +radii_rs_with_tip = @view radii_rs[:, end:end, :] +dradii_rs_with_tip = @view dradii_rs[:, end:end, :] +twist_rs_with_tip = @view twist_rs[:, end:end, :] +Us_rs_with_tip = @view Us_rs[:, end:end, :] +alphas_rs_with_tip = @view alphas_rs[:, end:end, :] +bls_rs_with_tip = @view bls_rs[:, end:end, :] + +positive_x_rotation = true +ses_no_tip = CombinedNoTipBroadbandSourceElement.(asound, nu, radii_rs_no_tip, θs_rs, dradii_rs_no_tip, chord, twist_rs_no_tip, h, Psi, Us_rs_no_tip, alphas_rs_no_tip, src_times, dt, bls_rs_no_tip, positive_x_rotation) .|> trans +ses_with_tip = CombinedWithTipBroadbandSourceElement.(asound, nu, radii_rs_with_tip, θs_rs, dradii_rs_with_tip, chord, twist_rs_with_tip, h, Psi, Us_rs_with_tip, alphas_rs_with_tip, src_times, dt, bls_rs_with_tip, Ref(blade_tip), positive_x_rotation) .|> trans + +# Put the source elements together: +ses = cat(ses_no_tip, ses_with_tip; dims=2) + +# Need to do the LBLVS with the untripped boundary layer. +ses_lblvs = AcousticAnalogies.LBLVSSourceElement.(asound, nu, radii_rs, θs_rs, dradii_rs, chord, twist_rs, Us_rs, alphas_rs, src_times, dt, Ref(bl_lblvs), positive_x_rotation) .|> trans + +# The predictions in Figure 24b appear to be on 1/3 octave, ranging from about 200 Hz to 60,000 Hz. +# But let's expand the range of source frequencies to account for Doppler shifting. +freqs_src = AcousticMetrics.ExactProportionalBands{3, :center}(10.0, 200000.0) +freqs_obs = AcousticMetrics.ExactProportionalBands{3, :center}(200.0, 60000.0) + +# Now we can do a noise prediction. +bpm_outs = AcousticAnalogies.noise.(ses, Ref(obs), Ref(freqs_src)) +pbs_lblvss = AcousticAnalogies.noise.(ses_lblvs, Ref(obs), Ref(freqs_src)) + +# This seperates out the noise prediction for each source-observer combination into the different sources. +pbs_tblte_ps = AcousticAnalogies.pbs_pressure.(bpm_outs) +pbs_tblte_ss = AcousticAnalogies.pbs_suction.(bpm_outs) +pbs_tblte_alphas = AcousticAnalogies.pbs_alpha.(bpm_outs) +pbs_tebs = AcousticAnalogies.pbs_teb.(bpm_outs) +pbs_tips = AcousticAnalogies.pbs_tip.(bpm_outs[:, end:end, :]) + +# Now, need to combine each broadband noise prediction. +# The time axis the axis over which the time varies for each source. +time_axis = 1 +pbs_pressure = AcousticMetrics.combine(pbs_tblte_ps, freqs_obs, time_axis) +pbs_suction = AcousticMetrics.combine(pbs_tblte_ss, freqs_obs, time_axis) +pbs_alpha = AcousticMetrics.combine(pbs_tblte_alphas, freqs_obs, time_axis) +pbs_teb = AcousticMetrics.combine(pbs_tebs, freqs_obs, time_axis) +pbs_tip = AcousticMetrics.combine(pbs_tips, freqs_obs, time_axis) +pbs_lblvs = AcousticMetrics.combine(pbs_lblvss, freqs_obs, time_axis) + +# Now I need to account for the fact that Figure 24b is actually comparing to narrowband experimental data with a frequency spacing of 20 Hz. +# So, to do that, I need to multiply the mean-squared pressure by Δf_nb/Δf_pbs, where `Δf_nb` is the 20 Hz narrowband and `Δf_pbs` is the bandwidth of each 1/3-octave proportional band. +# I think the paper describes that, right? +# Right, here's something: +# +# > The current prediction method is limited to one-third octave bands, but it is compared to the narrowband experiment with Δf = 20 Hz. +# > This is done by dividing the energy from the one-third octave bands by the number of bands in Δf = 20 Hz. +# +# So, `Δf_pbs/Δf_nb` would represent the number of `Δf_nb`-width bands that could fit in a proportional band of bin width `Δf_pbs`. +# And then I'm dividing by that. +# So that seems like the right thing. +# So, first thing is to get the proportional band spacing. +freqs_l = AcousticMetrics.lower_bands(freqs_obs) +freqs_u = AcousticMetrics.upper_bands(freqs_obs) +df_pbs = freqs_u .- freqs_l + +# Also need the experimental narrowband spacing. +df_nb = 20.0 +# Now multiply each by that. +nb_pressure = pbs_pressure .* df_nb ./ df_pbs +nb_suction = pbs_suction .* df_nb ./ df_pbs +nb_alpha = pbs_alpha .* df_nb ./ df_pbs +nb_lblvs = pbs_lblvs .* df_nb ./ df_pbs +nb_teb = pbs_teb .* df_nb ./ df_pbs +nb_tip = pbs_tip .* df_nb ./ df_pbs + +# Now I want the SPL, which should just be this: +pref = 20e-6 +spl_pressure = 10 .* log10.(nb_pressure./(pref^2)) +spl_suction = 10 .* log10.(nb_suction./(pref^2)) +spl_alpha = 10 .* log10.(nb_alpha./(pref^2)) +spl_lblvs = 10 .* log10.(nb_lblvs./(pref^2)) +spl_teb = 10 .* log10.(nb_teb./(pref^2)) +spl_tip = 10 .* log10.(nb_tip./(pref^2)) + +# Now I should be able to compare to the BARC data. +# Need to read it in first. +data_pressure_barc = readdlm(joinpath(@__DIR__, "..", "..", "test", "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure24b-TBL-TE-pressure.csv"), ',') +freq_pressure_barc = data_pressure_barc[:, 1] +spl_pressure_barc = data_pressure_barc[:, 2] + +data_suction_barc = readdlm(joinpath(@__DIR__, "..", "..", "test", "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure24b-TBL-TE-suction.csv"), ',') +freq_suction_barc = data_suction_barc[:, 1] +spl_suction_barc = data_suction_barc[:, 2] + +data_separation_barc = readdlm(joinpath(@__DIR__, "..", "..", "test", "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure24b-separation.csv"), ',') +freq_separation_barc = data_separation_barc[:, 1] +spl_separation_barc = data_separation_barc[:, 2] + +data_lblvs_barc = readdlm(joinpath(@__DIR__, "..", "..", "test", "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure24b-LBLVS.csv"), ',') +freq_lblvs_barc = data_lblvs_barc[:, 1] +spl_lblvs_barc = data_lblvs_barc[:, 2] + +data_teb_barc = readdlm(joinpath(@__DIR__, "..", "..", "test", "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure24b-BVS.csv"), ',') +freq_teb_barc = data_teb_barc[:, 1] +spl_teb_barc = data_teb_barc[:, 2] + +data_tip_barc = readdlm(joinpath(@__DIR__, "..", "..", "test", "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure24b-tip_vortex_shedding.csv"), ',') +freq_tip_barc = data_tip_barc[:, 1] +spl_tip_barc = data_tip_barc[:, 2] + +# Now let's plot. +fig = Figure() +ax1 = fig[2, 1] = Axis(fig, xlabel="frequency, Hz", ylabel="SPL (dB Ref: 20 μPa), Δf = 20 Hz", xscale=log10, xticks=[10^3, 10^4], xminorticksvisible=true, xminorgridvisible=true, xminorticks=IntervalsBetween(9), yticks=10:10:70)#, aspect=3) + +s_pressure = scatter!(ax1, freq_pressure_barc, spl_pressure_barc, color=:blue, marker=:rtriangle) +s_suction = scatter!(ax1, freq_suction_barc, spl_suction_barc, color=:red, marker=:ltriangle) +s_separation = scatter!(ax1, freq_separation_barc, spl_separation_barc, color=:yellow, marker=:diamond) +s_lblvs = scatter!(ax1, freq_lblvs_barc, spl_lblvs_barc, color=:purple, marker=:rect) +s_blunt = scatter!(ax1, freq_teb_barc, spl_teb_barc, color=:green, marker=:star6) +s_tip = scatter!(ax1, freq_tip_barc, spl_tip_barc, color=:cyan, marker=:circle) + +l_pressure = lines!(ax1, freqs_obs, spl_pressure, color=:blue) +l_suction = lines!(ax1, freqs_obs, spl_suction, color=:red) +l_alpha = lines!(ax1, freqs_obs, spl_alpha, color=:yellow) +l_lblvs = lines!(ax1, freqs_obs, spl_lblvs, color=:purple) +l_teb = lines!(ax1, freqs_obs, spl_teb, color=:green) +l_tip = lines!(ax1, freqs_obs, spl_tip, color=:cyan) + +xlims!(ax1, 2e2, 6e4) +ylims!(ax1, 0.0, 50.0) + + +leg = Legend(fig[1, 1], [ + [s_pressure, l_pressure], + [s_suction, l_suction], + [s_separation, l_alpha], + [s_lblvs, l_lblvs], + [s_blunt, l_teb], + [s_tip, l_tip], + ], + [ + "TBLTE-Pressure", + "TBLTE-Suction", + "Separation", + "LBLVS", + "BVS", + "Tip", + ]; orientation=:horizontal, tellwidth=false, tellheight=true, nbanks=2) + +text!(ax1, 210, 44; text="markers: CCBlade.jl+BPM.jl\nlines: CCBlade.jl+AcousticAnalogies.jl") + +save("figure24b-spl-barc.png", fig) +``` +![](figure24b-spl-barc.png) + diff --git a/docs/src/sqa.md b/docs/src/sqa.md index 83c6b13b..9a811a82 100644 --- a/docs/src/sqa.md +++ b/docs/src/sqa.md @@ -21,7 +21,7 @@ F1A tests | 2 2 5.9s Test Summary: | Pass Total Time CCBlade private utils tests | 1 1 0.3s Test Summary: | Pass Total Time -CCBlade CompactSourceElement test | 12 12 3.4s +CCBlade CompactF1ASourceElement test | 12 12 3.4s Test Summary: | Pass Total Time ANOPP2 Comparison | 176 176 5.9s Test Summary: | Time @@ -48,7 +48,7 @@ Mathematically, we need to solve the equation R(t) = t - \left( \tau + \frac{|\vec{x}(t) - \vec{y}(τ)|}{c_0} \right) = 0 ``` -whereon +where * ``τ`` is the time the source has emitted an acoustic disturbance * ``t`` is the time the observer encounters the acoustic disturbance @@ -84,7 +84,7 @@ y = @SVector [-4.0, 3.0, 6.0] c0 = 2.0 dummy0 = 1.0 dummy3 = @SVector [0.0, 0.0, 0.0] -se = AcousticAnalogies.CompactSourceElement(dummy0, c0, dummy0, dummy0, y, dummy3, dummy3, dummy3, dummy3, dummy3, τ, dummy3) +se = AcousticAnalogies.CompactF1ASourceElement(dummy0, c0, dummy0, dummy0, y, dummy3, dummy3, dummy3, dummy3, dummy3, τ, dummy3) # Define a function that solves the advanced time equation using `nlsolve. function adv_time_nlsolve(se, obs) @@ -123,11 +123,11 @@ println("constant velocity observer, exact: $(t_exact), nlsorve: $(t_nlsolve), d Almost identical results, so things are good! ### Combine `F1AOutput` Tests -The function `f1a(se::CompactSourceElement, obs::AcousticObserver)` uses Farassat's formulation 1A to perform a prediction of the noise experienced by one observer `obs` due to one acoustic source `se`. +The function `noise(se::CompactF1ASourceElement, obs::AcousticObserver)` uses Farassat's formulation 1A to perform a prediction of the noise experienced by one observer `obs` due to one acoustic source `se`. Typically we will not have just one source, however. For example, the [guided example in the docs](@ref guided_example) uses 30 "source elements" to model each propeller blade. But we're interested in the acoustics experienced by `obs` due to **all** of the source elements, not just one. -So, we need to combine the output of `f1a` for one observer and all of the source elements. +So, we need to combine the output of `noise` for one observer and all of the source elements. In AcousticAnalogies.jl, this is done by interpolating the time history of each source element's acoustics (the "pressure time history") onto a common chunk of time, and then adding them up. No big deal. @@ -338,14 +338,14 @@ function doit() f0dot(τ) = [-fn, -sin(omega*τ)*fc, cos(omega*τ)*fc] f1dot(τ) = [0, -omega*cos(omega*τ)*fc, -omega*sin(omega*τ)*fc] u(τ) = y0dot(τ)./radii - sef1 = CompactSourceElement(rho, c0, dradii, Λ, y0dot, y1dot, nothing, nothing, f0dot, nothing, 0.0, u) + sef1 = CompactF1ASourceElement(rho, c0, dradii, Λ, y0dot, y1dot, nothing, nothing, f0dot, nothing, 0.0, u) t = 0.0 dt = period*0.5^4 τ0, pmi0, pdiff0, pdinf0 = f1_integrand(sef1, obs, t) - sef1a = CompactSourceElement(rho, c0, dradii, Λ, y0dot(τ0), y1dot(τ0), y2dot(τ0), y3dot(τ0), f0dot(τ0), f1dot(τ0), τ0, u(τ0)) - apth = f1a(sef1a, obs) + sef1a = CompactF1ASourceElement(rho, c0, dradii, Λ, y0dot(τ0), y1dot(τ0), y2dot(τ0), y3dot(τ0), f0dot(τ0), f1dot(τ0), τ0, u(τ0)) + apth = noise(sef1a, obs) err_prev_pm = nothing err_prev_pd = nothing @@ -443,6 +443,8 @@ save("anopp2_comparison.png", fig) The difference between the two codes' predictions is very small (less than 1% error). +### Brooks, Pope & Marcolini Tests + ## Signed Commits The AcousticAnalogies.jl GitHub repository requires all commits to the `main` branch to be signed. See the [GitHub docs on signing commits](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) for more information. diff --git a/docs/src/writevtk_support.md b/docs/src/writevtk_support.md index ffec45bc..8b8b01de 100644 --- a/docs/src/writevtk_support.md +++ b/docs/src/writevtk_support.md @@ -240,7 +240,7 @@ function af_xrotor(alpha, Re, Mach, config::XROTORAirfoilConfig) end ``` -AcousticAnalogies.jl can write out [`CompactSourceElement`](@ref) `structs` to VTK +AcousticAnalogies.jl can write out [`CompactF1ASourceElement`](@ref) `structs` to VTK files, allowing us to easily visualize the state and motion of the acoustic sources in popular visualization tools (e.g. [ParaView](https://www.paraview.org/)). This is very useful for checking that @@ -305,7 +305,8 @@ outs = solve.(Ref(rotor), sections, ops) bpp = 60/(rpm*B) period = 2*bpp num_source_times = 64 -ses = source_elements_ccblade(rotor, sections, ops, outs, fill(cs_area_over_chord_squared, length(radii)), period, num_source_times) +positive_x_rotation = true +ses = f1a_source_elements_ccblade(rotor, sections, ops, outs, fill(cs_area_over_chord_squared, length(radii)), period, num_source_times, positive_x_rotation) @show size(ses) ``` `ses` is an array of source elements of shape `(num_source_times, num_radial, diff --git a/src/AcousticAnalogies.jl b/src/AcousticAnalogies.jl index 37b94d70..b7f926e7 100644 --- a/src/AcousticAnalogies.jl +++ b/src/AcousticAnalogies.jl @@ -1,37 +1,72 @@ module AcousticAnalogies -using AcousticMetrics -using CCBlade -using ConcreteStructs: @concrete +using AcousticMetrics: AcousticMetrics +using CCBlade: CCBlade using CSV: CSV using DataFrames: DataFrames -using FLOWMath: akima, linear, ksmax, dot_cs_safe, norm_cs_safe -using Formatting: format +using FillArrays: Fill +using FLOWMath: akima, linear, ksmax, norm_cs_safe, dot_cs_safe, atan_cs_safe, abs_cs_safe +using FlexiMaps: mapview +using Format: format, FormatExpr using JuliennedArrays: JuliennedArrays -using KinematicCoordinateTransformations +using KinematicCoordinateTransformations: KinematicTransformation, SteadyRotXTransformation, ConstantVelocityTransformation, compose using LinearAlgebra: cross, norm, mul! -using FlexiMaps: mapview -using StaticArrays -using WriteVTK +using Meshes: Meshes +using StaticArrays: @SVector +using WriteVTK: WriteVTK include("utils.jl") export get_dradii -include("core.jl") -export CompactSourceElement -export AcousticObserver, StationaryAcousticObserver, ConstVelocityAcousticObserver -export F1AOutput, F1APressureTimeHistory +include("abstract_source_elements.jl") +export AbstractCompactSourceElement + +include("observers.jl") +export AbstractAcousticObserver, StationaryAcousticObserver, ConstVelocityAcousticObserver + +include("advance_time.jl") export adv_time -export f1a + +include("boundary_layers.jl") +export AbstractBoundaryLayer, TrippedN0012BoundaryLayer, UntrippedN0012BoundaryLayer + +include("f1a.jl") +export CompactF1ASourceElement +export F1AOutput, F1APressureTimeHistory +export noise export common_obs_time export combine!, combine +include("abstract_broadband.jl") + +include("tbl_te.jl") +export TBLTESourceElement + +include("lbl_vs.jl") +export LBLVSSourceElement + +include("tip_vortex.jl") +export AbstractTipAlphaCorrection, NoTipAlphaCorrection, BPMTipAlphaCorrection, BMTipAlphaCorrection, SmoothBMTipAlphaCorrection +export AbstractBladeTip, RoundedTip, FlatTip +export TipVortexSourceElement + +include("teb_vs.jl") +export TEBVSSourceElement + +include("combined_broadband.jl") +export CombinedNoTipBroadbandSourceElement, CombinedWithTipBroadbandSourceElement +export pbs_suction, pbs_pressure, pbs_alpha, pbs_teb, pbs_tip + include("ccblade_helpers.jl") -export source_elements_ccblade +export f1a_source_elements_ccblade, tblte_source_elements_ccblade, lblvs_source_elements_ccblade, tebvs_source_elements_ccblade, tip_vortex_source_elements_ccblade, combined_broadband_source_elements_ccblade + +include("bpm_test_utils.jl") include("openfast_helpers.jl") -export read_openfast_file +export read_openfast_file, OpenFASTData include("writevtk.jl") +include("deprecated.jl") + end # module diff --git a/src/abstract_broadband.jl b/src/abstract_broadband.jl new file mode 100644 index 00000000..ff318f48 --- /dev/null +++ b/src/abstract_broadband.jl @@ -0,0 +1,321 @@ +abstract type AbstractDirectivity end +struct BPMDirectivity <: AbstractDirectivity end +struct BrooksBurleyDirectivity <: AbstractDirectivity end + +abstract type AbstractBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,TDoppler} <: AbstractCompactSourceElement end + +""" + doppler_factor(se::AbstractBroadbandSourceElement, obs::AbstractAcousticObserver, t_obs) + +Calculate the Doppler shift factor for noise emitted by source element `se` and recieved by observer `obs` at time `t_obs`, i.e. the ratio between an observer frequency `f` and emitted frequency `f_0`. + +The correct value for `t_obs` can be found using [`adv_time`](@ref). +""" +function doppler_factor(se::AbstractBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,true}, obs::AbstractAcousticObserver, t_obs) where {TDirect,TUInduction,TMachCorrection} + # Location of the observer at the observer time. + x_obs = obs(t_obs) + + # Also need the speed of sound. + c = speed_of_sound(se) + + # Get a unit vector pointing from the source position at the source time to the observer position at the observer time. + rv = x_obs .- position(se) + r = norm_cs_safe(rv) + rhat = rv/r + + # So, now, if I dot the source velocity with `rhat`, that would give me the component of velocity of the source in the direction of the observer, positive if moving toward it, negative if moving away. + v_src = dot_cs_safe(velocity(se), rhat) + + # And, if I dot the observer velocity `rhat`, that will give me the component of velocity of the observer in the direction of the source, positive if moving *away* from it, negative if moving toward. + v_obs = dot_cs_safe(velocity(t_obs, obs), rhat) + + # Now we can get the factor. + factor = (1 - v_obs/c) / (1 - v_src/c) + + return factor +end + +function doppler_factor(se::AbstractBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,false}, obs::AbstractAcousticObserver, t_obs) where {TDirect,TUInduction,TMachCorrection} + return 1 +end + +""" + doppler_factor(se::AbstractBroadbandSourceElement, obs::AbstractAcousticObserver) + +Calculate the Doppler shift factor for noise emitted by source element `se` and recieved by observer `obs`, i.e. the ratio between an observer frequency `f` and emitted frequency `f_0`. + +The correct value for `t_obs` will be found using [`adv_time`](@ref) internally. +""" +function doppler_factor(se::AbstractBroadbandSourceElement, obs::AbstractAcousticObserver) + # Do the advanced time calculation. + t_obs = adv_time(se, obs) + + return doppler_factor(se, obs, t_obs) +end + +function directivity(se::AbstractBroadbandSourceElement{BrooksBurleyDirectivity}, x_obs, top_is_suction) + # Position vector from source to observer. + rv = x_obs .- se.y0dot + + # Distance from source to observer. + r_er = norm_cs_safe(rv) + + # Unit vector normal to both the span and chord directions. + # Does the order matter? + # Doesn't look like it, since we're only using it to find z_er, which we square. + # But let's do it right, anyway! + # if se.chord_cross_span_to_get_top_uvec + # # But, if the angle of attack is negative, then the "top" of the airfoil (which is normally the suction side) is actually the suction side. + # if top_is_suction + # z_uvec_tmp = cross(se.chord_uvec, se.span_uvec) + # else + # z_uvec_tmp = cross(se.span_uvec, se.chord_uvec) + # end + # else + # if top_is_suction + # z_uvec_tmp = cross(se.span_uvec, se.chord_uvec) + # else + # z_uvec_tmp = cross(se.chord_uvec, se.span_uvec) + # end + # end + z_uvec_tmp = cross(se.chord_uvec, se.span_uvec)*ifelse(se.chord_cross_span_to_get_top_uvec, 1, -1)*ifelse(top_is_suction, 1, -1) + z_uvec = z_uvec_tmp / norm_cs_safe(z_uvec_tmp) + + # Component of rv along the chord line (see Figure 11 in Brooks and Burley AIAA 2001-2210). + x_er = dot_cs_safe(rv, se.chord_uvec) + + # Component of rv along the span line (see Figure 11 in Brooks and Burley AIAA 2001-2210). + y_er = dot_cs_safe(rv, se.span_uvec) + + # Component of rv in the direction normal to both span and chord (see Figure 11 in Brooks and Burley AIAA 2001-2210). + z_er = dot_cs_safe(rv, z_uvec) + + # Need to find sin(Θ_er)^2, where Θ_er = acos(x_er/r_er), equation (21) from Brooks and Burley AIAA 2001-2210. + # But sin(acos(x_er/r_er)) = sqrt(r_er^2 - x_er^2)/r_er, and so sin(Θ_er)^2 = (r_er^2 - x_er^2)/r_er^2 + sin2Θer = (r_er^2 - x_er^2)/r_er^2 + + # Need to find sin(Φ_er)^2, where Φ_er = acos(y_er/sqrt(y_er^2 + z_er^2)), equation (21) from Brooks and Burley AIAA 2001-2210. + # But sin(acos(y_er/sqrt(y_er^2 + z_er^2))) = z_er/sqrt(y_er^2 + z_er^2), and so sin(Φ_er)^2 = z_er^2/(y_er_^2 + z_er^2). + sin2Φer = (z_er^2)/(y_er^2 + z_er^2) + + # Need to find 2*sin(0.5*Θ_er)^2, where Θ_er = acos(x_er/r_er), equation (21) from Brooks and Burley AIAA 2001-2210. + # But there is a half-angle identity that says sin(θ/2)^2 = 0.5*(1 - cos(θ)). + # So I actually want 2*sin(0.5*Θ_er)^2 = 2*0.5*(1 - cos(Θ_er)) = (1 - cos(Θ_er)). + # But I can substitute in Θ_er = acos(x_er/r_er) and get 2*sin(0.5*Θ_er)^2 = 1 - x_er/r_er. + twosin2halfΘer = 1 - x_er/r_er + + # Now just need the denominator: (1 - M_tot*cos(ξR))^4. + # M_tot is the "total" velocity from... hmm... what perspective? + # Let's see... it looks like it's suppose to be from the fluid, aka the global frame. + # The definition is Brooks and Burley AIAA 2001-2210, equation (14): + # + # V_tot = V - V_wt - V_ind + # + # where + # + # * V is the velocity due to the rotation of the blade element + # * V_wt is the wind tunnel velocity, which is positive when it goes against the motion of the blade element. + # * V_ind is "the induced velocity due to the near and far wake of the rotor," and appears to be positive in roughly the thrust direction. + # + # So if I calculate V - V_wt, that's the "actual" velocity of the blade element, i.e., the velocity of the blade element relative to the fluid far away from the blade element, since it doesn't include the induced velocity. + # That's what I usually think of as the "actual" velocity, since it's what a stationary observer would observe on a calm day. + # But when we add in the induced velocity, I think what we're finding is the velocity of the blade element relative to the nearfield velocity. + # Cool. + # But does that mean I add or subtract `se.y1dot_fluid` from `se.y1dot`? + # Well, let's think about that. + # First, let's say I start with stuff in the blade-fixed frame. + # And let's say I'm imagining that, from the global frame, I'm assuming the + # blade element is moving in the positive x direction, initially aligned + # with the y axis + # So I think all I need to do is just use se.y1dot_fluid + se.y1dot. + # Now, cos(ξ_r) is defined by equation (18) in Brooks and Burley AIAA 2001-2210, which is the angle between the radiation vector (rv here) and the total velocity (se.y1dot here). + # But I can simplify that by just finding the unit radiation vector, then dotting that with the velocity vector, and dividing by c0. + + # Unit radiation vector. + r_uvec = rv./r_er + # Equation 14 from Brooks and Burley AIAA 2001-2210. + Vtotal = se.y1dot - se.y1dot_fluid + # Mach number vectory in the direction of the radiation vector. + Mtotcosξr = dot_cs_safe(Vtotal, r_uvec)/se.c0 + + # Convective amplification factor for the two directivity functions. + conv_amp = 1/(1 - Mtotcosξr)^4 + + # Now I can finally find the directivity function! + # Equation (19) from Brooks and Burley AIAA 2001-2210. + # Dl = (sin2Θer*sin2Φer)/(1 - Mtotcosξr)^4 + Dl = (sin2Θer*sin2Φer)*conv_amp + + # Now I can finally find the directivity function! + # Equation (20) from Brooks and Burley AIAA 2001-2210. + # Dh = (twosin2halfΘer*sin2Φer)/(1 - Mtotcosξr)^4 + Dh = (twosin2halfΘer*sin2Φer)*conv_amp + + return r_er, Dl, Dh +end + +function directivity(se::AbstractBroadbandSourceElement{BPMDirectivity}, x_obs, top_is_suction) + # Position vector from source to observer. + rv = x_obs .- se.y0dot + + # Distance from source to observer. + r_er = norm_cs_safe(rv) + + # So, the BPM report uses the local flow velocity, not the chord line, to define the x direction. + # So, I want to get a unit vector in that direction. + # Should it include induction? + # It won't matter for comparing to the data in the BPM report, since the flow including and excluding induction would be in the same direction. + # In the BPM report Appendix B, the x direction is defined as the opposite of the motion of the source element/flat plate, so I guess I won't use induction. + # But I want the velocity to be normal to the span direction, so let's remove_that. + # So, want the x direction to be opposite the velocity of the source element. + x_vec_tmp1 = -se.y1dot + # Then we want to remove any part of the velocity in the direction of the span. + x_vec_tmp2 = x_vec_tmp1 - dot_cs_safe(x_vec_tmp1, se.span_uvec)*x_vec_tmp1 + # Now make it a unit vector: + x_uvec = x_vec_tmp2 / norm_cs_safe(x_vec_tmp2) + + # Unit vector normal to both the span and chord directions. + # Does the order matter? + # Doesn't look like it, since we're only using it to find z_er, which we square. + # But it's supposed to be pointing from the pressure to the suction side, which we can figure out, so let's do it the right way. + # if se.chord_cross_span_to_get_top_uvec + # if top_is_suction + # z_uvec_tmp = cross(x_uvec, se.span_uvec) + # else + # z_uvec_tmp = cross(se.span_uvec, x_uvec) + # end + # else + # if top_is_suction + # z_uvec_tmp = cross(se.span_uvec, x_uvec) + # else + # z_uvec_tmp = cross(x_uvec, se.span_uvec) + # end + # end + z_uvec_tmp = cross(x_uvec, se.span_uvec)*ifelse(se.chord_cross_span_to_get_top_uvec, 1, -1)*ifelse(top_is_suction, 1, -1) + z_uvec = z_uvec_tmp / norm_cs_safe(z_uvec_tmp) + + # Component of rv along the chord line (see Figure B3 in the BPM report). + x_er = dot_cs_safe(rv, x_uvec) + + # Component of rv along the span line (see Figure B3 the BPM report). + y_er = dot_cs_safe(rv, se.span_uvec) + + # Component of rv in the direction normal to both span and chord (see Figure 11 in Brooks and Burley AIAA 2001-2210). + z_er = dot_cs_safe(rv, z_uvec) + + # Need to find sin(Θ_er)^2, where Θ_er = acos(x_er/r_er), equation (21) from Brooks and Burley AIAA 2001-2210. + # But sin(acos(x_er/r_er)) = sqrt(r_er^2 - x_er^2)/r_er, and so sin(Θ_er)^2 = (r_er^2 - x_er^2)/r_er^2 + sin2Θer = (r_er^2 - x_er^2)/r_er^2 + + # Need to find sin(Φ_er)^2, where Φ_er = acos(y_er/sqrt(y_er^2 + z_er^2)), equation (21) from Brooks and Burley AIAA 2001-2210. + # But sin(acos(y_er/sqrt(y_er^2 + z_er^2))) = z_er/sqrt(y_er^2 + z_er^2), and so sin(Φ_er)^2 = z_er^2/(y_er_^2 + z_er^2). + sin2Φer = (z_er^2)/(y_er^2 + z_er^2) + + # Need to find 2*sin(0.5*Θ_er)^2, where Θ_er = acos(x_er/r_er), equation (21) from Brooks and Burley AIAA 2001-2210. + # But there is a half-angle identity that says sin(θ/2)^2 = 0.5*(1 - cos(θ)). + # So I actually want 2*sin(0.5*Θ_er)^2 = 2*0.5*(1 - cos(Θ_er)) = (1 - cos(Θ_er)). + # But I can substitute in Θ_er = acos(x_er/r_er) and get 2*sin(0.5*Θ_er)^2 = 1 - x_er/r_er. + twosin2halfΘer = 1 - x_er/r_er + + # Now just need the denominator: (1 - M_tot*cos(ξR))^4. + # M_tot is the "total" velocity from... hmm... what perspective? + # Let's see... it looks like it's suppose to be from the fluid, aka the global frame. + # The definition is Brooks and Burley AIAA 2001-2210, equation (14): + # + # V_tot = V - V_wt - V_ind + # + # where + # + # * V is the velocity due to the rotation of the blade element + # * V_wt is the wind tunnel velocity, which is positive when it goes against the motion of the blade element. + # * V_ind is "the induced velocity due to the near and far wake of the rotor," and appears to be positive in roughly the thrust direction. + # + # So if I calculate V - V_wt, that's the "actual" velocity of the blade element, i.e., the velocity of the blade element relative to the fluid far away from the blade element, since it doesn't include the induced velocity. + # That's what I usually think of as the "actual" velocity, since it's what a stationary observer would observe on a calm day. + # But when we add in the induced velocity, I think what we're finding is the velocity of the blade element relative to the nearfield velocity. + # Cool. + # But does that mean I add or subtract `se.y1dot_fluid` from `se.y1dot`? + # Well, let's think about that. + # First, let's say I start with stuff in the blade-fixed frame. + # And let's say I'm imagining that, from the global frame, I'm assuming the + # blade element is moving in the positive x direction, initially aligned + # with the y axis + # So I think all I need to do is just use se.y1dot_fluid + se.y1dot. + # Now, cos(ξ_r) is defined by equation (18) in Brooks and Burley AIAA 2001-2210, which is the angle between the radiation vector (rv here) and the total velocity (se.y1dot here). + # But I can simplify that by just finding the unit radiation vector, then dotting that with the velocity vector, and dividing by c0. + + # Unit radiation vector. + r_uvec = rv./r_er + # For the BPM directivity function, the velocity/Mach number doesn't include induction. + Vtotal = se.y1dot + # Mach number vectory in the direction of the radiation vector. + Mtotcosξr = dot_cs_safe(Vtotal, r_uvec)/se.c0 + + # Convective amplification factor for the low-freqency directivity function. + conv_amp_l = 1/(1 - Mtotcosξr)^4 + + # The BPM high-frequency convective amplification factor is a bit different. + # It has a factor (M - M_c)*cos(Θ_er), which, in the more general coordinate system of Brooks & Burley would be -(M - M_c)*cos(ξ_r). + # So, the `M` is the speed of the blade element without induction, and `M_c` is the velocity of the blade element including induction. + # So `M_c = se.y1dot - se.y1dot_fluid` and then `M - M_c = se.y1dot - (se.y1dot - se.y1dot_fluid) = se.y1dot_fluid. + # And so what we'd want to do is this: + M_minus_M_ccosξr = dot_cs_safe(se.y1dot_fluid, r_uvec)/se.c0 + conv_amp_h = 1/((1 - Mtotcosξr)*(1 - M_minus_M_ccosξr)^2) + + # Now I can finally find the directivity function! + # Equation (B2) from the BPM report. + Dl = (sin2Θer*sin2Φer)*conv_amp_l + + # Now I can finally find the directivity function! + # Equation (B1) from the BPM report. + Dh = (twosin2halfΘer*sin2Φer)*conv_amp_h + + return r_er, Dl, Dh +end + +function angle_of_attack(se::AbstractBroadbandSourceElement) + # Find the total velocity of the fluid from the perspective of the blade element, which is just the total velocity of the blade element from the perspective of the fluid with the sign switched. + # Vtotal = -(se.y1dot - se.y1dot_fluid) + Vtotal = se.y1dot_fluid - se.y1dot + + # To get the angle of attack, I need to find the components of the velocity in the chordwise direction, and the direction normal to both the chord and span. + # So, first need to get a vector normal to both the chord and span, pointing from pressure side to suction side. + normal_uvec_tmp = ifelse(se.chord_cross_span_to_get_top_uvec, + cross(se.chord_uvec, se.span_uvec), + cross(se.span_uvec, se.chord_uvec)) + normal_uvec = normal_uvec_tmp ./ norm_cs_safe(normal_uvec_tmp) + + # Now get the component of velocity in the chord_uvec and normal_uvec directions. + V_chordwise = dot_cs_safe(Vtotal, se.chord_uvec) + V_normal = dot_cs_safe(Vtotal, normal_uvec) + + # Now we can find the angle of attack. + alphastar = atan_cs_safe(V_normal, V_chordwise) + # alphastar = atan(V_normal, V_chordwise) + + return alphastar +end + +function speed_normal_to_span(se::AbstractBroadbandSourceElement{TDirect,true}) where {TDirect} + # Find the total velocity of the fluid including induction, from the perspective of the blade element, which is just the total velocity of the blade element from the perspective of the fluid with the sign switched. + Vtotal = se.y1dot_fluid - se.y1dot + # Find the component of the velocity in the direction of the span. + Vspan = dot_cs_safe(Vtotal, se.span_uvec)*se.span_uvec + # Subtract that from the total velocity to get the velocity normal to the span, then get the norm for the speed normal to span. + return norm_cs_safe(Vtotal - Vspan) +end + +function speed_normal_to_span(se::AbstractBroadbandSourceElement{TDirect,false}) where {TDirect} + # Find the total velocity of the fluid, not including induction, from the perspective of the blade element, which is just the total velocity of the blade element from the perspective of the fluid with the sign switched. + Vtotal = -se.y1dot + # Find the component of the velocity in the direction of the span. + Vspan = dot_cs_safe(Vtotal, se.span_uvec)*se.span_uvec + # Subtract that from the total velocity to get the velocity normal to the span, then get the norm for the speed normal to span. + return norm_cs_safe(Vtotal - Vspan) +end + +function noise(se::AbstractBroadbandSourceElement, obs::AbstractAcousticObserver, freqs::AcousticMetrics.AbstractProportionalBands{3, :center}) + t_obs = adv_time(se, obs) + return noise(se, obs, t_obs, freqs) +end + diff --git a/src/abstract_source_elements.jl b/src/abstract_source_elements.jl new file mode 100644 index 00000000..35dbddd9 --- /dev/null +++ b/src/abstract_source_elements.jl @@ -0,0 +1,36 @@ +abstract type AbstractCompactSourceElement end + +""" + velocity(se::AbstractCompactSourceElement) + +Return the current velocity of `se`. +""" +@inline velocity(se::AbstractCompactSourceElement) = se.y1dot + +""" + source_time(se::AbstractCompactSourceElement) + +Return the source time of `se`. +""" +@inline source_time(se::AbstractCompactSourceElement) = se.τ + +""" + orientation(se::AbstractCompactSourceElement) + +Return a length-3 unit vector indicating the spanwise orientation of `se`. +""" +@inline orientation(se::AbstractCompactSourceElement) = se.span_uvec + +""" + position(se::AbstractCompactSourceElement) + +Return a length-3 vector indicating the position of `se`. +""" +@inline position(se::AbstractCompactSourceElement) = se.y0dot + +""" + speed_of_sound(se::AbstractCompactSourceElement) + +Return the ambient speed of sound associated with `se`. +""" +@inline speed_of_sound(se) = se.c0 diff --git a/src/advance_time.jl b/src/advance_time.jl new file mode 100644 index 00000000..c085d3be --- /dev/null +++ b/src/advance_time.jl @@ -0,0 +1,47 @@ +""" + adv_time(se::AbstractCompactSourceElement, obs::AbstractAcousticObserver) + +Calculate the time an acoustic wave emmited by source `se` at time `se.τ` is +recieved by observer `obs`. +""" +adv_time(se::AbstractCompactSourceElement, obs::AbstractAcousticObserver) + +function adv_time(se::AbstractCompactSourceElement, obs::StationaryAcousticObserver) + τ = source_time(se) + rv = obs(τ) .- position(se) + r = norm_cs_safe(rv) + t = τ + r/speed_of_sound(se) + return t +end + +function adv_time(se::AbstractCompactSourceElement, obs::ConstVelocityAcousticObserver) + # Source time of the source element. + τ = source_time(se) + + # Ambient speed of sound of the source element. + c0 = speed_of_sound(se) + + # Location of the observer at the source time. + x = obs(τ) + + # Vector from the source to the observer at the source time. + rv = x .- position(se) + + # Distance from the source to the observer at the source time. + r = norm_cs_safe(rv) + + # Speed of the observer divided by speed of sound. + Mo = norm_cs_safe(obs.v)/c0 + + # Unit vector pointing from the source to the observer. + rhat = rv/r + + # Velocity of observer dotted with rhat at the source time. + Mor = dot_cs_safe(obs.v, rhat)/c0 + + # Now get the observer time. + t = τ + r/c0*((Mor + sqrt(Mor^2 + 1 - Mo^2))/(1 - Mo^2)) + + return t +end + diff --git a/src/boundary_layers.jl b/src/boundary_layers.jl new file mode 100644 index 00000000..4eb7dede --- /dev/null +++ b/src/boundary_layers.jl @@ -0,0 +1,233 @@ +abstract type AbstractBoundaryLayer end + +struct TrippedN0012BoundaryLayer{TAlphaStall} <: AbstractBoundaryLayer + alphastar0::TAlphaStall +end + +TrippedN0012BoundaryLayer() = TrippedN0012BoundaryLayer(12.5*pi/180) + +struct UntrippedN0012BoundaryLayer{TAlphaStall} <: AbstractBoundaryLayer + alphastar0::TAlphaStall +end + +UntrippedN0012BoundaryLayer() = UntrippedN0012BoundaryLayer(12.5*pi/180) + +struct ITrip1N0012BoundaryLayer{TAlphaStall} <: AbstractBoundaryLayer + alphastar0::TAlphaStall +end + +ITrip1N0012BoundaryLayer() = ITrip1N0012BoundaryLayer(12.5*pi/180) + +struct ITrip2N0012BoundaryLayer{TAlphaStall} <: AbstractBoundaryLayer + alphastar0::TAlphaStall +end + +ITrip2N0012BoundaryLayer() = ITrip2N0012BoundaryLayer(12.5*pi/180) + +struct ITrip3N0012BoundaryLayer{TAlphaStall} <: AbstractBoundaryLayer + alphastar0::TAlphaStall +end + +ITrip3N0012BoundaryLayer() = ITrip3N0012BoundaryLayer(12.5*pi/180) + +alpha_stall(bl::AbstractBoundaryLayer, Re_c) = bl.alphastar0 +alpha_zerolift(bl::AbstractBoundaryLayer) = zero(bl.alphastar0) +is_top_suction(bl::AbstractBoundaryLayer, alphastar) = alphastar >= alpha_zerolift(bl) + +function bl_thickness_0(::TrippedN0012BoundaryLayer, Re_c) + # Equation 2 from the BPM report. + logRe_c = log10(Re_c) + return 10^(1.892 - 0.9045*logRe_c + 0.0596*logRe_c^2) +end + +function disp_thickness_0(::Union{TrippedN0012BoundaryLayer,ITrip1N0012BoundaryLayer}, Re_c) + # Equation 3 from the BPM report. + if Re_c ≤ 0.3e6 + return 0.0601*Re_c^(-0.114) + else + logRe_c = log10(Re_c) + return 10^(3.411 - 1.5397*logRe_c + 0.1059*logRe_c^2) + end +end + +function disp_thickness_0(::ITrip2N0012BoundaryLayer, Re_c) + # Equation 3 from the BPM report, multiplied by 0.6 as is done in the code listing in the BPM report appendix. + if Re_c ≤ 0.3e6 + return 0.6*0.0601*Re_c^(-0.114) + else + logRe_c = log10(Re_c) + return 0.6*10^(3.411 - 1.5397*logRe_c + 0.1059*logRe_c^2) + end +end + +function bl_thickness_0(::Union{UntrippedN0012BoundaryLayer,ITrip1N0012BoundaryLayer,ITrip3N0012BoundaryLayer}, Re_c) + # Equation 5 from the BPM report. + logRe_c = log10(Re_c) + return 10^(1.6569 - 0.9045*logRe_c + 0.0596*logRe_c^2) +end + +function bl_thickness_0(::ITrip2N0012BoundaryLayer, Re_c) + # Equation 5 from the BPM report, multiplied by 0.6 as is done in the code listing in the BPM report appendix. + logRe_c = log10(Re_c) + return 0.6*10^(1.6569 - 0.9045*logRe_c + 0.0596*logRe_c^2) +end + +function disp_thickness_0(::Union{UntrippedN0012BoundaryLayer,ITrip3N0012BoundaryLayer}, Re_c) + # Equation 6 from the BPM report. + logRe_c = log10(Re_c) + return 10^(3.0187 - 1.5397*logRe_c + 0.1059*logRe_c^2) +end + +function _bl_thickness_p(::Union{TrippedN0012BoundaryLayer,UntrippedN0012BoundaryLayer,ITrip1N0012BoundaryLayer,ITrip2N0012BoundaryLayer,ITrip3N0012BoundaryLayer}, alphastar) + # Equation 8 from the BPM report. + alphastar_deg = alphastar*180/pi + return 10^(-0.04175*alphastar_deg + 0.00106*alphastar_deg^2) +end + +function _disp_thickness_p(::Union{TrippedN0012BoundaryLayer,UntrippedN0012BoundaryLayer,ITrip1N0012BoundaryLayer,ITrip2N0012BoundaryLayer}, alphastar) + # Equation 9 from the BPM report. + alphastar_deg = alphastar*180/pi + return 10^(-0.0432*alphastar_deg + 0.00113*alphastar_deg^2) +end + +function _disp_thickness_p(::ITrip3N0012BoundaryLayer, alphastar) + # Equation 9 from the BPM report, multiplied by 1.48 as is done in the BPM report appendix. + alphastar_deg = alphastar*180/pi + return 1.48*10^(-0.0432*alphastar_deg + 0.00113*alphastar_deg^2) +end + +function _bl_thickness_s(::TrippedN0012BoundaryLayer, alphastar) + T = typeof(alphastar) + # Equation 11 from the BPM report. + # The report defines the suction-side boundary layer parameters for alphastar values from 0° to 25°. + # But what about negative angles of attack? + # The NACA0012 airfoil is symmetric, but if the angle of attack goes negative, I guess the pressure and suction sides would switch. + # So I'll check that the angle of attack is always positive here. + alphastar_deg = alphastar*180/pi + if alphastar_deg < 0 + return T(NaN) + elseif alphastar_deg ≤ 5 + return 10^(0.0311*alphastar_deg) + elseif alphastar_deg ≤ 12.5 + return 0.3468*10^(0.1231*alphastar_deg) + elseif alphastar_deg ≤ 25 + return 5.718*10^(0.0258*alphastar_deg) + else + # What should I do for angles of attack greater than 25°? + # Maybe just keep the same thickness? + return 5.718*10^(0.0258*25*pi/180)*one(T) + end +end + +function _disp_thickness_s(::Union{TrippedN0012BoundaryLayer,ITrip1N0012BoundaryLayer}, alphastar) + T = typeof(alphastar) + # Equation 12 from the BPM report. + alphastar_deg = alphastar*180/pi + if alphastar_deg < 0 + # throw(DomainError(alphastar, "negative alphastar argument invalid")) + return T(NaN) + elseif alphastar_deg ≤ 5 + return 10^(0.0679*alphastar_deg) + elseif alphastar_deg ≤ 12.5 + return 0.381*10^(0.1516*alphastar_deg) + elseif alphastar_deg ≤ 25 + return 14.296*10^(0.0258*alphastar_deg) + else + # What should I do for angles of attack greater than 25°? + # Maybe just keep the same thickness? + return 14.296*10^(0.0258*25)*one(T) + end +end + +function _bl_thickness_s(::Union{UntrippedN0012BoundaryLayer,ITrip1N0012BoundaryLayer,ITrip2N0012BoundaryLayer,ITrip3N0012BoundaryLayer}, alphastar) + T = typeof(alphastar) + # Equation 14 from the BPM report. + alphastar_deg = alphastar*180/pi + if alphastar_deg < 0 + # throw(DomainError(alphastar, "negative alphastar argument invalid")) + return T(NaN) + elseif alphastar_deg ≤ 7.5 + return 10^(0.03114*alphastar_deg) + elseif alphastar_deg ≤ 12.5 + return 0.0303*10^(0.2336*alphastar_deg) + elseif alphastar_deg ≤ 25 + return 12*10^(0.0258*alphastar_deg) + else + # What should I do for angles of attack greater than 25°? + # Maybe just keep the same thickness? + return 12*10^(0.0258*25*pi/180)*one(T) + end +end + +function _disp_thickness_s(::Union{UntrippedN0012BoundaryLayer,ITrip2N0012BoundaryLayer,ITrip3N0012BoundaryLayer}, alphastar) + T = typeof(alphastar) + # Equation 15 from the BPM report. + alphastar_deg = alphastar*180/pi + if alphastar_deg < 0 + # throw(DomainError(alphastar, "negative alphastar argument invalid")) + return T(NaN) + elseif alphastar_deg ≤ 7.5 + return 10^(0.0679*alphastar_deg) + elseif alphastar_deg ≤ 12.5 + return 0.0162*10^(0.3066*alphastar_deg) + elseif alphastar_deg ≤ 25 + return 52.42*10^(0.0258*alphastar_deg) + else + # What should I do for angles of attack greater than 25°? + # Maybe just keep the same thickness? + return 52.42*10^(0.0258*25)*one(T) + end +end + +function _disp_thickness_top(bl::Union{TrippedN0012BoundaryLayer,UntrippedN0012BoundaryLayer,ITrip1N0012BoundaryLayer,ITrip2N0012BoundaryLayer,ITrip3N0012BoundaryLayer}, alphastar) + # Switch sign on alphastar and call the "opposite" `disp_thickness_*` routine if the top surface isn't the suction surface. + return ifelse(is_top_suction(bl, alphastar), _disp_thickness_s(bl, alphastar), _disp_thickness_p(bl, -alphastar)) +end + +function _disp_thickness_bot(bl::Union{TrippedN0012BoundaryLayer,UntrippedN0012BoundaryLayer,ITrip1N0012BoundaryLayer,ITrip2N0012BoundaryLayer,ITrip3N0012BoundaryLayer}, alphastar) + return ifelse(is_top_suction(bl, alphastar), _disp_thickness_p(bl, alphastar), _disp_thickness_s(bl, -alphastar)) +end + +function _bl_thickness_top(bl::Union{TrippedN0012BoundaryLayer,UntrippedN0012BoundaryLayer,ITrip1N0012BoundaryLayer,ITrip2N0012BoundaryLayer,ITrip3N0012BoundaryLayer}, alphastar) + # Switch sign on alphastar and call the "opposite" `disp_thickness_*` routine if the top surface isn't the suction surface. + return ifelse(is_top_suction(bl, alphastar), _bl_thickness_s(bl, alphastar), _bl_thickness_p(bl, -alphastar)) +end + +function _bl_thickness_bot(bl::Union{TrippedN0012BoundaryLayer,UntrippedN0012BoundaryLayer,ITrip1N0012BoundaryLayer,ITrip2N0012BoundaryLayer,ITrip3N0012BoundaryLayer}, alphastar) + return ifelse(is_top_suction(bl, alphastar), _bl_thickness_p(bl, alphastar), _bl_thickness_s(bl, -alphastar)) +end + +function disp_thickness_bot(bl::AbstractBoundaryLayer, Re_c, alphastar) + # (δ^*_p/δ^*_0)*(δ^*_0/c) + return _disp_thickness_bot(bl, alphastar)*disp_thickness_0(bl, Re_c) +end + +function disp_thickness_top(bl::AbstractBoundaryLayer, Re_c, alphastar) + return _disp_thickness_top(bl, alphastar)*disp_thickness_0(bl, Re_c) +end + +function disp_thickness_s(bl::AbstractBoundaryLayer, Re_c, alphastar) + return ifelse(is_top_suction(bl, alphastar), disp_thickness_top(bl, Re_c, alphastar), disp_thickness_bot(bl, Re_c, alphastar)) +end + +function disp_thickness_p(bl::AbstractBoundaryLayer, Re_c, alphastar) + return ifelse(is_top_suction(bl, alphastar), disp_thickness_bot(bl, Re_c, alphastar), disp_thickness_top(bl, Re_c, alphastar)) +end + +function bl_thickness_bot(bl::AbstractBoundaryLayer, Re_c, alphastar) + # (δ_p/δ_0)*(δ_0/c) + return _bl_thickness_bot(bl, alphastar)*bl_thickness_0(bl, Re_c) +end + +function bl_thickness_top(bl::AbstractBoundaryLayer, Re_c, alphastar) + return _bl_thickness_top(bl, alphastar)*bl_thickness_0(bl, Re_c) +end + +function bl_thickness_s(bl::AbstractBoundaryLayer, Re_c, alphastar) + return ifelse(is_top_suction(bl, alphastar), bl_thickness_top(bl, Re_c, alphastar), bl_thickness_bot(bl, Re_c, alphastar)) +end + +function bl_thickness_p(bl::AbstractBoundaryLayer, Re_c, alphastar) + return ifelse(is_top_suction(bl, alphastar), bl_thickness_bot(bl, Re_c, alphastar), bl_thickness_top(bl, Re_c, alphastar)) +end + diff --git a/src/bpm_test_utils.jl b/src/bpm_test_utils.jl new file mode 100644 index 00000000..99fce5b8 --- /dev/null +++ b/src/bpm_test_utils.jl @@ -0,0 +1,320 @@ +function calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, alphastar, bl; do_lblvs=false, do_tip_vortex=false, blade_tip=nothing, do_tebvs=false, h=nothing, Psi=nothing, use_Ualpha=false) + if do_tebvs + if do_tip_vortex + combined_calc = :with_tip + else + combined_calc = :no_tip + end + else + combined_calc = :none + end + + M_c = 0.8*M + # How we're going to set this up: + # + # * Source starts at the origin, moving in the -x direction with velocity U. + # + c0 = U/M + # Hmm... how about the location stuff? + # I want the source element at the origin, so I guess that's r = 0, and θ doesn't matter. + r = 0.0 + θ = 0.0 + # Hmm... what about the twist? + # I want the chord line to be at an angle `alphastar` with the negative-x axis. + # But how does it work "by default"? + # Let's look at the doc strings. + # OK, so, if `twist_about_positive_y` is true, then initially the unit vector pointing from leading edge to trailing edge will be pointed in the negative z direction, then rotated about the positive y axis by an amount φ. + # I want the blade to be aligned with the x axis, with the chord unit vector in the positive x axis direction. + twist_about_positive_y = true + # So then I think I want to rotate it by this much: + ϕ = 3*pi/2 + alphastar + # ϕ = 3*pi/2 + # OK, so now, how about the velocities? + # Well, we're starting out in the blade fixed-frame, so the velocity should include everything, including induction. + # So, from the perspective of the source element, the total velocity is `M_c*c0` in the positive x direction. + # No velocity in the other directions. + vn = M_c*c0 + vr = 0.0 + vc = 0.0 + # Ah, now I've decided that's not right. + # I want the chord line to be aligned with the x axis, so I'll need to rotate the velocity to take into account the angle of attack. + # So that means the normal velocity would be + # vn = M_c*c0*cos(alphastar) + # vr = 0.0 + # vc = M_c*c0*sin(alphastar) + # We're starting at τ = 0, and the time step doesn't matter yet. + τ = 0.0 + Δτ = 1.0 + if use_Ualpha + se_tblte = AcousticAnalogies.TBLTESourceElement{AcousticAnalogies.BPMDirectivity,false,AcousticAnalogies.NoMachCorrection,true}(c0, nu, r, θ, L, chord, ϕ, M_c*c0, alphastar, τ, Δτ, bl, twist_about_positive_y) + if do_lblvs + se_lblvs = AcousticAnalogies.LBLVSSourceElement{AcousticAnalogies.BPMDirectivity,false,true}(c0, nu, r, θ, L, chord, ϕ, M_c*c0, alphastar, τ, Δτ, bl, twist_about_positive_y) + end + if do_tip_vortex + se_tip = AcousticAnalogies.TipVortexSourceElement{AcousticAnalogies.BPMDirectivity,false,true}(c0, r, θ, L, chord, ϕ, M_c*c0, alphastar, τ, Δτ, bl, blade_tip, twist_about_positive_y) + end + if do_tebvs + se_tebvs = AcousticAnalogies.TEBVSSourceElement{AcousticAnalogies.BPMDirectivity,false,true}(c0, nu, r, θ, L, chord, ϕ, h, Psi, M_c*c0, alphastar, τ, Δτ, bl, twist_about_positive_y) + end + + if combined_calc == :no_tip + se_combined = AcousticAnalogies.CombinedNoTipBroadbandSourceElement{AcousticAnalogies.BPMDirectivity,false,AcousticAnalogies.NoMachCorrection,true}(c0, nu, r, θ, L, chord, ϕ, h, Psi, M_c*c0, alphastar, τ, Δτ, bl, twist_about_positive_y) + elseif combined_calc == :with_tip + se_combined = AcousticAnalogies.CombinedWithTipBroadbandSourceElement{AcousticAnalogies.BPMDirectivity,false,AcousticAnalogies.NoMachCorrection,true}(c0, nu, r, θ, L, chord, ϕ, h, Psi, M_c*c0, alphastar, τ, Δτ, bl, blade_tip, twist_about_positive_y) + end + else + se_tblte = AcousticAnalogies.TBLTESourceElement{AcousticAnalogies.BPMDirectivity,false,AcousticAnalogies.NoMachCorrection,true}(c0, nu, r, θ, L, chord, ϕ, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) + if do_lblvs + se_lblvs = AcousticAnalogies.LBLVSSourceElement{AcousticAnalogies.BPMDirectivity,false,true}(c0, nu, r, θ, L, chord, ϕ, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) + end + if do_tip_vortex + se_tip = AcousticAnalogies.TipVortexSourceElement{AcousticAnalogies.BPMDirectivity,false,true}(c0, r, θ, L, chord, ϕ, vn, vr, vc, τ, Δτ, bl, blade_tip, twist_about_positive_y) + end + if do_tebvs + se_tebvs = AcousticAnalogies.TEBVSSourceElement{AcousticAnalogies.BPMDirectivity,false,true}(c0, nu, r, θ, L, chord, ϕ, h, Psi, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) + end + + if combined_calc == :no_tip + se_combined = AcousticAnalogies.CombinedNoTipBroadbandSourceElement{AcousticAnalogies.BPMDirectivity,false,AcousticAnalogies.NoMachCorrection,true}(c0, nu, r, θ, L, chord, ϕ, h, Psi, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) + elseif combined_calc == :with_tip + se_combined = AcousticAnalogies.CombinedWithTipBroadbandSourceElement{AcousticAnalogies.BPMDirectivity,false,AcousticAnalogies.NoMachCorrection,true}(c0, nu, r, θ, L, chord, ϕ, h, Psi, vn, vr, vc, τ, Δτ, bl, blade_tip, twist_about_positive_y) + end + end + + # Let's check that things are what we expect. + @assert se_tblte.y0dot ≈ [0.0, 0.0, 0.0] + @assert se_tblte.y1dot ≈ [0.0, 0.0, 0.0] + @assert se_tblte.y1dot_fluid ≈ [M_c*c0, 0.0, 0.0] + # @assert se_tblte.y1dot_fluid ≈ [M_c*c0*cos(alphastar), 0.0, M_c*c0*sin(alphastar)] + @assert se_tblte.span_uvec ≈ [0.0, 1.0, 0.0] + @assert se_tblte.chord_uvec ≈ [cos(alphastar), 0.0, -sin(alphastar)] + # @assert se_tblte.chord_uvec ≈ [1.0, 0.0, 0.0] + @assert isapprox(AcousticAnalogies.angle_of_attack(se_tblte), alphastar; atol=1e-12) + + if do_lblvs + # Let's check that things are what we expect. + @assert se_lblvs.y0dot ≈ [0.0, 0.0, 0.0] + @assert se_lblvs.y1dot ≈ [0.0, 0.0, 0.0] + @assert se_lblvs.y1dot_fluid ≈ [M_c*c0, 0.0, 0.0] + # @assert se_lblvs.y1dot_fluid ≈ [M_c*c0*cos(alphastar), 0.0, M_c*c0*sin(alphastar)] + @assert se_lblvs.span_uvec ≈ [0.0, 1.0, 0.0] + @assert se_lblvs.chord_uvec ≈ [cos(alphastar), 0.0, -sin(alphastar)] + # @assert se_lblvs.chord_uvec ≈ [1.0, 0.0, 0.0] + @assert isapprox(AcousticAnalogies.angle_of_attack(se_lblvs), alphastar; atol=1e-12) + end + + if do_tip_vortex + # Let's check that things are what we expect. + @assert se_tip.y0dot ≈ [0.0, 0.0, 0.0] + @assert se_tip.y1dot ≈ [0.0, 0.0, 0.0] + @assert se_tip.y1dot_fluid ≈ [M_c*c0, 0.0, 0.0] + # @assert se_tip.y1dot_fluid ≈ [M_c*c0*cos(alphastar), 0.0, M_c*c0*sin(alphastar)] + @assert se_tip.span_uvec ≈ [0.0, 1.0, 0.0] + @assert se_tip.chord_uvec ≈ [cos(alphastar), 0.0, -sin(alphastar)] + # @assert se_tip.chord_uvec ≈ [1.0, 0.0, 0.0] + @assert isapprox(AcousticAnalogies.angle_of_attack(se_tip), alphastar; atol=1e-12) + end + + if do_tebvs + # Let's check that things are what we expect. + @assert se_tebvs.y0dot ≈ [0.0, 0.0, 0.0] + @assert se_tebvs.y1dot ≈ [0.0, 0.0, 0.0] + @assert se_tebvs.y1dot_fluid ≈ [M_c*c0, 0.0, 0.0] + # @assert se_tebvs.y1dot_fluid ≈ [M_c*c0*cos(alphastar), 0.0, M_c*c0*sin(alphastar)] + @assert se_tebvs.span_uvec ≈ [0.0, 1.0, 0.0] + @assert se_tebvs.chord_uvec ≈ [cos(alphastar), 0.0, -sin(alphastar)] + # @assert se_tebvs.chord_uvec ≈ [1.0, 0.0, 0.0] + @assert isapprox(AcousticAnalogies.angle_of_attack(se_tebvs), alphastar; atol=1e-12) + end + + if combined_calc != :none + # Let's check that things are what we expect. + @assert se_combined.y0dot ≈ [0.0, 0.0, 0.0] + @assert se_combined.y1dot ≈ [0.0, 0.0, 0.0] + @assert se_combined.y1dot_fluid ≈ [M_c*c0, 0.0, 0.0] + # @assert se_combined.y1dot_fluid ≈ [M_c*c0*cos(alphastar), 0.0, M_c*c0*sin(alphastar)] + @assert se_combined.span_uvec ≈ [0.0, 1.0, 0.0] + @assert se_combined.chord_uvec ≈ [cos(alphastar), 0.0, -sin(alphastar)] + # @assert se_combined.chord_uvec ≈ [1.0, 0.0, 0.0] + @assert isapprox(AcousticAnalogies.angle_of_attack(se_combined), alphastar; atol=1e-12) + end + + # Now we want to transform the source element into the global frame, which just means we make it move with speed `U` in the negative x direction. + trans = ConstantVelocityTransformation(τ, [0.0, 0.0, 0.0], [-U, 0.0, 0.0]) + # No, that's not right, I want it to move in the direction of the velocity, which isn't aligned with the x axis any more. + # trans = ConstantVelocityTransformation(τ, [0.0, 0.0, 0.0], [-U*cos(alphastar), 0.0, -U*sin(alphastar)]) + se_tblte_global = trans(se_tblte) + if do_lblvs + se_lblvs_global = trans(se_lblvs) + end + if do_tip_vortex + se_tip_global = trans(se_tip) + end + if do_tebvs + se_tebvs_global = trans(se_tebvs) + end + if combined_calc != :none + se_combined_global = trans(se_combined) + end + + # Will that change the angle of attack? + # Originally the total velocity was `Vtotal = se_tblte.y1dot_fluid - se_tblte.y1dot = [M_c*c0, 0, 0]`, and now it will be `[M_c*c0 - U, 0, 0] - [-U, 0, 0] = [M_c*c0, 0, 0]`. + # So nope, which is good. :-) + # Oh, and I'm only changing the magnitude of the velocity, not the direction. + @assert se_tblte_global.y0dot ≈ [0.0, 0.0, 0.0] + @assert se_tblte_global.y1dot ≈ [-U, 0.0, 0.0] + # @assert se_tblte_global.y1dot ≈ [-U*cos(alphastar), 0.0, -U*sin(alphastar)] + @assert se_tblte_global.y1dot_fluid ≈ [M_c*c0 - U, 0.0, 0.0] + # @assert se_tblte_global.y1dot_fluid ≈ [(M_c*c0 - U)*cos(alphastar), 0.0, (M_c*c0 - U)*sin(alphastar)] + @assert se_tblte_global.span_uvec ≈ [0.0, 1.0, 0.0] + @assert se_tblte_global.chord_uvec ≈ [cos(alphastar), 0.0, -sin(alphastar)] + # @assert se_tblte_global.chord_uvec ≈ [1.0, 0.0, 0.0] + @assert isapprox(AcousticAnalogies.angle_of_attack(se_tblte_global), alphastar; atol=1e-12) + + if do_lblvs + @assert se_lblvs_global.y0dot ≈ [0.0, 0.0, 0.0] + @assert se_lblvs_global.y1dot ≈ [-U, 0.0, 0.0] + # @assert se_lblvs_global.y1dot ≈ [-U*cos(alphastar), 0.0, -U*sin(alphastar)] + @assert se_lblvs_global.y1dot_fluid ≈ [M_c*c0 - U, 0.0, 0.0] + # @assert se_lblvs_global.y1dot_fluid ≈ [(M_c*c0 - U)*cos(alphastar), 0.0, (M_c*c0 - U)*sin(alphastar)] + @assert se_lblvs_global.span_uvec ≈ [0.0, 1.0, 0.0] + @assert se_lblvs_global.chord_uvec ≈ [cos(alphastar), 0.0, -sin(alphastar)] + # @assert se_lblvs_global.chord_uvec ≈ [1.0, 0.0, 0.0] + @assert isapprox(AcousticAnalogies.angle_of_attack(se_lblvs_global), alphastar; atol=1e-12) + end + + if do_tip_vortex + @assert se_tip_global.y0dot ≈ [0.0, 0.0, 0.0] + @assert se_tip_global.y1dot ≈ [-U, 0.0, 0.0] + # @assert se_tip_global.y1dot ≈ [-U*cos(alphastar), 0.0, -U*sin(alphastar)] + @assert se_tip_global.y1dot_fluid ≈ [M_c*c0 - U, 0.0, 0.0] + # @assert se_tip_global.y1dot_fluid ≈ [(M_c*c0 - U)*cos(alphastar), 0.0, (M_c*c0 - U)*sin(alphastar)] + @assert se_tip_global.span_uvec ≈ [0.0, 1.0, 0.0] + @assert se_tip_global.chord_uvec ≈ [cos(alphastar), 0.0, -sin(alphastar)] + # @assert se_tip_global.chord_uvec ≈ [1.0, 0.0, 0.0] + @assert isapprox(AcousticAnalogies.angle_of_attack(se_tip_global), alphastar; atol=1e-12) + end + + if do_tebvs + @assert se_tebvs_global.y0dot ≈ [0.0, 0.0, 0.0] + @assert se_tebvs_global.y1dot ≈ [-U, 0.0, 0.0] + # @assert se_tebvs_global.y1dot ≈ [-U*cos(alphastar), 0.0, -U*sin(alphastar)] + @assert se_tebvs_global.y1dot_fluid ≈ [M_c*c0 - U, 0.0, 0.0] + # @assert se_tebvs_global.y1dot_fluid ≈ [(M_c*c0 - U)*cos(alphastar), 0.0, (M_c*c0 - U)*sin(alphastar)] + @assert se_tebvs_global.span_uvec ≈ [0.0, 1.0, 0.0] + @assert se_tebvs_global.chord_uvec ≈ [cos(alphastar), 0.0, -sin(alphastar)] + # @assert se_tebvs_global.chord_uvec ≈ [1.0, 0.0, 0.0] + @assert isapprox(AcousticAnalogies.angle_of_attack(se_tebvs_global), alphastar; atol=1e-12) + end + + if combined_calc != :none + @assert se_combined_global.y0dot ≈ [0.0, 0.0, 0.0] + @assert se_combined_global.y1dot ≈ [-U, 0.0, 0.0] + # @assert se_combined_global.y1dot ≈ [-U*cos(alphastar), 0.0, -U*sin(alphastar)] + @assert se_combined_global.y1dot_fluid ≈ [M_c*c0 - U, 0.0, 0.0] + # @assert se_combined_global.y1dot_fluid ≈ [(M_c*c0 - U)*cos(alphastar), 0.0, (M_c*c0 - U)*sin(alphastar)] + @assert se_combined_global.span_uvec ≈ [0.0, 1.0, 0.0] + @assert se_combined_global.chord_uvec ≈ [cos(alphastar), 0.0, -sin(alphastar)] + # @assert se_combined_global.chord_uvec ≈ [1.0, 0.0, 0.0] + @assert isapprox(AcousticAnalogies.angle_of_attack(se_combined_global), alphastar; atol=1e-12) + end + + # If the angle of attack is negative, then the pressure and suction sides of the airfoil section switch, and so the coordinate system does too. + if (alphastar - AcousticAnalogies.alpha_zerolift(bl)) < 0 + Φ_e *= -1 + end + + # What about the observer? + # That's the tricky part. + # We know the final position of the observer is this. + x_obs_final = [r_e*cos(θ_e), r_e*sin(θ_e)*cos(Φ_e), r_e*sin(θ_e)*sin(Φ_e)] + # This polar coordinate system is actually defined from the perspective of the fluid velocity, not the source element chord direction. + # So need to take into acount that. + # x_obs_final = [r_e*cos(θ_e)*cos(alphastar), r_e*sin(θ_e)*cos(Φ_e), r_e*sin(θ_e)*sin(Φ_e)*sin(alphastar)] + + # And we can use the distance from the initial position of the source to the final position of the observer to get the distance the acoustic wave travels, and then the final time. + t_final = τ + norm(x_obs_final - se_tblte_global.y0dot)/c0 + + # And then we can use that to get the initial position of the observer, which is moving with the same velocity as the source. + x_obs_initial = x_obs_final - se_tblte_global.y1dot*(t_final - τ) + + # So now I should be able to create the observer object thingy. + obs = AcousticAnalogies.ConstVelocityAcousticObserver(τ, x_obs_initial, se_tblte_global.y1dot) + + # And now I should check if I get the expected final time. + @assert AcousticAnalogies.adv_time(se_tblte_global, obs) ≈ t_final + if do_lblvs + @assert AcousticAnalogies.adv_time(se_lblvs_global, obs) ≈ t_final + end + if do_tip_vortex + @assert AcousticAnalogies.adv_time(se_tip_global, obs) ≈ t_final + end + if do_tebvs + @assert AcousticAnalogies.adv_time(se_tebvs_global, obs) ≈ t_final + end + if combined_calc != :none + @assert AcousticAnalogies.adv_time(se_combined_global, obs) ≈ t_final + end + + # So now I should be able to do a noise prediction. + freqs = AcousticMetrics.ExactThirdOctaveCenterBands(0.2, 20e3) + tblte_out = AcousticAnalogies.noise(se_tblte_global, obs, freqs) + tblte_s_out = AcousticAnalogies.pbs_suction(tblte_out) + tblte_p_out = AcousticAnalogies.pbs_pressure(tblte_out) + tblte_alpha_out = AcousticAnalogies.pbs_alpha(tblte_out) + SPL_s_jl = 10.0 .* log10.(tblte_s_out./((20e-6)^2)) + SPL_p_jl = 10.0 .* log10.(tblte_p_out./((20e-6)^2)) + SPL_alpha_jl = 10.0 .* log10.(tblte_alpha_out./((20e-6)^2)) + if do_lblvs + lblvs_out = AcousticAnalogies.noise(se_lblvs_global, obs, freqs) + SPL_lbl_vs = 10.0 .* log10.(lblvs_out./((20e-6)^2)) + end + if do_tip_vortex + tip_out = AcousticAnalogies.noise(se_tip_global, obs, freqs) + SPL_tip = 10.0 .* log10.(tip_out./((20e-6)^2)) + end + if do_tebvs + tebvs_out = AcousticAnalogies.noise(se_tebvs_global, obs, freqs) + SPL_teb = 10.0 .* log10.(tebvs_out./((20e-6)^2)) + end + if combined_calc != :none + combined_out = AcousticAnalogies.noise(se_combined_global, obs, freqs) + end + + @assert AcousticAnalogies.doppler(tblte_out) ≈ 1 + if do_lblvs + @assert AcousticAnalogies.doppler(lblvs_out) ≈ 1 + end + if do_tip_vortex + @assert AcousticAnalogies.doppler(tip_out) ≈ 1 + end + if do_tebvs + @assert AcousticAnalogies.doppler(tebvs_out) ≈ 1 + end + if combined_calc != :none + @assert AcousticAnalogies.doppler(combined_out) ≈ 1 + end + + if combined_calc in (:no_tip, :with_tip) + @assert all(pbs_suction(combined_out) .≈ tblte_s_out) + @assert all(pbs_pressure(combined_out) .≈ tblte_p_out) + @assert all(pbs_alpha(combined_out) .≈ tblte_alpha_out) + @assert all(pbs_teb(combined_out) .≈ tebvs_out) + end + if combined_calc in (:with_tip,) + @assert all(pbs_tip(combined_out) .≈ tip_out) + end + + res = (freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl) + if do_lblvs + res = (res..., SPL_lbl_vs) + end + if do_tip_vortex + res = (res..., SPL_tip) + end + if do_tebvs + res = (res..., SPL_teb) + end + return res +end + diff --git a/src/ccblade_helpers.jl b/src/ccblade_helpers.jl index 1588077f..6e204e46 100644 --- a/src/ccblade_helpers.jl +++ b/src/ccblade_helpers.jl @@ -1,5 +1,77 @@ +import FillArrays: getindex_value + +# Normal implementation is this from FillArrays.jl: +# +# @inline getindex_value(F::Fill) = F.value +# +# But that breaks with CCBlade. +# Why? +# Because, since a FillArrays.Fill <: AbstractArray, it calls this: +# +# function Base.getproperty(obj::AbstractVector{<:Section}, sym::Symbol) +# return getfield.(obj, sym) +# end +# +# which eventually calls FillArrays.getindex_value again, leading to recursion and a stack overflow. +# +# This is type piracy :-(. +# But it may also be type piracy to extend Base.getproperty in CCBlade.jl, since CCBlade.jl doesn't own Base.getproperty or AbstractVector. +@inline getindex_value(F::Fill{<:Union{CCBlade.Section,CCBlade.OperatingPoint,CCBlade.Outputs}}) = getfield(F, :value) + +# Normal implementation is this from FillArrays.jl: +# +# @inline axes(F::Fill) = F.axes +# +# But that hits +# +# function Base.getproperty(obj::AbstractVector{<:Section}, sym::Symbol) +# return getfield.(obj, sym) +# end +# +# from CCBlade. +# This is type piracy :-(. +# But it may also be type piracy to extend Base.getproperty in CCBlade.jl, since CCBlade.jl doesn't own Base.getproperty or AbstractVector. +@inline Base.axes(F::Fill{<:Union{CCBlade.Section,CCBlade.OperatingPoint,CCBlade.Outputs}}) = getfield(F, :axes) + +function _standard_ccblade_transform(rotor::CCBlade.Rotor, sections::AbstractVector{<:CCBlade.Section}, ops::AbstractVector{<:CCBlade.OperatingPoint}, period, num_src_times, positive_x_rotation) + # Assume the rotor is traveling in the positive x direction, with the first + # blade aligned with the positive y axis. Rotor hub is initially at the origin. + rot_axis = @SVector [1.0, 0.0, 0.0] + blade_axis = @SVector [0.0, 1.0, 0.0] + y0_hub = @SVector [0.0, 0.0, 0.0] # m + t0 = 0.0 + + # Get the time of each time step. + dt = period/num_src_times + src_times = t0 .+ (0:num_src_times-1).*dt + + # Get transformations for each blade element. + cos_precone = cos(rotor.precone) + # r = SingleFieldStructArray(sections, Val{:r}) + # Vx = SingleFieldStructArray(ops, Val{:Vx}) + # Vy = SingleFieldStructArray(ops, Val{:Vy}) + r = mapview(:r, sections) + Vx = mapview(:Vx, ops) + Vy = mapview(:Vy, ops) + if positive_x_rotation + rot_trans = SteadyRotXTransformation.(t0, Vy./(r.*cos_precone), 0.0) # size (num_radial,) + else + rot_trans = SteadyRotXTransformation.(t0, -Vy./(r.*cos_precone), 0.0) # size (num_radial,) + end + const_vel_trans = ConstantVelocityTransformation.(t0, Ref(y0_hub), Ref(rot_axis).*Vx./cos_precone) # size (num_radial,) + + # Reshape things to get broadcasting to work. + rot_trans_rs = reshape(rot_trans, 1, :) + const_vel_trans_rs = reshape(const_vel_trans, 1, :) + + # Now get all the transformations. + trans = compose.(src_times, const_vel_trans_rs, rot_trans_rs) # size (num_times, num_radial) + + return src_times, dt, trans +end + """ - CompactSourceElement(rotor::CCBlade.Rotor, section::CCBlade.Section, op::CCBlade.OperatingPoint, out::CCBlade.Outputs, θ, Δr, area_per_chord2, τ) + CompactF1ASourceElement(rotor::CCBlade.Rotor, section::CCBlade.Section, op::CCBlade.OperatingPoint, out::CCBlade.Outputs, θ, Δr, area_per_chord2, τ, positive_x_rotation=true) Construct a source element to be used with the compact form of Farassat's formulation 1A from CCBlade objects. @@ -20,8 +92,9 @@ where `y0dot` is the position of the source element. - `Δr`: length of the element. - `area_per_chord2`: cross-sectional area divided by the chord squared of the element. - `τ`: source time of the element. +- `positive_x_rotation`: rotate blade around the positive-x axis if `true`, negative-x axis otherwise. """ -function CompactSourceElement(rotor::CCBlade.Rotor, section::CCBlade.Section, op::CCBlade.OperatingPoint, out::CCBlade.Outputs, θ, Δr, area_per_chord2, τ) +function CompactF1ASourceElement(rotor::CCBlade.Rotor, section::CCBlade.Section, op::CCBlade.OperatingPoint, out::CCBlade.Outputs, θ, Δr, area_per_chord2, τ, positive_x_rotation) ρ0 = op.rho c0 = op.asound r = section.r @@ -67,9 +140,22 @@ function CompactSourceElement(rotor::CCBlade.Rotor, section::CCBlade.Section, op # the blade would be pointed in the negative z direction. So that means the # load on the fluid would be in the positive z direction, and we don't need # to switch the sign. + + # So after all that, the takeaway is that we'll start out with a loading + # vector [-Np, 0, Tp], then rotate it about the positive z-axis by an amount + # `-precone`, then rotate it about the x axis by an amount `θ`. + + # But, what if I decide the blade is rotating around the negative x-axis? + # The normal loading will still be in the same direction. + # The precone and theta stuff can still work the same way. + # I think the only thing that would switch is the circumferential loading. fn = -Np*cpc fr = Np*spc - fc = Tp + if positive_x_rotation + fc = Tp + else + fc = -Tp + end f0dot = @SVector [fn, cθ*fr - sθ*fc, sθ*fr + cθ*fc] T = eltype(f0dot) @@ -77,25 +163,26 @@ function CompactSourceElement(rotor::CCBlade.Rotor, section::CCBlade.Section, op u = @SVector [spc, cpc*cθ, cpc*sθ] - return CompactSourceElement(ρ0, c0, Δr, Λ, y0dot, y1dot, y2dot, y3dot, f0dot, f1dot, τ, u) + return CompactF1ASourceElement(ρ0, c0, Δr, Λ, y0dot, y1dot, y2dot, y3dot, f0dot, f1dot, τ, u) end """ - source_elements_ccblade(rotor::CCBlade.Rotor, sections::Vector{CCBlade.Section}, ops::Vector{CCBlade.OperatingPoint}, outputs::Vector{CCBlade.Outputs}, area_per_chord2::Vector{AbstractFloat}, period, num_src_times) + f1a_source_elements_ccblade(rotor::CCBlade.Rotor, sections::Vector{CCBlade.Section}, ops::Vector{CCBlade.OperatingPoint}, outputs::Vector{CCBlade.Outputs}, area_per_chord2::Vector{AbstractFloat}, period, num_src_times, positive_x_rotation) -Construct and return an array of CompactSourceElement objects from CCBlade structs. +Construct and return an array of CompactF1ASourceElement objects from CCBlade structs. # Arguments -- `rotor`: CCBlade rotor object.precone). +- `rotor`: CCBlade rotor object. - `sections`: `Vector` of CCBlade section object. - `ops`: `Vector` of CCBlade operating point. - `outputs`::`Vector` of CCBlade output objects. - `area_per_chord2`: cross-sectional area divided by the chord squared of the element at each CCBlade.section. Should be a Vector{AbstractFloat}, same length as `sections`, `ops`, `outputs`. - `period`: length of the source time over which the returned source elements will evaluated. - `num_src_times`: number of source times. +- `positive_x_rotation`: rotate blade around the positive-x axis if `true`, negative-x axis otherwise. """ -function source_elements_ccblade(rotor, sections, ops, outputs, area_per_chord2, period, num_src_times) +function f1a_source_elements_ccblade(rotor, sections, ops, outputs, area_per_chord2, period, num_src_times, positive_x_rotation) # Need to know the radial spacing. (CCBlade doesn't use this—when # integrating stuff [loading to get torque and thrust] it uses the # trapezoidal rule and passes in the radial locations, and assumes that @@ -104,54 +191,782 @@ function source_elements_ccblade(rotor, sections, ops, outputs, area_per_chord2, # Ah, no, I don't know the length at compile time. dradii = get_ccblade_dradii(rotor, sections) - # Assume the rotor is traveling in the positive x direction, with the first - # blade aligned with the positive y axis. Rotor hub is initially at the origin. - rot_axis = @SVector [1.0, 0.0, 0.0] - blade_axis = @SVector [0.0, 1.0, 0.0] - y0_hub = @SVector [0.0, 0.0, 0.0] # m - t0 = 0.0 + # Get the transformation that will put the source elements in the "standard" CCBlade.jl reference frame (moving axially in the positive x axis direction, rotating about the positive x axis or negative x axis, first blade initially aligned with the positive y axis). + src_times, dt, trans = _standard_ccblade_transform(rotor, sections, ops, period, num_src_times, positive_x_rotation) + + # This is just an array of the angular offsets of each blade. First blade is + # aligned with the y axis, next one is offset 2*pi/B radians, etc.. + num_blades = rotor.B + θs = 2*pi/num_blades.*(0:(num_blades-1)) .* ifelse(positive_x_rotation, 1, -1) - # Get the time of each time step. - dt = period/num_src_times - src_times = t0 .+ (0:num_src_times-1).*dt + # Reshape for broadcasting. Goal is to make everything work for a size of (num_times, + # num_radial, num_blades). + # trans_rs = reshape(trans, size(trans)..., 1) + θs_rs = reshape(θs, 1, 1, :) + sections_rs = reshape(sections, 1, :, 1) + ops_rs = reshape(ops, 1, :, 1) + outputs_rs = reshape(outputs, 1, :, 1) + dradii_rs = reshape(dradii, 1, :, 1) + area_per_chord2_rs = reshape(area_per_chord2, 1, :, 1) + # src_times = reshape(src_times, :, 1, 1) # This one isn't necessary. - # Get transformations for each blade element. - cos_precone = cos(rotor.precone) - r = mapview(:r, sections) - Vx = mapview(:Vx, ops) - Vy = mapview(:Vy, ops) - rot_trans = SteadyRotXTransformation.(t0, Vy./(r.*cos_precone), 0.0) # size (num_radial,) - const_vel_trans = ConstantVelocityTransformation.(t0, Ref(y0_hub), Ref(rot_axis).*Vx./cos_precone) # size (num_radial,) + # Construct and transform the source elements. + ses = CompactF1ASourceElement.(Ref(rotor), sections_rs, ops_rs, outputs_rs, θs_rs, dradii_rs, area_per_chord2_rs, src_times, positive_x_rotation) .|> trans - # Reshape things to get broadcasting to work. - rot_trans = reshape(rot_trans, 1, :) - const_vel_trans = reshape(const_vel_trans, 1, :) + return ses +end + +function _get_position_velocity_span_uvec_chord_uvec(theta, precone, pitch, r, θ, W, phi, positive_x_rotation) + sθ, cθ = sincos(θ) + spc, cpc = sincos(precone) + stwist, ctwist = sincos(theta + pitch) + + # The way this will work: + # + # * We're going to assume that the rotor blade is moving axially in the positive x direction, and rotating about the x axis. + # * The "first" blade is initially aligned with the positive y axis. + # * Then we'll rotate the element about the positive z-axis by an amount `-precone` to acount for the precone. + # * Then we'll rotate the element about the positive x-axis by an amount `θ`. + # + # Those transformations will be applied to the blade element position, but also other vectors associated with the element. + # In matrix form the precone transformation would be + # + # [ cos(-precone), -sin(-precone), 0 ] + # [ sin(-precone), cos(-precone), 0 ] + # [ 0, 0, 1 ] + # + # or equivalently + # + # [ cos(precone), sin(precone), 0 ] + # [-sin(precone), cos(precone), 0 ] + # [ 0, 0, 1 ] + # + # And the θ rotation about the x axis would be + # + # [ 1, 0 , 0 ] + # [ 0, cos(θ), -sin(θ) ] + # [ 0, sin(θ), cos(θ) ] + # + # So, to get the position, we start out with a vector + # + # [0] + # [r] + # [0] + # + # And then multiply that by the precone rotation matrix and θ rotation matrix. + # + # [ cos(precone), sin(precone), 0 ] [0] [ r*sin(precone) ] + # [-sin(precone), cos(precone), 0 ] [r] = [ r*cos(precone) ] + # [ 0, 0, 1 ] [0] [ 0 ] + # + # [ 1, 0 , 0 ] [ r*sin(precone) ] [ r*sin(precone) ] + # [ 0, cos(θ), -sin(θ) ] [ r*cos(precone) ] = [ r*cos(precone)*cos(θ) ] + # [ 0, sin(θ), cos(θ) ] [ 0 ] [ r*cos(precone)*sin(θ) ] + y0dot = @SVector [r*spc, r*cpc*cθ, r*cpc*sθ] + + # In the blade-fixed frame, the source isn't moving, since the blade-fixed reference frame is moving with the source. + y1dot = @SVector zeros(eltype(y0dot), 3) + + # Vx = op.Vx + # u = out.u + # Vy = op.Vy + # v = out.v + sphi, cphi = sincos(phi) + Vx_plus_u = W*sphi + Vy_minus_v = W*cphi + + # The `span_uvec` is a unit vector pointing from the hub to the tip, along the blade element's radial length. + # So that's just the same as the position vector, but without the r factor. + span_uvec = @SVector [spc, cpc*cθ, cpc*sθ] + + if positive_x_rotation + # Now, what is the velocity of the fluid in the blade-fixed frame? + # In our coordinate system, the rotor is rotating about the x axis, moving in the x axis direction. + # So that means it appears that the axial freestream velocity Vx is in the negative x axis direction. + # And the induced velocity `u` has the same sign convention as Vx. + # So the total axial velocity of the fluid is `(-Vx - u)`. + # + # For the tangential velocity, we're imagining the blade is initially aligned with the y axis, rotating about the positive x axis. + # So that means the blade is moving toward the z axis. + # So, from the perspective of the blade, the `Vy` velocity is in the negative z axis direction. + # But the sign convention for the induced tangential velocity `v` is that + # it's positive when it opposes `Vy`, so the total tangential velocity of the fluid is `(-Vy + v)`. + # + # So, finally, the fluid velocity vector we need to rotate is + # + # [-Vx - u ] + # [ 0 ] + # [-Vy + v ] + # + # and when I do all that I get + # + # [ (-Vx - u)*cos(precone) ] + # [ (Vx + u)*sin(precone)*cos(θ) - (-Vy + v)*sin(θ) ] + # [ (Vx + u)*sin(precone)*sin(θ) + (-Vy + v)*cos(θ) ] + # y1dot_fluid = @SVector [(-Vx - u)*cpc, (Vx + u)*spc*cθ - (-Vy + v)*sθ, (Vx + u)*spc*sθ + (-Vy + v)*cθ] + y1dot_fluid = @SVector [-Vx_plus_u*cpc, Vx_plus_u*spc*cθ - (-Vy_minus_v)*sθ, Vx_plus_u*spc*sθ + (-Vy_minus_v)*cθ] + + # Finally the `chord_uvec` is a unit vector pointing from the leading edge to the trailing edge. + # In our initial coordinate system (i.e., not accounting for the precone or + # θ rotations) we're imagining the blade is rotating about the x axis, + # aligned with the y axis, and so is moving in the direction of the z axis. + # So that means if the twist is zero, then the leading edge is headed in the + # z axis direction, and a vector pointing from leading edge to trailing edge + # would be in the negative z axis direction. Then, to account for the twist, + # we would rotate it about the positive y axis. And then do the usual + # precone and θ rotations. + # So, a rotation about the y axis is + # + # [ cos(twist) 0 sin(twist) ] + # [ 0 1 0 ] + # [-sin(twist) 0 cos(twist) ] + # + # So, start with + # + # [ 0 ] + # [ 0 ] + # [-1 ] + # + # then + # + # [ cos(twist) 0 sin(twist) ] [ 0 ] [-sin(twist) ] + # [ 0 1 0 ] [ 0 ] = [ 0 ] + # [-sin(twist) 0 cos(twist) ] [-1 ] [-cos(twist) ] + # + # Now do the precone transformation + # + # [ cos(precone), sin(precone), 0 ] [-sin(twist) ] [-sin(twist)*cos(precone) ] + # [-sin(precone), cos(precone), 0 ] [ 0 ] = [ sin(twist)*sin(precone) ] + # [ 0, 0, 1 ] [-cos(twist) ] [-cos(twist) ] + # + # Finally do the θ transformation + # + # [ 1, 0 , 0 ] [-sin(twist)*cos(precone) ] [-sin(twist)*cos(precone) ] + # [ 0, cos(θ), -sin(θ) ] [ sin(twist)*sin(precone) ] = [ sin(twist)*sin(precone)*cos(θ) + cos(twist)*sin(θ) ] + # [ 0, sin(θ), cos(θ) ] [-cos(twist) ] [ sin(twist)*sin(precone)*sin(θ) - cos(twist)*cos(θ) ] + chord_uvec = @SVector [-stwist*cpc, stwist*spc*cθ + ctwist*sθ, stwist*spc*sθ - ctwist*cθ] + + else + + # But, what if I want to assume that the blade is rotating in the opposite direction, i.e., about the negative x axis? + # For the velocity, the direction of the axial velocity is unchanged: we're still moving in the positive x direction, so the axial velocity from the perspective of the blade element will be in the negative x direction. + # So the total axial velocity of the fluid is `(-Vx - u)`. + # + # For the tangential velocity, we're rotating about the negative x axis now, so since the blade is initially aligned with the y axis, it is moving in the negative z direction. + # So that means the freestream tangential velocity appears to be in the opposite direction, aka the positive z direction. + # But the induced tangential velocity is in the opposite direction of the freestream tangential velocity, so the total velocity in the tangential direction is `(Vy - v)`. + # + # So the fluid velocity vector we want to rotate is + # + # [-Vx - u ] + # [ 0 ] + # [ Vy - v ] + # + # The theta and precone stuff doesn't change, so we'll do all the same stuff. + # First we do the precone: + # + # [ cos(precone), sin(precone), 0 ] [-Vx - u] [ (-Vx - u)*cos(precone) ] [ (-Vx - u)*cos(precone) ] + # [-sin(precone), cos(precone), 0 ] [ 0 ] = [ (-Vx - u)*(-sin(precone)) ] = [ ( Vx + u)*sin(precone) ] + # [ 0, 0, 1 ] [ Vy - v] [ Vy - v ] [ Vy - v ] + # + # then do the theta rotation. + # + # [ 1, 0 , 0 ] [ (-Vx - u)*cos(precone) ] [ (-Vx - u)*cos(precone) ] + # [ 0, cos(θ), -sin(θ) ] [ ( Vx + u)*sin(precone) ] = [ ( Vx + u)*sin(precone)*cos(θ) - (Vy - v)*sin(θ) ] + # [ 0, sin(θ), cos(θ) ] [ Vy - v ] [ ( Vx + u)*sin(precone)*sin(θ) + (Vy - v)*cos(θ) ] + # y1dot_fluid = @SVector [(-Vx - u)*cpc, (Vx + u)*spc*cθ - (Vy - v)*sθ, (Vx + u)*spc*sθ + (Vy - v)*cθ] + y1dot_fluid = @SVector [-Vx_plus_u*cpc, Vx_plus_u*spc*cθ - Vy_minus_v*sθ, Vx_plus_u*spc*sθ + Vy_minus_v*cθ] + # + # That should be the same thing as the opposite case, but with the sign on (Vy - v) switched. + # Yep, good. + # + # For the chord_uvec, I want to start with a unit vector pointing in the positive z axis, then do a negative-twist rotation about the positive y axis. + # So start with + # + # [ 0 ] + # [ 0 ] + # [ 1 ] + # + # then + # + # [ cos(-twist) 0 sin(-twist) ] [ 0 ] [ sin(-twist) ] + # [ 0 1 0 ] [ 0 ] = [ 0 ] + # [-sin(-twist) 0 cos(-twist) ] [ 1 ] [ cos(-twist) ] + # + # Now do the precone transformation + # + # [ cos(precone), sin(precone), 0 ] [ sin(-twist) ] [ sin(-twist)*cos(precone) ] + # [-sin(precone), cos(precone), 0 ] [ 0 ] = [-sin(-twist)*sin(precone) ] + # [ 0, 0, 1 ] [ cos(-twist) ] [ cos(-twist) ] + # + # Finally do the θ transformation + # + # [ 1, 0 , 0 ] [ sin(-twist)*cos(precone) ] [ sin(-twist)*cos(precone) ] + # [ 0, cos(θ), -sin(θ) ] [-sin(-twist)*sin(precone) ] = [-sin(-twist)*sin(precone)*cos(θ) - cos(-twist)*sin(θ) ] + # [ 0, sin(θ), cos(θ) ] [ cos(-twist) ] [-sin(-twist)*sin(precone)*sin(θ) + cos(-twist)*cos(θ) ] + # + # Now handle the `-twist`, + # + # [ sin(-twist)*cos(precone) ] [-sin(twist)*cos(precone) ] + # [-sin(-twist)*sin(precone)*cos(θ) - cos(-twist)*sin(θ) ] = [ sin(twist)*sin(precone)*cos(θ) - cos(twist)*sin(θ) ] + # [-sin(-twist)*sin(precone)*sin(θ) + cos(-twist)*cos(θ) ] [ sin(twist)*sin(precone)*sin(θ) + cos(twist)*cos(θ) ] + + chord_uvec = @SVector [-stwist*cpc, stwist*spc*cθ - ctwist*sθ, stwist*spc*sθ + ctwist*cθ] + end + + chord_cross_span_to_get_top_uvec = positive_x_rotation + return y0dot, y1dot, y1dot_fluid, span_uvec, chord_uvec, chord_cross_span_to_get_top_uvec +end + + +""" + TBLTESourceElement(rotor::CCBlade.Rotor, section::CCBlade.Section, op::CCBlade.OperatingPoint, out::CCBlade.Outputs, θ, Δr, τ, Δτ, bl::AbstractBoundaryLayer, positive_x_rotation) + +Construct a source element to be used to predict turbulent boundary layer-trailing edge (TBLTE) noise. + +The source element's position is calculated from `section.r`, `rotor.precone`, and the `θ` argument using +```julia + sθ, cθ = sincos(θ) + spc, cpc = sincos(precone) + y0dot = [r*spc, r*cpc*cθ, r*cpc*sθ] +``` +where `y0dot` is the position of the source element. + +# Arguments +- `rotor::CCBlade.Rotor`: CCBlade rotor object, needed for the precone angle. +- `section::CCBlade.Section`: CCBlade section object, needed for the radial location and chord length of the element. +- `op::CCBlade.OperatingPoint`: CCBlade operating point, needed for atmospheric properties. +- `out::CCBlade.Outputs`: CCBlade outputs object, needed for the loading. +- `θ`: polar coordinate of the element, in radians. +- `Δr`: length of the element, in meters. +- `τ`: source time of the element, in seconds. +- `Δτ`: source time duration, in seconds. +- `bl`: `AcousticAnalogies.AbstractBoundaryLayer`, needed for boundary layer properties. +- `positive_x_rotation`: rotate blade around the positive-x axis if `true`, negative-x axis otherwise. +""" +function TBLTESourceElement(rotor::CCBlade.Rotor, section::CCBlade.Section, op::CCBlade.OperatingPoint, out::CCBlade.Outputs, θ, Δr, τ, Δτ, bl::AbstractBoundaryLayer, positive_x_rotation) + return TBLTESourceElement{BrooksBurleyDirectivity,true,PrandtlGlauertMachCorrection,true}(rotor, section, op, out, θ, Δr, τ, Δτ, bl, positive_x_rotation) +end + +function TBLTESourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}(rotor::CCBlade.Rotor, section::CCBlade.Section, op::CCBlade.OperatingPoint, out::CCBlade.Outputs, θ, Δr, τ, Δτ, bl::AbstractBoundaryLayer, positive_x_rotation) where {TDirect,TUInduction,TMachCorrection,TDoppler} + + y0dot, y1dot, y1dot_fluid, span_uvec, chord_uvec, chord_cross_span_to_get_top_uvec = _get_position_velocity_span_uvec_chord_uvec( + section.theta, rotor.precone, op.pitch, section.r, θ, out.W, out.phi, positive_x_rotation) + + nu = op.mu/op.rho + + return TBLTESourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}(op.asound, nu, Δr, section.chord, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, chord_cross_span_to_get_top_uvec) +end + +""" + tblte_source_elements_ccblade(rotor::CCBlade.Rotor, sections::Vector{CCBlade.Section}, ops::Vector{CCBlade.OperatingPoint}, outputs::Vector{CCBlade.Outputs}, bls::Vector{AbstractBoundaryLayer}, period, num_src_times, positive_x_rotation) + +Construct and return an array of TBLTESourceElement objects from CCBlade structs. + +# Arguments +- `rotor`: CCBlade rotor object. +- `sections`: `Vector` of CCBlade section object. +- `ops`: `Vector` of CCBlade operating point. +- `outputs`: `Vector` of CCBlade output objects. +- `bls`::`Vector` of boundary layer `AbstractBoundaryLayer` `structs`. +- `period`: length of the source time over which the returned source elements will evaluated. +- `num_src_times`: number of source times. +- `positive_x_rotation`: rotate blade around the positive-x axis if `true`, negative-x axis otherwise. +""" +function tblte_source_elements_ccblade(rotor, sections, ops, outputs, bls, period, num_src_times, positive_x_rotation) + return tblte_source_elements_ccblade(BrooksBurleyDirectivity, true, PrandtlGlauertMachCorrection, true, rotor, sections, ops, outputs, bls, period, num_src_times, positive_x_rotation) +end + +function tblte_source_elements_ccblade(TDirect::Type{<:AbstractDirectivity}, TUInduction::Bool, TMachCorrection::Type{<:AbstractMachCorrection}, TDoppler::Bool, rotor, sections, ops, outputs, bls, period, num_src_times, positive_x_rotation) + # Need to know the radial spacing. (CCBlade doesn't use this—when + # integrating stuff [loading to get torque and thrust] it uses the + # trapezoidal rule and passes in the radial locations, and assumes that + # integrands go to zero at the hub and tip.) Kind of lame that I have to + # calcluate it here, but whatever. Maybe I should use StaticArrays for this? + # Ah, no, I don't know the length at compile time. + dradii = get_ccblade_dradii(rotor, sections) + + # Get the transformation that will put the source elements in the "standard" CCBlade.jl reference frame (moving axially in the positive x axis direction, rotating about the positive x axis, first blade initially aligned with the positive y axis). + src_times, dt, trans = _standard_ccblade_transform(rotor, sections, ops, period, num_src_times, positive_x_rotation) + + # This is just an array of the angular offsets of each blade. First blade is + # aligned with the y axis, next one is offset 2*pi/B radians, etc.. + num_blades = rotor.B + θs = 2*pi/num_blades.*(0:(num_blades-1)) .* ifelse(positive_x_rotation, 1, -1) + + # Reshape for broadcasting. Goal is to make everything work for a size of (num_times, + # num_radial, num_blades). + # trans_rs = reshape(trans, size(trans)..., 1) + θs_rs = reshape(θs, 1, 1, :) + sections_rs = reshape(sections, 1, :, 1) + ops_rs = reshape(ops, 1, :, 1) + outputs_rs = reshape(outputs, 1, :, 1) + dradii_rs = reshape(dradii, 1, :, 1) + bls_rs = reshape(bls, 1, :, 1) + # src_times = reshape(src_times, :, 1, 1) # This one isn't necessary. + + # Construct and transform the source elements. + ses = TBLTESourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}.(Ref(rotor), sections_rs, ops_rs, outputs_rs, θs_rs, dradii_rs, src_times, Ref(dt), bls_rs, positive_x_rotation) .|> trans + + return ses +end + +""" + LBLVSSourceElement(rotor::CCBlade.Rotor, section::CCBlade.Section, op::CCBlade.OperatingPoint, out::CCBlade.Outputs, θ, Δr, τ, Δτ, bl::AbstractBoundaryLayer, positive_x_rotation) + +Construct a source element to be used to predict laminary boundary layer-vortex shedding (LBLVS) noise. + +The source element's position is calculated from `section.r`, `rotor.precone`, and the `θ` argument using +```julia + sθ, cθ = sincos(θ) + spc, cpc = sincos(precone) + y0dot = [r*spc, r*cpc*cθ, r*cpc*sθ] +``` +where `y0dot` is the position of the source element. + +# Arguments +- `rotor::CCBlade.Rotor`: CCBlade rotor object, needed for the precone angle. +- `section::CCBlade.Section`: CCBlade section object, needed for the radial location and chord length of the element. +- `op::CCBlade.OperatingPoint`: CCBlade operating point, needed for atmospheric properties. +- `out::CCBlade.Outputs`: CCBlade outputs object, needed for the loading. +- `θ`: polar coordinate of the element, in radians. +- `Δr`: length of the element, in meters. +- `τ`: source time of the element, in seconds. +- `Δτ`: source time duration, in seconds. +- `bl`: `AcousticAnalogies.AbstractBoundaryLayer`, needed for boundary layer properties. +- `positive_x_rotation`: rotate blade around the positive-x axis if `true`, negative-x axis otherwise. +""" +function LBLVSSourceElement(rotor::CCBlade.Rotor, section::CCBlade.Section, op::CCBlade.OperatingPoint, out::CCBlade.Outputs, θ, Δr, τ, Δτ, bl::AbstractBoundaryLayer, positive_x_rotation) + return LBLVSSourceElement{BrooksBurleyDirectivity,true,true}(rotor, section, op, out, θ, Δr, τ, Δτ, bl, positive_x_rotation) +end + +function LBLVSSourceElement{TDirect,TUInduction,TDoppler}(rotor::CCBlade.Rotor, section::CCBlade.Section, op::CCBlade.OperatingPoint, out::CCBlade.Outputs, θ, Δr, τ, Δτ, bl::AbstractBoundaryLayer, positive_x_rotation) where {TDirect,TUInduction,TDoppler} + + y0dot, y1dot, y1dot_fluid, span_uvec, chord_uvec, chord_cross_span_to_get_top_uvec = _get_position_velocity_span_uvec_chord_uvec( + section.theta, rotor.precone, op.pitch, section.r, θ, out.W, out.phi, positive_x_rotation) + + nu = op.mu/op.rho + + return LBLVSSourceElement{TDirect,TUInduction,TDoppler}(op.asound, nu, Δr, section.chord, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, chord_cross_span_to_get_top_uvec) +end + +""" + lblvs_source_elements_ccblade(rotor::CCBlade.Rotor, sections::Vector{CCBlade.Section}, ops::Vector{CCBlade.OperatingPoint}, outputs::Vector{CCBlade.Outputs}, bls::Vector{AbstractBoundaryLayer}, period, num_src_times, positive_x_rotation) + +Construct and return an array of LBLVSSourceElement objects from CCBlade structs. + +# Arguments +- `rotor`: CCBlade rotor object. +- `sections`: `Vector` of CCBlade section object. +- `ops`: `Vector` of CCBlade operating point. +- `outputs`: `Vector` of CCBlade output objects. +- `bls`::`Vector` of boundary layer `AbstractBoundaryLayer` `structs`. +- `period`: length of the source time over which the returned source elements will evaluated. +- `num_src_times`: number of source times. +- `positive_x_rotation`: rotate blade around the positive-x axis if `true`, negative-x axis otherwise. +""" +function lblvs_source_elements_ccblade(rotor, sections, ops, outputs, bls, period, num_src_times, positive_x_rotation) + return lblvs_source_elements_ccblade(BrooksBurleyDirectivity, true, true, rotor, sections, ops, outputs, bls, period, num_src_times, positive_x_rotation) +end + +function lblvs_source_elements_ccblade(TDirect::Type{<:AbstractDirectivity}, TUInduction::Bool, TDoppler::Bool, rotor, sections, ops, outputs, bls, period, num_src_times, positive_x_rotation) + # Need to know the radial spacing. (CCBlade doesn't use this—when + # integrating stuff [loading to get torque and thrust] it uses the + # trapezoidal rule and passes in the radial locations, and assumes that + # integrands go to zero at the hub and tip.) Kind of lame that I have to + # calcluate it here, but whatever. Maybe I should use StaticArrays for this? + # Ah, no, I don't know the length at compile time. + dradii = get_ccblade_dradii(rotor, sections) + + # Get the transformation that will put the source elements in the "standard" CCBlade.jl reference frame (moving axially in the positive x axis direction, rotating about the positive x axis, first blade initially aligned with the positive y axis). + src_times, dt, trans = _standard_ccblade_transform(rotor, sections, ops, period, num_src_times, positive_x_rotation) - # Now get all the transformations. - trans = compose.(src_times, const_vel_trans, rot_trans) # size (num_times, num_radial) - # This is just an array of the angular offsets of each blade. First blade is # aligned with the y axis, next one is offset 2*pi/B radians, etc.. num_blades = rotor.B - θs = 2*pi/num_blades.*(0:(num_blades-1)) + θs = 2*pi/num_blades.*(0:(num_blades-1)) .* ifelse(positive_x_rotation, 1, -1) # Reshape for broadcasting. Goal is to make everything work for a size of (num_times, # num_radial, num_blades). - trans = reshape(trans, size(trans)..., 1) - θs = reshape(θs, 1, 1, :) - sections = reshape(sections, 1, :, 1) - ops = reshape(ops, 1, :, 1) - outputs = reshape(outputs, 1, :, 1) - dradii = reshape(dradii, 1, :, 1) - area_per_chord2 = reshape(area_per_chord2, 1, :, 1) - src_times = reshape(src_times, :, 1, 1) # This one isn't necessary. + # trans_rs = reshape(trans, size(trans)..., 1) + θs_rs = reshape(θs, 1, 1, :) + sections_rs = reshape(sections, 1, :, 1) + ops_rs = reshape(ops, 1, :, 1) + outputs_rs = reshape(outputs, 1, :, 1) + dradii_rs = reshape(dradii, 1, :, 1) + bls_rs = reshape(bls, 1, :, 1) + # src_times = reshape(src_times, :, 1, 1) # This one isn't necessary. # Construct and transform the source elements. - ses = CompactSourceElement.(Ref(rotor), sections, ops, outputs, θs, dradii, area_per_chord2, src_times) .|> trans + ses = LBLVSSourceElement{TDirect,TUInduction,TDoppler}.(Ref(rotor), sections_rs, ops_rs, outputs_rs, θs_rs, dradii_rs, src_times, Ref(dt), bls_rs, positive_x_rotation) .|> trans return ses end +""" + TipVortexSourceElement(rotor::CCBlade.Rotor, section::CCBlade.Section, op::CCBlade.OperatingPoint, out::CCBlade.Outputs, θ, Δr, τ, Δτ, bl::AbstractBoundaryLayer, blade_tip::AbstractBladeTip, positive_x_rotation) + +Construct a source element to be used to predict tip vortex noise. + +The source element's position is calculated from `section.r`, `rotor.precone`, and the `θ` argument using +```julia + sθ, cθ = sincos(θ) + spc, cpc = sincos(precone) + y0dot = [r*spc, r*cpc*cθ, r*cpc*sθ] +``` +where `y0dot` is the position of the source element. + +# Arguments +- `rotor::CCBlade.Rotor`: CCBlade rotor object, needed for the precone angle. +- `section::CCBlade.Section`: CCBlade section object, needed for the radial location and chord length of the element. +- `op::CCBlade.OperatingPoint`: CCBlade operating point, needed for atmospheric properties. +- `out::CCBlade.Outputs`: CCBlade outputs object, needed for the loading. +- `θ`: polar coordinate of the element, in radians. +- `Δr`: length of the element, in meters. +- `τ`: source time of the element, in seconds. +- `Δτ`: source time duration, in seconds. +- `bl`: `AcousticAnalogies.AbstractBoundaryLayer`, needed for boundary layer properties. +- `blade_tip`: `AcousticAnalogies.AbstractBladeTip` +- `positive_x_rotation`: rotate blade around the positive-x axis if `true`, negative-x axis otherwise. +""" +function TipVortexSourceElement(rotor::CCBlade.Rotor, section::CCBlade.Section, op::CCBlade.OperatingPoint, out::CCBlade.Outputs, θ, Δr, τ, Δτ, bl::AbstractBoundaryLayer, blade_tip::AbstractBladeTip, positive_x_rotation) + return TipVortexSourceElement{BrooksBurleyDirectivity,true,true}(rotor, section, op, out, θ, Δr, τ, Δτ, bl, blade_tip, positive_x_rotation) +end + +function TipVortexSourceElement{TDirect,TUInduction,TDoppler}(rotor::CCBlade.Rotor, section::CCBlade.Section, op::CCBlade.OperatingPoint, out::CCBlade.Outputs, θ, Δr, τ, Δτ, bl::AbstractBoundaryLayer, blade_tip::AbstractBladeTip, positive_x_rotation) where {TDirect,TUInduction,TDoppler} + + y0dot, y1dot, y1dot_fluid, span_uvec, chord_uvec, chord_cross_span_to_get_top_uvec = _get_position_velocity_span_uvec_chord_uvec( + section.theta, rotor.precone, op.pitch, section.r, θ, out.W, out.phi, positive_x_rotation) + + return TipVortexSourceElement{TDirect,TUInduction,TDoppler}(op.asound, Δr, section.chord, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, blade_tip, chord_cross_span_to_get_top_uvec) +end + +""" + tip_vortex_source_elements_ccblade(rotor::CCBlade.Rotor, section::CCBlade.Section, op::CCBlade.OperatingPoint, output::CCBlade.Outputs, bl::AbstractBoundaryLayer, blade_tip::AbstractBladeTip, period, num_src_times, positive_x_rotation) + +Construct and return an array of TipVortexSourceElement objects from CCBlade structs. + +Note that unlike the other `*_source_elements_ccblade` functions, `tip_vortex_source_elements_ccblade` expects scalar arguments instead of vectors for `section`, `op`, etc. as a blade only has one tip. + +# Arguments +- `rotor`: CCBlade rotor object. +- `section`: CCBlade section object at the blade tip. +- `op`: CCBlade operating point object at the blade tip. +- `output`: CCBlade output object at the blade tip. +- `Δr`: radial spacing. +- `bl`:: Boundary layer `struct` at the blade tip. +- `blade_tip`: `AcousticAnalogies.AbstractBladeTip` +- `period`: length of the source time over which the returned source elements will evaluated. +- `num_src_times`: number of source times. +- `positive_x_rotation`: rotate blade around the positive-x axis if `true`, negative-x axis otherwise. +""" +function tip_vortex_source_elements_ccblade(rotor, section, op, output, Δr, bl, blade_tip, period, num_src_times, positive_x_rotation) + return tip_vortex_source_elements_ccblade(BrooksBurleyDirectivity, true, true, rotor, section, op, output, Δr, bl, blade_tip, period, num_src_times, positive_x_rotation) +end + +function tip_vortex_source_elements_ccblade(TDirect::Type{<:AbstractDirectivity}, TUInduction::Bool, TDoppler::Bool, rotor, section, op, output, Δr, bl, blade_tip, period, num_src_times, positive_x_rotation) + # Ugh, hate doing this. + # Wish there was a way to make a allocation-free array-like thingy from a scaler. + # But I doubt it makes any difference. + # sections = [section] + # ops = [op] + # Good news! + # Learned about the FillArrays.jl package. + sections = Fill(section, 1) + ops = Fill(op, 1) + # But that breaks with CCBlade.jl. + # So back to 1D arrays. + # sections = [section] + # ops = [op] + + # Get the transformation that will put the source elements in the "standard" CCBlade.jl reference frame (moving axially in the positive x axis direction, rotating about the positive x axis, first blade initially aligned with the positive y axis). + src_times, dt, trans = _standard_ccblade_transform(rotor, sections, ops, period, num_src_times, positive_x_rotation) + + # This is just an array of the angular offsets of each blade. First blade is + # aligned with the y axis, next one is offset 2*pi/B radians, etc.. + num_blades = rotor.B + θs = 2*pi/num_blades.*(0:(num_blades-1)) .* ifelse(positive_x_rotation, 1, -1) + + # Reshape for broadcasting. Goal is to make everything work for a size of (num_times, num_radial, num_blades). + # But this will really be (num_times, 1, num_blades). + # trans_rs = reshape(trans, size(trans)..., 1) + θs_rs = reshape(θs, 1, 1, :) + # sections_rs = reshape(sections, 1, 1) + # ops_rs = reshape(ops, 1, 1) + # outputs = reshape(outputs, 1, :, 1) + # dradii = reshape(dradii, 1, :, 1) + # bls = reshape(bls, 1, :, 1) + # src_times = reshape(src_times, :, 1, 1) # This one isn't necessary. + + # Construct and transform the source elements. + # ses = TipVortexSourceElement.(Ref(rotor), sections_rs, ops_rs, Ref(output), θs_rs, Ref(Δr), src_times, Ref(dt), Ref(bl), positive_x_rotation) .|> trans_rs + # So Θs_rs has size (1, 1, num_blades), src_times has size (num_src_times,), trans has size (num_src_times, 1). + # So that should all work out. + ses = TipVortexSourceElement{TDirect,TUInduction,TDoppler}.(Ref(rotor), Ref(section), Ref(op), Ref(output), θs_rs, Ref(Δr), src_times, Ref(dt), Ref(bl), Ref(blade_tip), positive_x_rotation) .|> trans + + return ses +end + +""" + TEBVSSourceElement(rotor::CCBlade.Rotor, section::CCBlade.Section, op::CCBlade.OperatingPoint, out::CCBlade.Outputs, θ, Δr, h, Psi, τ, Δτ, bl::AbstractBoundaryLayer, positive_x_rotation) + +Construct a source element to be used to predict trailing edge bluntness-vortex shedding (TEBVS) noise. + +The source element's position is calculated from `section.r`, `rotor.precone`, and the `θ` argument using +```julia + sθ, cθ = sincos(θ) + spc, cpc = sincos(precone) + y0dot = [r*spc, r*cpc*cθ, r*cpc*sθ] +``` +where `y0dot` is the position of the source element. + +# Arguments +- `rotor::CCBlade.Rotor`: CCBlade rotor object, needed for the precone angle. +- `section::CCBlade.Section`: CCBlade section object, needed for the radial location and chord length of the element. +- `op::CCBlade.OperatingPoint`: CCBlade operating point, needed for atmospheric properties. +- `out::CCBlade.Outputs`: CCBlade outputs object, needed for the loading. +- `θ`: polar coordinate of the element, in radians. +- `Δr`: length of the element, in meters. +- `h`: trailing edge thickness (m) +- `Psi`: solid angle between the blade surfaces immediately upstream of the trailing edge (rad) +- `τ`: source time of the element, in seconds. +- `Δτ`: source time duration, in seconds. +- `bl`: `AcousticAnalogies.AbstractBoundaryLayer`, needed for boundary layer properties. +- `positive_x_rotation`: rotate blade around the positive-x axis if `true`, negative-x axis otherwise. +""" +function TEBVSSourceElement(rotor::CCBlade.Rotor, section::CCBlade.Section, op::CCBlade.OperatingPoint, out::CCBlade.Outputs, θ, Δr, h, Psi, τ, Δτ, bl::AbstractBoundaryLayer, positive_x_rotation) + return TEBVSSourceElement{BrooksBurleyDirectivity,true,true}(rotor, section, op, out, θ, Δr, h, Psi, τ, Δτ, bl, positive_x_rotation) +end + +function TEBVSSourceElement{TDirect,TUInduction,TDoppler}(rotor::CCBlade.Rotor, section::CCBlade.Section, op::CCBlade.OperatingPoint, out::CCBlade.Outputs, θ, Δr, h, Psi, τ, Δτ, bl::AbstractBoundaryLayer, positive_x_rotation) where {TDirect,TUInduction,TDoppler} + + y0dot, y1dot, y1dot_fluid, span_uvec, chord_uvec, chord_cross_span_to_get_top_uvec = _get_position_velocity_span_uvec_chord_uvec( + section.theta, rotor.precone, op.pitch, section.r, θ, out.W, out.phi, positive_x_rotation) + + nu = op.mu/op.rho + + return TEBVSSourceElement{TDirect,TUInduction,TDoppler}(op.asound, nu, Δr, section.chord, h, Psi, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, chord_cross_span_to_get_top_uvec) +end + +""" + tebvs_source_elements_ccblade(rotor::CCBlade.Rotor, sections::Vector{CCBlade.Section}, ops::Vector{CCBlade.OperatingPoint}, outputs::Vector{CCBlade.Outputs}, hs, Psis, bls::Vector{AbstractBoundaryLayer}, period, num_src_times, positive_x_rotation) + +Construct and return an array of TEBVSSourceElement objects from CCBlade structs. + +# Arguments +- `rotor`: CCBlade rotor object. +- `sections`: `Vector` of CCBlade section object. +- `ops`: `Vector` of CCBlade operating point. +- `outputs`: `Vector` of CCBlade output objects. +- `hs`: `Vector` of trailing edge thicknesses +- `Psis`: `Vector` of solid angles between the blade surfaces immediately upstream of the trailing edge (rad) +- `bls`::`Vector` of boundary layer `AbstractBoundaryLayer` `structs`. +- `period`: length of the source time over which the returned source elements will evaluated. +- `num_src_times`: number of source times. +- `positive_x_rotation`: rotate blade around the positive-x axis if `true`, negative-x axis otherwise. +""" +function tebvs_source_elements_ccblade(rotor, sections, ops, outputs, hs, Psis, bls, period, num_src_times, positive_x_rotation) + return tebvs_source_elements_ccblade(BrooksBurleyDirectivity, true, true, rotor, sections, ops, outputs, hs, Psis, bls, period, num_src_times, positive_x_rotation) +end + +function tebvs_source_elements_ccblade(TDirect::Type{<:AbstractDirectivity}, TUInduction::Bool, TDoppler::Bool, rotor, sections, ops, outputs, hs, Psis, bls, period, num_src_times, positive_x_rotation) + # Need to know the radial spacing. (CCBlade doesn't use this—when + # integrating stuff [loading to get torque and thrust] it uses the + # trapezoidal rule and passes in the radial locations, and assumes that + # integrands go to zero at the hub and tip.) Kind of lame that I have to + # calcluate it here, but whatever. Maybe I should use StaticArrays for this? + # Ah, no, I don't know the length at compile time. + dradii = get_ccblade_dradii(rotor, sections) + + # Get the transformation that will put the source elements in the "standard" CCBlade.jl reference frame (moving axially in the positive x axis direction, rotating about the positive x axis, first blade initially aligned with the positive y axis). + src_times, dt, trans = _standard_ccblade_transform(rotor, sections, ops, period, num_src_times, positive_x_rotation) + + # This is just an array of the angular offsets of each blade. First blade is + # aligned with the y axis, next one is offset 2*pi/B radians, etc.. + num_blades = rotor.B + θs = 2*pi/num_blades.*(0:(num_blades-1)) .* ifelse(positive_x_rotation, 1, -1) + + # Reshape for broadcasting. Goal is to make everything work for a size of (num_times, + # num_radial, num_blades). + # trans_rs = reshape(trans, size(trans)..., 1) + θs_rs = reshape(θs, 1, 1, :) + sections_rs = reshape(sections, 1, :, 1) + ops_rs = reshape(ops, 1, :, 1) + outputs_rs = reshape(outputs, 1, :, 1) + dradii_rs = reshape(dradii, 1, :, 1) + hs_rs = reshape(hs, 1, :, 1) + Psis_rs = reshape(Psis, 1, :, 1) + bls_rs = reshape(bls, 1, :, 1) + # src_times = reshape(src_times, :, 1, 1) # This one isn't necessary. + + # Construct and transform the source elements. + ses = TEBVSSourceElement{TDirect,TUInduction,TDoppler}.(Ref(rotor), sections_rs, ops_rs, outputs_rs, θs_rs, dradii_rs, hs_rs, Psis_rs, src_times, Ref(dt), bls_rs, positive_x_rotation) .|> trans + + return ses +end + +""" + CombinedNoTipBroadbandSourceElement(rotor::CCBlade.Rotor, section::CCBlade.Section, op::CCBlade.OperatingPoint, out::CCBlade.Outputs, θ, Δr, h, Psi, τ, Δτ, bl::AbstractBoundaryLayer, positive_x_rotation) + +Construct a source element for predicting turbulent boundary layer-trailing edge (TBLTE), laminar boundary layer-vortex shedding (LBLVS) noise, and trailing edge bluntness-vortex shedding (TEBVS) noise using the BPM/Brooks and Burley method from CCBlade structs. + +The source element's position is calculated from `section.r`, `rotor.precone`, and the `θ` argument using +```julia + sθ, cθ = sincos(θ) + spc, cpc = sincos(precone) + y0dot = [r*spc, r*cpc*cθ, r*cpc*sθ] +``` +where `y0dot` is the position of the source element. + +# Arguments +- `rotor::CCBlade.Rotor`: CCBlade rotor object, needed for the precone angle. +- `section::CCBlade.Section`: CCBlade section object, needed for the radial location and chord length of the element. +- `op::CCBlade.OperatingPoint`: CCBlade operating point, needed for atmospheric properties. +- `out::CCBlade.Outputs`: CCBlade outputs object, needed for the loading. +- `θ`: polar coordinate of the element, in radians. +- `Δr`: length of the element, in meters. +- `h`: trailing edge thickness (m) +- `Psi`: solid angle between the blade surfaces immediately upstream of the trailing edge (rad) +- `τ`: source time of the element, in seconds. +- `Δτ`: source time duration, in seconds. +- `bl`: `AcousticAnalogies.AbstractBoundaryLayer`, needed for boundary layer properties. +- `positive_x_rotation`: rotate blade around the positive-x axis if `true`, negative-x axis otherwise. +""" +function CombinedNoTipBroadbandSourceElement(rotor::CCBlade.Rotor, section::CCBlade.Section, op::CCBlade.OperatingPoint, out::CCBlade.Outputs, θ, Δr, h, Psi, τ, Δτ, bl::AbstractBoundaryLayer, positive_x_rotation) + return CombinedNoTipBroadbandSourceElement{BrooksBurleyDirectivity,true,PrandtlGlauertMachCorrection,true}(rotor, section, op, out, θ, Δr, h, Psi, τ, Δτ, bl, positive_x_rotation) +end + +function CombinedNoTipBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}(rotor::CCBlade.Rotor, section::CCBlade.Section, op::CCBlade.OperatingPoint, out::CCBlade.Outputs, θ, Δr, h, Psi, τ, Δτ, bl::AbstractBoundaryLayer, positive_x_rotation) where {TDirect,TUInduction,TMachCorrection,TDoppler} + + y0dot, y1dot, y1dot_fluid, span_uvec, chord_uvec, chord_cross_span_to_get_top_uvec = _get_position_velocity_span_uvec_chord_uvec( + section.theta, rotor.precone, op.pitch, section.r, θ, out.W, out.phi, positive_x_rotation) + + nu = op.mu/op.rho + + return CombinedNoTipBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}(op.asound, nu, Δr, section.chord, h, Psi, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, chord_cross_span_to_get_top_uvec) +end + +""" + CombinedWithTipBroadbandSourceElement(rotor::CCBlade.Rotor, section::CCBlade.Section, op::CCBlade.OperatingPoint, out::CCBlade.Outputs, θ, Δr, h, Psi, τ, Δτ, bl::AbstractBoundaryLayer, blade_tip::AbstractBladeTip, positive_x_rotation) + +Construct a source element for predicting turbulent boundary layer-trailing edge (TBLTE), laminar boundary layer-vortex shedding (LBLVS) noise, trailing edge bluntness-vortex shedding (TEBVS), and tip vortex noise using the BPM/Brooks and Burley method from CCBlade structs. + +The source element's position is calculated from `section.r`, `rotor.precone`, and the `θ` argument using +```julia + sθ, cθ = sincos(θ) + spc, cpc = sincos(precone) + y0dot = [r*spc, r*cpc*cθ, r*cpc*sθ] +``` +where `y0dot` is the position of the source element. + +# Arguments +- `rotor::CCBlade.Rotor`: CCBlade rotor object, needed for the precone angle. +- `section::CCBlade.Section`: CCBlade section object, needed for the radial location and chord length of the element. +- `op::CCBlade.OperatingPoint`: CCBlade operating point, needed for atmospheric properties. +- `out::CCBlade.Outputs`: CCBlade outputs object, needed for the loading. +- `θ`: polar coordinate of the element, in radians. +- `Δr`: length of the element, in meters. +- `h`: trailing edge thickness (m) +- `Psi`: solid angle between the blade surfaces immediately upstream of the trailing edge (rad) +- `τ`: source time of the element, in seconds. +- `Δτ`: source time duration, in seconds. +- `bl`: `AcousticAnalogies.AbstractBoundaryLayer`, needed for boundary layer properties. +- `blade_tip`: Blade tip struct, i.e. an AbstractBladeTip. +- `positive_x_rotation`: rotate blade around the positive-x axis if `true`, negative-x axis otherwise. +""" +function CombinedWithTipBroadbandSourceElement(rotor::CCBlade.Rotor, section::CCBlade.Section, op::CCBlade.OperatingPoint, out::CCBlade.Outputs, θ, Δr, h, Psi, τ, Δτ, bl::AbstractBoundaryLayer, blade_tip::AbstractBladeTip, positive_x_rotation) + return CombinedWithTipBroadbandSourceElement{BrooksBurleyDirectivity,true,PrandtlGlauertMachCorrection,true}(rotor, section, op, out, θ, Δr, h, Psi, τ, Δτ, bl, blade_tip, positive_x_rotation) +end + +function CombinedWithTipBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}(rotor::CCBlade.Rotor, section::CCBlade.Section, op::CCBlade.OperatingPoint, out::CCBlade.Outputs, θ, Δr, h, Psi, τ, Δτ, bl::AbstractBoundaryLayer, blade_tip::AbstractBladeTip, positive_x_rotation) where {TDirect,TUInduction,TMachCorrection,TDoppler} + + y0dot, y1dot, y1dot_fluid, span_uvec, chord_uvec, chord_cross_span_to_get_top_uvec = _get_position_velocity_span_uvec_chord_uvec( + section.theta, rotor.precone, op.pitch, section.r, θ, out.W, out.phi, positive_x_rotation) + + nu = op.mu/op.rho + + return CombinedWithTipBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}(op.asound, nu, Δr, section.chord, h, Psi, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, blade_tip, chord_cross_span_to_get_top_uvec) +end + +""" + combined_broadband_source_elements_ccblade(rotor::CCBlade.Rotor, sections::Vector{CCBlade.Section}, ops::Vector{CCBlade.OperatingPoint}, outputs::Vector{CCBlade.Outputs}, hs::Vector{Float64}, Psis::Vector{Float64}, bls::Vector{AbstractBoundaryLayer}, blade_tip::AbstractBladeTip, period, num_src_times, positive_x_rotation) + +Construct and return an array of broadband prediction source element objects from CCBlade structs. + +# Arguments +- `rotor`: CCBlade rotor object. +- `sections`: `Vector` of CCBlade section object. +- `ops`: `Vector` of CCBlade operating point. +- `outputs`: `Vector` of CCBlade output objects. +- `hs`: `Vector` of trailing edge thicknesses (m) +- `Psis`: `Vector` of solid angles between the blade surfaces immediately upstream of the trailing edge (rad) +- `bls`::`Vector` of boundary layer `AbstractBoundaryLayer` `structs`. +- `blade_tip`: Blade tip struct, i.e. an AbstractBladeTip. +- `period`: length of the source time over which the returned source elements will evaluated. +- `num_src_times`: number of source times. +- `positive_x_rotation`: rotate blade around the positive-x axis if `true`, negative-x axis otherwise. +""" +function combined_broadband_source_elements_ccblade(rotor, sections, ops, outputs, hs, Psis, bls, blade_tip, period, num_src_times, positive_x_rotation) + return combined_broadband_source_elements_ccblade(BrooksBurleyDirectivity, true, PrandtlGlauertMachCorrection, true, rotor, sections, ops, outputs, hs, Psis, bls, blade_tip, period, num_src_times, positive_x_rotation) +end + +function combined_broadband_source_elements_ccblade(TDirect::Type{<:AbstractDirectivity}, TUInduction::Bool, TMachCorrection::Type{<:AbstractMachCorrection}, TDoppler::Bool, rotor, sections, ops, outputs, hs, Psis, bls::AbstractVector{<:AbstractBoundaryLayer}, blade_tip, period, num_src_times, positive_x_rotation) + # Need to know the radial spacing. (CCBlade doesn't use this—when + # integrating stuff [loading to get torque and thrust] it uses the + # trapezoidal rule and passes in the radial locations, and assumes that + # integrands go to zero at the hub and tip.) Kind of lame that I have to + # calcluate it here, but whatever. Maybe I should use StaticArrays for this? + # Ah, no, I don't know the length at compile time. + dradii = get_ccblade_dradii(rotor, sections) + + # Get the transformation that will put the source elements in the "standard" CCBlade.jl reference frame (moving axially in the positive x axis direction, rotating about the positive x axis, first blade initially aligned with the positive y axis). + # Will be size (num_times, num_radial), so we'll need to adjust for the no tip/with tip stuff. + src_times, dt, trans = _standard_ccblade_transform(rotor, sections, ops, period, num_src_times, positive_x_rotation) + + # This is just an array of the angular offsets of each blade. First blade is + # aligned with the y axis, next one is offset 2*pi/B radians, etc.. + num_blades = rotor.B + θs = 2*pi/num_blades.*(0:(num_blades-1)) .* ifelse(positive_x_rotation, 1, -1) + + # Reshape for broadcasting. Goal is to make everything work for a size of (num_times, num_radial, num_blades). + θs_rs = reshape(θs, 1, 1, :) + sections_rs = reshape(sections, 1, :, 1) + ops_rs = reshape(ops, 1, :, 1) + outputs_rs = reshape(outputs, 1, :, 1) + dradii_rs = reshape(dradii, 1, :, 1) + hs_rs = reshape(hs, 1, :, 1) + Psis_rs = reshape(Psis, 1, :, 1) + bls_rs = reshape(bls, 1, :, 1) + # src_times = reshape(src_times, :, 1, 1) # This one isn't necessary. + + # So, I want to create some structs for all the non-blade tip elements, and the blade tip elements. + # So I just need to slice things appropriately. + sections_rs_no_tip = @view sections_rs[:, begin:end-1, :] + ops_rs_no_tip = @view ops_rs[:, begin:end-1, :] + outputs_rs_no_tip = @view outputs_rs[:, begin:end-1, :] + dradii_rs_no_tip = @view dradii_rs[:, begin:end-1, :] + hs_rs_no_tip = @view hs_rs[:, begin:end-1, :] + Psis_rs_no_tip = @view Psis_rs[:, begin:end-1, :] + bls_rs_no_tip = @view bls_rs[:, begin:end-1, :] + trans_no_tip = @view trans[:, begin:end-1] + + sections_rs_with_tip = @view sections_rs[:, end:end, :] + ops_rs_with_tip = @view ops_rs[:, end:end, :] + outputs_rs_with_tip = @view outputs_rs[:, end:end, :] + dradii_rs_with_tip = @view dradii_rs[:, end:end, :] + hs_rs_with_tip = @view hs_rs[:, end:end, :] + Psis_rs_with_tip = @view Psis_rs[:, end:end, :] + bls_rs_with_tip = @view bls_rs[:, end:end, :] + trans_with_tip = @view trans[:, end:end] + + # Construct and transform the source elements. + ses_no_tip = CombinedNoTipBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}.(Ref(rotor), sections_rs_no_tip, ops_rs_no_tip, outputs_rs_no_tip, θs_rs, dradii_rs_no_tip, hs_rs_no_tip, Psis_rs_no_tip, src_times, Ref(dt), bls_rs_no_tip, positive_x_rotation) .|> trans_no_tip + + ses_with_tip = CombinedWithTipBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}.(Ref(rotor), sections_rs_with_tip, ops_rs_with_tip, outputs_rs_with_tip, θs_rs, dradii_rs_with_tip, hs_rs_with_tip, Psis_rs_with_tip, src_times, Ref(dt), bls_rs_with_tip, Ref(blade_tip), positive_x_rotation) .|> trans_with_tip + + return ses_no_tip, ses_with_tip +end + """ get_ccblade_dradii(rotor::CCBlade.Rotor, sections::Vector{CCBlade.Section}) diff --git a/src/combined_broadband.jl b/src/combined_broadband.jl new file mode 100644 index 00000000..df12b1d9 --- /dev/null +++ b/src/combined_broadband.jl @@ -0,0 +1,728 @@ +struct CombinedNoTipBroadbandSourceElement{ + TDirect<:AbstractDirectivity,TUInduction,TMachCorrection,TDoppler, + Tc0,Tnu,TΔr,Tchord,Th,TPsi,Ty0dot,Ty1dot,Ty1dot_fluid,Tτ,TΔτ,Tspan_uvec,Tchord_uvec,Tbl + } <: AbstractBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,TDoppler} + # Speed of sound, m/s. + c0::Tc0 + # Kinematic viscosity, m^2/s + nu::Tnu + # Radial/spanwise length of element, m. + Δr::TΔr + # chord length of element, m. + chord::Tchord + # Trailing edge thickness, m. + h::Th + # Solid angle between blade surfaces immediately upstream of the trailing edge, rad. + Psi::TPsi + # Source position, m. + y0dot::Ty0dot + # Source velocity, m/s. + y1dot::Ty1dot + # Fluid velocity, m/s. + y1dot_fluid::Ty1dot_fluid + # Source time, s. + τ::Tτ + # Time step size, i.e. the amount of time this source element "exists" at with these properties, s. + Δτ::TΔτ + # Radial/spanwise unit vector, aka unit vector aligned with the element's span direction. + span_uvec::Tspan_uvec + # Chordwise unit vector, aka unit vector aligned with the element's chord line, pointing from leading edge to trailing edge. + chord_uvec::Tchord_uvec + # Boundary layer struct, i.e. an AbstractBoundaryLayer. + bl::Tbl + # `Bool` indicating chord_uvec×span_uvec will give a vector pointing from bottom side (usually pressure side) to top side (usually suction side) if `true`, or the opposite if `false`. + chord_cross_span_to_get_top_uvec::Bool + + function CombinedNoTipBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}(c0, nu, Δr, chord, h, Psi, y0dot::AbstractVector, y1dot::AbstractVector, y1dot_fluid::AbstractVector, τ, Δτ, span_uvec::AbstractVector, chord_uvec::AbstractVector, bl, chord_cross_span_to_get_top_uvec::Bool) where {TDirect<:AbstractDirectivity,TUInduction,TMachCorrection,TDoppler} + return new{ + TDirect,TUInduction,TMachCorrection,TDoppler, + typeof(c0), typeof(nu), typeof(Δr), typeof(chord), typeof(h), typeof(Psi), typeof(y0dot), typeof(y1dot), typeof(y1dot_fluid), typeof(τ), typeof(Δτ), typeof(span_uvec), typeof(chord_uvec), typeof(bl) + }(c0, nu, Δr, chord, h, Psi, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, chord_cross_span_to_get_top_uvec) + end +end + +# Default to using the `BrooksBurleyDirectivity` directivity function, include induction in the flow speed normal to span (TUInduction == true), use the Prandtl-Glauert mach number correction, and Doppler-shift. +function CombinedNoTipBroadbandSourceElement(c0, nu, Δr, chord, h, Psi, y0dot::AbstractVector, y1dot::AbstractVector, y1dot_fluid::AbstractVector, τ, Δτ, span_uvec::AbstractVector, chord_uvec::AbstractVector, bl, chord_cross_span_to_get_top_uvec) + return CombinedNoTipBroadbandSourceElement{BrooksBurleyDirectivity,true,PrandtlGlauertMachCorrection,true}(c0, nu, Δr, chord, h, Psi, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, chord_cross_span_to_get_top_uvec) +end + +""" + CombinedNoTipBroadbandSourceElement(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) + +Construct a source element for predicting turbulent boundary layer-trailing edge (TBLTE), laminar boundary layer-vortex shedding (LBLVS) noise, and trailing edge bluntness-vortex shedding (TEBVS) noise using the BPM/Brooks and Burley method, using position and velocity data expressed in a cylindrical coordinate system. + +The `r` and `θ` arguments are used to define the radial and circumferential position of the source element in a cylindrical coordinate system. +Likewise, the `vn`, `vr`, and `vc` arguments are used to define the normal, radial, and circumferential velocity of the fluid (in a reference frame moving with the element) in the same cylindrical coordinate system. +The cylindrical coordinate system is defined as follows: + + * The normal/axial direction is in the positive x axis + * The circumferential/azimuth angle `θ` is defined such that `θ = 0` means the radial direction is aligned with the positive y axis, and a positive `θ` indicates a right-handed rotation around the positive x axis. + +The `twist_about_positive_y` is a `Bool` controling how the `ϕ` argument is handled, which in turn controls the orientation of a unit vector defining `chord_uvec` indicating the orientation of the chord line, from leading edge to trailing edge. +If `twist_about_positive_y` is `true`, `chord_uvec` will initially be pointed in the negative-z direction, and then rotated around the positive y axis by an amount `ϕ` before being rotated by the azimuth angle `θ`. +(This would typcially be appropriate for a source element rotating around the positive x axis.) +If `twist_about_positive_y` is `false`, `chord_uvec` will initially be pointed in the positive-z direction, and then rotated around the negative y axis by an amount `ϕ` before being rotated by the azimuth angle `θ`. +(This would typcially be appropriate for a source element rotating around the negative x axis.) + +Note that, for a proper noise prediction, the source element needs to be transformed into the "global" frame, aka, the reference frame of the fluid. +This can be done easily with the transformations provided by the `KinematicCoordinateTransformations` package, or manually by modifying the components of the source element struct. + +# Arguments +- c0: Ambient speed of sound (m/s) +- nu: Kinematic viscosity (m^2/s) +- r: radial coordinate of the element in the blade-fixed coordinate system (m) +- θ: angular offest of the element in the blade-fixed coordinate system (rad) +- Δr: length of the element (m) +- chord: chord length of blade element (m) +- ϕ: twist of blade element (rad) +- h: trailing edge thickness (m) +- Psi: solid angle between the blade surfaces immediately upstream of the trailing edge (rad) +- vn: normal velocity of fluid (m/s) +- vr: radial velocity of fluid (m/s) +- vc: circumferential velocity of the fluid (m/s) +- τ: source time (s) +- Δτ: source time duration (s) +- bl: Boundary layer struct, i.e. an AbstractBoundaryLayer. +- twist_about_positive_y: if `true`, apply twist ϕ about positive y axis, negative y axis otherwise +""" +function CombinedNoTipBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) where {TDirect,TUInduction,TMachCorrection,TDoppler} + sθ, cθ = sincos(θ) + sϕ, cϕ = sincos(ϕ) + y0dot = @SVector [0, r*cθ, r*sθ] + T = eltype(y0dot) + y1dot = @SVector zeros(T, 3) + y1dot_fluid = @SVector [vn, vr*cθ - vc*sθ, vr*sθ + vc*cθ] + span_uvec = @SVector [0, cθ, sθ] + if twist_about_positive_y + chord_uvec = @SVector [-sϕ, cϕ*sθ, -cϕ*cθ] + else + chord_uvec = @SVector [-sϕ, -cϕ*sθ, cϕ*cθ] + end + + chord_cross_span_to_get_top_uvec = twist_about_positive_y + return CombinedNoTipBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}(c0, nu, Δr, chord, h, Psi, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, chord_cross_span_to_get_top_uvec) +end + +# Default to using the `BrooksBurleyDirectivity` directivity function, include induction in the flow speed normal to span (TUInduction == true), use the Prandtl-Glauert mach number correction, and Doppler-shift. +function CombinedNoTipBroadbandSourceElement(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) + return CombinedNoTipBroadbandSourceElement{BrooksBurleyDirectivity,true,PrandtlGlauertMachCorrection,true}(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) +end + +""" + CombinedNoTipBroadbandSourceElement(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, U, α, τ, Δτ, bl, twist_about_positive_y) + +Construct a source element for predicting turbulent boundary layer-trailing edge (TBLTE), laminar boundary layer-vortex shedding (LBLVS) noise, and trailing edge bluntness-vortex shedding (TEBVS) noise using the BPM/Brooks and Burley method, using the velocity magnitude `U` and angle of attack `α`. + +The `r` and `θ` arguments are used to define the radial and circumferential position of the source element in a cylindrical coordinate system. +The `U` and `α` arguments are the velocity magnitude normal to the source element length and the angle of attack, respectively. +The cylindrical coordinate system is defined as follows: + + * The normal/axial direction is in the positive x axis + * The circumferential/azimuth angle `θ` is defined such that `θ = 0` means the radial direction is aligned with the positive y axis, and a positive `θ` indicates a right-handed rotation around the positive x axis. + +The `twist_about_positive_y` is a `Bool` controling how the `ϕ` argument is handled, which in turn controls the orientation of a unit vector defining `chord_uvec` indicating the orientation of the chord line, from leading edge to trailing edge. +If `twist_about_positive_y` is `true`, `chord_uvec` will initially be pointed in the negative-z direction, and then rotated around the positive y axis by an amount `ϕ` before being rotated by the azimuth angle `θ`. +(This would typcially be appropriate for a source element rotating around the positive x axis.) +If `twist_about_positive_y` is `false`, `chord_uvec` will initially be pointed in the positive-z direction, and then rotated around the negative y axis by an amount `ϕ` before being rotated by the azimuth angle `θ`. +(This would typcially be appropriate for a source element rotating around the negative x axis.) + +Note that, for a proper noise prediction, the source element needs to be transformed into the "global" frame, aka, the reference frame of the fluid. +This can be done easily with the transformations provided by the `KinematicCoordinateTransformations` package, or manually by modifying the components of the source element struct. + +# Arguments +- c0: Ambient speed of sound (m/s) +- nu: Kinematic viscosity (m^2/s) +- r: radial coordinate of the element in the blade-fixed coordinate system (m) +- θ: angular offest of the element in the blade-fixed coordinate system (rad) +- Δr: length of the element (m) +- chord: chord length of blade element (m) +- ϕ: twist of blade element (rad) +- h: trailing edge thickness (m) +- Psi: solid angle between the blade surfaces immediately upstream of the trailing edge (rad) +- U: velocity magnitude (m/s) +- α: angle of attack (rad) +- τ: source time (s) +- Δτ: source time duration (s) +- bl: Boundary layer struct, i.e. an AbstractBoundaryLayer. +- twist_about_positive_y: if `true`, apply twist ϕ about positive y axis, negative y axis otherwise +""" +function CombinedNoTipBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, U, α, τ, Δτ, bl, twist_about_positive_y) where {TDirect,TUInduction,TMachCorrection,TDoppler} + precone = 0 + pitch = 0 + phi = ϕ - α + y0dot, y1dot, y1dot_fluid, span_uvec, chord_uvec, chord_cross_span_to_get_top_uvec = _get_position_velocity_span_uvec_chord_uvec(ϕ, precone, pitch, r, θ, U, phi, twist_about_positive_y) + return CombinedNoTipBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}(c0, nu, Δr, chord, h, Psi, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, chord_cross_span_to_get_top_uvec) +end + +# Default to using the `BrooksBurleyDirectivity` directivity function, include induction in the flow speed normal to span (TUInduction == true), use the PrandtlGlauertMachCorrection, and Doppler-shift. +function CombinedNoTipBroadbandSourceElement(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, U, α, τ, Δτ, bl, twist_about_positive_y::Bool) + return CombinedNoTipBroadbandSourceElement{BrooksBurleyDirectivity,true,PrandtlGlauertMachCorrection,true}(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, U, α, τ, Δτ, bl, twist_about_positive_y) +end + +""" + (trans::KinematicTransformation)(se::CombinedNoTipBroadbandSourceElement) + +Transform the position and orientation of a source element according to the coordinate system transformation `trans`. +""" +function (trans::KinematicTransformation)(se::CombinedNoTipBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}) where {TDirect,TUInduction,TMachCorrection,TDoppler} + linear_only = false + y0dot, y1dot = trans(se.τ, se.y0dot, se.y1dot, linear_only) + y0dot, y1dot_fluid = trans(se.τ, se.y0dot, se.y1dot_fluid, linear_only) + linear_only = true + span_uvec = trans(se.τ, se.span_uvec, linear_only) + chord_uvec = trans(se.τ, se.chord_uvec, linear_only) + + return CombinedNoTipBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}(se.c0, se.nu, se.Δr, se.chord, se.h, se.Psi, y0dot, y1dot, y1dot_fluid, se.τ, se.Δτ, span_uvec, chord_uvec, se.bl, se.chord_cross_span_to_get_top_uvec) +end + +""" + CombinedNoTipOutput(G_s, G_p, G_alpha, G_teb, cbands, dt, t) + +Output of the combined broadband noise calculation not including tip vortex noise: the acoustic pressure autospectrum centered at time `t` over observer duration `dt` and observer frequencies `cbands` for the TBLTE suction side `G_s`, TBLTE pressure side `G_p`, TBLTE separation noise `G_alpha`, and trailing edge bluntness noise `G_teb`. +""" +struct CombinedNoTipOutput{NO,TF,TG<:AbstractVector{TF},TFreqs<:AcousticMetrics.AbstractProportionalBands{NO,:center},TDTime,TTime} <: AcousticMetrics.AbstractProportionalBandSpectrum{NO,TF} + G_s::TG + G_p::TG + G_alpha::TG + G_lblvs::TG + G_teb::TG + cbands::TFreqs + dt::TDTime + t::TTime + + function CombinedNoTipOutput(G_s::TG, G_p::TG, G_alpha::TG, G_lblvs, G_teb::TG, cbands::AcousticMetrics.AbstractProportionalBands{NO,:center}, dt, t) where {NO,TG} + ncbands = length(cbands) + length(G_s) == ncbands || throw(ArgumentError("length(G_s) must match length(cbands)")) + length(G_p) == ncbands || throw(ArgumentError("length(G_p) must match length(cbands)")) + length(G_alpha) == ncbands || throw(ArgumentError("length(G_alpha) must match length(cbands)")) + length(G_lblvs) == ncbands || throw(ArgumentError("length(G_lblvs) must match length(cbands)")) + length(G_teb) == ncbands || throw(ArgumentError("length(G_teb) must match length(cbands)")) + dt > zero(dt) || throw(ArgumentError("dt must be positive")) + return new{NO,eltype(TG),TG,typeof(cbands),typeof(dt),typeof(t)}(G_s, G_p, G_alpha, G_lblvs, G_teb, cbands, dt, t) + end +end + +@inline function Base.getindex(pbs::CombinedNoTipOutput, i::Int) + @boundscheck checkbounds(pbs, i) + return @inbounds pbs.G_s[i] + pbs.G_p[i] + pbs.G_alpha[i] + +pbs.G_lblvs[i] + pbs.G_teb[i] +end + +@inline AcousticMetrics.has_observer_time(pbs::CombinedNoTipOutput) = true +@inline AcousticMetrics.observer_time(pbs::CombinedNoTipOutput) = pbs.t +@inline AcousticMetrics.timestep(pbs::CombinedNoTipOutput) = pbs.dt +@inline AcousticMetrics.time_scaler(pbs::CombinedNoTipOutput, period) = timestep(pbs)/period + +function noise(se::CombinedNoTipBroadbandSourceElement, obs::AbstractAcousticObserver, t_obs, freqs::AcousticMetrics.AbstractProportionalBands{3, :center}) + # Position of the observer: + x_obs = obs(t_obs) + + # Need the angle of attack. + alphastar = angle_of_attack(se) + + # Need the directivity functions. + top_is_suction = is_top_suction(se.bl, alphastar) + r_er, Dl, Dh = directivity(se, x_obs, top_is_suction) + + # Need the fluid velocity normal to the span. + # Brooks and Burley 2001 are a bit ambiguous on whether it should include induction, or just the freestream and rotation. + # + # * In the nomenclature section: `U` is "flow speed normal to span (`U_mn` with `mn` suppressed). + # So that's one point for "no induction." + # * In some discussion after equation (8), "The Mach number, `M = U/c0`, represents that component of velocity `U` normal to the span...". + # Hard to say one way or the other. + # * In equation (12), `U_mn` is the velocity without induction. + # So that's another point for "no induction." + # * Equation (14) defines `V_tot` as the velocity including the freestream, rotation, and induction. + # And then it defines `U` as the part of `V_tot` normal to the span. + # So that's a point for "yes induction." + # * In the directivity function definitions in equations (19) and (20), `M_tot` is used in the denominator, which seems to make it clear *that* velocity should include induction, since `V_tot` always includes induction. + # + # So, at the moment, the TBLTESourceElement type has a parameter TUInduction which, when true, will include induction in the flow speed normal to the span, and not otherwise. + U = speed_normal_to_span(se) + + # Reynolds number based on chord and the flow speed normal to span. + Re_c = U*se.chord/se.nu + + # Also need the displacement thicknesses for the pressure and suction sides. + deltastar_s = disp_thickness_s(se.bl, Re_c, alphastar)*se.chord + deltastar_p = disp_thickness_p(se.bl, Re_c, alphastar)*se.chord + + # Need the boundary layer thickness for the pressure side for LBL-VS noise. + delta_p = bl_thickness_p(se.bl, Re_c, alphastar)*se.chord + + # Now that we've decided on the directivity functions and the displacement thickness, and we know the correct value of `top_is_suction` we should be able to switch the sign on `alphastar` if it's negative, and reference it to the zero-lift value, as the BPM report does. + alphastar_positive = abs_cs_safe(alphastar - alpha_zerolift(se.bl)) + + # Mach number of the flow speed normal to span. + M = U/se.c0 + + # This stuff is used to decide if the blade element is stalled or not. + alphastar0 = alpha_stall(se.bl, Re_c) + gamma0_deg = gamma0(M) + deep_stall = (alphastar_positive*180/pi) > min(gamma0_deg, alphastar0*180/pi) + # if deep_stall + # println("deep_stall! M = $(M), alphastar_positive*180/pi = $(alphastar_positive*180/pi), gamma0_deg = $(gamma0_deg), alphastar0*180/pi = $(alphastar0*180/pi)") + # println("forcing deep_stall == false") + # deep_stall = false + # end + + St_peak_p = St_1(M) + St_peak_alpha = St_2(St_peak_p, alphastar_positive) + St_peak_s = 0.5*(St_peak_p + St_peak_alpha) + + Re_deltastar_p = U*deltastar_p/se.nu + k_1 = K_1(Re_c) + k_2 = K_2(Re_c, M, alphastar_positive) + Δk_1 = DeltaK_1(alphastar_positive, Re_deltastar_p) + + deltastar_s_U = deltastar_s/U + deltastar_p_U = deltastar_p/U + + # Stuff for LBLVS noise. + delta_p_U = delta_p/U + St_p_p = St_peak_prime(St_1_prime(Re_c), alphastar_positive) + Re_c_over_Re_c0 = Re_c / Re_c0(alphastar_positive) + g2 = G2(Re_c_over_Re_c0) + g3 = G3(alphastar_positive) + + # Brooks and Burley 2001 recommend a Prandtl-Glauert style Mach number correction, but only for the TBLTE noise. + # But whether or not it's included is dependent on the TMachCorrection type parameter for the source element. + m_corr = mach_correction(se, M) + + # Equation 73 from the BPM report. + deltastar_avg = 0.5*(deltastar_p + deltastar_s) + + h_over_deltastar_avg = se.h/deltastar_avg + h_U = se.h/U + St_3pp = St_3prime_peak(h_over_deltastar_avg, se.Psi) + g4 = G4(h_over_deltastar_avg, se.Psi) + + # The Brooks and Burley autospectrums appear to be scaled by the usual squared reference pressure (20 μPa)^2, but I'd like things in dimensional units, so multiply through by that. + pref2 = 4e-10 + G_s_scaler = (deltastar_s*M^5*se.Δr*Dh)/(r_er^2)*m_corr + G_s = _tble_te_s.(freqs, deltastar_s_U, Re_c, St_peak_s, k_1, G_s_scaler, deep_stall).*pref2 + + G_p_scaler = (deltastar_p*M^5*se.Δr*Dh)/(r_er^2)*m_corr + G_p = _tble_te_p.(freqs, deltastar_p_U, Re_c, St_peak_p, k_1, Δk_1, G_p_scaler, deep_stall).*pref2 + + G_alpha_scaler_l = (deltastar_s*M^5*se.Δr*Dl)/(r_er^2)*m_corr + G_alpha_scaler_h = G_s_scaler + G_alpha = _tble_te_alpha.(freqs, Re_c, deltastar_s_U, St_peak_alpha, k_2, G_alpha_scaler_l, G_alpha_scaler_h, deep_stall).*pref2 + + G_lbl_vs_scaler = (delta_p*M^5*se.Δr*Dh)/(r_er^2) + G_lbl_vs = _lbl_vs.(freqs, delta_p_U, St_p_p, g2, g3, G_lbl_vs_scaler) .* pref2 + + G_teb_vs_scaler = (se.h*(M^5.5)*se.Δr*Dh)/(r_er^2) + G_teb_vs = _teb_vs.(freqs, h_U, h_over_deltastar_avg, St_3pp, se.Psi, g4, G_teb_vs_scaler) .* pref2 + + # Also need the Doppler shift for this source-observer combination. + doppler = doppler_factor(se, obs, t_obs) + + # Get the doppler-shifted time step and proportional bands. + dt = se.Δτ/doppler + freqs_obs = AcousticMetrics.center_bands(freqs, doppler) + @assert AcousticMetrics.freq_scaler(freqs_obs) ≈ doppler + + # All done. + return CombinedNoTipOutput(G_s, G_p, G_alpha, G_lbl_vs, G_teb_vs, freqs_obs, dt, t_obs) +end + +struct CombinedWithTipBroadbandSourceElement{ + TDirect<:AbstractDirectivity,TUInduction,TMachCorrection,TDoppler, + Tc0,Tnu,TΔr,Tchord,Th,TPsi,Ty0dot,Ty1dot,Ty1dot_fluid,Tτ,TΔτ,Tspan_uvec,Tchord_uvec,Tbl,Tblade_tip + } <: AbstractBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,TDoppler} + # Speed of sound, m/s. + c0::Tc0 + # Kinematic viscosity, m^2/s + nu::Tnu + # Radial/spanwise length of element, m. + Δr::TΔr + # chord length of element, m. + chord::Tchord + # Trailing edge thickness, m. + h::Th + # Solid angle between blade surfaces immediately upstream of the trailing edge, rad. + Psi::TPsi + # Source position, m. + y0dot::Ty0dot + # Source velocity, m/s. + y1dot::Ty1dot + # Fluid velocity, m/s. + y1dot_fluid::Ty1dot_fluid + # Source time, s. + τ::Tτ + # Time step size, i.e. the amount of time this source element "exists" at with these properties, s. + Δτ::TΔτ + # Radial/spanwise unit vector, aka unit vector aligned with the element's span direction. + span_uvec::Tspan_uvec + # Chordwise unit vector, aka unit vector aligned with the element's chord line, pointing from leading edge to trailing edge. + chord_uvec::Tchord_uvec + # Boundary layer struct, i.e. an AbstractBoundaryLayer. + bl::Tbl + # Blade tip struct, i.e. and AbstractBladeTip + blade_tip::Tblade_tip + # `Bool` indicating chord_uvec×span_uvec will give a vector pointing from bottom side (usually pressure side) to top side (usually suction side) if `true`, or the opposite if `false`. + chord_cross_span_to_get_top_uvec::Bool + + function CombinedWithTipBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}(c0, nu, Δr, chord, h, Psi, y0dot::AbstractVector, y1dot::AbstractVector, y1dot_fluid::AbstractVector, τ, Δτ, span_uvec::AbstractVector, chord_uvec::AbstractVector, bl, blade_tip, chord_cross_span_to_get_top_uvec::Bool) where {TDirect<:AbstractDirectivity,TUInduction,TMachCorrection,TDoppler} + return new{ + TDirect,TUInduction,TMachCorrection,TDoppler, + typeof(c0), typeof(nu), typeof(Δr), typeof(chord), typeof(h), typeof(Psi), typeof(y0dot), typeof(y1dot), typeof(y1dot_fluid), typeof(τ), typeof(Δτ), typeof(span_uvec), typeof(chord_uvec), typeof(bl), typeof(blade_tip) + }(c0, nu, Δr, chord, h, Psi, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, blade_tip, chord_cross_span_to_get_top_uvec) + end +end + +# Default to using the `BrooksBurleyDirectivity` directivity function, include induction in the flow speed normal to span (TUInduction == true), use the Prandtl-Glauert mach number correction, and Doppler-shift. +function CombinedWithTipBroadbandSourceElement(c0, nu, Δr, chord, h, Psi, y0dot::AbstractVector, y1dot::AbstractVector, y1dot_fluid::AbstractVector, τ, Δτ, span_uvec::AbstractVector, chord_uvec::AbstractVector, bl, blade_tip, chord_cross_span_to_get_top_uvec) + return CombinedWithTipBroadbandSourceElement{BrooksBurleyDirectivity,true,PrandtlGlauertMachCorrection,true}(c0, nu, Δr, chord, h, Psi, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, blade_tip, chord_cross_span_to_get_top_uvec) +end + +""" + CombinedWithTipBroadbandSourceElement(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) + +Construct a source element for predicting turbulent boundary layer-trailing edge (TBLTE), laminar boundary layer-vortex shedding (LBLVS) noise, trailing edge bluntness-vortex shedding (TEBVS) noise, and tip vortex noise using the BPM/Brooks and Burley method, using position and velocity data expressed in a cylindrical coordinate system. + +The `r` and `θ` arguments are used to define the radial and circumferential position of the source element in a cylindrical coordinate system. +Likewise, the `vn`, `vr`, and `vc` arguments are used to define the normal, radial, and circumferential velocity of the fluid (in a reference frame moving with the element) in the same cylindrical coordinate system. +The cylindrical coordinate system is defined as follows: + + * The normal/axial direction is in the positive x axis + * The circumferential/azimuth angle `θ` is defined such that `θ = 0` means the radial direction is aligned with the positive y axis, and a positive `θ` indicates a right-handed rotation around the positive x axis. + +The `twist_about_positive_y` is a `Bool` controling how the `ϕ` argument is handled, which in turn controls the orientation of a unit vector defining `chord_uvec` indicating the orientation of the chord line, from leading edge to trailing edge. +If `twist_about_positive_y` is `true`, `chord_uvec` will initially be pointed in the negative-z direction, and then rotated around the positive y axis by an amount `ϕ` before being rotated by the azimuth angle `θ`. +(This would typcially be appropriate for a source element rotating around the positive x axis.) +If `twist_about_positive_y` is `false`, `chord_uvec` will initially be pointed in the positive-z direction, and then rotated around the negative y axis by an amount `ϕ` before being rotated by the azimuth angle `θ`. +(This would typcially be appropriate for a source element rotating around the negative x axis.) + +Note that, for a proper noise prediction, the source element needs to be transformed into the "global" frame, aka, the reference frame of the fluid. +This can be done easily with the transformations provided by the `KinematicCoordinateTransformations` package, or manually by modifying the components of the source element struct. + +# Arguments +- c0: Ambient speed of sound (m/s) +- nu: Kinematic viscosity (m^2/s) +- r: radial coordinate of the element in the blade-fixed coordinate system (m) +- θ: angular offest of the element in the blade-fixed coordinate system (rad) +- Δr: length of the element (m) +- chord: chord length of blade element (m) +- ϕ: twist of blade element (rad) +- h: trailing edge thickness (m) +- Psi: solid angle between the blade surfaces immediately upstream of the trailing edge (rad) +- vn: normal velocity of fluid (m/s) +- vr: radial velocity of fluid (m/s) +- vc: circumferential velocity of the fluid (m/s) +- τ: source time (s) +- Δτ: source time duration (s) +- bl: Boundary layer struct, i.e. an AbstractBoundaryLayer. +- blade_tip: Blade tip struct, i.e. an AbstractBladeTip. +- twist_about_positive_y: if `true`, apply twist ϕ about positive y axis, negative y axis otherwise +""" +function CombinedWithTipBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, vn, vr, vc, τ, Δτ, bl, blade_tip, twist_about_positive_y) where {TDirect,TUInduction,TMachCorrection,TDoppler} + sθ, cθ = sincos(θ) + sϕ, cϕ = sincos(ϕ) + y0dot = @SVector [0, r*cθ, r*sθ] + T = eltype(y0dot) + y1dot = @SVector zeros(T, 3) + y1dot_fluid = @SVector [vn, vr*cθ - vc*sθ, vr*sθ + vc*cθ] + span_uvec = @SVector [0, cθ, sθ] + if twist_about_positive_y + chord_uvec = @SVector [-sϕ, cϕ*sθ, -cϕ*cθ] + else + chord_uvec = @SVector [-sϕ, -cϕ*sθ, cϕ*cθ] + end + + chord_cross_span_to_get_top_uvec = twist_about_positive_y + return CombinedWithTipBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}(c0, nu, Δr, chord, h, Psi, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, blade_tip, chord_cross_span_to_get_top_uvec) +end + +# Default to using the `BrooksBurleyDirectivity` directivity function, include induction in the flow speed normal to span (TUInduction == true), use the Prandtl-Glauert mach number correction, and Doppler-shift. +function CombinedWithTipBroadbandSourceElement(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, vn, vr, vc, τ, Δτ, bl, blade_tip, twist_about_positive_y) + return CombinedWithTipBroadbandSourceElement{BrooksBurleyDirectivity,true,PrandtlGlauertMachCorrection,true}(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, vn, vr, vc, τ, Δτ, bl, blade_tip, twist_about_positive_y) +end + +""" + CombinedWithTipBroadbandSourceElement(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, U, α, τ, Δτ, bl, blade_tip, twist_about_positive_y) + +Construct a source element for predicting turbulent boundary layer-trailing edge (TBLTE), laminar boundary layer-vortex shedding (LBLVS) noise, trailing edge bluntness-vortex shedding (TEBVS), and tip vortex noise using the BPM/Brooks and Burley method, using the velocity magnitude `U` and angle of attack `α`. + +The `r` and `θ` arguments are used to define the radial and circumferential position of the source element in a cylindrical coordinate system. +The `U` and `α` arguments are the velocity magnitude normal to the source element length and the angle of attack, respectively. +The cylindrical coordinate system is defined as follows: + + * The normal/axial direction is in the positive x axis + * The circumferential/azimuth angle `θ` is defined such that `θ = 0` means the radial direction is aligned with the positive y axis, and a positive `θ` indicates a right-handed rotation around the positive x axis. + +The `twist_about_positive_y` is a `Bool` controling how the `ϕ` argument is handled, which in turn controls the orientation of a unit vector defining `chord_uvec` indicating the orientation of the chord line, from leading edge to trailing edge. +If `twist_about_positive_y` is `true`, `chord_uvec` will initially be pointed in the negative-z direction, and then rotated around the positive y axis by an amount `ϕ` before being rotated by the azimuth angle `θ`. +(This would typcially be appropriate for a source element rotating around the positive x axis.) +If `twist_about_positive_y` is `false`, `chord_uvec` will initially be pointed in the positive-z direction, and then rotated around the negative y axis by an amount `ϕ` before being rotated by the azimuth angle `θ`. +(This would typcially be appropriate for a source element rotating around the negative x axis.) + +Note that, for a proper noise prediction, the source element needs to be transformed into the "global" frame, aka, the reference frame of the fluid. +This can be done easily with the transformations provided by the `KinematicCoordinateTransformations` package, or manually by modifying the components of the source element struct. + +# Arguments +- c0: Ambient speed of sound (m/s) +- nu: Kinematic viscosity (m^2/s) +- r: radial coordinate of the element in the blade-fixed coordinate system (m) +- θ: angular offest of the element in the blade-fixed coordinate system (rad) +- Δr: length of the element (m) +- chord: chord length of blade element (m) +- ϕ: twist of blade element (rad) +- h: trailing edge thickness (m) +- Psi: solid angle between the blade surfaces immediately upstream of the trailing edge (rad) +- U: velocity magnitude (m/s) +- α: angle of attack (rad) +- τ: source time (s) +- Δτ: source time duration (s) +- bl: Boundary layer struct, i.e. an AbstractBoundaryLayer. +- blade_tip: Blade tip struct, i.e. an AbstractBladeTip +- twist_about_positive_y: if `true`, apply twist ϕ about positive y axis, negative y axis otherwise +""" +function CombinedWithTipBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, U, α, τ, Δτ, bl, blade_tip, twist_about_positive_y) where {TDirect,TUInduction,TMachCorrection,TDoppler} + precone = 0 + pitch = 0 + phi = ϕ - α + y0dot, y1dot, y1dot_fluid, span_uvec, chord_uvec, chord_cross_span_to_get_top_uvec = _get_position_velocity_span_uvec_chord_uvec(ϕ, precone, pitch, r, θ, U, phi, twist_about_positive_y) + return CombinedWithTipBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}(c0, nu, Δr, chord, h, Psi, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, blade_tip, chord_cross_span_to_get_top_uvec) +end + +# Default to using the `BrooksBurleyDirectivity` directivity function, include induction in the flow speed normal to span (TUInduction == true), use the PrandtlGlauertMachCorrection, and Doppler-shift. +function CombinedWithTipBroadbandSourceElement(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, U, α, τ, Δτ, bl, blade_tip, twist_about_positive_y::Bool) + return CombinedWithTipBroadbandSourceElement{BrooksBurleyDirectivity,true,PrandtlGlauertMachCorrection,true}(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, U, α, τ, Δτ, bl, blade_tip, twist_about_positive_y) +end + +""" + (trans::KinematicTransformation)(se::CombinedWithTipBroadbandSourceElement) + +Transform the position and orientation of a source element according to the coordinate system transformation `trans`. +""" +function (trans::KinematicTransformation)(se::CombinedWithTipBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}) where {TDirect,TUInduction,TMachCorrection,TDoppler} + linear_only = false + y0dot, y1dot = trans(se.τ, se.y0dot, se.y1dot, linear_only) + y0dot, y1dot_fluid = trans(se.τ, se.y0dot, se.y1dot_fluid, linear_only) + linear_only = true + span_uvec = trans(se.τ, se.span_uvec, linear_only) + chord_uvec = trans(se.τ, se.chord_uvec, linear_only) + + return CombinedWithTipBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}(se.c0, se.nu, se.Δr, se.chord, se.h, se.Psi, y0dot, y1dot, y1dot_fluid, se.τ, se.Δτ, span_uvec, chord_uvec, se.bl, se.blade_tip, se.chord_cross_span_to_get_top_uvec) +end + +""" + CombinedWithTipOutput(G_s, G_p, G_alpha, G_teb, G_tip, cbands, dt, t) + +Output of the combined broadband noise calculation: the acoustic pressure autospectrum centered at time `t` over observer duration `dt` and observer frequencies `cbands` for the TBLTE suction side `G_s`, TBLTE pressure side `G_p`, TBLTE separation noise `G_alpha`, trailing edge bluntness noise `G_teb`, and tip vortex noise `G_tip`. +""" +struct CombinedWithTipOutput{NO,TF,TG<:AbstractVector{TF},TFreqs<:AcousticMetrics.AbstractProportionalBands{NO,:center},TDTime,TTime} <: AcousticMetrics.AbstractProportionalBandSpectrum{NO,TF} + G_s::TG + G_p::TG + G_alpha::TG + G_lblvs::TG + G_teb::TG + G_tip::TG + cbands::TFreqs + dt::TDTime + t::TTime + + function CombinedWithTipOutput(G_s::TG, G_p::TG, G_alpha::TG, G_lblvs, G_teb::TG, G_tip::TG, cbands::AcousticMetrics.AbstractProportionalBands{NO,:center}, dt, t) where {NO,TG} + ncbands = length(cbands) + length(G_s) == ncbands || throw(ArgumentError("length(G_s) must match length(cbands)")) + length(G_p) == ncbands || throw(ArgumentError("length(G_p) must match length(cbands)")) + length(G_alpha) == ncbands || throw(ArgumentError("length(G_alpha) must match length(cbands)")) + length(G_lblvs) == ncbands || throw(ArgumentError("length(G_lblvs) must match length(cbands)")) + length(G_teb) == ncbands || throw(ArgumentError("length(G_teb) must match length(cbands)")) + length(G_tip) == ncbands || throw(ArgumentError("length(G_tip) must match length(cbands)")) + dt > zero(dt) || throw(ArgumentError("dt must be positive")) + return new{NO,eltype(TG),TG,typeof(cbands),typeof(dt),typeof(t)}(G_s, G_p, G_alpha, G_lblvs, G_teb, G_tip, cbands, dt, t) + end +end + +@inline function Base.getindex(pbs::CombinedWithTipOutput, i::Int) + @boundscheck checkbounds(pbs, i) + return @inbounds pbs.G_s[i] + pbs.G_p[i] + pbs.G_alpha[i] + pbs.G_teb[i] + pbs.G_tip[i] +end + +@inline AcousticMetrics.has_observer_time(pbs::CombinedWithTipOutput) = true +@inline AcousticMetrics.observer_time(pbs::CombinedWithTipOutput) = pbs.t +@inline AcousticMetrics.timestep(pbs::CombinedWithTipOutput) = pbs.dt +@inline AcousticMetrics.time_scaler(pbs::CombinedWithTipOutput, period) = timestep(pbs)/period + +function noise(se::CombinedWithTipBroadbandSourceElement, obs::AbstractAcousticObserver, t_obs, freqs::AcousticMetrics.AbstractProportionalBands{3, :center}) + # Position of the observer: + x_obs = obs(t_obs) + + # Need the angle of attack. + alphastar = angle_of_attack(se) + + # Need the angle of attack, including the possible tip correction. + alphatip = tip_vortex_alpha_correction(se.blade_tip, alphastar) + + # Need the directivity functions. + # But we have two angles of attack: one that includes a tip vortex correction, one that doesn't. + # But the angle of attack is only used to determine the value of `top_is_suction`, which in turn only depends on if the angle of attack is greater or less than the zero-lift angle of attack. + # And the tip vortex alpha correction is designed to not change that. + # So no worries about which alpha to use. + top_is_suction = is_top_suction(se.bl, alphastar) + r_er, Dl, Dh = directivity(se, x_obs, top_is_suction) + + # Need the fluid velocity normal to the span. + # Brooks and Burley 2001 are a bit ambiguous on whether it should include induction, or just the freestream and rotation. + # + # * In the nomenclature section: `U` is "flow speed normal to span (`U_mn` with `mn` suppressed). + # So that's one point for "no induction." + # * In some discussion after equation (8), "The Mach number, `M = U/c0`, represents that component of velocity `U` normal to the span...". + # Hard to say one way or the other. + # * In equation (12), `U_mn` is the velocity without induction. + # So that's another point for "no induction." + # * Equation (14) defines `V_tot` as the velocity including the freestream, rotation, and induction. + # And then it defines `U` as the part of `V_tot` normal to the span. + # So that's a point for "yes induction." + # * In the directivity function definitions in equations (19) and (20), `M_tot` is used in the denominator, which seems to make it clear *that* velocity should include induction, since `V_tot` always includes induction. + # + # So, at the moment, the TBLTESourceElement type has a parameter TUInduction which, when true, will include induction in the flow speed normal to the span, and not otherwise. + U = speed_normal_to_span(se) + + # Reynolds number based on chord and the flow speed normal to span. + Re_c = U*se.chord/se.nu + + # Also need the displacement thicknesses for the pressure and suction sides. + deltastar_s = disp_thickness_s(se.bl, Re_c, alphastar)*se.chord + deltastar_p = disp_thickness_p(se.bl, Re_c, alphastar)*se.chord + + # Need the boundary layer thickness for the pressure side for LBL-VS noise. + delta_p = bl_thickness_p(se.bl, Re_c, alphastar)*se.chord + + # Now that we've decided on the directivity functions and the displacement thickness, and we know the correct value of `top_is_suction` we should be able to switch the sign on `alphastar` if it's negative, and reference it to the zero-lift value, as the BPM report does. + alphastar_positive = abs_cs_safe(alphastar - alpha_zerolift(se.bl)) + + # Now that we've decided on the directivity functions and we know the correct value of `top_is_suction` we should be able to switch the sign on `alphastar` if it's negative, and reference it to the zero-lift value, as the BPM report does. + alphatip_positive = abs_cs_safe(alphatip - alpha_zerolift(se.bl)) + + # Mach number of the flow speed normal to span. + M = U/se.c0 + + # This stuff is used to decide if the blade element is stalled or not. + alphastar0 = alpha_stall(se.bl, Re_c) + gamma0_deg = gamma0(M) + deep_stall = (alphastar_positive*180/pi) > min(gamma0_deg, alphastar0*180/pi) + # if deep_stall + # println("deep_stall! M = $(M), alphastar_positive*180/pi = $(alphastar_positive*180/pi), gamma0_deg = $(gamma0_deg), alphastar0*180/pi = $(alphastar0*180/pi)") + # println("forcing deep_stall == false") + # deep_stall = false + # end + + St_peak_p = St_1(M) + St_peak_alpha = St_2(St_peak_p, alphastar_positive) + St_peak_s = 0.5*(St_peak_p + St_peak_alpha) + + Re_deltastar_p = U*deltastar_p/se.nu + k_1 = K_1(Re_c) + k_2 = K_2(Re_c, M, alphastar_positive) + Δk_1 = DeltaK_1(alphastar_positive, Re_deltastar_p) + + deltastar_s_U = deltastar_s/U + deltastar_p_U = deltastar_p/U + + # Stuff for LBLVS noise. + delta_p_U = delta_p/U + St_p_p = St_peak_prime(St_1_prime(Re_c), alphastar_positive) + Re_c_over_Re_c0 = Re_c / Re_c0(alphastar_positive) + g2 = G2(Re_c_over_Re_c0) + g3 = G3(alphastar_positive) + + # Brooks and Burley 2001 recommend a Prandtl-Glauert style Mach number correction, but only for the TBLTE noise. + # But whether or not it's included is dependent on the TMachCorrection type parameter for the source element. + m_corr = mach_correction(se, M) + + # Equation 73 from the BPM report. + deltastar_avg = 0.5*(deltastar_p + deltastar_s) + + h_over_deltastar_avg = se.h/deltastar_avg + h_U = se.h/U + St_3pp = St_3prime_peak(h_over_deltastar_avg, se.Psi) + g4 = G4(h_over_deltastar_avg, se.Psi) + + # Need the maximum mach number near the tip vortex. + M_max = tip_vortex_max_mach_number(se.blade_tip, M, alphatip_positive) + + # Now we can find the maximum speed near the tip vortex. + U_max = M_max * se.c0 + + # Get the tip vortex size. + l = tip_vortex_size_c(se.blade_tip, alphatip_positive) * se.chord + + # The Brooks and Burley autospectrums appear to be scaled by the usual squared reference pressure (20 μPa)^2, but I'd like things in dimensional units, so multiply through by that. + pref2 = 4e-10 + G_s_scaler = (deltastar_s*M^5*se.Δr*Dh)/(r_er^2)*m_corr + G_s = _tble_te_s.(freqs, deltastar_s_U, Re_c, St_peak_s, k_1, G_s_scaler, deep_stall).*pref2 + + G_p_scaler = (deltastar_p*M^5*se.Δr*Dh)/(r_er^2)*m_corr + G_p = _tble_te_p.(freqs, deltastar_p_U, Re_c, St_peak_p, k_1, Δk_1, G_p_scaler, deep_stall).*pref2 + + G_alpha_scaler_l = (deltastar_s*M^5*se.Δr*Dl)/(r_er^2)*m_corr + G_alpha_scaler_h = G_s_scaler + G_alpha = _tble_te_alpha.(freqs, Re_c, deltastar_s_U, St_peak_alpha, k_2, G_alpha_scaler_l, G_alpha_scaler_h, deep_stall).*pref2 + + G_lbl_vs_scaler = (delta_p*M^5*se.Δr*Dh)/(r_er^2) + G_lbl_vs = _lbl_vs.(freqs, delta_p_U, St_p_p, g2, g3, G_lbl_vs_scaler) .* pref2 + + G_teb_vs_scaler = (se.h*(M^5.5)*se.Δr*Dh)/(r_er^2) + G_teb_vs = _teb_vs.(freqs, h_U, h_over_deltastar_avg, St_3pp, se.Psi, g4, G_teb_vs_scaler) .* pref2 + + l_U_max = l/U_max + G_tip_scaler = (M^2*M_max^3*l^2*Dh/r_er^2) + G_tip = _tip.(freqs, l_U_max, G_tip_scaler) .* pref2 + + # Also need the Doppler shift for this source-observer combination. + doppler = doppler_factor(se, obs, t_obs) + + # Get the doppler-shifted time step and proportional bands. + dt = se.Δτ/doppler + freqs_obs = AcousticMetrics.center_bands(freqs, doppler) + # @assert AcousticMetrics.freq_scaler(freqs_obs) ≈ doppler + + # All done. + return CombinedWithTipOutput(G_s, G_p, G_alpha, G_lbl_vs, G_teb_vs, G_tip, freqs_obs, dt, t_obs) +end + +function pbs_suction(pbs::Union{TBLTEOutput,CombinedNoTipOutput,CombinedWithTipOutput}) + t = AcousticMetrics.observer_time(pbs) + dt = AcousticMetrics.timestep(pbs) + cbands = AcousticMetrics.center_bands(pbs) + return AcousticMetrics.ProportionalBandSpectrumWithTime(pbs.G_s, cbands, dt, t) +end + +function pbs_pressure(pbs::Union{TBLTEOutput,CombinedNoTipOutput,CombinedWithTipOutput}) + t = AcousticMetrics.observer_time(pbs) + dt = AcousticMetrics.timestep(pbs) + cbands = AcousticMetrics.center_bands(pbs) + return AcousticMetrics.ProportionalBandSpectrumWithTime(pbs.G_p, cbands, dt, t) +end + +function pbs_alpha(pbs::Union{TBLTEOutput,CombinedNoTipOutput,CombinedWithTipOutput}) + t = AcousticMetrics.observer_time(pbs) + dt = AcousticMetrics.timestep(pbs) + cbands = AcousticMetrics.center_bands(pbs) + return AcousticMetrics.ProportionalBandSpectrumWithTime(pbs.G_alpha, cbands, dt, t) +end + +function pbs_lblvs(pbs::Union{TBLTEOutput,CombinedNoTipOutput,CombinedWithTipOutput}) + t = AcousticMetrics.observer_time(pbs) + dt = AcousticMetrics.timestep(pbs) + cbands = AcousticMetrics.center_bands(pbs) + return AcousticMetrics.ProportionalBandSpectrumWithTime(pbs.G_lblvs, cbands, dt, t) +end + +function pbs_teb(pbs::Union{CombinedNoTipOutput,CombinedWithTipOutput}) + t = AcousticMetrics.observer_time(pbs) + dt = AcousticMetrics.timestep(pbs) + cbands = AcousticMetrics.center_bands(pbs) + return AcousticMetrics.ProportionalBandSpectrumWithTime(pbs.G_teb, cbands, dt, t) +end + +function pbs_tip(pbs::CombinedWithTipOutput) + t = AcousticMetrics.observer_time(pbs) + dt = AcousticMetrics.timestep(pbs) + cbands = AcousticMetrics.center_bands(pbs) + return AcousticMetrics.ProportionalBandSpectrumWithTime(pbs.G_tip, cbands, dt, t) +end diff --git a/src/deprecated.jl b/src/deprecated.jl new file mode 100644 index 00000000..d36b179c --- /dev/null +++ b/src/deprecated.jl @@ -0,0 +1,7 @@ +const CompactSourceElement = CompactF1ASourceElement +Base.@deprecate CompactSourceElement CompactF1ASourceElement + +Base.@deprecate f1a(se::CompactF1ASourceElement, obs::AbstractAcousticObserver, t_obs) noise(se::CompactF1ASourceElement, obs::AbstractAcousticObserver, t_obs) +Base.@deprecate f1a(se::CompactF1ASourceElement, obs::AbstractAcousticObserver) noise(se::CompactF1ASourceElement, obs::AbstractAcousticObserver) + +Base.@deprecate source_elements_ccblade(rotor, sections, ops, outputs, area_per_chord2, period, num_src_times, positive_x_rotation) f1a_source_elements_ccblade(rotor, sections, ops, outputs, area_per_chord2, period, num_src_times, positive_x_rotation) diff --git a/src/core.jl b/src/f1a.jl similarity index 61% rename from src/core.jl rename to src/f1a.jl index 99ef237a..7a407479 100644 --- a/src/core.jl +++ b/src/f1a.jl @@ -1,33 +1,45 @@ -@concrete struct CompactSourceElement +struct CompactF1ASourceElement{ + Tρ0,Tc0,TΔr,TΛ,Ty0dot,Ty1dot,Ty2dot,Ty3dot,Tf0dot,Tf1dot,Tτ,Tspan_uvec + } <: AbstractCompactSourceElement # Density. - ρ0 + ρ0::Tρ0 # Speed of sound. - c0 + c0::Tc0 # Radial length of element. - Δr + Δr::TΔr # Cross-sectional area. - Λ + Λ::TΛ # Source position and its time derivatives. - y0dot - y1dot - y2dot - y3dot + y0dot::Ty0dot + y1dot::Ty1dot + y2dot::Ty2dot + y3dot::Ty3dot # Load *on the fluid*, and its time derivative. - f0dot - f1dot + f0dot::Tf0dot + f1dot::Tf1dot # Source time. - τ + τ::Tτ # orientation of the element. Only used for WriteVTK. - u + span_uvec::Tspan_uvec end """ - CompactSourceElement(ρ0, c0, r, θ, Δr, Λ, fn, fc, τ) + CompactF1ASourceElement(ρ0, c0, r, θ, Δr, Λ, fn, fr, fc, τ) -Construct a source element to be used with the compact form of Farassat's formulation 1A. +Construct a source element to be used with the compact form of Farassat's formulation 1A, using position and loading data expressed in a cylindrical coordinate system. + +The `r` and `θ` arguments are used to define the radial and circumferential position of the source element in a cylindrical coordinate system. +Likewise, the `fn`, `fr`, and `fc` arguments are used to define the normal, radial, and circumferential loading per unit span *on the fluid* (in a reference frame moving with the element) in the same cylindrical coordinate system. +The cylindrical coordinate system is defined as follows: + + * The normal axial direction is in the positive x axis + * The circumferential/azimuth angle `θ` is defined such that `θ = 0` means the radial direction is aligned with the positive y axis, and a positive `θ` indicates a right-handed rotation around the positive x axis. + +Note that, for a proper noise prediction, the source element needs to be transformed into the "global" frame, aka, the reference frame of the fluid. +This can be done easily with the transformations provided by the `KinematicCoordinateTransformations` package, or manually by modifying the components of the source element struct. # Arguments - ρ0: Ambient air density (kg/m^3) @@ -41,7 +53,7 @@ Construct a source element to be used with the compact form of Farassat's formul - fc: circumferential load *on the fluid* (N/m) - τ: source time (s) """ -function CompactSourceElement(ρ0, c0, r, θ, Δr, Λ, fn, fr, fc, τ) +function CompactF1ASourceElement(ρ0, c0, r, θ, Δr, Λ, fn, fr, fc, τ) s, c = sincos(θ) y0dot = @SVector [0, r*c, r*s] T = eltype(y0dot) @@ -51,125 +63,46 @@ function CompactSourceElement(ρ0, c0, r, θ, Δr, Λ, fn, fr, fc, τ) f0dot = @SVector [fn, c*fr - s*fc, s*fr + c*fc] T = eltype(f0dot) f1dot = @SVector zeros(T, 3) - u = @SVector [0, c, s] + span_uvec = @SVector [0, c, s] - return CompactSourceElement(ρ0, c0, Δr, Λ, y0dot, y1dot, y2dot, y3dot, f0dot, f1dot, τ, u) + return CompactF1ASourceElement(ρ0, c0, Δr, Λ, y0dot, y1dot, y2dot, y3dot, f0dot, f1dot, τ, span_uvec) end """ - (trans::KinematicTransformation)(se::CompactSourceElement) + (trans::KinematicTransformation)(se::CompactF1ASourceElement) Transform the position and forces of a source element according to the coordinate system transformation `trans`. """ -function (trans::KinematicTransformation)(se::CompactSourceElement) +function (trans::KinematicTransformation)(se::CompactF1ASourceElement) linear_only = false y0dot, y1dot, y2dot, y3dot = trans(se.τ, se.y0dot, se.y1dot, se.y2dot, se.y3dot, linear_only) linear_only = true f0dot, f1dot= trans(se.τ, se.f0dot, se.f1dot, linear_only) - u = trans(se.τ, se.u, linear_only) + span_uvec = trans(se.τ, se.span_uvec, linear_only) - return CompactSourceElement(se.ρ0, se.c0, se.Δr, se.Λ, y0dot, y1dot, y2dot, y3dot, f0dot, f1dot, se.τ, u) -end - -""" -Supertype for an object that recieves a noise prediction when combined with an -acoustic analogy source; computational equivalent of a microphone. - - (obs::AcousticObserver)(t) - -Calculate the position of the acoustic observer at time `t`. -""" -abstract type AcousticObserver end - -""" - StationaryAcousticObserver(x) - -Construct an acoustic observer that does not move with position `x` (m). -""" -@concrete struct StationaryAcousticObserver <: AcousticObserver - x -end - -""" - ConstVelocityAcousticObserver(t0, x0, v) - -Construct an acoustic observer moving with a constant velocity `v`, located at -`x0` at time `t0`. -""" -@concrete struct ConstVelocityAcousticObserver <: AcousticObserver - t0 - x0 - v -end - -function (obs::StationaryAcousticObserver)(t) - return obs.x -end - -function (obs::ConstVelocityAcousticObserver)(t) - return obs.x0 .+ (t - obs.t0).*obs.v -end - -""" - adv_time(se::CompactSourceElement, obs::AcousticObserver) - -Calculate the time an acoustic wave emmited by source `se` at time `se.τ` is -recieved by observer `obs`. -""" -adv_time(se::CompactSourceElement, obs::AcousticObserver) - -function adv_time(se::CompactSourceElement, obs::StationaryAcousticObserver) - rv = obs(se.τ) .- se.y0dot - r = norm_cs_safe(rv) - t = se.τ + r/se.c0 - return t -end - -function adv_time(se::CompactSourceElement, obs::ConstVelocityAcousticObserver) - # Location of the observer at the source time. - x = obs(se.τ) - - # Vector from the source to the observer at the source time. - rv = x .- se.y0dot - - # Distance from the source to the observer at the source time. - r = norm_cs_safe(rv) - - # Speed of the observer divided by speed of sound. - Mo = norm_cs_safe(obs.v)/se.c0 - - # Unit vector pointing from the source to the observer. - rhat = rv/r - - # Velocity of observer dotted with rhat at the source time. - Mor = dot_cs_safe(obs.v, rhat)/se.c0 - - # Now get the observer time. - t = se.τ + r/se.c0*((Mor + sqrt(Mor^2 + 1 - Mo^2))/(1 - Mo^2)) - - return t + return CompactF1ASourceElement(se.ρ0, se.c0, se.Δr, se.Λ, y0dot, y1dot, y2dot, y3dot, f0dot, f1dot, se.τ, span_uvec) end """ Output of the F1A calculation: the acoustic pressure value at time `t`, broken into monopole component `p_m` and dipole component `p_d`. """ -@concrete struct F1AOutput - t - p_m - p_d +struct F1AOutput{Tt,Tp_m,Tp_d} + t::Tt + p_m::Tp_m + p_d::Tp_d end """ - f1a(se::CompactSourceElement, obs::AcousticObserver, t_obs) + noise(se::CompactF1ASourceElement, obs::AbstractAcousticObserver, t_obs) Calculate the acoustic pressure emitted by source element `se` and recieved by observer `obs` at time `t_obs`, returning an [`F1AOutput`](@ref) object. The correct value for `t_obs` can be found using [`adv_time`](@ref). """ -function f1a(se::CompactSourceElement, obs::AcousticObserver, t_obs) +function noise(se::CompactF1ASourceElement, obs::AbstractAcousticObserver, t_obs) x_obs = obs(t_obs) rv = x_obs .- se.y0dot @@ -224,17 +157,16 @@ function f1a(se::CompactSourceElement, obs::AcousticObserver, t_obs) end """ - f1a(se::CompactSourceElement, obs::AcousticObserver) + noise(se::CompactF1ASourceElement, obs::AbstractAcousticObserver) Calculate the acoustic pressure emitted by source element `se` and recieved by observer `obs`, returning an [`F1AOutput`](@ref) object. """ -function f1a(se::CompactSourceElement, obs::AcousticObserver) +function noise(se::CompactF1ASourceElement, obs::AbstractAcousticObserver) t_obs = adv_time(se, obs) - return f1a(se, obs, t_obs) + return noise(se, obs, t_obs) end - """ common_obs_time(apth::AbstractArray{<:F1AOutput}, period, n, axis=1) @@ -263,24 +195,20 @@ function common_obs_time(apth, period, n, axis=1) return t_common end -struct F1APressureTimeHistory{IsEven,T_p_m,T_p_d,T_dt,T_t0} <: AcousticMetrics.AbstractPressureTimeHistory{IsEven} - p_m::T_p_m - p_d::T_p_d - dt::T_dt - t0::T_t0 - function F1APressureTimeHistory{IsEven,T_p_m,T_p_d,T_dt,T_t0}(p_m, p_d, dt, t0) where {IsEven,T_p_m,T_p_d,T_dt,T_t0} +struct F1APressureTimeHistory{IsEven,Tp_m,Tp_d,Tdt,Tt0} <: AcousticMetrics.AbstractPressureTimeHistory{IsEven} + p_m::Tp_m + p_d::Tp_d + dt::Tdt + t0::Tt0 + function F1APressureTimeHistory{IsEven}(p_m, p_d, dt, t0) where {IsEven} n_p_m = length(p_m) n_p_d = length(p_d) - n_p_m == n_p_d || throw(ArgumentError("length(p_m) = $(n_p_m) is not the same as length(p_d) = $(n_p_d)")) - iseven(n_p_m) == IsEven || throw(ArgumentError("IsEven = $(IsEven) is not consistent with length(p_m) = $n_p_m")) - return new(p_m, p_d, dt, t0) + n_p_m == n_p_d || throw(ArgumentError("length(p_m) is not the same as length(p_d)")) + iseven(n_p_m) == IsEven || throw(ArgumentError("IsEven is not consistent with length(p_m) and length(p_d)")) + return new{IsEven, typeof(p_m), typeof(p_d), typeof(dt), typeof(t0)}(p_m, p_d, dt, t0) end end -function F1APressureTimeHistory{IsEven}(p_m::T_p_m, p_d::T_p_d, dt::T_dt, t0::T_t0) where {IsEven,T_p_m,T_p_d,T_dt,T_t0} - return F1APressureTimeHistory{IsEven,T_p_m,T_p_d,T_dt,T_t0}(p_m, p_d, dt, t0) -end - function F1APressureTimeHistory(p_m, p_d, dt, t0) ie = iseven(length(p_m)) return F1APressureTimeHistory{ie}(p_m, p_d, dt, t0) @@ -335,17 +263,21 @@ end @inline pressure_monopole(ap::F1APressureTimeHistory) = ap.p_m @inline pressure_dipole(ap::F1APressureTimeHistory) = ap.p_d +apth_monopole(ap::F1APressureTimeHistory) = AcousticMetrics.PressureTimeHistory(pressure_monopole(ap), AcousticMetrics.timestep(ap), AcousticMetrics.starttime(ap)) +apth_dipole(ap::F1APressureTimeHistory) = AcousticMetrics.PressureTimeHistory(pressure_dipole(ap), AcousticMetrics.timestep(ap), AcousticMetrics.starttime(ap)) + """ - combine!(apth_out::F1APressureTimeHistory, apth::AbstractArray{<:F1AOutput}, axis; f_interp=akima) + combine!(apth_out::F1APressureTimeHistory, apth::AbstractArray{<:F1AOutput}, time_axis; f_interp=akima) Combine the acoustic pressures of multiple sources (`apth`) into a single acoustic pressure time history `apth_out`. -The input acoustic pressures `apth` are interpolated onto the time grid -returned by `time(apth_out)`. The interpolation is performed by the function `f_intep(xpt, ypt, -x)`, where `xpt` and `ytp` are the input grid and function values, respectively, -and `x` is the output grid. +The input acoustic pressures `apth` are interpolated onto the time grid returned by `time(apth_out)`. +The interpolation is performed by the function `f_intep(xpt, ypt, x)`, where `xpt` and `ytp` are the input grid and function values, respectively, and `x` is the output grid. +`time_axis` is an integer indicating the time_axis of the `apth` array along which time varies. +For example, if `time_axis == 1` and `apth` is a three-dimensional array, then `apth[:, i, j]` would be the `F1AOutput` objects of the `i`, `j` source element for all time. +But if `time_axis == 3`, then `apth[i, j, :]` would be the `F1AOutput` objects of the `i`, `j` source element for all time. """ -function combine!(apth_out, apth, axis; f_interp=akima) +function combine!(apth_out, apth, time_axis; f_interp=akima) # This makes no difference compared to passing in a cache (an object with # working arrays that I'd copy stuff to) to this function (sometimes a # speedup of <1%, sometimes a slowdown of <1%). I'm sure it'd be worse if I @@ -361,15 +293,18 @@ function combine!(apth_out, apth, axis; f_interp=akima) p_m_interp = pressure_monopole(apth_out) p_d_interp = pressure_dipole(apth_out) - dimsAPTH = [axes(t_obs)...] + # dimsAPTH = [axes(t_obs)...] + dimsAPTH = axes(t_obs) ndimsAPTH = ndims(t_obs) - alldims = [1:ndimsAPTH;] # Is this any better than `collect(1:ndimsAPTH)`? + alldims = 1:ndimsAPTH - otherdims = setdiff(alldims, axis) + otherdims = setdiff(alldims, time_axis) itershape = tuple(dimsAPTH[otherdims]...) - idx = Any[first(ind) for ind in axes(t_obs)] - idx[axis] = Colon() + # idx = Any[first(ind) for ind in axes(t_obs)] + # idx[time_axis] = Colon() + # Create an array we'll use to index pbs_in, with a `Colon()` for the time_axis position and integers of the first value for all the others. + idx = [ifelse(d==time_axis, Colon(), first(ind)) for (d, ind) in enumerate(axes(t_obs))] nidx = length(otherdims) indices = CartesianIndices(itershape) @@ -383,21 +318,28 @@ function combine!(apth_out, apth, axis; f_interp=akima) for i in 1:nidx idx[otherdims[i]] = I.I[i] end - # Now I have the current indices of the source that I want to - # interpolate. - p_m_interp .+= f_interp(t_obs[idx...], p_m[idx...], t_common) - p_d_interp .+= f_interp(t_obs[idx...], p_d[idx...], t_common) + # Now I have the current indices of the source that I want to interpolate. + # p_m_interp .+= f_interp(t_obs[idx...], p_m[idx...], t_common) + # p_d_interp .+= f_interp(t_obs[idx...], p_d[idx...], t_common) + # Let's be cool and use views. + t_obs_v = @view t_obs[idx...] + p_m_v = @view p_m[idx...] + p_d_v = @view p_d[idx...] + p_m_interp .+= f_interp(t_obs_v, p_m_v, t_common) + p_d_interp .+= f_interp(t_obs_v, p_d_v, t_common) end return apth_out end """ - combine(apth::AbstractArray{<:F1AOutput}, period::AbstractFloat, n::Integer, axis=1; f_interp=akima) + combine(apth::AbstractArray{<:F1AOutput}, period::AbstractFloat, n::Integer, time_axis=1; f_interp=akima) + +Combine the acoustic pressures of multiple sources (`apth`) into a single acoustic pressure time history on a time grid of size `n` extending over time length `period`. -Combine the acoustic pressures of multiple sources (`apth`) into a single -acoustic pressure time history on a time grid of size `n` extending over time -length `period`. +`time_axis` is an integer indicating the time_axis of the `apth` array along which time varies. +For example, if `time_axis == 1` and `apth` is a three-dimensional array, then `apth[:, i, j]` would be the `F1AOutput` objects of the `i`, `j` source element for all time. +But if `time_axis == 3`, then `apth[i, j, :]` would be the `F1AOutput` objects of the `i`, `j` source element for all time. """ function combine(apth, period, n::Integer, axis::Integer=1; f_interp=akima) # Get the common observer time. diff --git a/src/lbl_vs.jl b/src/lbl_vs.jl new file mode 100644 index 00000000..f5dfde0a --- /dev/null +++ b/src/lbl_vs.jl @@ -0,0 +1,332 @@ +function St_1_prime(Re_c) + # Equation 55 in the BPM report. + T = typeof(Re_c) + if Re_c ≤ 1.3e5 + return 0.18*one(T) + elseif Re_c ≤ 4.0e5 + return 0.001756*Re_c^(0.3931) + else + return 0.28*one(T) + end +end + +function St_peak_prime(St_1_p, alphastar) + # Equation 56 in the BPM report. + alphastar_deg = alphastar*180/pi + return St_1_p*10.0^(-0.04*alphastar_deg) +end + +function G1(St_prime_over_St_peak_prime) + # Equation 57 in the BPM report. + e = St_prime_over_St_peak_prime + if e ≤ 0.5974 + return 39.8*log10(e) - 11.12 + elseif e ≤ 0.8545 + 98.409*log10(e) + 2.0 + elseif e ≤ 1.17 + return -5.076 + sqrt(2.484 - 506.25*log10(e)^2) + elseif e ≤ 1.674 + return -98.409*log10(e) + 2.0 + else + return -39.8*log10(e) - 11.12 + end +end + +function Re_c0(alphastar) + # Equation 59 in the BPM report. + alphastar_deg = alphastar*180/pi + if alphastar_deg ≤ 3.0 + return 10.0^(0.215*alphastar_deg + 4.978) + else + return 10.0^(0.120*alphastar_deg + 5.263) + end +end + +function G2(Re_c_over_Re_c0) + # Equation 58 in the BPM report. + d = Re_c_over_Re_c0 + if d ≤ 0.3237 + return 77.852*log10(d) + 15.328 + elseif d ≤ 0.5689 + return 65.188*log10(d) + 9.125 + elseif d ≤ 1.7579 + return -114.052*log10(d)^2 + elseif d ≤ 3.0889 + return -65.188*log10(d) + 9.125 + else + return -77.852*log10(d) + 15.328 + end +end + +function G3(alphastar) + alphastar_deg = alphastar*180/pi + return 171.04 - 3.03*alphastar_deg +end + +function LBL_VS(freq, nu, L, chord, U, M, M_c, r_e, theta_e, phi_e, alphastar, bl) + Re_c = U*chord/nu + delta_p = bl_thickness_p(bl, Re_c, alphastar)*chord + # Equation (54) from the BPM report. + St_prime = freq*delta_p/U + St_p_p = St_peak_prime(St_1_prime(Re_c), alphastar) + + St_prime_over_St_peak_prime = St_prime/St_p_p + Re_c_over_Re_c0 = Re_c / Re_c0(alphastar) + # SPL = 10*log10(delta_p*M^5*L*Dbar_h(theta_e, phi_e, M, M_c)/r_e^2) + G1(St_prime_over_St_peak_prime) + G2(Re_c_over_Re_c0) + G3(alphastar) + # Brooks and Burley AIAA 2001-2210 style. + H_l = 10^(0.1*(G1(St_prime_over_St_peak_prime) + G2(Re_c_over_Re_c0) + G3(alphastar))) + G_lbl_vs = (delta_p*M^5*L*Dbar_h(theta_e, phi_e, M, M_c))/(r_e^2)*H_l + SPL = 10*log10(G_lbl_vs) + return SPL +end + +struct LBLVSSourceElement{ + TDirect<:AbstractDirectivity,TUInduction,TDoppler, + Tc0,Tnu,TΔr,Tchord,Ty0dot,Ty1dot,Ty1dot_fluid,Tτ,TΔτ,Tspan_uvec,Tchord_uvec,Tbl + } <: AbstractBroadbandSourceElement{TDirect,TUInduction,NoMachCorrection,TDoppler} + # Speed of sound, m/s. + c0::Tc0 + # Kinematic viscosity, m^2/s + nu::Tnu + # Radial/spanwise length of element, m. + Δr::TΔr + # chord length of element, m. + chord::Tchord + # Source position, m. + y0dot::Ty0dot + # Source velocity, m/s. + y1dot::Ty1dot + # Fluid velocity, m/s. + y1dot_fluid::Ty1dot_fluid + # Source time, s. + τ::Tτ + # Time step size, i.e. the amount of time this source element "exists" with these properties, s. + Δτ::TΔτ + # Radial/spanwise unit vector, aka unit vector aligned with the element's span direction. + span_uvec::Tspan_uvec + # Chordwise unit vector, aka unit vector aligned with the element's chord line, pointing from leading edge to trailing edge. + chord_uvec::Tchord_uvec + # Boundary layer struct, i.e. an AbstractBoundaryLayer. + bl::Tbl + # `Bool` indicating chord_uvec×span_uvec will give a vector pointing from bottom side (usually pressure side) to top side (usually suction side) if `true`, or the opposite if `false`. + chord_cross_span_to_get_top_uvec::Bool + + function LBLVSSourceElement{TDirect,TUInduction,TDoppler}(c0, nu, Δr, chord, y0dot::AbstractVector, y1dot::AbstractVector, y1dot_fluid::AbstractVector, τ, Δτ, span_uvec::AbstractVector, chord_uvec::AbstractVector, bl, chord_cross_span_to_get_top_uvec::Bool) where {TDirect<:AbstractDirectivity,TUInduction,TDoppler} + return new{ + TDirect,TUInduction,TDoppler, + typeof(c0), typeof(nu), typeof(Δr), typeof(chord), typeof(y0dot), typeof(y1dot), typeof(y1dot_fluid), typeof(τ), typeof(Δτ), typeof(span_uvec), typeof(chord_uvec), typeof(bl) + }(c0, nu, Δr, chord, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, chord_cross_span_to_get_top_uvec) + end +end + +# Default to using the `BrooksBurleyDirectivity` directivity function, include induction in the flow speed normal to span (TUInduction == true), and Doppler-shift. +function LBLVSSourceElement(c0, nu, Δr, chord, y0dot::AbstractVector, y1dot::AbstractVector, y1dot_fluid::AbstractVector, τ, Δτ, span_uvec::AbstractVector, chord_uvec::AbstractVector, bl, chord_cross_span_to_get_top_uvec) + return LBLVSSourceElement{BrooksBurleyDirectivity,true,true}(c0, nu, Δr, chord, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, chord_cross_span_to_get_top_uvec) +end + +""" + LBLVSSourceElement(c0, nu, r, θ, Δr, chord, ϕ, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) + +Construct a source element for predicting laminar boundary layer-vortex shedding (LBLVS) noise using the BPM/Brooks and Burley method, using position and velocity data expressed in a cylindrical coordinate system. + +The `r` and `θ` arguments are used to define the radial and circumferential position of the source element in a cylindrical coordinate system. +Likewise, the `vn`, `vr`, and `vc` arguments are used to define the normal, radial, and circumferential velocity of the fluid (in a reference frame moving with the element) in the same cylindrical coordinate system. +The cylindrical coordinate system is defined as follows: + + * The normal/axial direction is in the positive x axis + * The circumferential/azimuth angle `θ` is defined such that `θ = 0` means the radial direction is aligned with the positive y axis, and a positive `θ` indicates a right-handed rotation around the positive x axis. + +The `twist_about_positive_y` is a `Bool` controling how the `ϕ` argument is handled, which in turn controls the orientation of a unit vector defining `chord_uvec` indicating the orientation of the chord line, from leading edge to trailing edge. +If `twist_about_positive_y` is `true`, `chord_uvec` will initially be pointed in the negative-z direction, and then rotated around the positive y axis by an amount `ϕ` before being rotated by the azimuth angle `θ`. +(This would typcially be appropriate for a source element rotating around the positive x axis.) +If `twist_about_positive_y` is `false`, `chord_uvec` will initially be pointed in the positive-z direction, and then rotated around the negative y axis by an amount `ϕ` before being rotated by the azimuth angle `θ`. +(This would typcially be appropriate for a source element rotating around the negative x axis.) + +Note that, for a proper noise prediction, the source element needs to be transformed into the "global" frame, aka, the reference frame of the fluid. +This can be done easily with the transformations provided by the `KinematicCoordinateTransformations` package, or manually by modifying the components of the source element struct. + +# Arguments +- c0: Ambient speed of sound (m/s) +- nu: Kinematic viscosity (m^2/s) +- r: radial coordinate of the element in the blade-fixed coordinate system (m) +- θ: angular offest of the element in the blade-fixed coordinate system (rad) +- Δr: length of the element (m) +- chord: chord length of blade element (m) +- ϕ: twist of blade element (rad) +- vn: normal velocity of fluid (m/s) +- vr: radial velocity of fluid (m/s) +- vc: circumferential velocity of the fluid (m/s) +- τ: source time (s) +- Δτ: source time duration (s) +- bl: Boundary layer struct, i.e. an AbstractBoundaryLayer. +- twist_about_positive_y: if `true`, apply twist ϕ about positive y axis, negative y axis otherwise +""" +function LBLVSSourceElement{TDirect,TUInduction,TDoppler}(c0, nu, r, θ, Δr, chord, ϕ, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) where {TDirect,TUInduction,TDoppler} + sθ, cθ = sincos(θ) + sϕ, cϕ = sincos(ϕ) + y0dot = @SVector [0, r*cθ, r*sθ] + T = eltype(y0dot) + y1dot = @SVector zeros(T, 3) + y1dot_fluid = @SVector [vn, vr*cθ - vc*sθ, vr*sθ + vc*cθ] + span_uvec = @SVector [0, cθ, sθ] + if twist_about_positive_y + chord_uvec = @SVector [-sϕ, cϕ*sθ, -cϕ*cθ] + else + chord_uvec = @SVector [-sϕ, -cϕ*sθ, cϕ*cθ] + end + + chord_cross_span_to_get_top_uvec = twist_about_positive_y + return LBLVSSourceElement{TDirect,TUInduction,TDoppler}(c0, nu, Δr, chord, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, chord_cross_span_to_get_top_uvec) +end + +# Default to using the `BrooksBurleyDirectivity` directivity function, include induction in the flow speed normal to span (TUInduction == true), and Doppler-shift. +function LBLVSSourceElement(c0, nu, r, θ, Δr, chord, ϕ, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) + return LBLVSSourceElement{BrooksBurleyDirectivity,true,true}(c0, nu, r, θ, Δr, chord, ϕ, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) +end + +""" + LBLVSSourceElement(c0, nu, r, θ, Δr, chord, ϕ, U, α, τ, Δτ, bl, twist_about_positive_y) + +Construct a source element for predicting laminar boundary layer-vortex shedding (LBLVS) noise using the BPM/Brooks and Burley method, using the velocity magnitude `U` and angle of attack `α`. + +The `r` and `θ` arguments are used to define the radial and circumferential position of the source element in a cylindrical coordinate system. +The `U` and `α` arguments are the velocity magnitude normal to the source element length and the angle of attack, respectively. +The cylindrical coordinate system is defined as follows: + + * The normal/axial direction is in the positive x axis + * The circumferential/azimuth angle `θ` is defined such that `θ = 0` means the radial direction is aligned with the positive y axis, and a positive `θ` indicates a right-handed rotation around the positive x axis. + +The `twist_about_positive_y` is a `Bool` controling how the `ϕ` argument is handled, which in turn controls the orientation of a unit vector defining `chord_uvec` indicating the orientation of the chord line, from leading edge to trailing edge. +If `twist_about_positive_y` is `true`, `chord_uvec` will initially be pointed in the negative-z direction, and then rotated around the positive y axis by an amount `ϕ` before being rotated by the azimuth angle `θ`. +(This would typcially be appropriate for a source element rotating around the positive x axis.) +If `twist_about_positive_y` is `false`, `chord_uvec` will initially be pointed in the positive-z direction, and then rotated around the negative y axis by an amount `ϕ` before being rotated by the azimuth angle `θ`. +(This would typcially be appropriate for a source element rotating around the negative x axis.) + +Note that, for a proper noise prediction, the source element needs to be transformed into the "global" frame, aka, the reference frame of the fluid. +This can be done easily with the transformations provided by the `KinematicCoordinateTransformations` package, or manually by modifying the components of the source element struct. + +# Arguments +- c0: Ambient speed of sound (m/s) +- nu: Kinematic viscosity (m^2/s) +- r: radial coordinate of the element in the blade-fixed coordinate system (m) +- θ: angular offest of the element in the blade-fixed coordinate system (rad) +- Δr: length of the element (m) +- chord: chord length of blade element (m) +- ϕ: twist of blade element (rad) +- U: velocity magnitude (m/s) +- α: angle of attack (rad) +- τ: source time (s) +- Δτ: source time duration (s) +- bl: Boundary layer struct, i.e. an AbstractBoundaryLayer. +- twist_about_positive_y: if `true`, apply twist ϕ about positive y axis, negative y axis otherwise +""" +function LBLVSSourceElement{TDirect,TUInduction,TDoppler}(c0, nu, r, θ, Δr, chord, ϕ, U, α, τ, Δτ, bl, twist_about_positive_y) where {TDirect,TUInduction,TDoppler} + precone = 0 + pitch = 0 + phi = ϕ - α + y0dot, y1dot, y1dot_fluid, span_uvec, chord_uvec, chord_cross_span_to_get_top_uvec = _get_position_velocity_span_uvec_chord_uvec(ϕ, precone, pitch, r, θ, U, phi, twist_about_positive_y::Bool) + return LBLVSSourceElement{TDirect,TUInduction,TDoppler}(c0, nu, Δr, chord, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, chord_cross_span_to_get_top_uvec) +end + +# Default to using the `BrooksBurleyDirectivity` directivity function, include induction in the flow speed normal to span (TUInduction == true), and Doppler-shift. +function LBLVSSourceElement(c0, nu, r, θ, Δr, chord, ϕ, U, α, τ, Δτ, bl, twist_about_positive_y) + return LBLVSSourceElement{BrooksBurleyDirectivity,true,true}(c0, nu, r, θ, Δr, chord, ϕ, U, α, τ, Δτ, bl, twist_about_positive_y) +end + +""" + (trans::KinematicTransformation)(se::LBLVSSourceElement) + +Transform the position and orientation of a source element according to the coordinate system transformation `trans`. +""" +function (trans::KinematicTransformation)(se::LBLVSSourceElement{TDirect,TUInduction,TDoppler}) where {TDirect,TUInduction,TDoppler} + linear_only = false + y0dot, y1dot = trans(se.τ, se.y0dot, se.y1dot, linear_only) + y0dot, y1dot_fluid = trans(se.τ, se.y0dot, se.y1dot_fluid, linear_only) + linear_only = true + span_uvec = trans(se.τ, se.span_uvec, linear_only) + chord_uvec = trans(se.τ, se.chord_uvec, linear_only) + + return LBLVSSourceElement{TDirect,TUInduction,TDoppler}(se.c0, se.nu, se.Δr, se.chord, y0dot, y1dot, y1dot_fluid, se.τ, se.Δτ, span_uvec, chord_uvec, se.bl, se.chord_cross_span_to_get_top_uvec) +end + +function _lbl_vs(freq, delta_p_U, St_p_p, g2, g3, scaler) + # St_prime = freq*deltastar_p/U + # St_prime_over_St_peak_prime = St_prime/St_p_p + # H_l = 10^(0.1*(G1(St_prime_over_St_peak_prime) + g2 + g3)) + St_prime = freq*delta_p_U + St_prime_over_St_peak_prime = St_prime/St_p_p + # return 10^(0.1*(G1(St_prime_over_St_peak_prime) + g2 + g3)) + H_l = 10^(0.1*(G1(St_prime_over_St_peak_prime) + g2 + g3)) + # G_lbl_vs = (deltastar_p*M^5*Δr*Dh)/(r_er^2)*H_l + G_lbl_vs = scaler*H_l + + # LBLVS = 10.0*log10((dpr*M^5*L*Dh)/rc^2)+G1+G2+G3 + # 10*log10((deltastar_p*M^5*Δr*Dh)/(r_er^2)*(10^(0.1*(G1(St_prime_over_St_peak_prime) + g2 + g3))) + # 10*log10((deltastar_p*M^5*Δr*Dh)/(r_er^2)) + 10*log10((10^(0.1*(G1(St_prime_over_St_peak_prime) + g2 + g3)))) + # 10*log10((deltastar_p*M^5*Δr*Dh)/(r_er^2)) + 10*(0.1*(G1(St_prime_over_St_peak_prime) + g2 + g3)) + # 10*log10((deltastar_p*M^5*Δr*Dh)/(r_er^2)) + G1(St_prime_over_St_peak_prime) + g2 + g3 + return G_lbl_vs +end + +function noise(se::LBLVSSourceElement, obs::AbstractAcousticObserver, t_obs, freqs::AcousticMetrics.AbstractProportionalBands{3, :center}) + # Position of the observer: + x_obs = obs(t_obs) + + # Need the angle of attack. + alphastar = angle_of_attack(se) + + # Need the directivity functions. + top_is_suction = is_top_suction(se.bl, alphastar) + r_er, Dl, Dh = directivity(se, x_obs, top_is_suction) + + # Need the fluid velocity normal to the span. + # Brooks and Burley 2001 are a bit ambiguous on whether it should include induction, or just the freestream and rotation. + # + # * In the nomenclature section: `U` is "flow speed normal to span (`U_mn` with `mn` suppressed). + # So that's one point for "no induction." + # * In some discussion after equation (8), "The Mach number, `M = U/c0`, represents that component of velocity `U` normal to the span...". + # Hard to say one way or the other. + # * In equation (12), `U_mn` is the velocity without induction. + # So that's another point for "no induction." + # * Equation (14) defines `V_tot` as the velocity including the freestream, rotation, and induction. + # And then it defines `U` as the part of `V_tot` normal to the span. + # So that's a point for "yes induction." + # * In the directivity function definitions in equations (19) and (20), `M_tot` is used in the denominator, which seems to make it clear *that* velocity should include induction, since `V_tot` always includes induction. + # + # So, at the moment, the TBLTESourceElement type has a parameter TUInduction which, when true, will include induction in the flow speed normal to the span, and not otherwise. + U = speed_normal_to_span(se) + + # Reynolds number based on chord and the flow speed normal to span. + Re_c = U*se.chord/se.nu + + # Need the boundary layer thickness for the pressure side for LBL-VS noise. + # deltastar_p = disp_thickness_p(se.bl, Re_c, alphastar)*se.chord + delta_p = bl_thickness_p(se.bl, Re_c, alphastar)*se.chord + + # Now that we've decided on the directivity functions and the displacement thickness, and we know the correct value of `top_is_suction` we should be able to switch the sign on `alphastar` if it's negative, and reference it to the zero-lift value, as the BPM report does. + alphastar_positive = abs_cs_safe(alphastar - alpha_zerolift(se.bl)) + + # Mach number of the flow speed normal to span. + M = U/se.c0 + + delta_p_U = delta_p/U + St_p_p = St_peak_prime(St_1_prime(Re_c), alphastar_positive) + Re_c_over_Re_c0 = Re_c / Re_c0(alphastar_positive) + g2 = G2(Re_c_over_Re_c0) + g3 = G3(alphastar_positive) + # The Brooks and Burley autospectrums appear to be scaled by the usual squared reference pressure (20 μPa)^2, but I'd like things in dimensional units, so multiply through by that. + pref2 = 4e-10 + # G = (delta_p*M^5*se.Δr*Dh)/(r_er^2) .* _Hl.(freq, delta_p_U, St_p_p, g2, g3) .* pref2 + G_lbl_vs_scaler = (delta_p*M^5*se.Δr*Dh)/(r_er^2) + G_lbl_vs = _lbl_vs.(freqs, delta_p_U, St_p_p, g2, g3, G_lbl_vs_scaler) .* pref2 + + # Also need the Doppler shift for this source-observer combination. + doppler = doppler_factor(se, obs, t_obs) + + # Get the doppler-shifted time step and proportional bands. + dt = se.Δτ/doppler + freqs_obs = AcousticMetrics.center_bands(freqs, doppler) + + # All done. + return AcousticMetrics.ProportionalBandSpectrumWithTime(G_lbl_vs, freqs_obs, dt, t_obs) +end diff --git a/src/observers.jl b/src/observers.jl new file mode 100644 index 00000000..bedfc4f1 --- /dev/null +++ b/src/observers.jl @@ -0,0 +1,52 @@ +""" +Supertype for an object that recieves a noise prediction when combined with an +acoustic analogy source; computational equivalent of a microphone. + + (obs::AbstractAcousticObserver)(t) + +Calculate the position of the acoustic observer at time `t`. +""" +abstract type AbstractAcousticObserver end + +""" + StationaryAcousticObserver(x) + +Construct an acoustic observer that does not move with position `x` (m). +""" +struct StationaryAcousticObserver{Tx} <: AbstractAcousticObserver + x::Tx +end + +""" + velocity(t_obs, obs::StationaryAcousticObserver) + +Return the velocity of `obs` at time `t_obs` (hint—will always be zero ☺) +""" +@inline velocity(t_obs, obs::StationaryAcousticObserver) = zero(obs.x) + +""" + ConstVelocityAcousticObserver(t0, x0, v) + +Construct an acoustic observer moving with a constant velocity `v`, located at +`x0` at time `t0`. +""" +struct ConstVelocityAcousticObserver{Tt0,Tx0,Tv} <: AbstractAcousticObserver + t0 ::Tt0 + x0::Tx0 + v::Tv +end + +function (obs::StationaryAcousticObserver)(t) + return obs.x +end + +function (obs::ConstVelocityAcousticObserver)(t) + return obs.x0 .+ (t - obs.t0).*obs.v +end + +""" + velocity(t_obs, obs::ConstVelocityAcousticObserver) + +Return the velocity of `obs` at time `t_obs` (hint—will always be the same) +""" +@inline velocity(t_obs, obs::ConstVelocityAcousticObserver) = obs.v diff --git a/src/tbl_te.jl b/src/tbl_te.jl new file mode 100644 index 00000000..39d046d0 --- /dev/null +++ b/src/tbl_te.jl @@ -0,0 +1,654 @@ +function K_1(Re_c) + # Equation (47) in the BPM paper. + if Re_c < 2.47e5 + return -4.31*log10(Re_c) + 156.3 + elseif Re_c < 8.0e5 + return -9.0*log10(Re_c) + 181.6 + else + return 128.5*one(Re_c) + end +end + +function DeltaK_1(alphastar, Re_deltastar_p) + # Equation (48) in the BPM report. + T = promote_type(typeof(alphastar), typeof(Re_deltastar_p)) + alphastar_deg = alphastar*180/pi + if Re_deltastar_p < 5000 + return alphastar_deg*(1.43*log10(Re_deltastar_p) - 5.29) + else + return zero(T) + end +end + +function St_1(M) + # Equation (31) from the BPM report. + return 0.02*M^(-0.6) +end + +function A_min(a) + # Equation (35) from the BPM report. + if a < 0.204 + return sqrt(67.552 - 886.788*a^2) - 8.219 + elseif a ≤ 0.244 + return -32.665*a + 3.981 + else + return -142.795*a^3 + 103.656*a^2 - 57.757*a + 6.006 + end +end + +function A_max(a) + # Equation (36) from the BPM report. + if a < 0.13 + return sqrt(67.552 - 886.788*a^2) - 8.219 + elseif a ≤ 0.321 + return -15.901*a + 1.098 + else + return -4.669*a^3 + 3.491*a^2 - 16.699*a + 1.149 + end +end + +function A(St_over_St_peak, Re_c) + # Equation (37) from the BPM report. + a = abs_cs_safe(log10(St_over_St_peak)) + + # Equation (38) from the BPM report. + if Re_c < 9.52e4 + a0 = 0.57*one(Re_c) + elseif Re_c ≤ 8.57e5 + a0 = (-9.57e-13)*(Re_c - 8.57e5)^2 + 1.13 + else + a0 = 1.13*one(Re_c) + end + + # Equation (39) from the BPM report. + A_min_a0 = A_min(a0) + A_max_a0 = A_max(a0) + A_R = (-20 - A_min_a0)/(A_max_a0 - A_min_a0) + + # Equation (40) from the BPM report. + A_min_a = A_min(a) + A_max_a = A_max(a) + return A_min_a + A_R*(A_max_a - A_min_a) +end + +function B_min(b) + # Equation (41) from the BPM report. + if b < 0.13 + return sqrt(16.888 - 886.788*b^2) - 4.109 + elseif b ≤ 0.145 + return -83.607*b + 8.138 + else + return -817.810*b^3 + 355.201*b^2 - 135.024*b + 10.619 + end +end + +function B_max(b) + # Equation (42) from the BPM report. + if b < 0.10 + return sqrt(16.888 - 886.788*b^2) - 4.109 + elseif b ≤ 0.187 + return -31.330*b + 1.854 + else + return -80.541*b^3 + 44.174*b^2 - 39.381*b + 2.344 + end +end + +function B(St_over_St_peak, Re_c) + # Equation (43) from the BPM report. + b = abs_cs_safe(log10(St_over_St_peak)) + + # Equation (44) from the BPM report. + if Re_c < 9.52e4 + b0 = 0.30*one(Re_c) + elseif Re_c ≤ 8.57e5 + b0 = (-4.48e-13)*(Re_c - 8.57e5)^2 + 0.56 + else + b0 = 0.56*one(Re_c) + end + + # Equation (45) from the BPM report. + B_min_b0 = B_min(b0) + B_max_b0 = B_max(b0) + B_R = (-20 - B_min_b0)/(B_max_b0 - B_min_b0) + + # Equation (46) from the BPM report. + B_min_b = B_min(b) + B_max_b = B_max(b) + return B_min_b + B_R*(B_max_b - B_min_b) +end + +function St_2(St_1, alphastar) + # Equation (34) from the BPM report. + T = promote_type(typeof(St_1), typeof(alphastar)) + alphastar_deg = alphastar*180/pi + if alphastar_deg < 1.333 + return St_1*one(T) + elseif alphastar_deg ≤ 12.5 + return St_1*10.0^(0.0054*(alphastar_deg - 1.333)^2) + else + return St_1*4.72*one(T) + end +end + +function gamma(M) + # Equation (50) from the BPM report. + gamma_deg = 27.094*M + 3.31 + return gamma_deg +end + +function gamma0(M) + # Equation (50) from the BPM report. + gamma0_deg = 23.43*M + 4.651 + return gamma0_deg +end + +function beta(M) + # Equation (50) from the BPM report. + beta_deg = 72.65*M + 10.74 + return beta_deg +end + +function beta0(M) + # Equation (50) from the BPM report. + beta0_deg = -34.19*M - 13.82 + return beta0_deg +end + +function K_2(Re_c, M, alphastar) + T = promote_type(typeof(Re_c), typeof(M), typeof(alphastar)) + alphastar_deg = alphastar*180/pi + + k_1 = K_1(Re_c)*one(T) + # Equation (50) from the BPM report. + # gamma_deg, gamma0_deg, beta_deg, beta0_deg = gammas_betas(M) + gamma_deg = gamma(M) + gamma0_deg = gamma0(M) + beta_deg = beta(M) + beta0_deg = beta0(M) + + # Equation (49) from the BPM report. + if alphastar_deg < gamma0_deg - gamma_deg + return k_1 - 1000 + # elseif alphastar_deg ≤ gamma0_deg + gamma_deg + elseif alphastar_deg ≤ gamma0_deg + sqrt(-(gamma_deg/beta_deg)^2*(-12 - beta0_deg)^2 + gamma_deg^2) + return k_1 + sqrt(beta_deg^2 - (beta_deg/gamma_deg)^2*(alphastar_deg - gamma0_deg)^2) + beta0_deg + else + return k_1 - 12 + end +end + +function St_1prime(Re_c) + # Equation (55) from the BPM report. + T = typeof(Re_c) + if Re_c < 1.3e5 + return 0.18*one(T) + elseif Re_c ≤ 4.0e5 + return 0.001756*Re_c^(0.3931) + else + return 0.28*one(T) + end +end + +function Dbar_h(theta_e, phi_e, M, M_c) + # Equation (B1) from the BPM report. + return (2*sin(0.5*theta_e)^2*sin(phi_e)^2)/((1 + M*cos(theta_e))*(1 + (M - M_c)*cos(theta_e))^2) +end + +function Dbar_l(theta_e, phi_e, M) + # Equation (B2) from the BPM report. + return (sin(theta_e)^2*sin(phi_e)^2)/((1 + M*cos(theta_e))^4) +end + +function TBL_TE_s(freq, nu, L, chord, U, M, M_c, r_e, theta_e, phi_e, alphastar, bl) + T = promote_type(typeof(freq), typeof(nu), typeof(L), typeof(chord), typeof(U), typeof(M), typeof(M_c), typeof(r_e), typeof(theta_e), typeof(phi_e), typeof(alphastar)) + + Re_c = U*chord/nu + alphastar0 = alpha_stall(bl, Re_c) + + gamma0_deg = gamma0(M) + if alphastar*180/pi > min(gamma0_deg, alphastar0*180/pi) + # SPL_s = -100*one(T) + G_s = 10^(0.1*(-100))*one(T) + else + D = Dbar_h(theta_e, phi_e, M, M_c) + deltastar_s = disp_thickness_top(bl, Re_c, alphastar)*chord + St_s = freq*deltastar_s/U + + St_peak_p = St_1(M) + St_peak_alpha = St_2(St_peak_p, alphastar) + St_peak_s = 0.5*(St_peak_p + St_peak_alpha) + + A_s = A(St_s/St_peak_s, Re_c) + + k_1 = K_1(Re_c) + + # SPL_s = 10*log10((deltastar_s*M^5*L*D)/(r_e^2)) + A_s + k_1 - 3 + # Brooks and Burley AIAA 2001-2210 style. + H_s = 10^(0.1*(A_s + k_1 - 3)) + G_s = (deltastar_s*M^5*L*D)/(r_e^2)*H_s + end + + SPL_s = 10*log10(G_s) + return SPL_s +end + +function TBL_TE_p(freq, nu, L, chord, U, M, M_c, r_e, theta_e, phi_e, alphastar, bl) + T = promote_type(typeof(freq), typeof(nu), typeof(L), typeof(chord), typeof(U), typeof(M), typeof(M_c), typeof(r_e), typeof(theta_e), typeof(phi_e), typeof(alphastar)) + + Re_c = U*chord/nu + alphastar0 = alpha_stall(bl, Re_c) + + gamma0_deg = gamma0(M) + + if alphastar*180/pi > min(gamma0_deg, alphastar0*180/pi) + # SPL_p = -100*one(T) + G_p = 10^(0.1*(-100))*one(T) + else + D = Dbar_h(theta_e, phi_e, M, M_c) + deltastar_p = disp_thickness_bot(bl, Re_c, alphastar)*chord + + k_1 = K_1(Re_c) + St_p = freq*deltastar_p/U + St_peak_p = St_1(M) + + A_p = A(St_p/St_peak_p, Re_c) + + Re_deltastar_p = U*deltastar_p/nu + Δk_1 = DeltaK_1(alphastar, Re_deltastar_p) + + # SPL_p = 10*log10((deltastar_p*M^5*L*D)/(r_e^2)) + A_p + k_1 - 3 + Δk_1 + # Brooks and Burley AIAA 2001-2210 style. + H_p = 10^(0.1*(A_p + k_1 - 3 + Δk_1)) + G_p = (deltastar_p*M^5*L*D)/(r_e^2)*H_p + end + + SPL_p = 10*log10(G_p) + return SPL_p +end + +function TBL_TE_alpha(freq, nu, L, chord, U, M, M_c, r_e, theta_e, phi_e, alphastar, bl) + Re_c = U*chord/nu + alphastar0 = alpha_stall(bl, Re_c) + gamma0_deg = gamma0(M) + deltastar_s = disp_thickness_top(bl, Re_c, alphastar)*chord + St_s = freq*deltastar_s/U + St_peak_p = St_1(M) + St_peak_alpha = St_2(St_peak_p, alphastar) + k2 = K_2(Re_c, M, alphastar) + + if alphastar*180/pi > min(gamma0_deg, alphastar0*180/pi) + D = Dbar_l(theta_e, phi_e, M) + A_prime = A(St_s/St_peak_alpha, 3*Re_c) + # SPL_alpha = 10*log10((deltastar_s*M^5*L*D)/(r_e^2)) + A_prime + k2 + # Brooks and Burley AIAA 2001-2210 style. + H_alpha = 10^(0.1*(A_prime + k2)) + G_alpha = (deltastar_s*M^5*L*D)/(r_e^2)*H_alpha + else + D = Dbar_h(theta_e, phi_e, M, M_c) + B_alpha = B(St_s/St_peak_alpha, Re_c) + # SPL_alpha = 10*log10((deltastar_s*M^5*L*D)/(r_e^2)) + B_alpha + k2 + # Brooks and Burley AIAA 2001-2210 style. + H_alpha = 10^(0.1*(B_alpha + k2)) + G_alpha = (deltastar_s*M^5*L*D)/(r_e^2)*H_alpha + end + + SPL_alpha = 10*log10(G_alpha) + return SPL_alpha +end + +function TBL_TE(freq, nu, L, chord, U, M, M_c, r_e, theta_e, phi_e, alphastar, bl) + SPL_s = TBL_TE_s(freq, nu, L, chord, U, M, M_c, r_e, theta_e, phi_e, alphastar, bl) + SPL_p = TBL_TE_p(freq, nu, L, chord, U, M, M_c, r_e, theta_e, phi_e, alphastar, bl) + SPL_alpha = TBL_TE_alpha(freq, nu, L, chord, U, M, M_c, r_e, theta_e, phi_e, alphastar, bl) + return SPL_s, SPL_p, SPL_alpha +end + +abstract type AbstractMachCorrection end +struct NoMachCorrection <: AbstractMachCorrection end +struct PrandtlGlauertMachCorrection <: AbstractMachCorrection end + +struct TBLTESourceElement{ + TDirect<:AbstractDirectivity,TUInduction,TMachCorrection,TDoppler, + Tc0,Tnu,TΔr,Tchord,Ty0dot,Ty1dot,Ty1dot_fluid,Tτ,TΔτ,Tspan_uvec,Tchord_uvec,Tbl + } <: AbstractBroadbandSourceElement{TDirect,TUInduction,TMachCorrection,TDoppler} + # Speed of sound, m/s. + c0::Tc0 + # Kinematic viscosity, m^2/s + nu::Tnu + # Radial/spanwise length of element, m. + Δr::TΔr + # chord length of element, m. + chord::Tchord + # Source position, m. + y0dot::Ty0dot + # Source velocity, m/s. + y1dot::Ty1dot + # Fluid velocity, m/s. + y1dot_fluid::Ty1dot_fluid + # Source time, s. + τ::Tτ + # Time step size, i.e. the amount of time this source element "exists" with these properties, s. + Δτ::TΔτ + # Radial/spanwise unit vector, aka unit vector aligned with the element's span direction. + span_uvec::Tspan_uvec + # Chordwise unit vector, aka unit vector aligned with the element's chord line, pointing from leading edge to trailing edge. + chord_uvec::Tchord_uvec + # Boundary layer struct, i.e. an AbstractBoundaryLayer. + bl::Tbl + # `Bool` indicating chord_uvec×span_uvec will give a vector pointing from bottom side (usually pressure side) to top side (usually suction side) if `true`, or the opposite if `false`. + chord_cross_span_to_get_top_uvec::Bool + + function TBLTESourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}(c0, nu, Δr, chord, y0dot::AbstractVector, y1dot::AbstractVector, y1dot_fluid::AbstractVector, τ, Δτ, span_uvec::AbstractVector, chord_uvec::AbstractVector, bl, chord_cross_span_to_get_top_uvec::Bool) where {TDirect<:AbstractDirectivity,TUInduction,TMachCorrection,TDoppler} + return new{ + TDirect,TUInduction,TMachCorrection,TDoppler, + typeof(c0), typeof(nu), typeof(Δr), typeof(chord), typeof(y0dot), typeof(y1dot), typeof(y1dot_fluid), typeof(τ), typeof(Δτ), typeof(span_uvec), typeof(chord_uvec), typeof(bl) + }(c0, nu, Δr, chord, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, chord_cross_span_to_get_top_uvec) + end +end + +# Default to using the `BrooksBurleyDirectivity` directivity function, include induction in the flow speed normal to span (TUInduction == true), use the PrandtlGlauertMachCorrection, and Doppler-shift. +function TBLTESourceElement(c0, nu, Δr, chord, y0dot::AbstractVector, y1dot::AbstractVector, y1dot_fluid::AbstractVector, τ, Δτ, span_uvec::AbstractVector, chord_uvec::AbstractVector, bl, chord_cross_span_to_get_top_uvec::Bool) + return TBLTESourceElement{BrooksBurleyDirectivity,true,PrandtlGlauertMachCorrection,true}(c0, nu, Δr, chord, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, chord_cross_span_to_get_top_uvec) +end + +""" + TBLTESourceElement(c0, nu, r, θ, Δr, chord, ϕ, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) + +Construct a source element for predicting turbulent boundary layer-trailing edge (TBLTE) noise using the BPM/Brooks and Burley method, using position and velocity data expressed in a cylindrical coordinate system. + +The `r` and `θ` arguments are used to define the radial and circumferential position of the source element in a cylindrical coordinate system. +Likewise, the `vn`, `vr`, and `vc` arguments are used to define the normal, radial, and circumferential velocity of the fluid (in a reference frame moving with the element) in the same cylindrical coordinate system. +The cylindrical coordinate system is defined as follows: + + * The normal/axial direction is in the positive x axis + * The circumferential/azimuth angle `θ` is defined such that `θ = 0` means the radial direction is aligned with the positive y axis, and a positive `θ` indicates a right-handed rotation around the positive x axis. + +The `twist_about_positive_y` is a `Bool` controling how the `ϕ` argument is handled, which in turn controls the orientation of a unit vector defining `chord_uvec` indicating the orientation of the chord line, from leading edge to trailing edge. +If `twist_about_positive_y` is `true`, `chord_uvec` will initially be pointed in the negative-z direction, and then rotated around the positive y axis by an amount `ϕ` before being rotated by the azimuth angle `θ`. +(This would typcially be appropriate for a source element rotating around the positive x axis.) +If `twist_about_positive_y` is `false`, `chord_uvec` will initially be pointed in the positive-z direction, and then rotated around the negative y axis by an amount `ϕ` before being rotated by the azimuth angle `θ`. +(This would typcially be appropriate for a source element rotating around the negative x axis.) + +Note that, for a proper noise prediction, the source element needs to be transformed into the "global" frame, aka, the reference frame of the fluid. +This can be done easily with the transformations provided by the `KinematicCoordinateTransformations` package, or manually by modifying the components of the source element struct. + +# Arguments +- c0: Ambient speed of sound (m/s) +- nu: Kinematic viscosity (m^2/s) +- r: radial coordinate of the element in the blade-fixed coordinate system (m) +- θ: angular offest of the element in the blade-fixed coordinate system (rad) +- Δr: length of the element (m) +- chord: chord length of blade element (m) +- ϕ: twist of blade element (rad) +- vn: normal velocity of fluid (m/s) +- vr: radial velocity of fluid (m/s) +- vc: circumferential velocity of the fluid (m/s) +- τ: source time (s) +- Δτ: source time duration (s) +- bl: Boundary layer struct, i.e. an AbstractBoundaryLayer. +- twist_about_positive_y: if `true`, apply twist ϕ about positive y axis, negative y axis otherwise +""" +function TBLTESourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}(c0, nu, r, θ, Δr, chord, ϕ, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y::Bool) where {TDirect,TUInduction,TMachCorrection,TDoppler} + sθ, cθ = sincos(θ) + sϕ, cϕ = sincos(ϕ) + y0dot = @SVector [0, r*cθ, r*sθ] + T = eltype(y0dot) + y1dot = @SVector zeros(T, 3) + y1dot_fluid = @SVector [vn, vr*cθ - vc*sθ, vr*sθ + vc*cθ] + span_uvec = @SVector [0, cθ, sθ] + if twist_about_positive_y + chord_uvec = @SVector [-sϕ, cϕ*sθ, -cϕ*cθ] + else + chord_uvec = @SVector [-sϕ, -cϕ*sθ, cϕ*cθ] + end + + chord_cross_span_to_get_top_uvec = twist_about_positive_y + return TBLTESourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}(c0, nu, Δr, chord, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, chord_cross_span_to_get_top_uvec::Bool) +end + +# Default to using the `BrooksBurleyDirectivity` directivity function, include induction in the flow speed normal to span (TUInduction == true), use the PrandtlGlauertMachCorrection, and Doppler-shift. +function TBLTESourceElement(c0, nu, r, θ, Δr, chord, ϕ, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y::Bool) + return TBLTESourceElement{BrooksBurleyDirectivity,true,PrandtlGlauertMachCorrection,true}(c0, nu, r, θ, Δr, chord, ϕ, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) +end + +""" + TBLTESourceElement(c0, nu, r, θ, Δr, chord, ϕ, U, α, τ, Δτ, bl, twist_about_positive_y) + +Construct a source element for predicting turbulent boundary layer-trailing edge (TBLTE) noise using the BPM/Brooks and Burley method, using the velocity magnitude `U` and angle of attack `α`. + +The `r` and `θ` arguments are used to define the radial and circumferential position of the source element in a cylindrical coordinate system. +The `U` and `α` arguments are the velocity magnitude normal to the source element length and the angle of attack, respectively. +The cylindrical coordinate system is defined as follows: + + * The normal/axial direction is in the positive x axis + * The circumferential/azimuth angle `θ` is defined such that `θ = 0` means the radial direction is aligned with the positive y axis, and a positive `θ` indicates a right-handed rotation around the positive x axis. + +The `twist_about_positive_y` is a `Bool` controling how the `ϕ` argument is handled, which in turn controls the orientation of a unit vector defining `chord_uvec` indicating the orientation of the chord line, from leading edge to trailing edge. +If `twist_about_positive_y` is `true`, `chord_uvec` will initially be pointed in the negative-z direction, and then rotated around the positive y axis by an amount `ϕ` before being rotated by the azimuth angle `θ`. +(This would typcially be appropriate for a source element rotating around the positive x axis.) +If `twist_about_positive_y` is `false`, `chord_uvec` will initially be pointed in the positive-z direction, and then rotated around the negative y axis by an amount `ϕ` before being rotated by the azimuth angle `θ`. +(This would typcially be appropriate for a source element rotating around the negative x axis.) + +Note that, for a proper noise prediction, the source element needs to be transformed into the "global" frame, aka, the reference frame of the fluid. +This can be done easily with the transformations provided by the `KinematicCoordinateTransformations` package, or manually by modifying the components of the source element struct. + +# Arguments +- c0: Ambient speed of sound (m/s) +- nu: Kinematic viscosity (m^2/s) +- r: radial coordinate of the element in the blade-fixed coordinate system (m) +- θ: angular offest of the element in the blade-fixed coordinate system (rad) +- Δr: length of the element (m) +- chord: chord length of blade element (m) +- ϕ: twist of blade element (rad) +- U: velocity magnitude (m/s) +- α: angle of attack (rad) +- τ: source time (s) +- Δτ: source time duration (s) +- bl: Boundary layer struct, i.e. an AbstractBoundaryLayer. +- twist_about_positive_y: if `true`, apply twist ϕ about positive y axis, negative y axis otherwise +""" +function TBLTESourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}(c0, nu, r, θ, Δr, chord, ϕ, U, α, τ, Δτ, bl, twist_about_positive_y) where {TDirect,TUInduction,TMachCorrection,TDoppler} + precone = 0 + pitch = 0 + phi = ϕ - α + y0dot, y1dot, y1dot_fluid, span_uvec, chord_uvec, chord_cross_span_to_get_top_uvec = _get_position_velocity_span_uvec_chord_uvec(ϕ, precone, pitch, r, θ, U, phi, twist_about_positive_y) + return TBLTESourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}(c0, nu, Δr, chord, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, chord_cross_span_to_get_top_uvec) +end + +# Default to using the `BrooksBurleyDirectivity` directivity function, include induction in the flow speed normal to span (TUInduction == true), use the PrandtlGlauertMachCorrection, and Doppler-shift. +function TBLTESourceElement(c0, nu, r, θ, Δr, chord, ϕ, U, α, τ, Δτ, bl, twist_about_positive_y::Bool) + return TBLTESourceElement{BrooksBurleyDirectivity,true,PrandtlGlauertMachCorrection,true}(c0, nu, r, θ, Δr, chord, ϕ, U, α, τ, Δτ, bl, twist_about_positive_y) +end + +""" + (trans::KinematicTransformation)(se::TBLTESourceElement) + +Transform the position and orientation of a source element according to the coordinate system transformation `trans`. +""" +function (trans::KinematicTransformation)(se::TBLTESourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}) where {TDirect,TUInduction,TMachCorrection,TDoppler} + linear_only = false + y0dot, y1dot = trans(se.τ, se.y0dot, se.y1dot, linear_only) + y0dot, y1dot_fluid = trans(se.τ, se.y0dot, se.y1dot_fluid, linear_only) + linear_only = true + span_uvec = trans(se.τ, se.span_uvec, linear_only) + chord_uvec = trans(se.τ, se.chord_uvec, linear_only) + + return TBLTESourceElement{TDirect,TUInduction,TMachCorrection,TDoppler}(se.c0, se.nu, se.Δr, se.chord, y0dot, y1dot, y1dot_fluid, se.τ, se.Δτ, span_uvec, chord_uvec, se.bl, se.chord_cross_span_to_get_top_uvec) +end + +doppler(pbs::AcousticMetrics.AbstractProportionalBandSpectrum) = AcousticMetrics.freq_scaler(pbs) + +""" +Output of the turbulent boundary layer-trailing edge (TBL-TE) calculation: the acoustic pressure autospectrum centered at time `t` over observer duration `dt` and observer frequencies `cbands` for the suction side `G_s`, pressure side `G_p`, and the separation `G_alpha`. +""" +struct TBLTEOutput{NO,TF,TG<:AbstractVector{TF},TFreqs<:AcousticMetrics.AbstractProportionalBands{NO,:center},TDTime,TTime} <: AcousticMetrics.AbstractProportionalBandSpectrum{NO,TF} + G_s::TG + G_p::TG + G_alpha::TG + cbands::TFreqs + dt::TDTime + t::TTime + + function TBLTEOutput(G_s::TG, G_p::TG, G_alpha::TG, cbands::AcousticMetrics.AbstractProportionalBands{NO,:center}, dt, t) where {NO,TG} + ncbands = length(cbands) + length(G_s) == ncbands || throw(ArgumentError("length(G_s) must match length(cbands)")) + length(G_p) == ncbands || throw(ArgumentError("length(G_p) must match length(cbands)")) + length(G_alpha) == ncbands || throw(ArgumentError("length(G_alpha) must match length(cbands)")) + dt > zero(dt) || throw(ArgumentError("dt must be positive")) + return new{NO,eltype(TG),TG,typeof(cbands),typeof(dt),typeof(t)}(G_s, G_p, G_alpha, cbands, dt, t) + end +end + +@inline function Base.getindex(pbs::TBLTEOutput, i::Int) + @boundscheck checkbounds(pbs, i) + return @inbounds pbs.G_s[i] + pbs.G_p[i] + pbs.G_alpha[i] +end + +@inline AcousticMetrics.has_observer_time(pbs::TBLTEOutput) = true +@inline AcousticMetrics.observer_time(pbs::TBLTEOutput) = pbs.t +@inline AcousticMetrics.timestep(pbs::TBLTEOutput) = pbs.dt +@inline AcousticMetrics.time_scaler(pbs::TBLTEOutput, period) = timestep(pbs)/period + +function _tble_te_s(freq, deltastar_s_U, Re_c, St_peak_s, k_1, scaler, deep_stall) + St_s = freq*deltastar_s_U + A_s = A(St_s/St_peak_s, Re_c) + + # SPL_s = 10*log10((deltastar_s*M^5*L*Dh)/(r_er^2)) + A_s + k_1 - 3 + # Brooks and Burley AIAA 2001-2210 style. + H_s = 10^(0.1*(A_s + k_1 - 3)) + # G_s = (deltastar_s*M^5*Δr*Dh)/(r_er^2)*H_s + G_s = scaler*H_s + + return ifelse(deep_stall, 10^(0.1*(-100))*one(typeof(G_s)), G_s) +end + +function _tble_te_p(freq, deltastar_p_U, Re_c, St_peak_p, k_1, Δk_1, scaler, deep_stall) + + St_p = freq*deltastar_p_U + + A_p = A(St_p/St_peak_p, Re_c) + + # SPL_p = 10*log10((deltastar_p*M^5*L*Dh)/(r_er^2)) + A_p + k_1 - 3 + Δk_1 + # Brooks and Burley AIAA 2001-2210 style. + H_p = 10^(0.1*(A_p + k_1 - 3 + Δk_1)) + # G_p = (deltastar_p*M^5*Δr*Dh)/(r_er^2)*H_p + G_p = scaler*H_p + + return ifelse(deep_stall, 10^(0.1*(-100))*one(typeof(G_p)), G_p) +end + +function _tble_te_alpha(freq, Re_c, deltastar_s_U, St_peak_alpha, k_2, scaler_l, scaler_h, deep_stall) + # Don't know if this is really necessary. + T = promote_type(typeof(freq), typeof(Re_c), typeof(deltastar_s_U), typeof(St_peak_alpha), typeof(k_2), typeof(scaler_l), typeof(scaler_h)) + St_s = freq*deltastar_s_U + + A_prime_stall = A(St_s/St_peak_alpha, 3*Re_c) + # SPL_alpha = 10*log10((deltastar_s*M^5*L*D)/(r_er^2)) + A_prime + k_2 + # Brooks and Burley AIAA 2001-2210 style. + H_alpha_stall = 10^(0.1*(A_prime_stall + k_2)) + # G_alpha_stall = (deltastar_s*M^5*Δr*Dl)/(r_er^2)*H_alpha_stall + G_alpha_stall = scaler_l*H_alpha_stall*one(T) + + B_alpha = B(St_s/St_peak_alpha, Re_c) + # SPL_alpha = 10*log10((deltastar_s*M^5*L*Dh)/(r_er^2)) + B_alpha + k_2 + # Brooks and Burley AIAA 2001-2210 style. + H_alpha = 10^(0.1*(B_alpha + k_2)) + # G_alpha = (deltastar_s*M^5*Δr*Dh)/(r_er^2)*H_alpha + G_alpha = scaler_h*H_alpha*one(T) + + return ifelse(deep_stall, G_alpha_stall, G_alpha) +end + +# Should use traits or something for this. +function mach_correction(se::AbstractBroadbandSourceElement{TDirect,TUInduction,NoMachCorrection}, M) where {TDirect,TUInduction} + return one(typeof(M)) +end + +function mach_correction(se::AbstractBroadbandSourceElement{TDirect,TUInduction,PrandtlGlauertMachCorrection}, M) where {TDirect,TUInduction} + return 1/(1 - M^2) +end + +function noise(se::TBLTESourceElement, obs::AbstractAcousticObserver, t_obs, freqs::AcousticMetrics.AbstractProportionalBands{3, :center}) + # Position of the observer: + x_obs = obs(t_obs) + + # Need the angle of attack. + alphastar = angle_of_attack(se) + + # Need the directivity functions. + top_is_suction = is_top_suction(se.bl, alphastar) + r_er, Dl, Dh = directivity(se, x_obs, top_is_suction) + + # Need the fluid velocity normal to the span. + # Brooks and Burley 2001 are a bit ambiguous on whether it should include induction, or just the freestream and rotation. + # + # * In the nomenclature section: `U` is "flow speed normal to span (`U_mn` with `mn` suppressed). + # So that's one point for "no induction." + # * In some discussion after equation (8), "The Mach number, `M = U/c0`, represents that component of velocity `U` normal to the span...". + # Hard to say one way or the other. + # * In equation (12), `U_mn` is the velocity without induction. + # So that's another point for "no induction." + # * Equation (14) defines `V_tot` as the velocity including the freestream, rotation, and induction. + # And then it defines `U` as the part of `V_tot` normal to the span. + # So that's a point for "yes induction." + # * In the directivity function definitions in equations (19) and (20), `M_tot` is used in the denominator, which seems to make it clear *that* velocity should include induction, since `V_tot` always includes induction. + # + # So, at the moment, the TBLTESourceElement type has a parameter TUInduction which, when true, will include induction in the flow speed normal to the span, and not otherwise. + U = speed_normal_to_span(se) + + # Reynolds number based on chord and the flow speed normal to span. + Re_c = U*se.chord/se.nu + + # Also need the displacement thicknesses for the pressure and suction sides. + deltastar_s = disp_thickness_s(se.bl, Re_c, alphastar)*se.chord + deltastar_p = disp_thickness_p(se.bl, Re_c, alphastar)*se.chord + + # Now that we've decided on the directivity functions and the displacement thickness, and we know the correct value of `top_is_suction` we should be able to switch the sign on `alphastar` if it's negative, and reference it to the zero-lift value, as the BPM report does. + alphastar_positive = abs_cs_safe(alphastar - alpha_zerolift(se.bl)) + + # Mach number of the flow speed normal to span. + M = U/se.c0 + + # This stuff is used to decide if the blade element is stalled or not. + alphastar0 = alpha_stall(se.bl, Re_c) + gamma0_deg = gamma0(M) + deep_stall = (alphastar_positive*180/pi) > min(gamma0_deg, alphastar0*180/pi) + + St_peak_p = St_1(M) + St_peak_alpha = St_2(St_peak_p, alphastar_positive) + St_peak_s = 0.5*(St_peak_p + St_peak_alpha) + + Re_deltastar_p = U*deltastar_p/se.nu + k_1 = K_1(Re_c) + k_2 = K_2(Re_c, M, alphastar_positive) + Δk_1 = DeltaK_1(alphastar_positive, Re_deltastar_p) + + deltastar_s_U = deltastar_s/U + deltastar_p_U = deltastar_p/U + + # Brooks and Burley 2001 recommend a Prandtl-Glauert style Mach number correction. + # But whether or not it's included is dependent on the TMachCorrection type parameter for the source element. + m_corr = mach_correction(se, M) + + # The Brooks and Burley autospectrums appear to be scaled by the usual squared reference pressure (20 μPa)^2, but I'd like things in dimensional units, so multiply through by that. + pref2 = 4e-10 + G_s_scaler = (deltastar_s*M^5*se.Δr*Dh)/(r_er^2)*m_corr + G_s = _tble_te_s.(freqs, deltastar_s_U, Re_c, St_peak_s, k_1, G_s_scaler, deep_stall).*pref2 + + G_p_scaler = (deltastar_p*M^5*se.Δr*Dh)/(r_er^2)*m_corr + G_p = _tble_te_p.(freqs, deltastar_p_U, Re_c, St_peak_p, k_1, Δk_1, G_p_scaler, deep_stall).*pref2 + + G_alpha_scaler_l = (deltastar_s*M^5*se.Δr*Dl)/(r_er^2)*m_corr + G_alpha_scaler_h = G_s_scaler + G_alpha = _tble_te_alpha.(freqs, Re_c, deltastar_s_U, St_peak_alpha, k_2, G_alpha_scaler_l, G_alpha_scaler_h, deep_stall).*pref2 + + # Also need the Doppler shift for this source-observer combination. + doppler = doppler_factor(se, obs, t_obs) + + # Get the doppler-shifted time step and proportional bands. + dt = se.Δτ/doppler + freqs_obs = AcousticMetrics.center_bands(freqs, doppler) + + # All done. + return TBLTEOutput(G_s, G_p, G_alpha, freqs_obs, dt, t_obs) +end diff --git a/src/teb_vs.jl b/src/teb_vs.jl new file mode 100644 index 00000000..5848a2b2 --- /dev/null +++ b/src/teb_vs.jl @@ -0,0 +1,393 @@ +function St_3prime_peak(h_over_deltastar_avg, Psi) + Psi_deg = Psi*180/pi + # Equation 72 from the BPM report. + if h_over_deltastar_avg < 0.2 + return 0.1*(h_over_deltastar_avg) + 0.095 - 0.00243*Psi_deg + else + return (0.212 - 0.0045*Psi_deg)/(1 + 0.235/h_over_deltastar_avg - 0.0132/(h_over_deltastar_avg^2)) + end +end + +function G4(h_over_deltastar_avg, Psi) + Psi_deg = Psi*180/pi + # Equation 74 from the BPM report. + if h_over_deltastar_avg ≤ 5 + return 17.5*log10(h_over_deltastar_avg) + 157.5 - 1.114*Psi_deg + else + return 169.7 - 1.114*Psi_deg + end +end + +function G5_Psi14(h_over_deltastar_avg, St_3prime_over_St_3prime_peak) + # Equation 77 from the BPM report. + η = log10(St_3prime_over_St_3prime_peak) + + # Equation 78 from the BPM report. + if h_over_deltastar_avg < 0.25 + μ = 0.1211*one(h_over_deltastar_avg) + elseif h_over_deltastar_avg < 0.62 + μ = -0.2175*h_over_deltastar_avg + 0.1755 + elseif h_over_deltastar_avg < 1.15 + μ = -0.0308*h_over_deltastar_avg + 0.0596 + else + μ = 0.0242*one(h_over_deltastar_avg) + end + + # Equation 79 from the BPM report. + if h_over_deltastar_avg < 0.02 + m = zero(h_over_deltastar_avg) + elseif h_over_deltastar_avg ≤ 0.5 + m = 68.724*h_over_deltastar_avg - 1.35 + elseif h_over_deltastar_avg ≤ 0.62 + m = 308.475*h_over_deltastar_avg - 121.23 + elseif h_over_deltastar_avg < 1.15 + m = 224.811*h_over_deltastar_avg - 69.354 + elseif h_over_deltastar_avg < 1.2 + m = 1583.28*h_over_deltastar_avg - 1631.592 + else + m = 268.344*one(h_over_deltastar_avg) + end + # This is in the code listing in the BPM report appendix. + if m < 0 + m = zero(h_over_deltastar_avg) + end + + # Equation 80 from the BPM report. + η_0 = -sqrt((m^2*μ^4)/(6.25 + m^2*μ^2)) + + # Equation 81 from the BPM report. + k = 2.5*sqrt(1 - (η_0/μ)^2) - 2.5 - m*η_0 + + # Equation 76 from the BPM report. + if η < η_0 + return m*η + k + elseif η < 0 + return 2.5*sqrt(1 - (η/μ)^2) - 2.5 + elseif η < 0.03616 + return sqrt(1.5625 - 1194.99*η^2) - 1.25*one(h_over_deltastar_avg) + else + return -155.543*η + 4.375*one(h_over_deltastar_avg) + end +end + +function G5_Psi0(h_over_deltastar_avg, St_3prime_over_St_3prime_peak) + # Equation 82 from the BPM report. + h_over_deltastar_avg_prime = 6.724*h_over_deltastar_avg^2 - 4.019*h_over_deltastar_avg + 1.107 + return G5_Psi14(h_over_deltastar_avg_prime, St_3prime_over_St_3prime_peak) +end + +function G5(h_over_deltastar_avg, Psi, St_3prime_over_St_3prime_peak) + Psi_deg = 180/pi*Psi + # Equation 75 from the BPM report. + G5_0 = G5_Psi0(h_over_deltastar_avg, St_3prime_over_St_3prime_peak) + G5_14 = G5_Psi14(h_over_deltastar_avg, St_3prime_over_St_3prime_peak) + g5 = G5_0 + 0.0714*Psi_deg*(G5_14 - G5_0) + # This check is in the code listing in the BPM report appendix: + if g5 > 0 + return zero(g5) + else + return g5 + end +end + +function BLUNT(freq, nu, L, chord, h, Psi, U, M, M_c, r_e, theta_e, phi_e, alphastar, bl) + Re_c = U*chord/nu + # deltastar_s = disp_thickness_s(bl, Re_c, alphastar)*chord + # deltastar_p = disp_thickness_p(bl, Re_c, alphastar)*chord + deltastar_top = disp_thickness_top(bl, Re_c, alphastar)*chord + deltastar_bot = disp_thickness_bot(bl, Re_c, alphastar)*chord + top_is_suction = alphastar > alpha_zerolift(bl) + deltastar_s, deltastar_p = ifelse(top_is_suction, + (deltastar_top, deltastar_bot), + (deltastar_bot, deltastar_top)) + + # Equation 73 from the BPM report. + deltastar_avg = 0.5*(deltastar_p + deltastar_s) + + h_over_deltastar_avg = h/deltastar_avg + D = Dbar_h(theta_e, phi_e, M, M_c) + + # Equation 71 from the BPM report. + St_3p = freq*h/U + + St_3prime_over_St_3prime_peak = St_3p/St_3prime_peak(h_over_deltastar_avg, Psi) + + g5temp = G5(h_over_deltastar_avg, Psi, St_3prime_over_St_3prime_peak) + + # This next check is in the code listing in the BPM report appendix. + # Need to find G5 for h_over_deltastar_avg = 0.25 for the F4TEMP variable. + f4temp = G5_Psi14(0.25, St_3prime_over_St_3prime_peak) + # if g5 > f4temp + # g5 = f4temp + # end + g5 = ifelse(g5temp > f4temp, f4temp, g5temp) + + # Equation 70 from the BPM report. + # SPL_blunt = 10*log10((h*(M^5.5)*L*D)/(r_e^2)) + G4(h_over_deltastar_avg, Psi) + g5 + # Brooks and Burley AIAA 2001-2210 style. + H_b = 10^(0.1*(G4(h_over_deltastar_avg, Psi) + g5)) + G_bte = (h*(M^5.5)*L*D)/(r_e^2)*H_b + SPL_blunt = 10*log10(G_bte) + return SPL_blunt +end + +struct TEBVSSourceElement{ + TDirect<:AbstractDirectivity,TUInduction,TDoppler, + Tc0,Tnu,TΔr,Tchord,Th,TPsi,Ty0dot,Ty1dot,Ty1dot_fluid,Tτ,TΔτ,Tspan_uvec,Tchord_uvec,Tbl + } <: AbstractBroadbandSourceElement{TDirect,TUInduction,NoMachCorrection,TDoppler} + # Speed of sound, m/s. + c0::Tc0 + # Kinematic viscosity, m^2/s + nu::Tnu + # Radial/spanwise length of element, m. + Δr::TΔr + # chord length of element, m. + chord::Tchord + # Trailing edge thickness, m. + h::Th + # Solid angle between blade surfaces immediately upstream of the trailing edge, rad. + Psi::TPsi + # Source position, m. + y0dot::Ty0dot + # Source velocity, m/s. + y1dot::Ty1dot + # Fluid velocity, m/s. + y1dot_fluid::Ty1dot_fluid + # Source time, s. + τ::Tτ + # Time step size, i.e. the amount of time this source element "exists" with these properties, s. + Δτ::TΔτ + # Radial/spanwise unit vector, aka unit vector aligned with the element's span direction. + span_uvec::Tspan_uvec + # Chordwise unit vector, aka unit vector aligned with the element's chord line, pointing from leading edge to trailing edge. + chord_uvec::Tchord_uvec + # Boundary layer struct, i.e. an AbstractBoundaryLayer. + bl::Tbl + # `Bool` indicating chord_uvec×span_uvec will give a vector pointing from bottom side (usually pressure side) to top side (usually suction side) if `true`, or the opposite if `false`. + chord_cross_span_to_get_top_uvec::Bool + + function TEBVSSourceElement{TDirect,TUInduction,TDoppler}(c0, nu, Δr, chord, h, Psi, y0dot::AbstractVector, y1dot::AbstractVector, y1dot_fluid::AbstractVector, τ, Δτ, span_uvec::AbstractVector, chord_uvec::AbstractVector, bl, chord_cross_span_to_get_top_uvec::Bool) where {TDirect<:AbstractDirectivity,TUInduction,TDoppler} + return new{ + TDirect,TUInduction,TDoppler, + typeof(c0), typeof(nu), typeof(Δr), typeof(chord), typeof(h), typeof(Psi), typeof(y0dot), typeof(y1dot), typeof(y1dot_fluid), typeof(τ), typeof(Δτ), typeof(span_uvec), typeof(chord_uvec), typeof(bl) + }(c0, nu, Δr, chord, h, Psi, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, chord_cross_span_to_get_top_uvec) + end +end + +# Default to using the `BrooksBurleyDirectivity` directivity function, include induction in the flow speed normal to span (TUInduction == true), and Doppler-shift. +function TEBVSSourceElement(c0, nu, Δr, chord, h, Psi, y0dot::AbstractVector, y1dot::AbstractVector, y1dot_fluid::AbstractVector, τ, Δτ, span_uvec::AbstractVector, chord_uvec::AbstractVector, bl, chord_cross_span_to_get_top_uvec) + return TEBVSSourceElement{BrooksBurleyDirectivity,true,true}(c0, nu, Δr, chord, h, Psi, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, chord_cross_span_to_get_top_uvec) +end + +""" + TEBVSSourceElement(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) + +Construct a source element for predicting trailing edge bluntness-vortex shedding (TEBVS) noise using the BPM/Brooks and Burley method, using position and velocity data expressed in a cylindrical coordinate system. + +The `r` and `θ` arguments are used to define the radial and circumferential position of the source element in a cylindrical coordinate system. +Likewise, the `vn`, `vr`, and `vc` arguments are used to define the normal, radial, and circumferential velocity of the fluid (in a reference frame moving with the element) in the same cylindrical coordinate system. +The cylindrical coordinate system is defined as follows: + + * The normal/axial direction is in the positive x axis + * The circumferential/azimuth angle `θ` is defined such that `θ = 0` means the radial direction is aligned with the positive y axis, and a positive `θ` indicates a right-handed rotation around the positive x axis. + +The `twist_about_positive_y` is a `Bool` controling how the `ϕ` argument is handled, which in turn controls the orientation of a unit vector defining `chord_uvec` indicating the orientation of the chord line, from leading edge to trailing edge. +If `twist_about_positive_y` is `true`, `chord_uvec` will initially be pointed in the negative-z direction, and then rotated around the positive y axis by an amount `ϕ` before being rotated by the azimuth angle `θ`. +(This would typcially be appropriate for a source element rotating around the positive x axis.) +If `twist_about_positive_y` is `false`, `chord_uvec` will initially be pointed in the positive-z direction, and then rotated around the negative y axis by an amount `ϕ` before being rotated by the azimuth angle `θ`. +(This would typcially be appropriate for a source element rotating around the negative x axis.) + +Note that, for a proper noise prediction, the source element needs to be transformed into the "global" frame, aka, the reference frame of the fluid. +This can be done easily with the transformations provided by the `KinematicCoordinateTransformations` package, or manually by modifying the components of the source element struct. + +# Arguments +- c0: Ambient speed of sound (m/s) +- nu: Kinematic viscosity (m^2/s) +- r: radial coordinate of the element in the blade-fixed coordinate system (m) +- θ: angular offest of the element in the blade-fixed coordinate system (rad) +- Δr: length of the element (m) +- chord: chord length of blade element (m) +- ϕ: twist of blade element (rad) +- h: trailing edge thickness (m) +- Psi: solid angle between the blade surfaces immediately upstream of the trailing edge (rad) +- vn: normal velocity of fluid (m/s) +- vr: radial velocity of fluid (m/s) +- vc: circumferential velocity of the fluid (m/s) +- τ: source time (s) +- Δτ: source time duration (s) +- bl: Boundary layer struct, i.e. an AbstractBoundaryLayer. +- twist_about_positive_y: if `true`, apply twist ϕ about positive y axis, negative y axis otherwise +""" +function TEBVSSourceElement{TDirect,TUInduction,TDoppler}(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) where {TDirect,TUInduction,TDoppler} + sθ, cθ = sincos(θ) + sϕ, cϕ = sincos(ϕ) + y0dot = @SVector [0, r*cθ, r*sθ] + T = eltype(y0dot) + y1dot = @SVector zeros(T, 3) + y1dot_fluid = @SVector [vn, vr*cθ - vc*sθ, vr*sθ + vc*cθ] + span_uvec = @SVector [0, cθ, sθ] + if twist_about_positive_y + chord_uvec = @SVector [-sϕ, cϕ*sθ, -cϕ*cθ] + else + chord_uvec = @SVector [-sϕ, -cϕ*sθ, cϕ*cθ] + end + + chord_cross_span_to_get_top_uvec = twist_about_positive_y + return TEBVSSourceElement{TDirect,TUInduction,TDoppler}(c0, nu, Δr, chord, h, Psi, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, chord_cross_span_to_get_top_uvec) +end + +# Default to using the `BrooksBurleyDirectivity` directivity function, include induction in the flow speed normal to span (TUInduction == true), and Doppler-shift. +function TEBVSSourceElement(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) + return TEBVSSourceElement{BrooksBurleyDirectivity,true,true}(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) +end + +""" + TEBVSSourceElement(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, U, α, τ, Δτ, bl, twist_about_positive_y) + +Construct a source element for predicting trailing edge bluntness-vortex shedding (TEBVS) noise using the BPM/Brooks and Burley method, using the velocity magnitude `U` and angle of attack `α`. + +The `r` and `θ` arguments are used to define the radial and circumferential position of the source element in a cylindrical coordinate system. +The `U` and `α` arguments are the velocity magnitude normal to the source element length and the angle of attack, respectively. +The cylindrical coordinate system is defined as follows: + + * The normal/axial direction is in the positive x axis + * The circumferential/azimuth angle `θ` is defined such that `θ = 0` means the radial direction is aligned with the positive y axis, and a positive `θ` indicates a right-handed rotation around the positive x axis. + +The `twist_about_positive_y` is a `Bool` controling how the `ϕ` argument is handled, which in turn controls the orientation of a unit vector defining `chord_uvec` indicating the orientation of the chord line, from leading edge to trailing edge. +If `twist_about_positive_y` is `true`, `chord_uvec` will initially be pointed in the negative-z direction, and then rotated around the positive y axis by an amount `ϕ` before being rotated by the azimuth angle `θ`. +(This would typcially be appropriate for a source element rotating around the positive x axis.) +If `twist_about_positive_y` is `false`, `chord_uvec` will initially be pointed in the positive-z direction, and then rotated around the negative y axis by an amount `ϕ` before being rotated by the azimuth angle `θ`. +(This would typcially be appropriate for a source element rotating around the negative x axis.) + +Note that, for a proper noise prediction, the source element needs to be transformed into the "global" frame, aka, the reference frame of the fluid. +This can be done easily with the transformations provided by the `KinematicCoordinateTransformations` package, or manually by modifying the components of the source element struct. + +# Arguments +- c0: Ambient speed of sound (m/s) +- nu: Kinematic viscosity (m^2/s) +- r: radial coordinate of the element in the blade-fixed coordinate system (m) +- θ: angular offest of the element in the blade-fixed coordinate system (rad) +- Δr: length of the element (m) +- chord: chord length of blade element (m) +- ϕ: twist of blade element (rad) +- h: trailing edge thickness (m) +- Psi: solid angle between the blade surfaces immediately upstream of the trailing edge (rad) +- U: velocity magnitude (m/s) +- α: angle of attack (rad) +- τ: source time (s) +- Δτ: source time duration (s) +- bl: Boundary layer struct, i.e. an AbstractBoundaryLayer. +- twist_about_positive_y: if `true`, apply twist ϕ about positive y axis, negative y axis otherwise +""" +function TEBVSSourceElement{TDirect,TUInduction,TDoppler}(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, U, α, τ, Δτ, bl, twist_about_positive_y) where {TDirect,TUInduction,TDoppler} + precone = 0 + pitch = 0 + phi = ϕ - α + y0dot, y1dot, y1dot_fluid, span_uvec, chord_uvec, chord_cross_span_to_get_top_uvec = _get_position_velocity_span_uvec_chord_uvec(ϕ, precone, pitch, r, θ, U, phi, twist_about_positive_y) + return TEBVSSourceElement{TDirect,TUInduction,TDoppler}(c0, nu, Δr, chord, h, Psi, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, chord_cross_span_to_get_top_uvec) +end + +# Default to using the `BrooksBurleyDirectivity` directivity function, include induction in the flow speed normal to span (TUInduction == true), and Doppler-shift. +function TEBVSSourceElement(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, U, α, τ, Δτ, bl, twist_about_positive_y) + return TEBVSSourceElement{BrooksBurleyDirectivity,true,true}(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, U, α, τ, Δτ, bl, twist_about_positive_y) +end + +""" + (trans::KinematicTransformation)(se::TEBVSSourceElement) + +Transform the position and orientation of a source element according to the coordinate system transformation `trans`. +""" +function (trans::KinematicTransformation)(se::TEBVSSourceElement{TDirect,TUInduction,TDoppler}) where {TDirect,TUInduction,TDoppler} + linear_only = false + y0dot, y1dot = trans(se.τ, se.y0dot, se.y1dot, linear_only) + y0dot, y1dot_fluid = trans(se.τ, se.y0dot, se.y1dot_fluid, linear_only) + linear_only = true + span_uvec = trans(se.τ, se.span_uvec, linear_only) + chord_uvec = trans(se.τ, se.chord_uvec, linear_only) + + return TEBVSSourceElement{TDirect,TUInduction,TDoppler}(se.c0, se.nu, se.Δr, se.chord, se.h, se.Psi, y0dot, y1dot, y1dot_fluid, se.τ, se.Δτ, span_uvec, chord_uvec, se.bl, se.chord_cross_span_to_get_top_uvec) +end + +function _teb_vs(freq, h_U, h_over_deltastar_avg, St_3pp, Psi, g4, G_teb_vs_scaler) + # Equation 71 from the BPM report. + St_3p = freq*h_U + St_3prime_over_St_3prime_peak = St_3p/St_3pp + g5temp = G5(h_over_deltastar_avg, Psi, St_3prime_over_St_3prime_peak) + + # This next check is in the code listing in the BPM report appendix. + # Need to find G5 for h_over_deltastar_avg = 0.25 for the F4TEMP variable. + f4temp = G5_Psi14(0.25, St_3prime_over_St_3prime_peak) + g5 = ifelse(g5temp > f4temp, f4temp, g5temp) + + # Equation 70 from the BPM report. + # SPL_blunt = 10*log10((h*(M^5.5)*L*D)/(r_e^2)) + G4(h_over_deltastar_avg, Psi) + g5 + # Brooks and Burley AIAA 2001-2210 style. + H_b = 10^(0.1*(g4 + g5)) + G_bte = G_teb_vs_scaler*H_b + return G_bte +end + +function noise(se::TEBVSSourceElement, obs::AbstractAcousticObserver, t_obs, freqs::AcousticMetrics.AbstractProportionalBands{3, :center}) + # Position of the observer: + x_obs = obs(t_obs) + + # Need the angle of attack. + alphastar = angle_of_attack(se) + + # Need the directivity functions. + top_is_suction = is_top_suction(se.bl, alphastar) + r_er, Dl, Dh = directivity(se, x_obs, top_is_suction) + + # Need the fluid velocity normal to the span. + # Brooks and Burley 2001 are a bit ambiguous on whether it should include induction, or just the freestream and rotation. + # + # * In the nomenclature section: `U` is "flow speed normal to span (`U_mn` with `mn` suppressed). + # So that's one point for "no induction." + # * In some discussion after equation (8), "The Mach number, `M = U/c0`, represents that component of velocity `U` normal to the span...". + # Hard to say one way or the other. + # * In equation (12), `U_mn` is the velocity without induction. + # So that's another point for "no induction." + # * Equation (14) defines `V_tot` as the velocity including the freestream, rotation, and induction. + # And then it defines `U` as the part of `V_tot` normal to the span. + # So that's a point for "yes induction." + # * In the directivity function definitions in equations (19) and (20), `M_tot` is used in the denominator, which seems to make it clear *that* velocity should include induction, since `V_tot` always includes induction. + # + # So, at the moment, the TBLTESourceElement type has a parameter TUInduction which, when true, will include induction in the flow speed normal to the span, and not otherwise. + U = speed_normal_to_span(se) + + # Reynolds number based on chord and the flow speed normal to span. + Re_c = U*se.chord/se.nu + + # Also need the displacement thicknesses for the pressure and suction sides. + deltastar_s = disp_thickness_s(se.bl, Re_c, alphastar)*se.chord + deltastar_p = disp_thickness_p(se.bl, Re_c, alphastar)*se.chord + + # Now that we've decided on the directivity functions and the displacement thickness, and we know the correct value of `top_is_suction` we should be able to switch the sign on `alphastar` if it's negative, and reference it to the zero-lift value, as the BPM report does. + alphastar_positive = abs_cs_safe(alphastar - alpha_zerolift(se.bl)) + + # Mach number of the flow speed normal to span. + M = U/se.c0 + + # Equation 73 from the BPM report. + deltastar_avg = 0.5*(deltastar_p + deltastar_s) + + h_over_deltastar_avg = se.h/deltastar_avg + h_U = se.h/U + St_3pp = St_3prime_peak(h_over_deltastar_avg, se.Psi) + g4 = G4(h_over_deltastar_avg, se.Psi) + + # The Brooks and Burley autospectrums appear to be scaled by the usual squared reference pressure (20 μPa)^2, but I'd like things in dimensional units, so multiply through by that. + pref2 = 4e-10 + G_teb_vs_scaler = (se.h*(M^5.5)*se.Δr*Dh)/(r_er^2) + G_teb_vs = _teb_vs.(freqs, h_U, h_over_deltastar_avg, St_3pp, se.Psi, g4, G_teb_vs_scaler) .* pref2 + + # Also need the Doppler shift for this source-observer combination. + doppler = doppler_factor(se, obs, t_obs) + + # Get the doppler-shifted time step and proportional bands. + dt = se.Δτ/doppler + freqs_obs = AcousticMetrics.center_bands(freqs, doppler) + + # All done. + return AcousticMetrics.ProportionalBandSpectrumWithTime(G_teb_vs, freqs_obs, dt, t_obs) +end diff --git a/src/tip_vortex.jl b/src/tip_vortex.jl new file mode 100644 index 00000000..44fe71d9 --- /dev/null +++ b/src/tip_vortex.jl @@ -0,0 +1,338 @@ +abstract type AbstractTipAlphaCorrection end + +struct NoTipAlphaCorrection <: AbstractTipAlphaCorrection end +struct BPMTipAlphaCorrection <: AbstractTipAlphaCorrection end + +# struct BMTipAlphaCorrection{TCorrection} <: AbstractTipAlphaCorrection +# correction::TCorrection + +# function BMTipAlphaCorrection(aspect_ratio) +# correction = BPM._tip_vortex_alpha_correction_nonsmooth(aspect_ratio) +# return new{typeof(correction)}(correction) +# end +# end + +# struct SmoothBMTipAlphaCorrection{TCorrection} <: AbstractTipAlphaCorrection +# correction::TCorrection + +# function SmoothBMTipAlphaCorrection(aspect_ratio) +# correction = BPM._tip_vortex_alpha_correction_smooth(aspect_ratio) +# return new{typeof(correction)}(correction) +# end +# end + +abstract type AbstractBladeTip{TTipAlphaCorrection} end + +alpha_zerolift(blade_tip::AbstractBladeTip) = blade_tip.alpha0lift +tip_alpha_correction(blade_tip::AbstractBladeTip) = blade_tip.tip_alpha_correction + +struct RoundedTip{TTipAlphaCorrection,TAlpha0Lift} <: AbstractBladeTip{TTipAlphaCorrection} + tip_alpha_correction::TTipAlphaCorrection + alpha0lift::TAlpha0Lift + + function RoundedTip(tip_alpha_correction::TTipAlphaCorrection, alpha0lift::TAlpha0Lift) where {TTipAlphaCorrection<:AbstractTipAlphaCorrection,TAlpha0Lift} + return new{TTipAlphaCorrection, TAlpha0Lift}(tip_alpha_correction, alpha0lift) + end +end +RoundedTip(alpha0lift=0.0) = RoundedTip(NoTipAlphaCorrection(), alpha0lift) + +struct FlatTip{TTipAlphaCorrection,TAlpha0Lift} <: AbstractBladeTip{TTipAlphaCorrection} + tip_alpha_correction::TTipAlphaCorrection + alpha0lift::TAlpha0Lift + + function FlatTip(tip_alpha_correction::TTipAlphaCorrection, alpha0lift::TAlpha0Lift) where {TTipAlphaCorrection<:AbstractTipAlphaCorrection,TAlpha0Lift} + return new{TTipAlphaCorrection, TAlpha0Lift}(tip_alpha_correction, alpha0lift) + end +end +FlatTip(alpha0lift=0.0) = FlatTip(NoTipAlphaCorrection(), alpha0lift) + +function tip_vortex_alpha_correction(blade_tip::AbstractBladeTip{NoTipAlphaCorrection}, alphatip) + return alphatip +end + +function tip_vortex_alpha_correction(blade_tip::AbstractBladeTip{BPMTipAlphaCorrection}, alphatip) + # Referencing the tip vortex angle of attack correction to the zero-lift angle of attack ensures that the correction will never cause the angle of attack to drop below the zero-lift value, assuming the correction factor (0.71 here) is between 0 and 1. + return 0.71*(alphatip - alpha_zerolift(blade_tip)) + alpha_zerolift(blade_tip) + # return 0.71*alphatip + (1 - 0.71)*alpha_zerolift(blade_tip) +end + +# function tip_vortex_alpha_correction(blade_tip::AbstractBladeTip{<:Union{BMTipAlphaCorrection,SmoothBMTipAlphaCorrection}}, alphatip) +# return tip_alpha_correction(blade_tip).correction * (alphatip - alpha_zerolift(blade_tip)) + alpha_zerolift(blade_tip) +# end + +function tip_vortex_size_c(::RoundedTip, alphatip) + # Equation 63 in the BPM report. + alphatip_deg = alphatip*180/pi + return 0.008*alphatip_deg +end + +function tip_vortex_size_c(::FlatTip, alphatip) + alphatip_deg = alphatip*180/pi + # Equation 67 in the BPM report. + if alphatip_deg < 2 + return 0.0230 + 0.0169*alphatip_deg + else + return 0.0378 + 0.0095*alphatip_deg + end +end + +function tip_vortex_max_mach_number(::AbstractBladeTip, M, alphatip) + alphatip_deg = alphatip*180/pi + # Equation 64 in the BPM report. + M_max = (1 + 0.036*alphatip_deg)*M + return M_max +end + +function TIP(freq, chord, M, M_c, U_max, M_max, r_e, theta_e, phi_e, alphatip, blade_tip::AbstractBladeTip) + l = tip_vortex_size_c(blade_tip, alphatip) * chord + # Equation 62 in the BPM report. + St_pp = freq*l/U_max + + D = Dbar_h(theta_e, phi_e, M, M_c) + + # Equation 61 in the BPM report. + # SPL_tip = 10*log10(M^2*M_max^3*l^2*D/r_e^2) - 30.5*(log10(St_pp) + 0.3)^2 + 126 + # Brooks and Burley AIAA 2001-2210 style. + H_t = 10^(0.1*(-30.5*(log10(St_pp) + 0.3)^2 + 126)) + G_tip = (M^2*M_max^3*l^2*D/r_e^2)*H_t + SPL_tip = 10*log10(G_tip) + return SPL_tip +end + +struct TipVortexSourceElement{ + TDirect<:AbstractDirectivity,TUInduction,TDoppler, + Tc0,TΔr,Tchord,Ty0dot,Ty1dot,Ty1dot_fluid,Tτ,TΔτ,Tspan_uvec,Tchord_uvec,Tbl,Tblade_tip + } <: AbstractBroadbandSourceElement{TDirect,TUInduction,NoMachCorrection,TDoppler} + # Speed of sound, m/s. + # c0 + c0::Tc0 + # Radial/spanwise length of element, m. + Δr::TΔr + # chord length of element, m. + chord::Tchord + # Source position, m. + y0dot::Ty0dot + # Source velocity, m/s. + y1dot::Ty1dot + # Fluid velocity, m/s. + y1dot_fluid::Ty1dot_fluid + # Source time, s. + τ::Tτ + # Time step size, i.e. the amount of time this source element "exists" with these properties, s. + Δτ::TΔτ + # Radial/spanwise unit vector, aka unit vector aligned with the element's span direction. + span_uvec::Tspan_uvec + # Chordwise unit vector, aka unit vector aligned with the element's chord line, pointing from leading edge to trailing edge. + chord_uvec::Tchord_uvec + # Boundary layer struct, i.e. an AbstractBoundaryLayer. + bl::Tbl + # Blade tip struct, i.e. an AbstractBladeTip. + blade_tip::Tblade_tip + # `Bool` indicating chord_uvec×span_uvec will give a vector pointing from bottom side (usually pressure side) to top side (usually suction side) if `true`, or the opposite if `false`. + chord_cross_span_to_get_top_uvec::Bool + + function TipVortexSourceElement{TDirect,TUInduction,TDoppler}(c0, Δr, chord, y0dot::AbstractVector, y1dot::AbstractVector, y1dot_fluid::AbstractVector, τ, Δτ, span_uvec::AbstractVector, chord_uvec::AbstractVector, bl, blade_tip, chord_cross_span_to_get_top_uvec::Bool) where {TDirect<:AbstractDirectivity,TUInduction,TDoppler} + return new{ + TDirect,TUInduction,TDoppler, + typeof(c0), typeof(Δr), typeof(chord), typeof(y0dot), typeof(y1dot), typeof(y1dot_fluid), typeof(τ), typeof(Δτ), typeof(span_uvec), typeof(chord_uvec), typeof(bl), typeof(blade_tip) + }(c0, Δr, chord, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, blade_tip, chord_cross_span_to_get_top_uvec) + end +end + +# Default to using the `BrooksBurleyDirectivity` directivity function, include induction in the flow speed normal to span (TUInduction == true), and Doppler-shift. +function TipVortexSourceElement(c0, Δr, chord, y0dot::AbstractVector, y1dot::AbstractVector, y1dot_fluid::AbstractVector, τ, Δτ, span_uvec::AbstractVector, chord_uvec::AbstractVector, bl, blade_tip, chord_cross_span_to_get_top_uvec) + return TipVortexSourceElement{BrooksBurleyDirectivity,true,true}(c0, Δr, chord, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, blade_tip, chord_cross_span_to_get_top_uvec) +end + +""" + TipVortexSourceElement(c0, r, θ, Δr, chord, ϕ, vn, vr, vc, τ, Δτ, bl, blade_tip, twist_about_positive_y) + +Construct a source element for predicting turbulent boundary layer-trailing edge (TBLTE) noise using the BPM/Brooks and Burley method, using position and velocity data expressed in a cylindrical coordinate system. + +The `r` and `θ` arguments are used to define the radial and circumferential position of the source element in a cylindrical coordinate system. +Likewise, the `vn`, `vr`, and `vc` arguments are used to define the normal, radial, and circumferential velocity of the fluid (in a reference frame moving with the element) in the same cylindrical coordinate system. +The cylindrical coordinate system is defined as follows: + + * The normal/axial direction is in the positive x axis + * The circumferential/azimuth angle `θ` is defined such that `θ = 0` means the radial direction is aligned with the positive y axis, and a positive `θ` indicates a right-handed rotation around the positive x axis. + +The `twist_about_positive_y` is a `Bool` controling how the `ϕ` argument is handled, which in turn controls the orientation of a unit vector defining `chord_uvec` indicating the orientation of the chord line, from leading edge to trailing edge. +If `twist_about_positive_y` is `true`, `chord_uvec` will initially be pointed in the negative-z direction, and then rotated around the positive y axis by an amount `ϕ` before being rotated by the azimuth angle `θ`. +(This would typcially be appropriate for a source element rotating around the positive x axis.) +If `twist_about_positive_y` is `false`, `chord_uvec` will initially be pointed in the positive-z direction, and then rotated around the negative y axis by an amount `ϕ` before being rotated by the azimuth angle `θ`. +(This would typcially be appropriate for a source element rotating around the negative x axis.) + +Note that, for a proper noise prediction, the source element needs to be transformed into the "global" frame, aka, the reference frame of the fluid. +This can be done easily with the transformations provided by the `KinematicCoordinateTransformations` package, or manually by modifying the components of the source element struct. + +# Arguments +- c0: Ambient speed of sound (m/s) +- r: radial coordinate of the element in the blade-fixed coordinate system (m) +- θ: angular offest of the element in the blade-fixed coordinate system (rad) +- Δr: length of the element (m) +- chord: chord length of blade element (m) +- ϕ: twist of blade element (rad) +- vn: normal velocity of fluid (m/s) +- vr: radial velocity of fluid (m/s) +- vc: circumferential velocity of the fluid (m/s) +- τ: source time (s) +- Δτ: source time duration (s) +- bl: Boundary layer struct, i.e. an AbstractBoundaryLayer. +- blade_tip: Blade tip struct, i.e. an AbstractBladeTip. +- twist_about_positive_y: if `true`, apply twist ϕ about positive y axis, negative y axis otherwise +""" +function TipVortexSourceElement{TDirect,TUInduction,TDoppler}(c0, r, θ, Δr, chord, ϕ, vn, vr, vc, τ, Δτ, bl, blade_tip, twist_about_positive_y) where {TDirect,TUInduction,TDoppler} + sθ, cθ = sincos(θ) + sϕ, cϕ = sincos(ϕ) + y0dot = @SVector [0, r*cθ, r*sθ] + T = eltype(y0dot) + y1dot = @SVector zeros(T, 3) + y1dot_fluid = @SVector [vn, vr*cθ - vc*sθ, vr*sθ + vc*cθ] + span_uvec = @SVector [0, cθ, sθ] + if twist_about_positive_y + chord_uvec = @SVector [-sϕ, cϕ*sθ, -cϕ*cθ] + else + chord_uvec = @SVector [-sϕ, -cϕ*sθ, cϕ*cθ] + end + + chord_cross_span_to_get_top_uvec = twist_about_positive_y + return TipVortexSourceElement{TDirect,TUInduction,TDoppler}(c0, Δr, chord, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, blade_tip, chord_cross_span_to_get_top_uvec) +end + +# Default to using the `BrooksBurleyDirectivity` directivity function, include induction in the flow speed normal to span (TUInduction == true), and Doppler-shift. +function TipVortexSourceElement(c0, r, θ, Δr, chord, ϕ, vn, vr, vc, τ, Δτ, bl, blade_tip, twist_about_positive_y) + return TipVortexSourceElement{BrooksBurleyDirectivity,true,true}(c0, r, θ, Δr, chord, ϕ, vn, vr, vc, τ, Δτ, bl, blade_tip, twist_about_positive_y) +end + +""" + TipVortexSourceElement(c0, r, θ, Δr, chord, ϕ, U, α, τ, Δτ, bl, blade_tip, twist_about_positive_y) + +Construct a source element for predicting tip vortex noise using the BPM/Brooks and Burley method, using the velocity magnitude `U` and angle of attack `α`. + +The `r` and `θ` arguments are used to define the radial and circumferential position of the source element in a cylindrical coordinate system. +The `U` and `α` arguments are the velocity magnitude normal to the source element length and the angle of attack, respectively. +The cylindrical coordinate system is defined as follows: + + * The normal/axial direction is in the positive x axis + * The circumferential/azimuth angle `θ` is defined such that `θ = 0` means the radial direction is aligned with the positive y axis, and a positive `θ` indicates a right-handed rotation around the positive x axis. + +The `twist_about_positive_y` is a `Bool` controling how the `ϕ` argument is handled, which in turn controls the orientation of a unit vector defining `chord_uvec` indicating the orientation of the chord line, from leading edge to trailing edge. +If `twist_about_positive_y` is `true`, `chord_uvec` will initially be pointed in the negative-z direction, and then rotated around the positive y axis by an amount `ϕ` before being rotated by the azimuth angle `θ`. +(This would typcially be appropriate for a source element rotating around the positive x axis.) +If `twist_about_positive_y` is `false`, `chord_uvec` will initially be pointed in the positive-z direction, and then rotated around the negative y axis by an amount `ϕ` before being rotated by the azimuth angle `θ`. +(This would typcially be appropriate for a source element rotating around the negative x axis.) + +Note that, for a proper noise prediction, the source element needs to be transformed into the "global" frame, aka, the reference frame of the fluid. +This can be done easily with the transformations provided by the `KinematicCoordinateTransformations` package, or manually by modifying the components of the source element struct. + +# Arguments +- c0: Ambient speed of sound (m/s) +- r: radial coordinate of the element in the blade-fixed coordinate system (m) +- θ: angular offest of the element in the blade-fixed coordinate system (rad) +- Δr: length of the element (m) +- chord: chord length of blade element (m) +- ϕ: twist of blade element (rad) +- U: velocity magnitude (m/s) +- α: angle of attack (rad) +- τ: source time (s) +- Δτ: source time duration (s) +- bl: Boundary layer struct, i.e. an AbstractBoundaryLayer. +- blade_tip: Blade tip struct, i.e. an AbstractBladeTip. +- twist_about_positive_y: if `true`, apply twist ϕ about positive y axis, negative y axis otherwise +""" +function TipVortexSourceElement{TDirect,TUInduction,TDoppler}(c0, r, θ, Δr, chord, ϕ, U, α, τ, Δτ, bl, blade_tip, twist_about_positive_y) where {TDirect,TUInduction,TDoppler} + precone = 0 + pitch = 0 + phi = ϕ - α + y0dot, y1dot, y1dot_fluid, span_uvec, chord_uvec, chord_cross_span_to_get_top_uvec = _get_position_velocity_span_uvec_chord_uvec(ϕ, precone, pitch, r, θ, U, phi, twist_about_positive_y) + return TipVortexSourceElement{TDirect,TUInduction,TDoppler}(c0, Δr, chord, y0dot, y1dot, y1dot_fluid, τ, Δτ, span_uvec, chord_uvec, bl, blade_tip, chord_cross_span_to_get_top_uvec) +end + +# Default to using the `BrooksBurleyDirectivity` directivity function, include induction in the flow speed normal to span (TUInduction == true), and Doppler-shift. +function TipVortexSourceElement(c0, r, θ, Δr, chord, ϕ, U, α, τ, Δτ, bl, blade_tip, twist_about_positive_y) + return TipVortexSourceElement{BrooksBurleyDirectivity,true,true}(c0, r, θ, Δr, chord, ϕ, U, α, τ, Δτ, bl, blade_tip, twist_about_positive_y) +end + +""" + (trans::KinematicTransformation)(se::TipVortexSourceElement) + +Transform the position and orientation of a source element according to the coordinate system transformation `trans`. +""" +function (trans::KinematicTransformation)(se::TipVortexSourceElement{TDirect,TUInduction,TDoppler}) where {TDirect,TUInduction,TDoppler} + linear_only = false + y0dot, y1dot = trans(se.τ, se.y0dot, se.y1dot, linear_only) + y0dot, y1dot_fluid = trans(se.τ, se.y0dot, se.y1dot_fluid, linear_only) + linear_only = true + span_uvec = trans(se.τ, se.span_uvec, linear_only) + chord_uvec = trans(se.τ, se.chord_uvec, linear_only) + + return TipVortexSourceElement{TDirect,TUInduction,TDoppler}(se.c0, se.Δr, se.chord, y0dot, y1dot, y1dot_fluid, se.τ, se.Δτ, span_uvec, chord_uvec, se.bl, se.blade_tip, se.chord_cross_span_to_get_top_uvec) +end + +function _tip(freq, l_U_max, scaler) + St_pp = freq*l_U_max + H_t = 10^(0.1*(-30.5*(log10(St_pp) + 0.3)^2 + 126)) + # G_tip = (M^2*M_max^3*l^2*D/r_e^2)*H_t + G_tip = scaler*H_t + return G_tip +end + +function noise(se::TipVortexSourceElement, obs::AbstractAcousticObserver, t_obs, freqs::AcousticMetrics.AbstractProportionalBands{3, :center}) + # Position of the observer: + x_obs = obs(t_obs) + + # Need the angle of attack, including the possible tip correction. + alphatip = tip_vortex_alpha_correction(se.blade_tip, angle_of_attack(se)) + + # Need the directivity functions. + top_is_suction = is_top_suction(se.bl, alphatip) + r_er, Dl, Dh = directivity(se, x_obs, top_is_suction) + + # Need the fluid velocity normal to the span. + # Brooks and Burley 2001 are a bit ambiguous on whether it should include induction, or just the freestream and rotation. + # + # * In the nomenclature section: `U` is "flow speed normal to span (`U_mn` with `mn` suppressed). + # So that's one point for "no induction." + # * In some discussion after equation (8), "The Mach number, `M = U/c0`, represents that component of velocity `U` normal to the span...". + # Hard to say one way or the other. + # * In equation (12), `U_mn` is the velocity without induction. + # So that's another point for "no induction." + # * Equation (14) defines `V_tot` as the velocity including the freestream, rotation, and induction. + # And then it defines `U` as the part of `V_tot` normal to the span. + # So that's a point for "yes induction." + # * In the directivity function definitions in equations (19) and (20), `M_tot` is used in the denominator, which seems to make it clear *that* velocity should include induction, since `V_tot` always includes induction. + # + # So, at the moment, the TBLTESourceElement type has a parameter TUInduction which, when true, will include induction in the flow speed normal to the span, and not otherwise. + U = speed_normal_to_span(se) + + # Now that we've decided on the directivity functions and we know the correct value of `top_is_suction` we should be able to switch the sign on `alphastar` if it's negative, and reference it to the zero-lift value, as the BPM report does. + alphatip_positive = abs_cs_safe(alphatip - alpha_zerolift(se.bl)) + + # Mach number of the flow speed normal to span. + M = U/se.c0 + + # Need the maximum mach number near the tip vortex. + M_max = tip_vortex_max_mach_number(se.blade_tip, M, alphatip_positive) + + # Now we can find the maximum speed near the tip vortex. + U_max = M_max * se.c0 + + # Get the tip vortex size. + l = tip_vortex_size_c(se.blade_tip, alphatip_positive) * se.chord + + # The Brooks and Burley autospectrums appear to be scaled by the usual squared reference pressure (20 μPa)^2, but I'd like things in dimensional units, so multiply through by that. + pref2 = 4e-10 + l_U_max = l/U_max + G_tip_scaler = (M^2*M_max^3*l^2*Dh/r_er^2) + G_tip = _tip.(freqs, l_U_max, G_tip_scaler) .* pref2 + + # Also need the Doppler shift for this source-observer combination. + doppler = doppler_factor(se, obs, t_obs) + + # Get the doppler-shifted time step and proportional bands. + dt = se.Δτ/doppler + freqs_obs = AcousticMetrics.center_bands(freqs, doppler) + + # All done. + return AcousticMetrics.ProportionalBandSpectrumWithTime(G_tip, freqs_obs, dt, t_obs) +end diff --git a/src/writevtk.jl b/src/writevtk.jl index c3f5251d..8f259932 100644 --- a/src/writevtk.jl +++ b/src/writevtk.jl @@ -1,22 +1,22 @@ """ - endpoints(se::CompactSourceElement) + endpoints(se::AbstractCompactSourceElement) Return the Tuple containing the endpoint locations of the compact source element `se`. """ -function endpoints(se::CompactSourceElement) - p1 = se.y0dot - 0.5*se.Δr*se.u - p2 = se.y0dot + 0.5*se.Δr*se.u +function endpoints(se::AbstractCompactSourceElement) + p1 = se.y0dot - 0.5*se.Δr*orientation(se) + p2 = se.y0dot + 0.5*se.Δr*orientation(se) # Don't like the idea of having a billion SVectors, so convert them to plain # Vectors. Maybe not necessary. return (Vector(p1), Vector(p2)) end """ - to_vtp(name::AbstractString, ses::AbstractArray{<:CompactSourceElement}) + to_vtp(name::AbstractString, ses::AbstractArray{<:AbstractCompactSourceElement}) -Construct and return a VTK polygonal (.vtp) data file object for an array of `CompactSourceElement` with name `name.vtp` (i.e., the `name` argument should not contain a file extension). +Construct and return a VTK polygonal (.vtp) data file object for an array of `AbstractCompactSourceElement` with name `name.vtp` (i.e., the `name` argument should not contain a file extension). """ -function to_vtp(name, ses::AbstractArray{<:CompactSourceElement}) +function to_vtp(name, ses::AbstractArray{<:AbstractCompactSourceElement}) # This will be an array of the same size as ses, with each entry a # length-two tuple of the endpoints. points_all = AcousticAnalogies.endpoints.(ses) @@ -49,63 +49,273 @@ function to_vtp(name, ses::AbstractArray{<:CompactSourceElement}) # (2, length(ses)). line_ids = reshape(line_ids, 2, length(ses)) # Now create the array of VTK lines. - lines = [MeshCell(PolyData.Lines(), line) for line in eachcol(line_ids)] + lines = [WriteVTK.MeshCell(WriteVTK.PolyData.Lines(), line) for line in eachcol(line_ids)] - vtkfile = vtk_grid(name, points, lines) + vtkfile = WriteVTK.vtk_grid(name, points, lines) + _write_data_to_vtk!(vtkfile, ses) + + return vtkfile +end + +function _write_data_to_vtk!(vtkfile, ses::AbstractArray{<:CompactF1ASourceElement}) + # Now need to add the cell data. I would have expected to have to flatten + # these arrays, but apparently that's not necessary. + vtkfile["Length", WriteVTK.VTKCellData()] = mapview(:Δr, ses) + vtkfile["CSArea", WriteVTK.VTKCellData()] = mapview(:Λ, ses) + vtkfile["Position", WriteVTK.VTKCellData()] = hcat(mapview(:y0dot, ses)...) + vtkfile["Velocity", WriteVTK.VTKCellData()] = hcat(mapview(:y1dot, ses)...) + vtkfile["Acceleration", WriteVTK.VTKCellData()] = hcat(mapview(:y2dot, ses)...) + vtkfile["Jerk", WriteVTK.VTKCellData()] = hcat(mapview(:y3dot, ses)...) + vtkfile["Loading", WriteVTK.VTKCellData()] = hcat(mapview(:f0dot, ses)...) + vtkfile["LoadingDot", WriteVTK.VTKCellData()] = hcat(mapview(:f1dot, ses)...) +end + +function _write_data_to_vtk!(vtkfile, ses::AbstractArray{<:Union{TBLTESourceElement,LBLVSSourceElement,TipVortexSourceElement}}) # Now need to add the cell data. I would have expected to have to flatten # these arrays, but apparently that's not necessary. - vtkfile["Length", VTKCellData()] = mapview(:Δr, ses) - vtkfile["CSArea", VTKCellData()] = mapview(:Λ, ses) - vtkfile["Position", VTKCellData()] = hcat(mapview(:y0dot, ses)...) - vtkfile["Velocity", VTKCellData()] = hcat(mapview(:y1dot, ses)...) - vtkfile["Acceleration", VTKCellData()] = hcat(mapview(:y2dot, ses)...) - vtkfile["Jerk", VTKCellData()] = hcat(mapview(:y3dot, ses)...) - vtkfile["Loading", VTKCellData()] = hcat(mapview(:f0dot, ses)...) - vtkfile["LoadingDot", VTKCellData()] = hcat(mapview(:f1dot, ses)...) + vtkfile["Length", WriteVTK.VTKCellData()] = mapview(:Δr, ses) + vtkfile["Chord", WriteVTK.VTKCellData()] = mapview(:chord, ses) + vtkfile["Position", WriteVTK.VTKCellData()] = hcat(mapview(:y0dot, ses)...) + vtkfile["Velocity", WriteVTK.VTKCellData()] = hcat(mapview(:y1dot, ses)...) + vtkfile["FluidVelocity", WriteVTK.VTKCellData()] = hcat(mapview(:y1dot_fluid, ses)...) + vtkfile["SpanUnitVector", WriteVTK.VTKCellData()] = hcat(mapview(:span_uvec, ses)...) + vtkfile["ChordUnitVector", WriteVTK.VTKCellData()] = hcat(mapview(:chord_uvec, ses)...) +end + +function _write_data_to_vtk!(vtkfile, ses::AbstractArray{<:Union{TEBVSSourceElement,CombinedNoTipBroadbandSourceElement,CombinedWithTipBroadbandSourceElement}}) + # Now need to add the cell data. I would have expected to have to flatten + # these arrays, but apparently that's not necessary. + vtkfile["Length", WriteVTK.VTKCellData()] = mapview(:Δr, ses) + vtkfile["Chord", WriteVTK.VTKCellData()] = mapview(:chord, ses) + vtkfile["TrailingEdgeThickness", WriteVTK.VTKCellData()] = mapview(:h, ses) + vtkfile["TrailingEdgeAngle", WriteVTK.VTKCellData()] = mapview(:Psi, ses) + vtkfile["Position", WriteVTK.VTKCellData()] = hcat(mapview(:y0dot, ses)...) + vtkfile["Velocity", WriteVTK.VTKCellData()] = hcat(mapview(:y1dot, ses)...) + vtkfile["FluidVelocity", WriteVTK.VTKCellData()] = hcat(mapview(:y1dot_fluid, ses)...) + vtkfile["SpanUnitVector", WriteVTK.VTKCellData()] = hcat(mapview(:span_uvec, ses)...) + vtkfile["ChordUnitVector", WriteVTK.VTKCellData()] = hcat(mapview(:chord_uvec, ses)...) +end + +function to_vtu(name, obs::AbstractAcousticObserver, t; sphere_radius=1.0, n=10) + # Get the current position of the observer. + x = obs(t) + + # Create a sphere at the observer position with the specified radius. + s = Meshes.Sphere(tuple(x...), sphere_radius) + + # Discretize the sphere. + mesh = Meshes.simplexify(Meshes.discretize(s, Meshes.RegularDiscretization(n))) + + # This gets a fancy Unitful vector of Points that represent the verticies of the discretized sphere. + verts = Meshes.vertices(mesh) + + # This gets the connectivity of the discretized sphere. + connec = Meshes.elements(Meshes.topology(mesh)) + + # This converts the fancy `verts` into a plain old Matrix{Float64}. + points = stack(p -> Meshes.ustrip.(Meshes.to(p)), verts) + + # This creates VTK cells that we can eventually write out, converting the Meshes.jl connectivity into VTK MeshCells. + cells = [WriteVTK.MeshCell(WriteVTK.VTKCellTypes.VTK_TRIANGLE, Meshes.indices(c)) for c in connec] + + # Now we can finally create a VTK file. + vtkfile = WriteVTK.vtk_grid(name, points, cells) return vtkfile end +r""" +to_paraview_collection(name::AbstractString, ses::NTuple{N, AbstractArray{<:AbstractCompactSourceElement}}; time_axes::NTuple{N, Int64}=ntuple(i->1, N), block_names=["block$(b)" for b in 1:N], observers=(), observer_names=nothing, observer_radii=nothing) + + +Construct and write out a ParaView collection data file (`.pvd`) object for a tuple of arrays of `CompactF1ASourceElement`s with name `name.pvd` (i.e., the `name` argument should not contain a file extension). + +`time_axes` is a tuple of time axis indices, one for each entry of `ses`, indicating the axis over which the source time for the source elements in `ses` vary. +`block_names` is a `Vector` of strings, one for each entry in `ses`, that will be used to name each `ses` entry in the multiblock VTK file. + +`observers` should be an iterable of `AbstractAcousticObserver` objects that will also be written out to the paraview file as discretized spheres. +`observer_names` can either be an iterable of Strings that will be used to name each VTK observer file, or `nothing`, in which case each observer will be named `observer`. +`observer_radii` can either be an iterable of Float64 representing the radius of each observer sphere, or `nothing`, in which case a suitible radius will be calculated. + +One VTK PolyData (`.vtp`) file will be written for each valid index along `time_axis` for each array in the `ses` tuple. + +Returns a list of filenames written out by [WriteVTK.jl](https://github.com/jipolanco/WriteVTK.jl). +""" +function to_paraview_collection(name, ses::NTuple{N, AbstractArray{<:AbstractCompactSourceElement}}; time_axes::NTuple{N, Int64}=ntuple(i->1, N), block_names=["block$(b)" for b in 1:N], observers=(), observer_names=nothing, observer_radii=nothing) where {N} + + # Check that the size of each array in the `ses` is the the same along the time axis. + # This will get the length of each array in `ses` along the time axis. + time_axis_lengths = size.(ses, time_axes) + # Now check if they're the same. + if !all(time_axis_lengths .== first(time_axis_lengths)) + throw(ArgumentError("length of each array in ses tuple must be the same along the time axis. Length of each: $(time_axis_lengths)")) + end + time_axis_len = first(time_axis_lengths) + + # Also check that the block names are unique. + length(unique(block_names)) == N || throw(ArgumentError("entries in block_names = $(block_names) must be unique")) + + if length(observers) > 0 + if observer_names === nothing + obs_names = ["observer$(i)" for i in 1:length(observers)] + else + # Check that the number of observers matches the number of observer names. + length(observer_names) == length(observers) || throw(ArgumentError("length of observer_names does not match length of observers")) + # Check that the observer names are unique. + length(unique(observer_names)) == length(observer_names) || throw(ArgumentError("entries in observer_names = $(observer_names) must be unique")) + + # Also should check that the observer names aren't the same as the source element block names. + all_names = vcat(block_names, observer_names) + length(unique(all_names)) == length(all_names) || throw(ArgumentError("observer_names = $(observer_names) shares entries with block_names = $(block_names)")) + + obs_names = observer_names + end + + if observer_radii === nothing + # Check out this sorcery. + # (xmin, xmax) = mapreduce(x->extrema(getindex.(getproperty.(x, :y0dot), 1)), (a, b)->(min(a[1], b[1]), max(a[2], b[2])), ses) + # (ymin, ymax) = mapreduce(x->extrema(getindex.(getproperty.(x, :y0dot), 2)), (a, b)->(min(a[1], b[1]), max(a[2], b[2])), ses) + # (zmin, zmax) = mapreduce(x->extrema(getindex.(getproperty.(x, :y0dot), 3)), (a, b)->(min(a[1], b[1]), max(a[2], b[2])), ses) + # But could I do it in one line? + # That would mean I'd need to have a function that could take in a vector, then compare it to another vector. + # ((xmin, ymin, zmin), (xmax, ymax, zmax)) = mapreduce( + # (a, b)->((min(a[1][1], b[1][1]), + # min(a[1][2], b[1][2]), + # min(a[1][3], b[1][3])), + # (max(a[2][1], b[2][1]), + # max(a[2][2], b[2][2]), + # max(a[2][3], b[2][3]))), ses) do x + # xmin, xmax = extrema(getindex.(getproperty.(x, :y0dot), 1)) + # ymin, ymax = extrema(getindex.(getproperty.(x, :y0dot), 2)) + # zmin, zmax = extrema(getindex.(getproperty.(x, :y0dot), 3)) + # return ((xmin, ymin, zmin), (xmax, ymax, zmax)) + # end + # Still kind of annoying that I have to iterate over each source element array three times. + # How to avoid that? + # It would come down to not using extrema. + # I'd need a version of extrema that iterates over each vector, keeping track of the minimum and maximum of each element. + ((xmin, ymin, zmin), (xmax, ymax, zmax)) = mapreduce( + (a, b)->((min(a[1][1], b[1][1]), + min(a[1][2], b[1][2]), + min(a[1][3], b[1][3])), + (max(a[2][1], b[2][1]), + max(a[2][2], b[2][2]), + max(a[2][3], b[2][3]))), ses) do X + + mins = (Inf, Inf, Inf) + maxs = (-Inf, -Inf, -Inf) + for x in X + y0dot = x.y0dot + mins = (min(y0dot[1], mins[1]), min(y0dot[2], mins[2]), min(y0dot[3], mins[3])) + maxs = (max(y0dot[1], maxs[1]), max(y0dot[2], maxs[2]), max(y0dot[3], maxs[3])) + end + return mins, maxs + end + + # Now find the diagonal of the boundary box. + r = sqrt((xmax - xmin)^2 + (ymax - ymin)^2 + (zmax - zmin)^2) + + # Set the observer radii to be a fraction of that boundary box diagonal + obs_radii = fill(0.02*r, length(observers)) + else + # Check that the length of observer_radii matches observers. + length(observer_radii) == length(observers) || throw(ArgumentError("length of observer_radii does not match length of observers")) + obs_radii = observer_radii + end + else + obs_names = nothing + obs_radii = nothing + end + + outfiles = WriteVTK.paraview_collection(name) do pvd + for tidx in 1:time_axis_len + # We want to check that the source times for all elements we write out for this time index `tidx` is the same. + # So get the time for the first element in the first array, and compare later. + ses_first = first(ses) + time_axis_first = first(time_axes) + axes_first = axes(ses_first) + idx_first = [d == time_axis_first ? axes_first[d][tidx] : axes_first[d][begin] for d in 1:ndims(ses_first)] + t = source_time(ses_first[idx_first...]) + + # We will create a multiblock VTK file for each time step, with one block for each array in `ses`. + name_mb = format(FormatExpr("{}-{:08d}"), name, tidx) + WriteVTK.vtk_multiblock(name_mb) do vtm + for (i, (sesi, time_axis)) in enumerate(zip(ses, time_axes)) + # This will give me each valid index allong the time axis for `sesi`. + time_indices = axes(sesi, time_axis) + + # This will give me a `:` for each dimension of `sesi` except for the dimension corresponding to `time_axis`. + idx = [d == time_axis ? time_indices[tidx] : Colon() for d in 1:ndims(sesi)] + + # Now we can grab all the source elements we want. + sesiv = @view sesi[idx...] + + # Now check if all the source times are what we expect. + all(source_time.(sesiv) .≈ t) || thow(ArgumentError("ses[$i][$(idx)] does not have all source elements with source time $(t)")) + + # Now create a VTK file for the source elements we've selected. + namei = format(FormatExpr("{}-{}-{:08d}"), name, block_names[i], tidx) + vtkfile = to_vtp(namei, sesiv) + + # And add it to the multiblock file. + WriteVTK.multiblock_add_block(vtm, vtkfile) + end + + for (obs, obs_name, obs_radius) in zip(observers, obs_names, obs_radii) + # Now also need to write out the observers. + namei = format(FormatExpr("{}-{}-{:08d}"), name, obs_name, tidx) + vtkfile = to_vtu(namei, obs, t; sphere_radius=obs_radius) + + WriteVTK.multiblock_add_block(vtm, vtkfile) + end + + # Now add the the multiblock file to the paraview collection. + pvd[t] = vtm + end + end + end + + return outfiles +end + """ - to_paraview_collection(name::AbstractString, ses::AbstractArray{<:CompactSourceElement}, axis::Integer=1) + to_paraview_collection(name::AbstractString, ses::AbstractArray{<:AbstractCompactSourceElement}; time_axis::Integer=1) -Construct and write out a ParaView collection data file (`.pvd`) object for an array of `CompactSourceElement` with name `name.pvd` (i.e., the `name` argument should not contain a file extension). +Construct and write out a ParaView collection data file (`.pvd`) object for an array of `AbstractCompactSourceElement`s with name `name.pvd` (i.e., the `name` argument should not contain a file extension). -`axis` indicates the axis of `ses` over which the source time for the source +`time_axis` indicates the time_axis of `ses` over which the source time for the source elements in `ses` vary. One VTK PolyData (`.vtp`) file will be written for each -valid index along `axis`. +valid index along `time_axis`. Returns a list of filenames written out by [WriteVTK.jl](https://github.com/jipolanco/WriteVTK.jl). """ -function to_paraview_collection(name, ses, axis=1) - # pvd = paraview_collection(name) - outfiles = paraview_collection(name) do pvd +function to_paraview_collection(name, ses::AbstractArray{<:AbstractCompactSourceElement}; time_axis=1) + outfiles = WriteVTK.paraview_collection(name) do pvd # These are the time indices, i.e., the ones we actually want to iterate # over. - indices = axes(ses, axis) + time_indices = axes(ses, time_axis) # idx is all the indicies, including the time one that we want to iterate # over, and the others that we want to grab all at once. They're all colons # right now, but the time one will be replaced with each index in `indices` # in the `for i in indices` loop below. - idx = Any[Colon() for ind in axes(ses)] + idx = [d == time_axis ? first(time_indices) : Colon() for d in 1:ndims(ses)] - for i in indices - idx[axis] = i - namei = format("{}{:08d}", name, i) + for (i, it) in enumerate(time_indices) + idx[time_axis] = it + namei = format(FormatExpr("{}{:08d}"), name, i) sesi = @view ses[idx...] vtkfile = to_vtp(namei, sesi) # Assume that all the times in sesi are the same. They should be if the - # user specified the correct axis. I suppose I could check that and + # user specified the correct time_axis. I suppose I could check that and # issue a warning. t = first(sesi).τ pvd[t] = vtkfile end - end return outfiles diff --git a/test/.gitignore b/test/.gitignore index d101e4f2..8241b57a 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -1,3 +1,5 @@ *.png *.vtp +*.vtu +*.vtm *.pvd diff --git a/test/Project.toml b/test/Project.toml index 93aed7bd..4ab2916f 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -4,6 +4,7 @@ CCBlade = "e1828068-15df-11e9-03e4-ef195ea46fa4" DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" FLOWMath = "6cb5d3fb-0fe8-4cc2-bd89-9fe0b19a99d3" +FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" Formatting = "59287772-0a20-5a39-b81b-1366585eb4c0" ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59" @@ -15,6 +16,7 @@ Polynomials = "f27b6e38-b328-58d1-80ce-0feddd5e7a45" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce" +SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/test/adv_time_tests.jl b/test/adv_time_tests.jl index 01b4acef..5294863b 100644 --- a/test/adv_time_tests.jl +++ b/test/adv_time_tests.jl @@ -22,7 +22,7 @@ using Test c0 = 2.0 dummy0 = 1.0 dummy3 = @SVector [0.0, 0.0, 0.0] - se = CompactSourceElement(dummy0, c0, dummy0, dummy0, y, dummy3, dummy3, dummy3, dummy3, dummy3, τ, dummy3) + se = CompactF1ASourceElement(dummy0, c0, dummy0, dummy0, y, dummy3, dummy3, dummy3, dummy3, dummy3, τ, dummy3) # Define a function that takes a source element and an observer and compares # the advanced time solution to one found by NLsolve. diff --git a/test/anopp2_run.jl b/test/anopp2_run.jl index 7180283a..3c399c95 100644 --- a/test/anopp2_run.jl +++ b/test/anopp2_run.jl @@ -6,6 +6,7 @@ using StaticArrays: @SVector, SVector using KinematicCoordinateTransformations: KinematicCoordinateTransformations, compose using Printf: @sprintf using LinearAlgebra: × +using FileIO: load include(joinpath(@__DIR__, "gen_test_data", "gen_ccblade_data", "constants.jl")) using .CCBladeTestCaseConstants @@ -56,10 +57,10 @@ function cf1a_noise(num_blades, v, omega, radii, dradii, cs_area, fn, fc, statio trans = compose.(src_times, Ref(const_vel_trans), compose.(src_times, Ref(global_trans), Ref(rot_trans))) # Transform the source elements. - ses = AcousticAnalogies.CompactSourceElement.(ccbc.rho, ccbc.c0, radii, θs, dradii, cs_area, -fn, 0.0, fc, src_times) .|> trans + ses = AcousticAnalogies.CompactF1ASourceElement.(ccbc.rho, ccbc.c0, radii, θs, dradii, cs_area, -fn, 0.0, fc, src_times) .|> trans # Do the acoustics. - apth = AcousticAnalogies.f1a.(ses, Ref(obs)) + apth = AcousticAnalogies.noise.(ses, Ref(obs)) # Combine all the acoustic pressure time histories into one. apth_total = AcousticAnalogies.combine(apth, obs_time_range, num_obs_times, 1; f_interp=f_interp) @@ -78,10 +79,10 @@ function get_results(; stationary_observer, theta, f_interp, rpm, irpm) omega = rpm*(2*pi/60.0) # Get the normal and circumferential loading from the CCBlade output. - fname = joinpath(@__DIR__, "gen_test_data", "gen_ccblade_data", "ccblade_omega$(@sprintf "%02d" irpm).csv") - data = DelimitedFiles.readdlm(fname, ',') - fn = data[:, 1] - fc = data[:, 2] + fname = joinpath(@__DIR__, "gen_test_data", "gen_ccblade_data", "ccblade_omega$(@sprintf "%02d" irpm)-outputs.jld2") + data_d = load(fname) + fn = data_d["Np"] + fc = data_d["Tp"] # Blade passing period. bpp = 2*pi/omega/ccbc.num_blades diff --git a/test/boundary_layer_tests.jl b/test/boundary_layer_tests.jl new file mode 100644 index 00000000..173ba9cf --- /dev/null +++ b/test/boundary_layer_tests.jl @@ -0,0 +1,402 @@ +module BoundaryLayerTests + +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: AcousticMetrics +using DelimitedFiles: DelimitedFiles +using FLOWMath: linear +using Test + +@testset "boundary layer thickness" begin + @testset "zero angle of attack" begin + @testset "untripped" begin + # Get the digitized data from the BPM report plot. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure06-bl_thickness-untripped.csv") + bpm_untripped = DelimitedFiles.readdlm(fname, ',') + Re_c_1e6 = bpm_untripped[:, 1] + delta0_c = bpm_untripped[:, 2] + + # Get the AcousticAnalogies.jl implementation. + Re_c_1e6_jl = range(minimum(Re_c_1e6), maximum(Re_c_1e6); length=50) + delta0_c_jl = AcousticAnalogies.bl_thickness_0.(Ref(AcousticAnalogies.UntrippedN0012BoundaryLayer()), Re_c_1e6_jl.*1e6) + # Interpolate the BPM report data onto the uniform Re spacing. + delta0_c_interp = linear(Re_c_1e6, delta0_c, Re_c_1e6_jl) + + # Find the scaled error. + vmin, vmax = extrema(delta0_c) + err = abs.(delta0_c_jl .- delta0_c_interp)/(vmax - vmin) + @test maximum(err) < 0.041 + + end + + @testset "tripped" begin + # Get the digitized data from the BPM report plot. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure06-bl_thickness-tripped.csv") + bpm_tripped = DelimitedFiles.readdlm(fname, ',') + Re_c_1e6 = bpm_tripped[:, 1] + delta0_c = bpm_tripped[:, 2] + + # Get the AcousticAnalogies.jl implementation. + Re_c_1e6_jl = range(minimum(Re_c_1e6), maximum(Re_c_1e6); length=50) + delta0_c_jl = AcousticAnalogies.bl_thickness_0.(Ref(AcousticAnalogies.TrippedN0012BoundaryLayer()), Re_c_1e6_jl.*1e6) + # Interpolate the BPM report data onto the uniform Re spacing. + delta0_c_interp = linear(Re_c_1e6, delta0_c, Re_c_1e6_jl) + + # Find the scaled error. + vmin, vmax = extrema(delta0_c) + err = abs.(delta0_c_jl .- delta0_c_interp)/(vmax - vmin) + @test maximum(err) < 0.0086 + + end + end + + @testset "non-zero angle of attack, tripped" begin + @testset "pressure side" begin + # Get the digitized data from the BPM report plot. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure07-bl_thickness-pressure_side.csv") + bpm_pressure_side = DelimitedFiles.readdlm(fname, ',') + alpha_deg = bpm_pressure_side[:, 1] + delta_bpm = bpm_pressure_side[:, 2] + + # Get the AcousticAnalogies.jl implementation. + alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=50) + delta_jl = AcousticAnalogies._bl_thickness_p.(Ref(AcousticAnalogies.TrippedN0012BoundaryLayer()), alpha_deg_jl.*pi/180) + + # Interpolate the BPM report data onto the uniform alpha spacing. + delta_bpm_interp = linear(alpha_deg, delta_bpm, alpha_deg_jl) + + # Find the scaled error. + vmin, vmax = extrema(delta_bpm) + err = abs.(delta_jl .- delta_bpm_interp)./(vmax - vmin) + @test maximum(err) < 0.032 + end + + @testset "suction side" begin + # Get the digitized data from the BPM report plot. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure07-bl_thickness-suction_side.csv") + bpm_pressure_side = DelimitedFiles.readdlm(fname, ',') + alpha_deg = bpm_pressure_side[:, 1] + delta_bpm = bpm_pressure_side[:, 2] + + # Get the AcousticAnalogies.jl implementation. + alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=50) + delta_jl = AcousticAnalogies._bl_thickness_s.(Ref(AcousticAnalogies.TrippedN0012BoundaryLayer()), alpha_deg_jl.*pi/180) + + # Interpolate the BPM report data onto the uniform alpha spacing. + delta_bpm_interp = linear(alpha_deg, delta_bpm, alpha_deg_jl) + + # Find the scaled error. + vmin, vmax = extrema(delta_bpm) + err = abs.(delta_jl .- delta_bpm_interp)./(vmax - vmin) + @test maximum(err) < 0.023 + end + end + + @testset "non-zero angle of attack, untripped" begin + @testset "pressure side" begin + # Non-zero boundary layer thickness for the pressure side is the same for tripped and untripped, so getting the data for the tripped case. + # Get the digitized data from the BPM report plot. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure07-bl_thickness-pressure_side.csv") + bpm_pressure_side = DelimitedFiles.readdlm(fname, ',') + alpha_deg = bpm_pressure_side[:, 1] + delta_bpm = bpm_pressure_side[:, 2] + + # Get the AcousticAnalogies.jl implementation. + alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=50) + delta_jl = AcousticAnalogies._bl_thickness_p.(Ref(AcousticAnalogies.UntrippedN0012BoundaryLayer()), alpha_deg_jl.*pi/180) + + # Interpolate the BPM report data onto the uniform alpha spacing. + delta_bpm_interp = linear(alpha_deg, delta_bpm, alpha_deg_jl) + + # Find the scaled error. + vmin, vmax = extrema(delta_bpm) + err = abs.(delta_jl .- delta_bpm_interp)./(vmax - vmin) + @test maximum(err) < 0.032 + end + + @testset "suction side" begin + # Get the digitized data from the BPM report plot. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure08-bl_thickness-suction_side.csv") + bpm_pressure_side = DelimitedFiles.readdlm(fname, ',') + alpha_deg = bpm_pressure_side[:, 1] + delta_bpm = bpm_pressure_side[:, 2] + + # Get the AcousticAnalogies.jl implementation. + alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=50) + delta_jl = AcousticAnalogies._bl_thickness_s.(Ref(AcousticAnalogies.UntrippedN0012BoundaryLayer()), alpha_deg_jl.*pi/180) + + # Interpolate the BPM report data onto the uniform alpha spacing. + delta_bpm_interp = linear(alpha_deg, delta_bpm, alpha_deg_jl) + + # Find the scaled error. + vmin, vmax = extrema(delta_bpm) + err = abs.(delta_jl .- delta_bpm_interp)./(vmax - vmin) + @test maximum(err) < 0.028 + end + end + + @testset "positive/negative angle of attack" begin + for bl in [AcousticAnalogies.TrippedN0012BoundaryLayer(), AcousticAnalogies.UntrippedN0012BoundaryLayer()] + for Re_c in (range(0.04, 3.0; length=30)) .* 10^6 + for alphastar_deg in 0:30 + alphastar = alphastar_deg*pi/180 + # For a positive angle of attack, the pressure side should be the bottom side. + delta_p = AcousticAnalogies.bl_thickness_p(bl, Re_c, alphastar) + delta_bot = AcousticAnalogies.bl_thickness_bot(bl, Re_c, alphastar) + @test delta_p ≈ delta_bot + + # For a positive angle of attack, the suction side should be the top side. + delta_s = AcousticAnalogies.bl_thickness_s(bl, Re_c, alphastar) + delta_top = AcousticAnalogies.bl_thickness_top(bl, Re_c, alphastar) + @test delta_s ≈ delta_top + + # But if we switch the sign on alpha, the top and bottom switch too. + delta_bot_neg = AcousticAnalogies.bl_thickness_bot(bl, Re_c, -alphastar) + @test delta_bot_neg ≈ delta_s + + delta_top_neg = AcousticAnalogies.bl_thickness_top(bl, Re_c, -alphastar) + @test delta_top_neg ≈ delta_p + + # But the value of the pressure and suction sides should never change. + delta_p_neg = AcousticAnalogies.bl_thickness_p(bl, Re_c, -alphastar) + @test delta_p_neg ≈ delta_p + delta_s_neg = AcousticAnalogies.bl_thickness_s(bl, Re_c, -alphastar) + @test delta_s_neg ≈ delta_s + end + end + end + end + + @testset "ITrip1N0012BoundaryLayer" begin + + bl = AcousticAnalogies.ITrip1N0012BoundaryLayer() + bl_untripped = AcousticAnalogies.UntrippedN0012BoundaryLayer() + bl_tripped = AcousticAnalogies.TrippedN0012BoundaryLayer() + for Re_c in (range(0.04, 3.0; length=30)) .* 10^6 + for alphastar in (-30:30) .* (pi/180) + # Should use the untripped pressure-side and suction-side boundary layer thickness. + @test AcousticAnalogies.bl_thickness_p(bl, Re_c, alphastar) ≈ AcousticAnalogies.bl_thickness_p(bl_untripped, Re_c, alphastar) + @test AcousticAnalogies.bl_thickness_s(bl, Re_c, alphastar) ≈ AcousticAnalogies.bl_thickness_s(bl_untripped, Re_c, alphastar) + + # Should use the tripped displacement thickness. + @test AcousticAnalogies.disp_thickness_p(bl, Re_c, alphastar) ≈ AcousticAnalogies.disp_thickness_p(bl_tripped, Re_c, alphastar) + @test AcousticAnalogies.disp_thickness_s(bl, Re_c, alphastar) ≈ AcousticAnalogies.disp_thickness_s(bl_tripped, Re_c, alphastar) + + end + end + end + + @testset "ITrip2N0012BoundaryLayer" begin + bl = AcousticAnalogies.ITrip2N0012BoundaryLayer() + bl_untripped = AcousticAnalogies.UntrippedN0012BoundaryLayer() + bl_tripped = AcousticAnalogies.TrippedN0012BoundaryLayer() + for Re_c in (range(0.04, 3.0; length=30)) .* 10^6 + for alphastar in (-30:30) .* (pi/180) + # boundary layer thickness should be untripped multiplied by 0.6. + @test AcousticAnalogies.bl_thickness_p(bl, Re_c, alphastar) ≈ 0.6*AcousticAnalogies.bl_thickness_p(bl_untripped, Re_c, alphastar) + @test AcousticAnalogies.bl_thickness_s(bl, Re_c, alphastar) ≈ 0.6*AcousticAnalogies.bl_thickness_s(bl_untripped, Re_c, alphastar) + + # The pressure-side displacement thickness should be tripped multiplied by 0.6. + @test AcousticAnalogies.disp_thickness_p(bl, Re_c, alphastar) ≈ 0.6*AcousticAnalogies.disp_thickness_p(bl_tripped, Re_c, alphastar) + # The suction-side displacement thickness should be the tripped zero-alpha displacement thickness multipled by 0.6 multiplied by the untripped suction-side to zero-alpha displacement thickness ratio. + @test AcousticAnalogies.disp_thickness_s(bl, Re_c, alphastar) ≈ AcousticAnalogies.disp_thickness_s(bl_tripped, Re_c, 0) * 0.6 * AcousticAnalogies.disp_thickness_s(bl_untripped, Re_c, alphastar) / AcousticAnalogies.disp_thickness_s(bl_untripped, Re_c, 0) + end + end + end + + @testset "ITrip3N0012BoundaryLayer" begin + bl = AcousticAnalogies.ITrip3N0012BoundaryLayer() + bl_untripped = AcousticAnalogies.UntrippedN0012BoundaryLayer() + bl_tripped = AcousticAnalogies.TrippedN0012BoundaryLayer() + for Re_c in (range(0.04, 3.0; length=30)) .* 10^6 + for alphastar in (-30:30) .* (pi/180) + # boundary layer thickness should be untripped. + @test AcousticAnalogies.bl_thickness_p(bl, Re_c, alphastar) ≈ AcousticAnalogies.bl_thickness_p(bl_untripped, Re_c, alphastar) + @test AcousticAnalogies.bl_thickness_s(bl, Re_c, alphastar) ≈ AcousticAnalogies.bl_thickness_s(bl_untripped, Re_c, alphastar) + + # The pressure-side displacement thickness should be untripped multiplied by 1.48. + @test AcousticAnalogies.disp_thickness_p(bl, Re_c, alphastar) ≈ 1.48*AcousticAnalogies.disp_thickness_p(bl_untripped, Re_c, alphastar) + # The suction-side displacement thickness should be the untripped. + @test AcousticAnalogies.disp_thickness_s(bl, Re_c, alphastar) ≈ AcousticAnalogies.disp_thickness_s(bl_untripped, Re_c, alphastar) + end + end + end +end + +@testset "displacement thickness" begin + @testset "zero angle of attack" begin + @testset "tripped" begin + # Get the digitized data from the BPM report plot. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure06-disp_thickness-tripped.csv") + bpm_tripped = DelimitedFiles.readdlm(fname, ',') + Re_c_1e6 = bpm_tripped[:, 1] + deltastar0_c = bpm_tripped[:, 2] + + # Get the AcousticAnalogies.jl implementation. + Re_c_1e6_jl = range(minimum(Re_c_1e6), maximum(Re_c_1e6); length=50) + deltastar0_c_jl = AcousticAnalogies.disp_thickness_0.(Ref(AcousticAnalogies.TrippedN0012BoundaryLayer()), Re_c_1e6_jl.*1e6) + + # Interpolate the BPM report data onto the uniform Re spacing. + deltastar0_c_interp = linear(Re_c_1e6, deltastar0_c, Re_c_1e6_jl) + + # Find the scaled error. + vmin, vmax = extrema(deltastar0_c) + err = abs.(deltastar0_c_jl .- deltastar0_c_interp)/(vmax - vmin) + @test maximum(err) < 0.05 + end + + @testset "untripped" begin + # Get the digitized data from the BPM report plot. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure06-disp_thickness-untripped.csv") + bpm_untripped = DelimitedFiles.readdlm(fname, ',') + Re_c_1e6 = bpm_untripped[:, 1] + deltastar0_c = bpm_untripped[:, 2] + + # Get the AcousticAnalogies.jl implementation. + Re_c_1e6_jl = range(minimum(Re_c_1e6), maximum(Re_c_1e6); length=50) + deltastar0_c_jl = AcousticAnalogies.disp_thickness_0.(Ref(AcousticAnalogies.UntrippedN0012BoundaryLayer()), Re_c_1e6_jl.*1e6) + # Interpolate the BPM report data onto the uniform Re spacing. + deltastar0_c_interp = linear(Re_c_1e6, deltastar0_c, Re_c_1e6_jl) + + # Find the scaled error. + vmin, vmax = extrema(deltastar0_c) + err = abs.(deltastar0_c_jl .- deltastar0_c_interp)/(vmax - vmin) + @test maximum(err) < 0.02 + end + end + + @testset "non-zero angle of attack, tripped" begin + @testset "pressure side" begin + # Get the digitized data from the BPM report plot. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure07-pressure_side.csv") + bpm_pressure_side = DelimitedFiles.readdlm(fname, ',') + alpha_deg = bpm_pressure_side[:, 1] + deltastar_bpm = bpm_pressure_side[:, 2] + + # Get the AcousticAnalogies.jl implementation. + alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=50) + deltastar_jl = AcousticAnalogies._disp_thickness_p.(Ref(AcousticAnalogies.TrippedN0012BoundaryLayer()), alpha_deg_jl.*pi/180) + + # Interpolate the BPM report data onto the uniform alpha spacing. + deltastar_bpm_interp = linear(alpha_deg, deltastar_bpm, alpha_deg_jl) + + # Find the scaled error. + vmin, vmax = extrema(deltastar_bpm) + err = abs.(deltastar_jl .- deltastar_bpm_interp)./(vmax - vmin) + @test maximum(err) < 0.06 + end + + @testset "suction side" begin + # Get the digitized data from the BPM report plot. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure07-suction_side.csv") + bpm_suction_side = DelimitedFiles.readdlm(fname, ',') + alpha_deg = bpm_suction_side[:, 1] + deltastar_bpm = bpm_suction_side[:, 2] + + # Get the AcousticAnalogies.jl implementation. + alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=50) + deltastar_jl = AcousticAnalogies._disp_thickness_s.(Ref(AcousticAnalogies.TrippedN0012BoundaryLayer()), alpha_deg_jl.*pi/180) + + # Interpolate the BPM report data onto the uniform alpha spacing. + deltastar_bpm_interp = linear(alpha_deg, deltastar_bpm, alpha_deg_jl) + + # Find the scaled error. + vmin, vmax = extrema(deltastar_bpm) + err = abs.(deltastar_jl .- deltastar_bpm_interp)./(vmax - vmin) + @test maximum(err) < 0.04 + end + end + + @testset "non-zero angle of attack, untripped" begin + @testset "boundary layer thickness, pressure side" begin + # Get the digitized data from the BPM report plot. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure08-bl_thickness-pressure_side.csv") + bpm_pressure_side = DelimitedFiles.readdlm(fname, ',') + alpha_deg = bpm_pressure_side[:, 1] + delta_bpm = bpm_pressure_side[:, 2] + + # Get the AcousticAnalogies.jl implementation. + alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=50) + delta_jl = AcousticAnalogies._bl_thickness_p.(Ref(AcousticAnalogies.UntrippedN0012BoundaryLayer()), alpha_deg_jl.*pi/180) + + # Interpolate the BPM report onto the uniform alpha spacing. + delta_bpm_interp = linear(alpha_deg, delta_bpm, alpha_deg_jl) + + # Find the scaled error. + vmin, vmax = extrema(delta_bpm) + err = abs.(delta_jl .- delta_bpm_interp)./(vmax - vmin) + @test maximum(err) < 0.037 + end + + @testset "displacement thickness, pressure side" begin + # Get the digitized data from the BPM report plot. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure08-pressure_side.csv") + bpm_pressure_side = DelimitedFiles.readdlm(fname, ',') + alpha_deg = bpm_pressure_side[:, 1] + deltastar_bpm = bpm_pressure_side[:, 2] + + # Get the AcousticAnalogies.jl implementation. + alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=50) + deltastar_jl = AcousticAnalogies._disp_thickness_p.(Ref(AcousticAnalogies.UntrippedN0012BoundaryLayer()), alpha_deg_jl.*pi/180) + + # Interpolate the BPM report onto the uniform alpha spacing. + deltastar_bpm_interp = linear(alpha_deg, deltastar_bpm, alpha_deg_jl) + + # Find the scaled error. + vmin, vmax = extrema(deltastar_bpm) + err = abs.(deltastar_jl .- deltastar_bpm_interp)./(vmax - vmin) + # This is dumb. Maybe I have a bug? + @test maximum(err) < 0.11 + end + + @testset "displacement thinckness, suction side" begin + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure08-suction_side.csv") + bpm_suction_side = DelimitedFiles.readdlm(fname, ',') + alpha_deg = bpm_suction_side[:, 1] + deltastar_bpm = bpm_suction_side[:, 2] + + alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=50) + deltastar_jl = AcousticAnalogies._disp_thickness_s.(Ref(AcousticAnalogies.UntrippedN0012BoundaryLayer()), alpha_deg_jl.*pi/180) + + deltastar_bpm_interp = linear(alpha_deg, deltastar_bpm, alpha_deg_jl) + + vmin, vmax = extrema(deltastar_bpm) + err = abs.(deltastar_jl .- deltastar_bpm_interp)./(vmax - vmin) + # This is dumb. Maybe I have a bug? + @test maximum(err) < 0.081 + end + end + + @testset "positive/negative angle of attack" begin + for bl in [AcousticAnalogies.TrippedN0012BoundaryLayer(), AcousticAnalogies.UntrippedN0012BoundaryLayer()] + for Re_c in (range(0.04, 3.0; length=30)) .* 10^6 + for alphastar_deg in 0:30 + alphastar = alphastar_deg*pi/180 + # For a positive angle of attack, the pressure side should be the bottom side. + deltastar_p = AcousticAnalogies.disp_thickness_p(bl, Re_c, alphastar) + deltastar_bot = AcousticAnalogies.disp_thickness_bot(bl, Re_c, alphastar) + @test deltastar_p ≈ deltastar_bot + + # For a positive angle of attack, the suction side should be the top side. + deltastar_s = AcousticAnalogies.disp_thickness_s(bl, Re_c, alphastar) + deltastar_top = AcousticAnalogies.disp_thickness_top(bl, Re_c, alphastar) + @test deltastar_s ≈ deltastar_top + + # But if we switch the sign on alpha, the top and bottom switch too. + deltastar_bot_neg = AcousticAnalogies.disp_thickness_bot(bl, Re_c, -alphastar) + @test deltastar_bot_neg ≈ deltastar_s + + deltastar_top_neg = AcousticAnalogies.disp_thickness_top(bl, Re_c, -alphastar) + @test deltastar_top_neg ≈ deltastar_p + + # But the value of the pressure and suction sides should never change. + deltastar_p_neg = AcousticAnalogies.disp_thickness_p(bl, Re_c, -alphastar) + @test deltastar_p_neg ≈ deltastar_p + deltastar_s_neg = AcousticAnalogies.disp_thickness_s(bl, Re_c, -alphastar) + @test deltastar_s_neg ≈ deltastar_s + end + end + end + end +end + +end # module diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure06-bl_thickness-tripped.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure06-bl_thickness-tripped.csv new file mode 100644 index 00000000..16485c11 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure06-bl_thickness-tripped.csv @@ -0,0 +1,95 @@ +0.043515365256685146, 0.0947800184783715 +0.045848593655796285, 0.09328481651943997 +0.04685731826591985, 0.09274224063188645 +0.04915532059093932, 0.0909854583945438 +0.050236797200033205, 0.0902516249784931 +0.0527005377861259, 0.08889923417697465 +0.053860013468863446, 0.08819332284299246 +0.056337733754360624, 0.08699043072725679 +0.05766082843132637, 0.08633634031612064 +0.060400966381931265, 0.084718213138473 +0.061729860823538575, 0.08404021435554875 +0.0645696174172093, 0.0830453376346922 +0.06666383319442536, 0.08237586606707253 +0.07421936620516459, 0.07942044685569741 +0.07585228218511761, 0.07901814109950826 +0.07934171202679355, 0.07725370860237943 +0.08457182555886235, 0.0758730213826319 +0.08668367278330774, 0.07550437497242121 +0.09040865978999096, 0.07469365642805845 +0.09906174093569786, 0.0724721129870678 +0.10331864060315113, 0.07157710268764206 +0.11370115864388741, 0.06961177455334903 +0.11977591965345706, 0.0686428410813515 +0.12304671122968373, 0.06861674731213446 +0.1273245722140997, 0.06765950119993239 +0.131617723633292, 0.0663614568857871 +0.14677816097726254, 0.06464233075115117 +0.15022525390312602, 0.06414659219933098 +0.15736420647383828, 0.0633033391766955 +0.17217567204994622, 0.06177344241245178 +0.1808818471449405, 0.06099894020893365 +0.18512986695632805, 0.060640913629718976 +0.19336564243052917, 0.059854651192383826 +0.19819418541835665, 0.0594216106307787 +0.20731170548660793, 0.05879209770884262 +0.21218043192842706, 0.05842055605805862 +0.22226359704623794, 0.05767579304339302 +0.22715366547359922, 0.05733311706216263 +0.23760340747365163, 0.056636583744935104 +0.24318353614954083, 0.05628149653174323 +0.25474002006581475, 0.05558917660581798 +0.26300211902890985, 0.05514104340213724 +0.2715321864064626, 0.05471028849634238 +0.278716711605826, 0.05456058505996748 +0.2919617907993815, 0.053686019017968815 +0.29881852900202793, 0.053322587448247014 +0.31301887981102794, 0.05265341366081758 +0.32037014487031323, 0.05241027184173632 +0.33559466411643313, 0.05169267557211123 +0.3434761226721955, 0.05145655988817186 +0.35875616512879516, 0.051004551414532175 +0.3666492354269987, 0.05074299454210361 +0.38463064850523415, 0.05006130011393048 +0.42144393851940765, 0.04852198071350772 +0.44179202132832207, 0.048335922907703235 +0.4492250336023366, 0.04820760254544114 +0.4767577984498747, 0.04740825840967347 +0.49412875240919935, 0.047137853555968647 +0.5126282171375136, 0.0468378484260626 +0.5416840919345477, 0.04630394440007238 +0.5536017982561184, 0.04605490195345933 +0.5807518415494157, 0.04549339276771509 +0.5935290856966068, 0.0453484511686862 +0.6190343286255171, 0.04489823236259359 +0.6344922653568736, 0.04465198443957871 +0.6636807904911014, 0.04421230542902445 +0.6792673691939628, 0.04394838223604719 +0.7134769338937448, 0.04348430682567297 +0.7347267292104404, 0.043315732288660744 +0.7575352061647295, 0.04341635329855059 +0.7773909821287895, 0.04277466970756252 +0.8155162174280624, 0.04217030026344729 +0.8346686592171286, 0.04210145294224447 +0.8743334946265842, 0.04175973209883832 +0.8948672633024274, 0.041495827927955656 +0.9373928359595964, 0.041194252696499484 +0.9594075566242881, 0.04098958363455732 +1.005000190783791, 0.040626206059801065 +1.0286026737763319, 0.04048951546288959 +1.0774835743666709, 0.04006599248136533 +1.148510040508136, 0.03965144101003401 +1.2313437499724256, 0.0390948297871373 +1.2620916954440236, 0.03889508976194755 +1.3201516548565282, 0.03861399043961191 +1.355081815279942, 0.0384543801892165 +1.4236024106196106, 0.03775600329195844 +1.4826250991662007, 0.03802611592133082 +1.534170272562992, 0.037589365839040545 +1.5643892666904162, 0.037547390722686744 +1.6316144949797584, 0.03724484715168311 +1.672357620953663, 0.03702193760424273 +1.7543743014518025, 0.03671347996383577 +1.7955758753343642, 0.036580747689181466 +1.8700206183757198, 0.03635190670515587 +1.9167169954076175, 0.036277078165304434 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure06-bl_thickness-untripped.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure06-bl_thickness-untripped.csv new file mode 100644 index 00000000..4b66d932 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure06-bl_thickness-untripped.csv @@ -0,0 +1,121 @@ +0.04040131712460812, 0.05838291914634628 +0.04160860147041628, 0.05722360006892484 +0.043072506877375835, 0.0559518465017467 +0.04447264362147685, 0.05536475095332723 +0.0459183177070235, 0.05476993520928728 +0.04741103550030498, 0.054154057578502675 +0.04895217729697358, 0.05359940642010075 +0.05054352013617096, 0.05299669116562158 +0.05218659452586714, 0.05240075333093568 +0.05388297051092858, 0.05186405968625346 +0.055634661765666914, 0.05125487542484593 +0.057443150284932964, 0.05071706459145757 +0.059310426448816914, 0.050184896938159154 +0.06123849640669605, 0.04962057720125712 +0.06322911326164521, 0.04911235839262301 +0.06528436941514297, 0.048633986365757956 +0.06740653622316821, 0.0481236761850861 +0.06959761515520121, 0.04764286000114537 +0.0718599532908753, 0.04715489716565682 +0.07419586936184783, 0.04666010687823939 +0.07660767822041986, 0.04618220949642904 +0.07909780332175034, 0.045732378173214995 +0.08166899661504415, 0.045252514195119255 +0.08432381410248373, 0.04476634009630792 +0.08706466124464823, 0.04435277222704175 +0.08989482926037082, 0.04388738427717764 +0.09281709231470964, 0.043404876331718786 +0.09583390426255874, 0.043025686141617635 +0.09894907847966729, 0.042585012852734486 +0.102165249843885, 0.04220228963137287 +0.10548606667163794, 0.04180181543750553 +0.10891476812984938, 0.041415634934369554 +0.11245503203453772, 0.04101223176099571 +0.11611025157666235, 0.04063334572146785 +0.1198843418656755, 0.04024775985600711 +0.12378123481494172, 0.039845634003615904 +0.12780479797335884, 0.039447525895361005 +0.1319589437388061, 0.03908309518252474 +0.13624797400434135, 0.038741660589352696 +0.1406769197180398, 0.03833514931416758 +0.14524953401683485, 0.037971371942075366 +0.14997062287535215, 0.03763011278032644 +0.15484516269094753, 0.03729192060851019 +0.1603147316608354, 0.03691120649272889 +0.1657155037419209, 0.036435389861249216 +0.17043929743481512, 0.036387561340229684 +0.17597941015790824, 0.03603313341127857 +0.1793376536327586, 0.0357993364375049 +0.190906906333647, 0.03522507693527661 +0.19711180614484913, 0.034926195661859956 +0.20351827359815486, 0.03463862671628852 +0.21013296209125004, 0.034353425503500234 +0.21696320111718595, 0.03402743228120675 +0.2240153366979387, 0.033713074381166996 +0.23129609463155373, 0.03344396747304403 +0.2388138567632244, 0.033151796973883506 +0.24657545600972372, 0.03289550503152399 +0.2545894439537646, 0.032632924183806214 +0.26362959781209205, 0.032332471927215334 +0.27220302592214546, 0.03177828744726832 +0.2810457757381244, 0.03175392182368161 +0.29017918708766166, 0.031548383304889856 +0.29961112282384905, 0.03125692776856217 +0.3093486711247335, 0.031015284797102527 +0.3194021994453275, 0.030798914462115627 +0.3297836534149131, 0.030529851462360785 +0.34050200415986587, 0.03028615390337818 +0.3515694422003597, 0.030013963909573546 +0.36299510415961744, 0.029804579037956767 +0.37480213309253285, 0.02921119619042039 +0.3926402775885296, 0.029253644973271455 +0.40540133142343304, 0.02902748910313259 +0.41857691063288827, 0.028810381266611413 +0.4321804734560461, 0.02860214415687275 +0.44622637715549035, 0.028388217639987202 +0.46072996730765386, 0.02814021477594789 +0.47666249816993594, 0.027909501162679276 +0.5011382721502626, 0.0276839941041423 +0.5175540879993439, 0.027387425424182935 +0.5343735344717834, 0.02721015060167553 +0.551740721713494, 0.027006635343860535 +0.5696733769388092, 0.026780879665373902 +0.5881849176077869, 0.026644639838215488 +0.6073006649771612, 0.026452056382321842 +0.6270376656064389, 0.026260864890729776 +0.6474137623278388, 0.026117341358576823 +0.6684561520914496, 0.025895738315442195 +0.6901813938203449, 0.02569554195574181 +0.7126119811549727, 0.025509818436829732 +0.7357700894596877, 0.025350084264980033 +0.7596818320624507, 0.025174264560658088 +0.7843581504738899, 0.025195791061150205 +0.8098374841746665, 0.025194980542107295 +0.8338812122999554, 0.025021642258226243 +0.8633541503879749, 0.024516340286245875 +0.8914118514994493, 0.024351478110030238 +0.9203804318106141, 0.024199986056352374 +0.9502914006210232, 0.024037251230556327 +0.9811729057695654, 0.023893767938924886 +1.0130600626132957, 0.023727079075454308 +1.0459770186947288, 0.02363330836474603 +1.0799702456315208, 0.023468436531997063 +1.1150718701751874, 0.02326741767861444 +1.1513171442460826, 0.0230410607764546 +1.1857897562618942, 0.022754370191599958 +1.2273434423689011, 0.02293050741288989 +1.2672269614361298, 0.022805185286918363 +1.3084078833179724, 0.022669056450062324 +1.3509249572325228, 0.02255087692268545 +1.394824357702032, 0.02242762959162612 +1.440148066657337, 0.02232201866020247 +1.4869468443208236, 0.022200022108442775 +1.5352655908623634, 0.02208428777577163 +1.585158574079454, 0.02194133939216066 +1.6366687377827693, 0.021826953637945734 +1.6898509876609715, 0.021724171268795764 +1.7447694869073556, 0.021572618050906843 +1.801465317910936, 0.021465593247613244 +1.8600044287284925, 0.021353687678431044 +1.9204447892164687, 0.02124774901961902 +1.9542365815794616, 0.021187257309573077 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure06-disp_thickness-tripped.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure06-disp_thickness-tripped.csv new file mode 100644 index 00000000..01601404 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure06-disp_thickness-tripped.csv @@ -0,0 +1,108 @@ +0.04037433404302965, 0.01782147857312894 +0.04072736976854077, 0.0184323060028401 +0.042048450836318786, 0.017931112337930023 +0.04341238404990346, 0.018010382397535267 +0.04499432215471717, 0.017976267327306606 +0.04627441201351699, 0.017897839938265235 +0.04753340952625329, 0.017824495726928825 +0.049325123557721014, 0.01778083994793001 +0.050483659218970224, 0.017721084206775914 +0.052883003827397135, 0.017641039547060332 +0.05412510605419282, 0.017587877405463515 +0.05669751826441675, 0.017451619836116428 +0.05802921481327154, 0.01744453098718378 +0.060611028407633945, 0.017353644742145898 +0.062034644463923365, 0.01732345467557858 +0.06498297451829997, 0.017247208027706785 +0.06698608305581204, 0.017012203218299316 +0.0692670767232461, 0.017125071448086143 +0.0709557513750097, 0.016856591102102074 +0.07469567471667717, 0.01691313726456771 +0.07656111760691704, 0.01686428931305488 +0.080083563243578, 0.016814281182770844 +0.08196454512878336, 0.016786977976501905 +0.08561128026986996, 0.016652092001064153 +0.08762209573355104, 0.016659825744790427 +0.09258911167007308, 0.016453861505447937 +0.09559244145063266, 0.01608031016896024 +0.09858309475396242, 0.01609129822833225 +0.1010112707552887, 0.016317231969310116 +0.10550542551611061, 0.016243528393093055 +0.10814030828083948, 0.016256260915638795 +0.11311565828822488, 0.016162651297375274 +0.11594059830421571, 0.01606383019372569 +0.12127482626971298, 0.015989105700548657 +0.12475526535821443, 0.015860055415182137 +0.13002252481502896, 0.01590026413382095 +0.13346321127305757, 0.015826344245913563 +0.13940120533899195, 0.015743236088674634 +0.1428825981823775, 0.01572436338337017 +0.1494563813278422, 0.015678493809031968 +0.15318889120885618, 0.01560450511856119 +0.1600938329835394, 0.01531593003149915 +0.16473980732861798, 0.015585716876378275 +0.1703057608359019, 0.015324250249923637 +0.1755750536996477, 0.015360091459655941 +0.18418669897688278, 0.015267211103929755 +0.18851282821288526, 0.015215902868911446 +0.1974723062893463, 0.015182380658785488 +0.20211048441124413, 0.01514014235660276 +0.21110270665473335, 0.014988011176186719 +0.21637476617803464, 0.014985981524360299 +0.22632979785508642, 0.01493070696365369 +0.2319821373494366, 0.0148955074492687 +0.24125093671066372, 0.014495757136337424 +0.24907643702859375, 0.01452582608802758 +0.25757070379194585, 0.01453229117256631 +0.2660311267758637, 0.014588679586315937 +0.27371171663743304, 0.014340416889246341 +0.2830004916944808, 0.014373629309638468 +0.2990428830630295, 0.014192202309478348 +0.3060667244501852, 0.014122358481139607 +0.3206132045684983, 0.01399100677657704 +0.32814368405174416, 0.013944796795575207 +0.3437394192123809, 0.013780660745591382 +0.35181308120470445, 0.01372558251855411 +0.3685337554312148, 0.013463630681732893 +0.3766428713769725, 0.013372124556126491 +0.3951165368331504, 0.013251211279995291 +0.43743053002700216, 0.012610353837238762 +0.46014272701078424, 0.01248200540748955 +0.48252517004715406, 0.012238600629053561 +0.4996109361764893, 0.01215656025121354 +0.5145354351867956, 0.012035369151301385 +0.5281511921992177, 0.011886905268481435 +0.554860596333185, 0.011710231907877438 +0.5670695971182917, 0.011603672278036176 +0.5914406316702766, 0.011482743432216155 +0.6053322352564272, 0.011391138931918959 +0.6341019531698971, 0.011234868026043236 +0.648995574769353, 0.011162072389155848 +0.6798404869113523, 0.011011500113492988 +0.6947995110217327, 0.010921594646525147 +0.7288781959011412, 0.010919851578859675 +0.7470811327318478, 0.010905495067872948 +0.7791885498663015, 0.010549357340977363 +0.8500656736012902, 0.010250549103612729 +0.8956502052300221, 0.010158025472027828 +0.916687004084664, 0.01008342466261324 +0.9574718910857517, 0.009969945139968156 +0.9813837057738873, 0.009916178882802199 +1.0235607794941373, 0.009813785700612077 +1.049123091985163, 0.009730693688321572 +1.1005807206741887, 0.009534740645498512 +1.179966926908226, 0.009436480119222254 +1.205930596399675, 0.009376141946401122 +1.2614133936756136, 0.009240002898157188 +1.2891691889429384, 0.009188528592167306 +1.3524006533428254, 0.00911959209014705 +1.388994139098373, 0.009046419762121255 +1.4415597394558353, 0.00894142968778257 +1.5232771434893926, 0.008941911595790674 +1.5726879600159562, 0.008808497988592554 +1.666668293587214, 0.00867908963303141 +1.703341206818738, 0.008626983901217137 +1.7817090126873563, 0.008570464075570026 +1.823557330142698, 0.008527791435327624 +1.915777380786581, 0.008417638857665364 +1.9579316222315237, 0.008385942099503753 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure06-disp_thickness-untripped.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure06-disp_thickness-untripped.csv new file mode 100644 index 00000000..2c28f4eb --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure06-disp_thickness-untripped.csv @@ -0,0 +1,118 @@ +0.040617768187194966, 0.014673570162313375 +0.042048450836318786, 0.014715625233306351 +0.04341238404990346, 0.01447084888278145 +0.04482055941210757, 0.014242538322652449 +0.04627441201351699, 0.014009696241552032 +0.047775423495010655, 0.013768668447305456 +0.049325123557721014, 0.013539643559766732 +0.05092509152197321, 0.013295122871571401 +0.05257695793679158, 0.013070181291945333 +0.05428240624161459, 0.012834138909423492 +0.05604317448191047, 0.012602359360377463 +0.05786105708044305, 0.012378357360596122 +0.05973790666599235, 0.012154809048767973 +0.0616756359613934, 0.011959568093344662 +0.06367621973281838, 0.011760635368072644 +0.06587391053592068, 0.011677027711757937 +0.067874172125459, 0.011382547276985892 +0.0698966120183625, 0.0114554313943525 +0.0723488809644594, 0.01102940978486743 +0.07469567471667717, 0.010861698095687143 +0.07711859184277481, 0.010690330099499361 +0.07980001709550286, 0.010365718321410014 +0.08490437066706959, 0.010192785541599317 +0.08600971738877042, 0.009916620138934707 +0.08864514580313489, 0.009943939447960322 +0.09152054444872587, 0.009792733271523569 +0.09448921292083874, 0.00963543400071915 +0.09755417662972493, 0.009483413110195734 +0.10071855912141614, 0.009347343941790152 +0.10398558526097215, 0.00921055380287129 +0.10735858451898465, 0.009075765467055229 +0.11084099436468584, 0.008955935360852912 +0.1144363637691197, 0.008819752638762099 +0.11829130518998779, 0.008727330141253686 +0.1229375404122297, 0.008596638321248906 +0.1288954548215152, 0.008361641219065852 +0.1330764600289488, 0.008060246934704798 +0.14228950384451344, 0.007789161884877837 +0.1473034131404887, 0.00787916070767636 +0.15208152062508493, 0.007775129739951052 +0.1570146164473417, 0.007668020485779306 +0.16210772799203169, 0.007566777266955751 +0.16736604571811786, 0.007462538251446737 +0.17279492844842037, 0.007364008077385317 +0.1783999088308657, 0.007264670300711412 +0.18418669897688278, 0.007160435924851982 +0.1901611962826932, 0.007069996761712929 +0.1963294894394278, 0.0069766494329524765 +0.20269786463819392, 0.006876547615645951 +0.20927281197641845, 0.0067916647427863205 +0.21606103207199337, 0.006690332887454406 +0.22306944289196665, 0.006605831313274693 +0.230305186802736, 0.006518612502839618 +0.23825383063031957, 0.006479933039708831 +0.2454884092684032, 0.006511805890944338 +0.252879934872845, 0.0064134145384671815 +0.2616726089488799, 0.006220691102674694 +0.27016053074699875, 0.0061296567719166285 +0.27892377680141034, 0.005998381600349714 +0.2879712778548694, 0.0060036060983946786 +0.2973122543382508, 0.005931219660496085 +0.3069562257672151, 0.005863107979537431 +0.316913020443676, 0.0057873748355040475 +0.3271927854719565, 0.005725897838118919 +0.3378059970998394, 0.005655218380145786 +0.34876347139505387, 0.005585411376750204 +0.3600763752680764, 0.005526079757430019 +0.37175623785248113, 0.00546737839447123 +0.383814962254435, 0.005404593275355728 +0.3962648376833152, 0.005291847436616211 +0.4218787710048077, 0.005140974149646922 +0.4360903196364343, 0.005172575258747141 +0.4502358602983303, 0.005114659605565607 +0.4648402424240408, 0.005060328596406115 +0.4799183495372112, 0.005003669732820031 +0.4941393411279053, 0.0050560533486039535 +0.5115577023782769, 0.004895088378490563 +0.5281511921992177, 0.004841684518112355 +0.5452829280541006, 0.004791643557534758 +0.5629703691269898, 0.004739368247317053 +0.5812315409286651, 0.0046971955023371705 +0.6000850536666625, 0.004645950590421358 +0.6195501212111901, 0.004600602058566116 +0.6396465806762428, 0.0045556961679532925 +0.6603949126358739, 0.0045295942166816185 +0.6897769500902408, 0.004447533365709137 +0.7121513699197721, 0.004402843660359712 +0.7368535807947776, 0.00427864906930494 +0.7686501267190228, 0.004246977485559278 +0.7973356539059833, 0.004168165406864758 +0.820707638788883, 0.004183612445548774 +0.8439207259240049, 0.004172790694671719 +0.8878864698892782, 0.004105674394348162 +0.916687004084664, 0.0040940145346061736 +0.9464217464227236, 0.004059940118859287 +0.9771209999821381, 0.004027317869403919 +1.0088160507880417, 0.003992639729368936 +1.0415391996960313, 0.003955963471169471 +1.075323795310402, 0.0039287345483016226 +1.1102042679701691, 0.003894905282461622 +1.1462161648374853, 0.0038624880497509 +1.1833961861242415, 0.0038281181263751076 +1.2217822224937467, 0.0037973586026365386 +1.2614133936756136, 0.00376575324934027 +1.302330088333213, 0.003722508891759594 +1.344574005224297, 0.003694741774148193 +1.3881881956967774, 0.003673572678099024 +1.433217107562934, 0.0036451126159551895 +1.4797066303967772, 0.0036242278711491782 +1.527704142300744, 0.0036024172060917336 +1.577258558189358, 0.0035755458821660107 +1.628420379639078, 0.003551966013611859 +1.6812417463551497, 0.003527517807929801 +1.7357764893078718, 0.003504254673019909 +1.792080185592479, 0.0034811449529119336 +1.8502102150685082, 0.0034551782288179253 +1.9102258188363836, 0.003433388387170133 +1.952257905230749, 0.003422197439232577 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure07-bl_thickness-pressure_side.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure07-bl_thickness-pressure_side.csv new file mode 100644 index 00000000..717b93e1 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure07-bl_thickness-pressure_side.csv @@ -0,0 +1,74 @@ +0.7342464345577309, 0.933795097958901 +0.9896521086558021, 0.8982802371381512 +1.2454728760531566, 0.8755969060411909 +2.013259855182284, 0.8193413558348672 +2.269343651997005, 0.8053589377520405 +3.46865504932469, 0.7215268843690286 +3.7121175439404386, 0.7169126218643977 +4.944836965141455, 0.6363872516022215 +5.201558608293293, 0.6383432101259998 +5.457691723123769, 0.6284343184361536 +5.713763190434555, 0.6174676926559408 +5.969834657745334, 0.606692442294725 +6.225943113567936, 0.5968067319554506 +6.482076228398416, 0.5875426038611762 +6.738221672732831, 0.5786490905250323 +7.008781452054542, 0.5668785703238617 +7.506842948295169, 0.5560283336791481 +7.762815779574439, 0.5446144759438585 +8.018961223908853, 0.5363707569811258 +8.275069679731455, 0.527630898746009 +8.531313760097387, 0.5212765870381043 +8.787446874927863, 0.5131849003725663 +9.043690955293794, 0.507004563268528 +9.29986105863609, 0.49972180652396064 +9.556117468505956, 0.49389719645505786 +9.81243552589552, 0.4890982684129109 +10.068630288245693, 0.48245085482610384 +10.324849709603747, 0.4762670727092701 +10.581155437489372, 0.47145458148087677 +10.837374858847422, 0.46541174337478286 +11.60625505399248, 0.45091477364276916 +11.862573111382044, 0.4465334822173788 +12.981039129414242, 0.42773408295833687 +13.237534731660531, 0.4259760470587431 +13.493889777561908, 0.422333494804702 +13.750170846439659, 0.41773831220497526 +14.00663685787649, 0.41563011103496217 +14.263004233281809, 0.4122376097101212 +14.519359279183192, 0.40871253583609024 +14.775825290620027, 0.4066498850782492 +15.03215567751353, 0.4028565963467541 +15.288560041430667, 0.4000385735351496 +15.54108977993737, 0.4105551476090471 +15.801578370831905, 0.3970992689615243 +16.05808137078056, 0.39556018001746407 +16.31451039370557, 0.3931012986670046 +16.571013393654223, 0.39157770517297436 +16.82757804112257, 0.39082536294353387 +17.084167347598793, 0.39038043594520705 +17.34074432457108, 0.38978317479906044 +17.597259654023667, 0.3884246900678073 +17.853799642484134, 0.3873745537890573 +18.110302642432785, 0.3858731561800765 +18.366953596428704, 0.3861901359155558 +18.623567561912807, 0.3860530638647379 +18.88016919789297, 0.38576477548303517 +19.136758504369194, 0.3853256096051526 +20.163313002337116, 0.3859875248657655 +20.41996395633304, 0.38630459855065535 +20.676602580825012, 0.38647039103281533 +20.933191887301234, 0.38603042186159947 +21.189929147824735, 0.38740923350280104 +21.44659243132459, 0.3878795096564289 +21.703231055816566, 0.3880459780519025 +21.96006695237157, 0.3906552903561799 +22.21679188339113, 0.39189695144730174 +22.473492155402802, 0.39283442441483163 +22.730217086422357, 0.3940830116785659 +22.987003664961613, 0.39611126481972564 +23.243864220524493, 0.3990876042006921 +23.50049051551253, 0.39910238794716846 +23.75717845802027, 0.39990028957862855 +24.014088331598913, 0.40353741508304447 +24.270788603610583, 0.40450273368690226 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure07-bl_thickness-suction_side.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure07-bl_thickness-suction_side.csv new file mode 100644 index 00000000..683e42fc --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure07-bl_thickness-suction_side.csv @@ -0,0 +1,58 @@ +0.878008450487421, 1.0532100463776388 +1.123498737517684, 1.071107340733469 +1.5092367208715327, 1.09871324585482 +1.7197313549045727, 1.117336985880531 +2.16403735885331, 1.1550658679613817 +2.421058197967403, 1.1696911074823708 +2.6778608048617727, 1.1763105909280047 +2.9358671823240616, 1.2291247636977025 +3.7773406197781796, 1.2936601618238441 +4.034274330397768, 1.3064159213879543 +4.822772220559088, 1.4132134798675935 +5.059200922862267, 1.441382935990729 +5.322800785278254, 1.5511807690297224 +5.573954835434662, 1.6691629975727422 +5.864227524705527, 1.8096503289044634 +6.302132050209099, 2.0534448210305465 +6.592865040960351, 2.1500958333337774 +6.8056517297756685, 2.351847403653882 +7.158818040606718, 2.6056472191678024 +7.676496922496927, 2.9996560931242593 +8.240943325259181, 3.4651682331029425 +8.785702250120483, 4.096388045805003 +9.00629556984656, 4.348552998019177 +9.327454488451753, 4.567367891024411 +9.912728642737584, 5.652017294645706 +10.14825422468428, 6.067337985695341 +10.481096228950609, 6.652448877970667 +10.695499257020412, 7.075152121786196 +10.889713603068824, 7.4789351904614145 +11.227102258692497, 8.22705608897023 +11.675823594996306, 9.391639452310029 +11.937487177315905, 10.15132285819967 +12.196234146981467, 10.859844550285844 +12.503591368645939, 11.76496755780224 +13.250123155182333, 12.355897941008791 +13.647490737634989, 12.660179833555977 +13.904610212780593, 12.860753069363442 +14.161606392886807, 13.013386103292781 +14.418750527040288, 13.229924391438406 +14.675845343178015, 13.428990460984984 +14.886162021370868, 13.579561527067792 +15.283430967792011, 13.87040755060444 +15.531348839305537, 13.988064238951576 +15.798185291347874, 14.549872211129728 +16.05491268826821, 14.597262109330464 +16.312032163413818, 14.82852423464703 +16.569163968063364, 15.069356846494674 +16.826271113705026, 15.302098079390195 +17.071737974677806, 15.550540479399071 +17.480819818822983, 15.958584710447436 +17.656225506612326, 16.18034182184931 +18.01841084957481, 16.480047194402005 +18.27560430174405, 16.7805635416936 +18.532612811354205, 16.986375417302668 +18.789744616003745, 17.262254061248584 +19.046814773133594, 17.508259922675194 +19.292291497709524, 17.798102394343204 +19.754144187768, 18.692850388015703 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure07-pressure_side.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure07-pressure_side.csv new file mode 100644 index 00000000..9f69558b --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure07-pressure_side.csv @@ -0,0 +1,89 @@ +0.6433925811500547, 0.9701906171308675 +0.9175516858756954, 0.9173355459611888 +1.1726632061102347, 0.8951280038577215 +1.4267753807062107, 0.842918372643146 +2.1002465798640984, 0.8160476880118434 +2.35547700241257, 0.7996712509147121 +2.611284321373107, 0.7998896763076493 +2.8665834430362995, 0.7857575853214372 +3.6313252536859935, 0.7148114162009909 +3.886634944443756, 0.7024468012207672 +4.164262159148432, 0.705539410965608 +4.398944122865281, 0.6925733071565539 +4.549916089474744, 0.6835818715784314 +4.746292068519432, 0.6836921697495566 +4.979487250021856, 0.6621199078589373 +5.255715821211487, 0.6327208295297687 +5.5110123006010365, 0.6214837180826456 +5.766282357254157, 0.6098720171086247 +6.021631682116565, 0.6001691578516193 +6.276941372874331, 0.5897875937192499 +6.532277486368523, 0.5801312545582724 +6.787666445335583, 0.5717079584774755 +7.043582018876384, 0.5740730828034756 +7.299169213524776, 0.5697458932707363 +7.5541292568847656, 0.5529619944602919 +7.809103378889864, 0.536941673517597 +8.064399858279417, 0.5274055982940177 +8.319868085455765, 0.5212171828369359 +8.575217410318173, 0.5129247922606713 +8.830685637494517, 0.5069062901381799 +9.08606138509336, 0.49931121255124966 +9.341489978165063, 0.49275643025994487 +9.596958205341407, 0.48697457750855244 +9.852360375676676, 0.48012973090650624 +10.107788968748379, 0.4738267563716586 +10.363230773188297, 0.4678265860046625 +10.618791479942148, 0.46386247246444307 +10.874220073013847, 0.45777304878702413 +11.129767568399485, 0.45368061633068113 +11.385222584207616, 0.4481463644306681 +11.64070402275218, 0.44309638059388606 +11.896251518137815, 0.43913515567241934 +12.151825436259882, 0.4356190688832441 +12.406838814901965, 0.42359017753522643 +12.763778857511072, 0.4113739883269687 +13.034661905869035, 0.42285497917412923 +13.29022261262289, 0.41927193109896777 +13.545756896640311, 0.41532823553073056 +13.801330814762375, 0.41200276704282285 +14.056984001093737, 0.40985932788035534 +14.312584341952236, 0.4069604182305919 +14.568092203233226, 0.4027533556620505 +14.823745389564584, 0.40065803644480963 +15.079398575895942, 0.39857361809918346 +15.344709272392576, 0.39605026564763435 +15.591472859336166, 0.40537312275488496 +15.828032098340605, 0.4040811492897069 +16.10205095532602, 0.3908951836952973 +16.357770198498457, 0.3897774313852421 +16.61352907577554, 0.38921186099414895 +16.869182262106897, 0.3871869912309191 +17.12494113938397, 0.38662517959067505 +17.380700016661052, 0.38606418314393176 +17.636485316674566, 0.3858669311923504 +17.89209886890128, 0.3833180272320473 +18.14785774617836, 0.3827618294916996 +18.40365625756008, 0.38274630483388483 +18.659441557573594, 0.3825507480874023 +18.915213646218888, 0.3821754351649914 +19.17097252349597, 0.3816208953355185 +19.42685030308698, 0.38268421249911055 +19.682648814468706, 0.3826686909894097 +19.93850017132329, 0.3833740024347669 +20.194351528177883, 0.38408061386689163 +20.450255730505326, 0.385513382539727 +20.694458624004618, 0.38593235757079297 +21.45040914986501, 0.388398124864866 +21.706181238510304, 0.38801707519751927 +21.96219113178347, 0.3909332372228347 +22.218121756847346, 0.3927609835662378 +22.4741184387523, 0.39552665934644354 +22.73000942971153, 0.3968153803630008 +22.98590042067076, 0.3981083003426862 +23.241936736680366, 0.401477917015286 +23.49785415037602, 0.40316522920970244 +23.753718718598826, 0.40409840244948003 +24.00978145734485, 0.4079023758807748 +24.265857407459094, 0.41193592847791427 +24.52162949610439, 0.4115317863400766 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure07-suction_side.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure07-suction_side.csv new file mode 100644 index 00000000..f47e6647 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure07-suction_side.csv @@ -0,0 +1,67 @@ +0.2693843460828411, 1.019282928688709 +0.9238931426189669, 1.1497658891350881 +1.1573512303488762, 1.1877628301656449 +1.7168394628922439, 1.2475910637224454 +2.115030100896851, 1.3815523014964262 +2.3719647899450766, 1.4385421675541639 +2.8856599392127276, 1.550023882321968 +3.1336713472238866, 1.6358676606142926 +3.388126838560419, 1.6940471335363605 +3.7033139990903408, 1.7712415290637527 +3.8550201403049034, 1.8063933680303306 +4.46075778702671, 1.9944823889239807 +5.175545275471494, 2.288706384311476 +5.351577508980613, 2.4249253545625877 +5.7156828169901335, 2.762560065440481 +6.138486233979565, 3.210810258321147 +6.420086547485473, 3.5155646447885336 +6.678236682409496, 3.822515459536465 +6.956148462795666, 4.1310626966408295 +7.173680486940997, 4.465121635278031 +7.385015908354729, 4.828478402241083 +7.535322543946295, 5.136442874396151 +7.9051384658668145, 5.8301875604521065 +8.19049025747215, 6.355370380271513 +8.425991231651425, 6.991591347161059 +8.702497052839744, 7.7156391957958705 +8.885708343836972, 8.234085073924652 +9.2770816222566, 9.426674992699311 +9.70760341414328, 10.94331854087119 +9.963497047376153, 11.928054778250488 +10.228846056840615, 13.072704269568174 +10.487161333867325, 14.297950751915668 +10.658594029532336, 15.176671497221747 +10.99611145900887, 17.029134356245162 +11.445376585964832, 20.00513074387587 +11.6989978638647, 21.846566779818552 +11.952677271784717, 23.906944695510134 +12.805312553654039, 29.78301345656397 +12.968354048797197, 30.059961269496085 +13.340993900673704, 30.673816223108954 +13.597281232679391, 31.211211147409543 +13.853581776053291, 31.77296673439158 +14.109736994376826, 32.177864627410806 +14.365984692277864, 32.695427729179904 +14.587202447356438, 33.046471445872236 +14.995178305419065, 34.27125440434331 +15.130558278172286, 34.89169014874281 +15.5424676009315, 35.27203678611376 +15.833767127560156, 36.05708185162522 +16.08965869194021, 36.17530324273938 +16.34578748752731, 36.60184359380213 +16.602154087742292, 37.34838150158539 +16.800212314339703, 37.87729544503711 +17.20796137724797, 38.96512762193292 +17.382711447471806, 39.44151643786255 +17.743840894790864, 40.41478883431438 +17.999956479009754, 40.8720817845069 +18.256151331437934, 41.45140144859228 +18.512359395234327, 42.05871637035423 +18.768646727240018, 42.79557090894917 +19.001539661996276, 43.32894374289496 +19.444483075864802, 45.07231050216964 +19.700791315041165, 45.89612252023768 +19.956965001434227, 46.511579480972514 +20.21294564096349, 46.81234403514544 +20.469235398663017, 47.6365955335323 +20.70200385297209, 48.01696388223941 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure08-bl_thickness-pressure_side.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure08-bl_thickness-pressure_side.csv new file mode 100644 index 00000000..9c793be8 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure08-bl_thickness-pressure_side.csv @@ -0,0 +1,97 @@ +0.5665154651447253, 0.9694362876462931 +0.7627190434989366, 0.9475308133169189 +1.010525989207439, 0.9117181356345037 +1.266582268741919, 0.8898984240173042 +1.5373212181344744, 0.8685582347271924 +1.7569078289732403, 0.8474236697697107 +2.034653870783517, 0.8331867276192311 +2.290677738130716, 0.8150976574659662 +2.5505545217731793, 0.8114747986144274 +2.790169726665596, 0.7938238373652933 +3.0584813994241067, 0.7776327384018973 +3.2446220948785154, 0.7684636327874905 +3.50085157471033, 0.7410141583692238 +3.756862477182615, 0.7255858270758639 +4.0130175367164345, 0.7033301571017433 +4.254135043390011, 0.6862389164922028 +4.510335903278193, 0.6753639503170998 +4.757728405151973, 0.663808516022972 +4.99367880528057, 0.6561711405575235 +5.269506845485747, 0.6474133456843949 +5.525452923583465, 0.6368231586521066 +5.781457343618296, 0.6238477673176659 +6.037396939278558, 0.6139221709478503 +6.293381912001017, 0.60223441375109 +6.549340954973651, 0.5918447324985239 +6.805280550633913, 0.582428313564078 +7.061213663856723, 0.5734224120548264 +7.317172706829357, 0.563529792257132 +7.5731252673645315, 0.5540597353404432 +7.829006521087685, 0.5474805652766944 +8.084965564060322, 0.5380354913398362 +8.3408727475333, 0.5306804333643734 +8.596773448568825, 0.5236639980246591 +8.85286214029059, 0.5099705571502511 +9.20172916580168, 0.5039161432018298 +9.45756335355173, 0.49957912502825214 +9.713425159962515, 0.4943207880460369 +9.969345308310409, 0.4871200905719279 +10.225226562033562, 0.4813357938383422 +10.481127263069087, 0.4749717727404743 +10.736969622167504, 0.4706140262850929 +10.992883288077941, 0.46396959980811714 +11.248706199863985, 0.4603403745258522 +11.504626348211879, 0.4536346646867391 +11.760475189747751, 0.44926833355335716 +12.016304583971252, 0.44555144665324076 +12.218330425663748, 0.4432976068567442 +12.481393206431775, 0.440591199832615 +12.759031551422918, 0.43351857994904824 +12.993169014051485, 0.4297885623708185 +13.248953031212793, 0.4275917766272683 +13.504814837623577, 0.42309114491611965 +13.760611819659797, 0.42054593869993595 +14.016415284133469, 0.4178259978849595 +14.27225116079443, 0.4141808518029092 +14.528061107705565, 0.4113149936929785 +14.783890501929065, 0.40791210237458353 +15.03971341371511, 0.40472136549119264 +15.295419641626935, 0.40485594532568914 +15.551131840335565, 0.40482097523816585 +15.831826135803983, 0.39683647048739495 +16.109309111611566, 0.3974365502977515 +16.365047751710673, 0.3966657803098184 +16.620883628371633, 0.3932052375903632 +16.87664819822057, 0.3917294830588436 +17.1324581451317, 0.3890189736013538 +17.388190302793355, 0.38844112829303473 +17.643909495580093, 0.3882170573706138 +17.899648135679204, 0.38746416723909194 +18.155347881153574, 0.3877693032148248 +18.411138380752337, 0.3856118977527592 +18.666864055976536, 0.3852142462441941 +18.922602696075643, 0.3844671796251145 +19.17838023079949, 0.38267602484066265 +19.434054046524036, 0.3836746463749394 +19.689766756873322, 0.3836277366536244 +19.9455248442848, 0.3823617639429062 +20.201192177571887, 0.38353393441645073 +20.45689192304626, 0.38383597525325486 +20.712598150958083, 0.3839636101804614 +20.968297896432457, 0.3842659893957392 +21.2238679931577, 0.38808214370080385 +21.479567738632067, 0.3883877663456697 +21.73522210704424, 0.3899328860337816 +21.990967229580807, 0.38899973387724196 +22.246628080430437, 0.39036973058829194 +22.502288931280074, 0.39174455221520826 +22.757962747004616, 0.39276683874580715 +23.01359766810442, 0.39486770019921724 +23.26923258920422, 0.39697979890183155 +23.524925852241136, 0.39747313494658 +23.780534843591116, 0.40032668806329824 +24.036137352503633, 0.4033841211807624 +24.291837097978007, 0.4037017944466243 +24.5474590542029, 0.406230437094723 +24.803251242712573, 0.4039224624816097 +24.989306273128545, 0.40156571713283096 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure08-bl_thickness-suction_side.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure08-bl_thickness-suction_side.csv new file mode 100644 index 00000000..a0cb45d4 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure08-bl_thickness-suction_side.csv @@ -0,0 +1,62 @@ +0.8820639104698476, 1.06151690506704 +1.137682667406585, 1.0837297741305454 +1.4648031745354153, 1.0802321264250965 +1.7186343877173496, 1.1251132684763623 +2.01491976507584, 1.133542508256153 +2.2298719015908244, 1.16998681768386 +3.866219247132813, 1.2839203708946865 +4.096067581604483, 1.319840776966452 +4.36777423233444, 1.333914685552834 +4.64663105808361, 1.3789246279873264 +4.9022498150203475, 1.3844091567069459 +5.157868571957085, 1.4333689993564218 +5.413487328893819, 1.4640262184621022 +5.6458680170181275, 1.4819568622812533 +6.087391324454309, 1.5324875798282918 +6.250057806141324, 1.5476885022372122 +6.645104975952645, 1.593774316349917 +6.900723732889382, 1.6249149878572153 +7.156342489826116, 1.651418589973704 +7.4119612467628535, 1.6829229509758903 +7.655960969293375, 1.822426360425092 +7.8999606918239, 2.0707047296402563 +8.062627173510911, 2.2563840777988604 +8.376341102478726, 2.665985642368276 +8.56224565297817, 2.957122702367502 +8.75976923788383, 3.291472659403951 +8.95729282278949, 3.670225255581472 +9.10834027007029, 4.003785051980603 +9.440312681676442, 4.759698112927343 +9.750291921013687, 5.6502871357710305 +9.968148816130224, 6.3924401770414505 +10.18600571124676, 7.172253359681692 +10.355449963004066, 7.878067167559737 +10.502624398816128, 8.58330433103774 +10.781481224565297, 10.004141803677129 +10.998369866814649, 11.222201919124679 +11.176528394376618, 12.373717919412634 +11.385671013688494, 13.88015152324985 +11.594813633000367, 15.518342093173652 +11.803956252312243, 17.426905564565242 +12.036336940436549, 19.668547448577627 +12.152527284498703, 21.228828487578742 +12.477860247872734, 24.2191377347197 +12.727669487606363, 25.56216344790078 +13.012335830558637, 25.63804563886704 +13.267954587495375, 26.1034834737726 +13.523573344432112, 26.52925118778422 +13.755954032556417, 26.84740970250799 +14.174239271180166, 27.49360727908446 +14.37176285608583, 27.799008484910864 +14.731952922678502, 28.399470098434673 +14.992551265789334, 29.176523263830862 +15.243190436551977, 29.21409765607994 +15.977513411024784, 29.992533619813162 +16.40509387717351, 31.314287075894185 +16.60261746207917, 31.60241637730399 +16.986045597484274, 32.376305170750214 +17.24166435442101, 32.93421548386202 +17.49728311135775, 33.35030382005953 +17.752901868294487, 33.80226325936886 +18.00852062523122, 34.38474576252859 +18.15956807251202, 34.57877868239897 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure08-pressure_side.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure08-pressure_side.csv new file mode 100644 index 00000000..4221756b --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure08-pressure_side.csv @@ -0,0 +1,89 @@ +0.4798245681205575, 1.0203400939902614 +0.7221345871110021, 0.9776095954493949 +0.9790415951972555, 0.9408279615002207 +1.235948603283509, 0.9193089731776002 +1.6233766233766236, 0.8713510125314436 +2.0066696275422693, 0.8611443760099514 +2.2635766356285227, 0.8419353994789205 +2.857142857142856, 0.7857867389195877 +3.734953136486155, 0.7507206023454989 +3.9918601445724082, 0.7284695606564573 +4.259276984807645, 0.7003958460927333 +4.483778677101199, 0.6892009064829666 +5.089553724577311, 0.6773918908473207 +5.346460732663562, 0.667673341942503 +5.6033677407498175, 0.6531581560354391 +5.860274748836069, 0.6422976427395455 +6.117181756922324, 0.6308865479587079 +6.374088765008576, 0.6229165399322915 +6.630995773094831, 0.6100805999129093 +6.887902781181083, 0.6027223936811228 +7.144809789267338, 0.5920143949229559 +7.40171679735359, 0.5821705613154148 +7.658623805439845, 0.5754821674729614 +7.915530813526097, 0.565258120052039 +8.172437821612352, 0.5603843866768243 +8.429344829698604, 0.5517051463407956 +8.686251837784859, 0.5447354392535568 +8.94315884587111, 0.5381653635875524 +9.200065853957366, 0.5282982412188625 +9.456972862043617, 0.5225313025297543 +9.713879870129873, 0.5153329037329477 +9.970786878216124, 0.5102982216780761 +10.22769388630238, 0.5041434946545377 +10.484600894388631, 0.49864023078321146 +10.741507902474886, 0.4931970409058127 +10.998414910561138, 0.4878132692506387 +11.255321918647393, 0.4830474475943184 +11.512228926733645, 0.4780512480679341 +11.7691359348199, 0.4709198340065015 +12.026042942906152, 0.4690275332944689 +12.282949950992407, 0.4655224065271373 +12.539856959078659, 0.4593753287595661 +12.796763967164914, 0.45515085893701984 +13.053670975251165, 0.4533219228161504 +13.31057798333742, 0.4507165711327641 +13.567484991423672, 0.44838579605628376 +13.824391999509928, 0.4437481048459261 +14.08129900759618, 0.44017689784919567 +14.338206015682434, 0.43866210497491925 +14.595113023768686, 0.43563612579996747 +14.852020031854941, 0.43238053900182466 +15.108927039941193, 0.430144584416601 +15.365834048027448, 0.4266828561687519 +15.6227410561137, 0.4244763658144689 +15.879648064199955, 0.4227706892400993 +16.136555072286207, 0.4213157968306097 +16.393462080372462, 0.42083968339463224 +16.650369088458714, 0.42085128951358275 +16.90727609654497, 0.41891749742166373 +17.16418310463122, 0.4162687286279596 +17.421090112717472, 0.41507652946255086 +17.677997120803727, 0.4138877447713793 +17.93490412888998, 0.4138991591664277 +18.191811136976234, 0.41104399975793493 +18.448718145062486, 0.4112934633038613 +18.70562515314874, 0.4110666720083268 +18.962532161234993, 0.4108400057677641 +19.219439169321248, 0.4101381344015942 +19.4763461774075, 0.410387048175758 +19.733253185493755, 0.41063611301626285 +19.990160193580007, 0.41088532901478964 +20.24706720166626, 0.41304395247475373 +20.503974209752517, 0.41425316159264003 +20.76088121783877, 0.4142645860653292 +21.01778822592502, 0.4166822102726536 +21.274695234011272, 0.4179020705923699 +21.53160224209753, 0.417188134527007 +21.788509250183782, 0.4203525153132856 +22.045416258270034, 0.42060762821864583 +22.302323266356286, 0.4228173286620509 +22.559230274442545, 0.4262712062817298 +22.816137282528796, 0.428758900431451 +23.073044290615048, 0.43126111262060923 +23.3299512987013, 0.4310233109651712 +23.58685830678756, 0.43228515565389714 +23.84376531487381, 0.4348079468649496 +24.10067232296006, 0.43937643654356817 +24.357579331046313, 0.44296558092796096 +24.614486339132572, 0.44560231272905654 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure08-suction_side.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure08-suction_side.csv new file mode 100644 index 00000000..4b6464f5 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure08-suction_side.csv @@ -0,0 +1,89 @@ +0.324675324675324, 1.0744070048836116 +0.5194805194805205, 1.1136616043020828 +0.7142857142857135, 1.1543504121429682 +1.0053161755697122, 1.2239325401032952 +1.2271904098260222, 1.2422531282430687 +1.4928556113697624, 1.3256608838107748 +2.076735175202156, 1.4337819219973431 +2.3336421832884096, 1.4888251792308465 +2.590549191374663, 1.477299605092961 +2.8474561994609164, 1.5677710687092192 +3.107477231887609, 1.6395492162873375 +3.3762842615605404, 1.6429641595587285 +3.602008251182779, 1.788180130836887 +3.880923027444256, 1.8991252278037445 +4.089659971514333, 2.031183643059697 +4.3583568554087435, 2.00340279050595 +4.599094890958099, 2.025909285208591 +4.856001899044351, 2.182312893272245 +5.112908907130606, 2.264780442208253 +5.369815915216858, 2.354451482415145 +5.556657375643226, 2.427787010369722 +5.930340296495956, 2.565583627614478 +6.1055041656456766, 2.6332704977086885 +6.490864677775054, 2.79726829400452 +6.747771685861309, 2.906338834269315 +7.004678693947561, 3.012675097998435 +7.261585702033816, 3.135587842532363 +7.518492710120068, 3.3187890558799125 +7.752044535653027, 3.8130188922512525 +7.95056358735604, 4.350463860071321 +8.277536143102182, 5.415394300626917 +8.476055194805195, 6.236915721173679 +8.700264947316835, 7.100716549825783 +8.89644848076452, 8.380764703951074 +9.04825716736094, 9.271893508748374 +9.305164175447196, 11.03631925579049 +9.503683227150209, 12.642123980995967 +9.713879870129873, 14.667672141127252 +9.912398921832885, 16.922694371225358 +10.110917973535898, 19.403853628225267 +10.309437025238914, 22.31187710433151 +10.476815833537533, 25.252967223284582 +10.694797537368295, 29.27367762110737 +11.021770093114434, 36.717783996155966 +11.22028914481745, 42.078900550677616 +11.418808196520462, 48.1630894864053 +11.617327248223475, 55.170907481266575 +11.7691359348199, 61.64075011986763 +12.072753308012743, 75.45156124202711 +12.266970089245408, 95.74853573223277 +12.292292024013726, 88.06145061975393 +12.512380273721835, 103.20120927792581 +12.769721124208466, 109.19977847416833 +13.03031579269787, 105.9062665854469 +13.287222800784125, 107.01901461428392 +13.544129808870377, 108.45705908017005 +13.832177060361023, 110.41165975185042 +14.057943825042884, 111.71440141820582 +14.2331076941926, 112.76837883481524 +14.57175784121539, 115.53700974436379 +14.828664849301646, 116.8185819013199 +15.080567175412195, 122.14879949867205 +15.342478865474149, 120.81584347330201 +15.590403111039905, 123.23013920749443 +15.869638700248544, 128.30888000628346 +16.253330985052685, 126.67078177847719 +16.440172445479053, 128.35165261689826 +16.813855366331783, 130.94375837952333 +17.070762374418038, 133.3967762347923 +17.32766938250429, 135.65984434047775 +17.584576390590545, 137.48274365514524 +17.8181282161235, 139.78942673875184 +18.181818181818187, 143.6071810213105 +18.518783692722376, 144.9906105549027 +18.70562515314874, 146.57463563237272 +19.05595289144818, 149.69980720423072 +19.31285989953443, 152.50418905905707 +19.569766907620686, 153.92814223327318 +19.826673915706937, 156.26778488398955 +20.078576241817483, 159.1669862296754 +20.3054551580495, 160.8545486955556 +20.737526035285473, 165.55767888520978 +20.924367495711838, 167.366399561109 +21.298050416564568, 175.50532620464404 +21.554957424650826, 179.18012335366956 +21.811864432737078, 180.6996010609957 +22.06877144082333, 182.3093750478241 +22.32567844890958, 183.90508580016396 +22.53587509188925, 185.1876189584014 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure11-a-TBL-TE-suction.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure11-a-TBL-TE-suction.csv new file mode 100644 index 00000000..44d18260 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure11-a-TBL-TE-suction.csv @@ -0,0 +1,20 @@ +0.19122884328458217, 47.47663551401869 +0.2445397785389371, 49.719626168224295 +0.3057995860613679, 51.588785046728965 +0.3910506478432203, 53.27102803738318 +0.48901298166689, 54.95327102803737 +0.6253404255629251, 56.44859813084111 +0.781994833017049, 58.130841121495315 +0.9778928306368182, 59.81308411214952 +1.2228653538814906, 60.56074766355139 +1.5991289849841541, 60.56074766355139 +1.9555194321247966, 59.43925233644859 +2.5006807584394393, 57.57009345794391 +3.1271278046105184, 56.07476635514018 +3.998911083012669, 54.579439252336435 +5.000680712102545, 52.710280373831765 +6.253404255629254, 50.841121495327094 +7.99673347137438, 48.97196261682242 +10, 47.102803738317746 +12.505106035854066, 44.85981308411214 +15.991289849841541, 42.616822429906534 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure11-b-TBL-TE-suction.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure11-b-TBL-TE-suction.csv new file mode 100644 index 00000000..b153bbd1 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure11-b-TBL-TE-suction.csv @@ -0,0 +1,21 @@ +0.2, 44.49999999999999 +0.24410038095696923, 46.39122596153845 +0.31141368095074606, 48.28605769230768 +0.38858992294316563, 50.179086538461526 +0.49574776495506734, 51.69891826923076 +0.6186066880395188, 53.216947115384606 +0.789194121811289, 54.73677884615383 +0.9847765263413465, 56.25480769230768 +1.2288292322897234, 56.272836538461526 +1.5676920821958156, 55.54266826923076 +1.95620611001812, 54.060697115384606 +2.4410038095696898, 52.57872596153845 +3.1141368095074573, 51.09855769230768 +3.9728934589573064, 49.24338942307691 +4.957477649550668, 47.38641826923076 +6.324555320336747, 45.90624999999999 +7.891941218112874, 43.674278846153825 +10.06822871371386, 41.44411057692306 +12.56339223148977, 39.21213942307691 +15.676920821958156, 36.60516826923076 +19.99999999999996, 33.999999999999986 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure11-c-TBL-TE-suction.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure11-c-TBL-TE-suction.csv new file mode 100644 index 00000000..6226df16 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure11-c-TBL-TE-suction.csv @@ -0,0 +1,21 @@ +0.2, 39.00000000000003 +0.24956509409400443, 40.875 +0.31141368095074623, 42.375000000000014 +0.3972893458957312, 44.250000000000014 +0.49574776495506784, 45.750000000000014 +0.632455532033676, 47.625000000000014 +0.8068619331773571, 48.750000000000014 +1.0068228713713865, 49.125000000000014 +1.2563392231489776, 48.375000000000014 +1.6027882483009852, 46.500000000000014 +2.0447743105980503, 45.000000000000014 +2.495650940940043, 43.500000000000014 +3.1838534738843176, 42.000000000000014 +4.061835241809468, 40.125000000000014 +4.957477649550676, 38.25 +6.324555320336749, 36.375 +7.891941218112885, 34.125000000000014 +10.068228713713866, 31.875000000000014 +12.288292322897252, 29.625000000000014 +16.02788248300985, 26.625000000000014 +19.999999999999993, 23.625000000000014 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure11-d-TBL-TE-suction.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure11-d-TBL-TE-suction.csv new file mode 100644 index 00000000..16147784 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure11-d-TBL-TE-suction.csv @@ -0,0 +1,19 @@ +0.19733138705584236, 35.847955881682694 +0.246708176799955, 37.375689348707894 +0.3154455089777354, 39.282621576044846 +0.39437713158935017, 40.81035504307005 +0.49305923683834, 42.33808851009526 +0.6303020948101578, 43.86764504808349 +0.8054082886958644, 44.642450207374324 +1.0056724401058368, 43.90592953830728 +1.2552051011121506, 42.41465749054282 +1.6018989565557475, 40.925208513741396 +1.9993704327060953, 39.43393646597694 +2.495464592707136, 37.94266441821249 +3.184055884533878, 36.07583975206235 +4.062655068504369, 34.20901508591223 +5.068573991546193, 31.96299165945034 +6.323559808693353, 29.716968232988478 +8.06677133471125, 27.47276787748963 +10.059891090263687, 24.471993072330363 +12.827708660108557, 21.47304133813408 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure12-U71.3-TBL-TE-pressure.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure12-U71.3-TBL-TE-pressure.csv new file mode 100644 index 00000000..64a72ab5 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure12-U71.3-TBL-TE-pressure.csv @@ -0,0 +1,21 @@ +0.2, 45.50000000000003 +0.24956509409400443, 47.75000000000006 +0.3183853473884317, 49.62500000000003 +0.4061835241809472, 51.50000000000006 +0.5068461471582617, 53.00000000000003 +0.632455532033676, 54.50000000000003 +0.8068619331773571, 56.37500000000003 +1.0068228713713865, 57.87500000000003 +1.2563392231489776, 59.37500000000003 +1.6027882483009852, 60.12500000000003 +2.022263242309491, 59.375 +2.495650940940043, 57.87500000000003 +3.1838534738843176, 56.37500000000003 +4.017118203830592, 54.68750000000003 +5.068461471582615, 53.00000000000003 +6.324555320336749, 51.50000000000006 +8.068619331773567, 49.62500000000003 +10.068228713713866, 47.75000000000006 +12.56339223148979, 45.87500000000003 +16.02788248300985, 43.25000000000003 +19.99999999999995, 40.81250000000003 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure12-U71.3-TBL-TE-suction.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure12-U71.3-TBL-TE-suction.csv new file mode 100644 index 00000000..3befd28f --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure12-U71.3-TBL-TE-suction.csv @@ -0,0 +1,20 @@ +0.2, 50.75000000000003 +0.24956509409400443, 52.62500000000003 +0.3183853473884317, 54.12500000000003 +0.4061835241809472, 56.00000000000003 +0.5068461471582617, 57.50000000000003 +0.632455532033676, 59.00000000000003 +0.8068619331773563, 60.68750000000003 +1.0068228713713865, 61.62500000000003 +1.2563392231489776, 61.25 +1.6027882483009852, 60.12500000000003 +1.9999999999999993, 58.25000000000003 +2.523431581749075, 56.75000000000003 +3.1838534738843176, 55.25000000000003 +4.061835241809468, 53.37500000000003 +5.068461471582615, 51.87500000000003 +6.324555320336749, 50 +7.891941218112885, 48.12500000000003 +9.957386855546654, 45.87500000000003 +12.425080937674517, 43.62500000000003 +16.02788248300985, 41.00000000000003 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure12-U71.3-separation.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure12-U71.3-separation.csv new file mode 100644 index 00000000..96de2192 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure12-U71.3-separation.csv @@ -0,0 +1,10 @@ +0.4061835241809472, 42.87500000000006 +0.5068461471582617, 46.25 +0.632455532033676, 50 +0.8068619331773571, 53.00000000000003 +1.0068228713713865, 55.25000000000003 +1.2563392231489776, 54.87500000000003 +1.6386701177271523, 51.87500000000003 +1.9999999999999993, 48.875 +2.495650940940043, 45.50000000000003 +3.1838534738843176, 41.00000000000003 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure12-b-TBL-TE-pressure.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure12-b-TBL-TE-pressure.csv new file mode 100644 index 00000000..6303bd8e --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure12-b-TBL-TE-pressure.csv @@ -0,0 +1,21 @@ +0.19559968899256894, 37.12318840579712 +0.24433546979935863, 39.01630434782612 +0.3120805557126614, 40.536231884058 +0.39860881980786933, 42.4311594202899 +0.4979265240939303, 44.32427536231887 +0.6219903099880392, 45.84239130434787 +0.7944449561431122, 47.362318840579746 +0.9923895206005797, 48.505434782608745 +1.2396541169813167, 48.523550724637715 +1.5833638318526004, 47.41847826086962 +2.02237139350116, 45.938405797101495 +2.526267127953674, 44.081521739130494 +3.1557139417061566, 42.224637681159464 +4.030675371883462, 40.74456521739137 +5.034961791965142, 38.88768115942034 +6.4309683539554054, 36.65760869565224 +8.033313765075567, 34.80072463768121 +10.147148246624083, 32.75724637681165 +12.675420123274442, 30.52536231884062 +16.010748595215397, 27.731884057971087 +19.99999999999996, 25.125000000000057 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure12-b-TBL-TE-separation.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure12-b-TBL-TE-separation.csv new file mode 100644 index 00000000..735c2638 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure12-b-TBL-TE-separation.csv @@ -0,0 +1,12 @@ +0.19559968899256894, 22.498188405797094 +0.24433546979935863, 28.51630434782612 +0.3120805557126614, 33.036231884058 +0.39860881980786933, 36.8061594202899 +0.4979265240939303, 39.82427536231887 +0.6219903099880392, 42.84239130434787 +0.7944449561431122, 43.612318840579746 +0.9923895206005797, 41.38043478260872 +1.2396541169813167, 38.398550724637715 +1.5833638318526004, 34.66847826086962 +1.9778760779814692, 30.93659420289859 +2.4706853226994423, 26.07971014492759 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure12-b-TBL-TE-suction.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure12-b-TBL-TE-suction.csv new file mode 100644 index 00000000..26e0ba5d --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure12-b-TBL-TE-suction.csv @@ -0,0 +1,21 @@ +0.20201505550299306, 41.88843537414962 +0.25186397316140885, 43.434013605442146 +0.3139479561385023, 45.35691609977323 +0.4001791758335442, 46.906122448979545 +0.4880027686095134, 48.44807256235825 +0.6220411438527994, 49.99727891156459 +0.79339241744819, 50.414512471655314 +0.9904089953652075, 49.69614512471651 +1.237123952705327, 47.84580498866211 +1.579558316961316, 46.37641723356006 +2.0171993359764544, 44.52970521541948 +2.519165807618344, 43.05668934240359 +3.1467003793636934, 41.20634920634919 +4.01854230236993, 39.35963718820858 +5.0195777304993525, 37.50929705215418 +6.2712848330576705, 35.281632653061195 +8.189830124760856, 33.061224489795904 +10.0101463389338, 30.452607709750538 +12.788952794128654, 27.85124716553284 +15.988084524004146, 24.49160997732426 +19.987472849540442, 21.131972789115622 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure26-a-TBL-TE-suction.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure26-a-TBL-TE-suction.csv new file mode 100644 index 00000000..8f4d9ef5 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure26-a-TBL-TE-suction.csv @@ -0,0 +1,19 @@ +0.31207633691744474, 39.775171659476214 +0.39910271632651695, 43.15124263231452 +0.49902862323938363, 45.77444248647993 +0.6238863230749762, 48.0202953150635 +0.7975299766018652, 50.264325211156354 +0.9969336607042019, 52.132831014158114 +1.2742277127084614, 53.99951388466915 +1.628650258119821, 55.86619675518018 +2.0355712676638595, 57.35735553260012 +2.5441621766739138, 58.84851431002006 +3.249993709807516, 59.205809078203814 +4.058033698767741, 58.055538676551016 +5.06626629411179, 56.52792124931641 +6.324997786649053, 55.00030382208179 +8.072973371942346, 53.09351643677463 +10.07732163248435, 51.1885519839582 +12.579307103561472, 49.28358753114178 +16.05347653447461, 46.99945312025279 +20.48428034332578, 44.33797168378198 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure26-b-TBL-TE-suction.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure26-b-TBL-TE-suction.csv new file mode 100644 index 00000000..dd3493b6 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure26-b-TBL-TE-suction.csv @@ -0,0 +1,20 @@ +0.24956509409400418, 32.016187925998054 +0.31141368095074606, 36.184274586173316 +0.3972893458957306, 39.97170155793574 +0.49574776495506734, 43.00054771178189 +0.6186066880395188, 45.649647030185015 +0.789194121811289, 47.91808666017528 +0.9847765263413465, 49.80769230769231 +1.2288292322897234, 51.507424537487836 +1.5851430365421124, 53.39566090555015 +1.977981855335443, 54.90551971762415 +2.4410038095696946, 55.846214703018504 +3.1141368095074573, 55.07667964946447 +3.9728934589573144, 53.54765092502435 +4.957477649550668, 52.01953505355405 +6.32455532033676, 50.1107594936709 +7.89194121811289, 48.202896786757556 +9.957386855546659, 46.10470423563778 +12.56339223148977, 43.62676484907498 +16.027882483009844, 40.57874878286271 +19.99999999999996, 37.15189873417723 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure26-c-TBL-TE-suction.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure26-c-TBL-TE-suction.csv new file mode 100644 index 00000000..62d5d455 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure26-c-TBL-TE-suction.csv @@ -0,0 +1,19 @@ +0.24983216594852678, 25.12500000000003 +0.3120805557126614, 30.75000000000003 +0.3986088198078691, 35.625000000000014 +0.4979265240939303, 39.00000000000003 +0.6219903099880398, 41.62500000000003 +0.7944449561431122, 44.250000000000014 +0.9923895206005807, 46.125000000000014 +1.2396541169813153, 48.000000000000014 +1.5833638318526004, 49.500000000000014 +1.9778760779814735, 50.250000000000014 +2.4706853226994445, 49.500000000000014 +3.1557139417061566, 48.000000000000014 +4.030675371883467, 46.125000000000014 +4.924184802989251, 44.250000000000014 +6.2894770497736445, 42.000000000000014 +8.033313765075567, 39.00000000000003 +10.03490088836472, 35.625000000000014 +12.535205120094762, 31.31250000000003 +16.010748595215397, 25.500000000000014 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure26-d-TBL-TE-suction.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure26-d-TBL-TE-suction.csv new file mode 100644 index 00000000..570a1f14 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure26-d-TBL-TE-suction.csv @@ -0,0 +1,16 @@ +0.3126294409171655, 25.02707965678816 +0.39174500143052676, 30.704679608105636 +0.5011679863267893, 34.481835331345465 +0.6267653323476254, 37.501369196129744 +0.8011608255486816, 40.13935373942677 +1.0010971659110657, 42.01971642426824 +1.2512798896586061, 44.27980283575732 +1.5976527013805848, 45.39889247246394 +1.9930062775139767, 45.00091279741983 +2.4848005959869446, 43.84348566908052 +3.165525419599971, 41.92478549260635 +4.031608588980645, 39.62636158948456 +5.0222244579901485, 37.329763281202446 +6.250989317051318, 33.893993792977525 +7.950103479489087, 29.696951256617766 +9.99135264414231, 24.361650337735014 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-a-TBL-TE-pressure.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-a-TBL-TE-pressure.csv new file mode 100644 index 00000000..f94c36a7 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-a-TBL-TE-pressure.csv @@ -0,0 +1,8 @@ +2.4956509409400445, 51.20552884615385 +3.1488022006949494, 52.91195913461537 +4.017118203830595, 54.4317908653846 +4.957477649550679, 55.38641826923077 +6.32455532033676, 55.031249999999986 +7.979791317928454, 53.362680288461526 +9.957386855546659, 51.69320913461537 +12.563392231489782, 50.21213942307691 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-a-TBL-TE-suction.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-a-TBL-TE-suction.csv new file mode 100644 index 00000000..bdfbb9b0 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-a-TBL-TE-suction.csv @@ -0,0 +1,16 @@ +0.19562061100181222, 54.373197115384606 +0.24956509409400443, 56.64302884615384 +0.31141368095074623, 58.536057692307686 +0.3972893458957312, 60.43088942307691 +0.506846147158262, 61.950721153846146 +0.6324555320336762, 63.46875 +0.8068619331773571, 64.98858173076923 +1.0068228713713865, 65.00661057692307 +1.2563392231489783, 64.2746394230769 +1.602788248300986, 62.419471153846146 +2.0000000000000004, 60.93749999999999 +2.4956509409400445, 59.08052884615383 +3.1838534738843194, 57.60036057692307 +3.9728934589573104, 55.36838942307692 +4.957477649550679, 53.13641826923075 +6.32455532033676, 50.53124999999999 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-a-separation.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-a-separation.csv new file mode 100644 index 00000000..11aacf3f --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-a-separation.csv @@ -0,0 +1,10 @@ +0.3972893458957312, 56.30588942307691 +0.506846147158262, 61.57572115384615 +0.6324555320336762, 65.71875 +0.8068619331773571, 69.11358173076923 +1.0068228713713865, 71.38161057692307 +1.2563392231489783, 71.3996394230769 +1.602788248300986, 68.41947115384615 +2.0000000000000004, 65.0625 +2.4956509409400445, 60.58052884615384 +3.1838534738843194, 54.97536057692306 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-b-TBL-TE-pressure.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-b-TBL-TE-pressure.csv new file mode 100644 index 00000000..ee851f16 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-b-TBL-TE-pressure.csv @@ -0,0 +1,14 @@ +0.9846402658323226, 40.25 +1.241391025662117, 42.3125 +1.5999075929444284, 44.74999999999999 +1.9953007281803254, 46.25 +2.4880650254638517, 48.125 +3.1724192215653626, 49.625 +3.956982506408099, 50.75 +5.048162903094697, 50.75 +6.301841787213741, 49.625 +8.045206710977787, 47.75 +10.045962070954591, 45.875 +12.54254780240878, 44.375 +16.014580711281045, 42.125 +19.99999999999996, 39.875 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-b-TBL-TE-suction.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-b-TBL-TE-suction.csv new file mode 100644 index 00000000..5c1ed40b --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-b-TBL-TE-suction.csv @@ -0,0 +1,16 @@ +0.20357399682922497, 51.875 +0.24829060351907786, 53.75000000000001 +0.30960905192998983, 55.625 +0.3947138809139725, 57.5 +0.49219337631515303, 59.37500000000001 +0.6275735206953629, 60.875 +0.8004121076932287, 61.625 +0.9990510669918726, 60.875 +1.2473315822107587, 59.37500000000001 +1.5923980250309249, 57.5 +1.9884100851623028, 55.625 +2.4825624830942763, 54.125 +3.1697863849222285, 51.875 +4.047807954466729, 49.24999999999999 +5.056552432501364, 46.25 +6.317557835162936, 42.87499999999999 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-b-separation.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-b-separation.csv new file mode 100644 index 00000000..28f76502 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-b-separation.csv @@ -0,0 +1,11 @@ +0.31059600190717196, 46.99999999999999 +0.39515107588735565, 54.5 +0.49219337631515303, 59.37500000000001 +0.6269659249861568, 63.50000000000001 +0.7989735449710955, 66.5 +0.9967036607291092, 67.25 +1.244659127699273, 65.1875 +1.5904161051149528, 60.875 +1.9875848087403334, 56.75 +2.485656164057426, 50.75 +3.1464066510111293, 41.93749999999999 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-c-TBL-TE-pressure.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-c-TBL-TE-pressure.csv new file mode 100644 index 00000000..257ab137 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-c-TBL-TE-pressure.csv @@ -0,0 +1,14 @@ +0.8061880970493079, 32.07547169811322 +1.0049319915389328, 34.90566037735847 +1.2528452662871294, 37.358490566037744 +1.5969959783219596, 39.62264150943395 +1.9913853050610466, 41.50943396226414 +2.4831718345214244, 43.39622641509433 +3.166610022653156, 44.52830188679245 +3.9959182492163303, 44.15094339622641 +5.043819721325635, 43.01886792452831 +6.298190204759981, 41.132075471698116 +8.041699632379189, 38.867924528301884 +10.043024877459867, 36.60377358490567 +12.544163427883158, 33.96226415094338 +16.023419441793944, 30.56603773584905 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-c-TBL-TE-suction.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-c-TBL-TE-suction.csv new file mode 100644 index 00000000..3089da34 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-c-TBL-TE-suction.csv @@ -0,0 +1,15 @@ +0.198667688159059, 47.92452830188678 +0.24773006329427427, 49.811320754716974 +0.3157803484885661, 52.075471698113205 +0.4025237275021722, 54.339622641509436 +0.502069581083929, 55.47169811320754 +0.6263207606101797, 56.22641509433963 +0.7992579899328551, 55.47169811320754 +0.9980290972707953, 53.58490566037736 +1.2462334959990038, 51.698113207547166 +1.5912246408594677, 49.43396226415095 +1.987230235438525, 47.16981132075472 +2.4821347299576324, 44.52830188679245 +3.17102249719571, 40.75471698113208 +4.007899179431113, 36.03773584905663 +5.067050134029268, 30.56603773584905 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-c-separation.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-c-separation.csv new file mode 100644 index 00000000..2da3edab --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-c-separation.csv @@ -0,0 +1,10 @@ +0.24911373791035224, 34.716981132075475 +0.31661691130374225, 44.9056603773585 +0.3940387619179325, 52.075471698113205 +0.5018598901367922, 56.60377358490567 +0.6324555320336757, 59.81132075471699 +0.797923575706387, 60 +0.9965015714918111, 57.73584905660377 +1.2455395531676294, 53.20754716981132 +1.5927764075923079, 46.792452830188694 +1.994160176895641, 37.73584905660377 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-d-TBL-TE-pressure.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-d-TBL-TE-pressure.csv new file mode 100644 index 00000000..9e791d34 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-d-TBL-TE-pressure.csv @@ -0,0 +1,10 @@ +0.9847290618887449, 29.94224896441203 +1.2550455320266316, 32.603634384543284 +1.5997889065884308, 34.88767272397422 +1.994576904790426, 37.16989689474798 +2.487481363898925, 38.69742690412117 +3.173407679893117, 38.717382759350514 +4.0490428557113125, 38.35999153387958 +5.056687856905546, 36.11405073625009 +6.45646814209933, 33.86992410727781 +8.064347939192823, 31.246636228948063 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-d-TBL-TE-suction.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-d-TBL-TE-suction.csv new file mode 100644 index 00000000..eba4ef83 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-d-TBL-TE-suction.csv @@ -0,0 +1,13 @@ +0.1989722545655486, 43.77347080700267 +0.24803910396449638, 46.43304205847669 +0.3092920315454877, 48.33791914855016 +0.39425020713285885, 50.62195748798112 +0.491815174574402, 51.39479333595378 +0.6274338673380312, 51.41474919118312 +0.8008955470585419, 49.92531672361139 +1.0000671900509177, 48.056723006682176 +1.2491178777069258, 45.43343512835243 +1.5951178055129855, 42.81196141867986 +1.9926337415608903, 39.81132645964986 +2.4902538145707407, 35.67865025851901 +3.183587061951412, 30.03839990324431 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-d-separation.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-d-separation.csv new file mode 100644 index 00000000..53ede705 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure28-d-separation.csv @@ -0,0 +1,9 @@ +0.24942446269428653, 31.339158830465948 +0.31002503135521287, 41.92301877664558 +0.39452478480419195, 48.73522208447977 +0.5024052680069998, 53.66068998881261 +0.6266480701629653, 54.81087291748554 +0.7822688955535648, 53.696973361956864 +0.9996495214550998, 49.188764248782974 +1.2501618962143333, 43.16935264415079 +1.601348978022264, 32.246243159072336 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure38-d-TBL-TE-suction.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure38-d-TBL-TE-suction.csv new file mode 100644 index 00000000..d6ea4795 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure38-d-TBL-TE-suction.csv @@ -0,0 +1,12 @@ +1.591716941901872, 22.486785345403746 +1.9783340536338525, 29.074062822771737 +2.4810711786738358, 33.672762622273524 +3.1385452736905126, 37.562427851023756 +4.0045137521306255, 40.885229965368495 +4.9843497243388875, 42.35433501427791 +6.311486527964002, 42.689713834376334 +7.994863342464926, 41.74554954736011 +10.045785044607687, 39.520019442250444 +12.626361856720948, 36.299289142718266 +16.145606980416492, 31.80266115802904 +20.13555906774264, 26.305364845980918 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure39-d-TBL-TE-pressure.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure39-d-TBL-TE-pressure.csv new file mode 100644 index 00000000..9012bc77 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure39-d-TBL-TE-pressure.csv @@ -0,0 +1,9 @@ +3.1471039443872, 22.286935613144536 +3.9923161669660274, 27.002404488378318 +5.019265075905392, 30.49692759818329 +6.395923932839587, 33.61474752872029 +8.07732974048349, 34.674058242051856 +10.109593642382482, 34.969275981832766 +12.653177089187697, 33.66550895004008 +16.123627054423885, 30.691958322201444 +20.180347069970292, 27.40849585893669 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure39-d-TBL-TE-suction.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure39-d-TBL-TE-suction.csv new file mode 100644 index 00000000..0fb575e3 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure39-d-TBL-TE-suction.csv @@ -0,0 +1,13 @@ +0.796929418850918, 24.923857868020306 +0.9974376242018511, 31.538872562115955 +1.2596510951101805, 36.481432006411964 +1.6196160129706267, 40.667913438418395 +2.0089971164723095, 43.62543414373499 +2.5371365150402814, 45.37002404488378 +3.1754824931503123, 45.8936681806038 +4.0464379085596605, 45.20438151215602 +5.064525563397584, 42.986908896607005 +6.395923932839587, 39.706118087095916 +8.07732974048349, 35.66390595778789 +10.109593642382482, 30.400748063051026 +12.540098587319626, 22.77451242318996 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure39-d-separation.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure39-d-separation.csv new file mode 100644 index 00000000..9403495e --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure39-d-separation.csv @@ -0,0 +1,7 @@ +1.5907971014046818, 26.347849318728308 +2.0089971164723095, 37.99091637723751 +2.514462715872422, 45.97648944696766 +3.1754824931503123, 48.17793213999467 +4.0464379085596605, 47.48864547154689 +5.064525563397584, 41.4640662570131 +6.338765047660795, 31.02324338765696 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure45-a-LBL-VS.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure45-a-LBL-VS.csv new file mode 100644 index 00000000..2d3a85b5 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure45-a-LBL-VS.csv @@ -0,0 +1,3 @@ +2.515284132691356, 47.07182029107781 +3.1510601896995754, 48.93851508120653 +4.009044004226417, 41.827673486606216 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure45-a-TBL-TE-pressure.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure45-a-TBL-TE-pressure.csv new file mode 100644 index 00000000..0cc1150e --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure45-a-TBL-TE-pressure.csv @@ -0,0 +1,17 @@ +0.495236196047142, 42.078756476683964 +0.6286940093355667, 44.49948186528496 +0.8076954051273012, 46.12124352331611 +1.0131953969974448, 48.14093264248703 +1.2559069298684298, 49.35958549222798 +1.6328530211091588, 51.38238341968912 +2.024003889817087, 52.60103626943004 +2.508855171307443, 54.219689119170994 +3.1849493818933237, 55.44041450777203 +4.0432395943909185, 56.26113989637307 +5.011799935888166, 55.479792746114015 +6.516034326975962, 53.90259067357513 +8.076954051273011, 52.32124352331607 +10.253557123337979, 51.141968911917104 +12.709802556509684, 49.160621761658035 +16.13488026702086, 47.58134715025909 +20.48295872997347, 46.00207253886012 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure45-a-TBL-TE-suction.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure45-a-TBL-TE-suction.csv new file mode 100644 index 00000000..b5c43d89 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure45-a-TBL-TE-suction.csv @@ -0,0 +1,20 @@ +0.2538966312856989, 40.82072538860103 +0.31471771352980493, 43.23937823834197 +0.3995288363557754, 45.26010362694302 +0.5071951282611334, 47.28082901554404 +0.643875672350099, 49.301554404145094 +0.8173893208825227, 50.92227979274611 +1.0131953969974448, 52.540932642487036 +1.2559069298684298, 54.15958549222796 +1.6328530211091588, 55.7823834196891 +2.024003889817087, 57.001036269430045 +2.508855171307443, 57.81968911917099 +3.1849493818933237, 57.84041450777201 +4.0432395943909185, 56.26113989637307 +5.011799935888166, 54.679792746114 +6.3623956019994345, 53.10051813471503 +8.271995824805863, 51.52331606217618 +10.253557123337979, 49.54196891191711 +12.709802556509684, 47.96062176165805 +16.13488026702086, 46.3813471502591 +19.999999999999982, 44.00000000000003 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure45-a-separation.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure45-a-separation.csv new file mode 100644 index 00000000..60caec84 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure45-a-separation.csv @@ -0,0 +1,8 @@ +1.2559069298684298, 42.95958549222797 +1.6328530211091588, 46.58238341968911 +2.024003889817087, 49.40103626943005 +2.508855171307443, 51.41968911917101 +3.1849493818933237, 51.44041450777203 +4.0432395943909185, 48.26113989637307 +5.132824562484053, 45.0818652849741 +6.3623956019994345, 41.10051813471503 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure48-c-LBL-VS.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure48-c-LBL-VS.csv new file mode 100644 index 00000000..9a8dbc37 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure48-c-LBL-VS.csv @@ -0,0 +1,9 @@ +0.7946179079287674, 22.26008165234019 +0.9947815615976292, 25.869838590205177 +1.2589749622916813, 32.080067526829865 +2.0161689438421546, 44.90051850958639 +2.5029048405891947, 39.70991025133074 +3.150583084195995, 29.51990491119878 +4.053008464832621, 24.53084356858625 +5.028278322508261, 20.940207748359214 +1.6289910453613516, 42.49125768720607 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure54-a-LBL-VS.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure54-a-LBL-VS.csv new file mode 100644 index 00000000..6e581231 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure54-a-LBL-VS.csv @@ -0,0 +1,12 @@ +1.255906929868431, 51.21212121212122 +1.6134880267020877, 55.454545454545524 +2.0000000000000004, 59.49494949494951 +2.508855171307443, 63.33333333333334 +3.1471771352980524, 67.77777777777777 +4.043239594390923, 77.87878787878788 +6.3623956019994345, 80.7070707070707 +8.076954051273011, 71.01010101010101 +10.011792982166742, 64.54545454545453 +12.410123677992818, 60.50505050505052 +16.13488026702086, 56.46464646464648 +19.999999999999982, 52.62626262626267 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure59-c-LBL-VS.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure59-c-LBL-VS.csv new file mode 100644 index 00000000..2ec82f21 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure59-c-LBL-VS.csv @@ -0,0 +1,11 @@ +0.998900147361505, 41.69811320754718 +1.245378663805296, 45.47169811320755 +1.604898851815439, 49.81132075471699 +1.9996510746033878, 55.283018867924525 +2.515435781003538, 64.90566037735849 +3.1354627693923716, 69.24528301886792 +4.009717745648088, 64.33962264150945 +5.023948173564555, 54.71698113207549 +6.284186430492234, 49.622641509433976 +8.034150727479528, 45.47169811320755 +10.044578466616215, 41.69811320754718 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure60-c-LBL-VS.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure60-c-LBL-VS.csv new file mode 100644 index 00000000..161a2a94 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure60-c-LBL-VS.csv @@ -0,0 +1,13 @@ +0.8056269968349395, 43.96226415094344 +1.0038830376382706, 47.7358490566038 +1.2648525871974698, 51.50943396226418 +1.6110673334671342, 55.84905660377359 +2.0061362534131506, 61.50943396226418 +2.5222020521784163, 71.13207547169819 +3.1780952489270304, 74.71698113207552 +4.062400878751684, 69.43396226415098 +5.086844672054134, 60.00000000000006 +6.359880571290804, 54.71698113207552 +8.12499181758166, 50.94339622641513 +10.041626515739349, 46.98113207547175 +12.547657383627204, 43.20754716981139 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure60-d-LBL-VS.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure60-d-LBL-VS.csv new file mode 100644 index 00000000..2c1e4660 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure60-d-LBL-VS.csv @@ -0,0 +1,13 @@ +0.5033184803696572, 31.121358970350627 +0.621858373057373, 35.18472200510655 +0.796093343322128, 39.24964827262778 +0.9952997637133331, 43.31353238497209 +1.258970724330752, 47.78333593872128 +1.5886755306681373, 58.334114949715996 +2.0092198483850385, 63.20931686728153 +2.489583262526167, 59.97550935334269 +3.129777909692455, 50.05314991402216 +4.023070942371006, 43.780417904225914 +6.328224092647111, 35.89495075816788 +8.031609734089493, 31.85138867177318 +4.9861013536035745, 39.93851284456255 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure65-d-LBL-VS.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure65-d-LBL-VS.csv new file mode 100644 index 00000000..2c59a9af --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure65-d-LBL-VS.csv @@ -0,0 +1,13 @@ +0.6323804729499642, 50.70031957664685 +0.8005351953916066, 54.72079997250954 +1.001526190200231, 58.54025634857908 +1.2529801505682856, 62.35971272464863 +1.5860314954080894, 66.58018624789526 +1.9803165209619773, 75.39947080856327 +2.4735986166865658, 83.21878973231159 +3.1368026518717325, 82.83942132572761 +4.040310018041636, 73.06140682450773 +5.016861111841286, 65.88021030205145 +6.2215651964188385, 61.898903817738216 +8.090681093231776, 57.92172090306174 +10.033504771771565, 53.94041441874849 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure66-b-LBL-VS.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure66-b-LBL-VS.csv new file mode 100644 index 00000000..cb7717e1 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure66-b-LBL-VS.csv @@ -0,0 +1,3 @@ +3.165671170218893, 39.350131471259175 +4.008629977030465, 42.624549427969384 +5.033894958326965, 36.97894718512194 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure69-a-separation.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure69-a-separation.csv new file mode 100644 index 00000000..320b26c8 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure69-a-separation.csv @@ -0,0 +1,15 @@ +0.198921032245301, 74.87477975392679 +0.24821095117363703, 76.4018191949159 +0.31666443668194044, 77.93156935680616 +0.40410862713785956, 78.71135340270772 +0.5045210718339805, 78.73846061171935 +0.6302334505656204, 77.26563558875353 +0.8050483196115684, 75.42053822869448 +1.0055041100985864, 74.32269626372303 +1.2562215201461528, 72.47488818276284 +1.6046736696471975, 70.6297908227038 +2.0047910061999294, 68.7819827417436 +2.504675595146879, 66.9341746607834 +3.1643392737805045, 64.9002304112766 +3.9977404894235598, 62.86628616176981 +4.995942761981002, 60.26851196482087 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure69-b-separation.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure69-b-separation.csv new file mode 100644 index 00000000..10a96f37 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure69-b-separation.csv @@ -0,0 +1,11 @@ +0.19873691690470505, 57.16948614449635 +0.24791744679170302, 57.95138101501202 +0.31632389218967794, 57.60397296929566 +0.3949329474852795, 56.121819583654585 +0.4986001986225585, 54.45235611592363 +0.6294794082119991, 52.78289264819266 +0.7948241969241341, 50.73608780443558 +0.9925517461001079, 48.687922354755315 +1.2394677621778598, 46.63975690507506 +1.6006298602271163, 43.652319833099 +1.9996519290789554, 40.47213025534036 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure77.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure77.csv new file mode 100644 index 00000000..a1708860 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure77.csv @@ -0,0 +1,14 @@ +9990.048445307111, 139.0351175216975 +16298.84305872965, 138.06745529233717 +58208.64518330107, 135.79516323315931 +204961.29945196148, 133.37214689440032 +252823.1362459006, 133.04444513080273 +325017.3914307232, 131.9507675201532 +379010.73577773944, 131.47697439540414 +560275.5145774433, 129.91104796614883 +730425.6156975653, 128.81582604935602 +851888.3499450693, 128.4943015103314 +966370.7468891324, 128.48040275504215 +2208681.944680089, 128.3892886925904 +5647560.459253071, 128.4380887667171 +9754853.312375984, 128.5301294128548 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure78-A_max.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure78-A_max.csv new file mode 100644 index 00000000..e13e39ad --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure78-A_max.csv @@ -0,0 +1,157 @@ +0.1007120387104791, -16.37595973731831 +0.09933849976221693, -16.569365275194727 +0.10353423748565803, -15.836106474997 +0.10412278410363193, -16.135281862765616 +0.1070105760705445, -15.843639291249728 +0.11030392056888605, -15.594636050601212 +0.11335774381281573, -15.345191882364253 +0.11649482883217412, -15.105519975939258 +0.1197182349824111, -14.86951266769375 +0.1230306629907115, -14.634726892174735 +0.12643508967306455, -14.39749805120273 +0.1299333632011245, -14.162712275683718 +0.13352769241196477, -13.93281263107068 +0.13722164026643385, -13.701691453731152 +0.1410183618321188, -13.466905678212141 +0.144919933305207, -13.23334143541962 +0.14915637846326915, -12.981141633061421 +0.15351421236645882, -12.743111610330567 +0.15800076132483426, -12.497263778150144 +0.16286469230375616, -12.241086808944212 +0.16762340554342292, -12.001102333850968 +0.17226011183727552, -11.772424221964426 +0.17702434391902588, -11.547410708257372 +0.18192034131247087, -11.322397194550325 +0.18723503774940917, -11.086199470909216 +0.19299604940720497, -10.843215055149427 +0.1986350830205213, -10.60359703987413 +0.2044371606899326, -10.371430374230455 +0.210727723824952, -10.127346579016825 +0.21688347284619955, -9.893347614283401 +0.22288186207464364, -9.668334100576354 +0.22939233981693277, -9.435556668569427 +0.2364504842741849, -9.192572252809642 +0.24372549746635558, -8.950687216503702 +0.25122465707389086, -8.707702800743919 +0.2589545573934318, -8.464718384984133 +0.266920641956979, -8.227230866493576 +0.27554653381180866, -7.985499664924047 +0.28445548259439235, -7.7303760227349425 +0.2936459158537635, -7.495041210715064 +0.3031358462671552, -7.252210629691691 +0.3129327508394055, -7.008580499974611 +0.32353318401809117, -6.760906574351985 +0.33398323464180524, -6.533367362095738 +0.34477330875844986, -6.299431760289842 +0.35590993267926374, -6.070593281406326 +0.3674082733942306, -5.836957510360568 +0.3792794588060848, -5.60012354453999 +0.3915314710375975, -5.369486081095632 +0.40478571864589763, -5.140801436948525 +0.41849290207550505, -4.903121869997225 +0.43265985660338796, -4.674437225850117 +0.44730891836908654, -4.440755402367348 +0.4624513618251715, -4.212070758220239 +0.47810803011415914, -3.980387806471734 +0.49429142206923515, -3.754701469926024 +0.5110237556735249, -3.5270162616460503 +0.5283195180849094, -3.304328232701737 +0.5462006611054532, -3.0816402037574235 +0.5646850860935275, -2.8619504824145086 +0.5837950576828245, -2.6422607610715936 +0.6035531072220071, -2.420572167994413 +0.6247384123268234, -2.23107700460141 +0.6884114648349446, -1.6064228920765249 +0.7106461217736716, -1.3799830592741245 +0.7346907078388645, -1.1662899531340045 +0.7595342722081081, -0.969587256735136 +0.7852099495743219, -0.7818794831404601 +0.8051922291365005, -0.6007967935379694 +0.8315913453280492, -0.48809433015778136 +0.8596427497049118, -0.36235158032531967 +0.8907106629484776, -0.24433913875679814 +0.9164051458350063, -0.15539906720785623 +0.949487441438139, -0.09306240447824088 +0.9814039165100592, -0.06826267722615942 +1.067489101969357, -0.07327945334353103 +1.103288743772752, -0.11544192918932428 +1.1402289702748347, -0.20422570862764378 +1.164956352052084, -0.26403387326781846 +1.1924784046522436, -0.4180750291133828 +1.2323167996351183, -0.5701754503437497 +1.2734473307686862, -0.7492606399866943 +1.3159090933985986, -0.9563300339093495 +1.3597468167501625, -1.1893847603774468 +1.4050385942811046, -1.4264372303140753 +1.4518389946575967, -1.6634897002507056 +1.5001965762207539, -1.9015416060544652 +1.8102717740032663, -3.064679189188732 +1.8706122812480976, -3.2817429417827135 +1.932955353751773, -3.5028044378452226 +1.997391945542759, -3.716869882837802 +2.0639695969714515, -3.9339336354317815 +2.2038365385688774, -4.376056627556801 +2.277285185564061, -4.59711812361931 +2.3531790472531267, -4.81917905554895 +2.4316021829560865, -5.0412399874785905 +2.51263038106168, -5.266299227009629 +2.5963703947415606, -5.487360723072138 +2.682901264547338, -5.708422219134645 +2.772287856656084, -5.9384786380013495 +2.8646525542040377, -6.16853505686805 +2.9601045968417683, -6.395593168133354 +3.0587199096937425, -6.6276484587343205 +3.1606241380836577, -6.858704313468154 +3.265893931256504, -7.097755655139046 +3.374681329020585, -7.333808689208544 +3.4870924506904015, -7.56986172327804 +3.597863381784625, -7.800563856102036 +3.7121296102136565, -8.03686282978197 +3.8301238158742152, -8.250274722104576 +3.9516136087162157, -8.520854346027159 +4.077043927429893, -8.772544632060935 +4.206514439365957, -9.011841913342268 +4.340135581895799, -9.243143707686546 +4.47789818806179, -9.494833993720322 +4.620095612633023, -9.734630992935221 +4.766677367060864, -9.998814227308157 +4.918010691251178, -10.244807728899277 +5.066628166726011, -10.474556478293158 +5.219684900350282, -10.7131002633178 +5.3773919844566915, -10.947246530527062 +5.539836518666533, -11.185790315551708 +5.707195388568024, -11.423234721122506 +5.879610182275267, -11.660679126693305 +6.057165992774217, -11.908017947348712 +6.230798743416678, -12.144309082315965 +6.409408794026092, -12.380600217283222 +6.5931315499512095, -12.617868578431674 +6.7821187640045855, -12.85538124612542 +6.976428890534152, -13.104864934538822 +7.176314976644506, -13.35324924349838 +7.381897591908803, -13.605298150637422 +7.570804828570549, -13.833419387310409 +7.764546315994902, -14.061540623983403 +7.975123404764162, -14.29948801361805 +8.191422708544147, -14.536213870526202 +8.41354202662467, -14.777825858340341 +8.641648606600285, -15.02310244433396 +8.875939574989673, -15.268379030327582 +9.116595171568022, -15.512434083594703 +9.363607889813736, -15.77236906230627 +9.617366419223547, -16.02741791011185 +9.877988314213654, -16.28368829064393 +10.145700802908294, -16.537515605723016 +10.420496404563963, -16.80600131352005 +10.702720069447826, -17.075708554043572 +10.992617655493476, -17.34297272911411 +11.273406635919631, -17.611862620533877 +11.527238148571804, -17.839418000135034 +11.804147905564179, -18.093137532914724 +12.105609807298357, -18.366150097286415 +12.3778856874759, -18.614711477166402 +12.656335998755747, -18.859739137373325 +12.94091262681313, -19.114190050041778 +13.212257977361757, -19.35366692182977 +13.409518630000644, -19.52696546178823 +13.715658452039687, -19.81500018413832 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure78-A_min.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure78-A_min.csv new file mode 100644 index 00000000..0898c5b5 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure78-A_min.csv @@ -0,0 +1,157 @@ +0.27355039055049124, -19.74824252244953 +0.2742285859358864, -19.45488989843456 +0.27663525533876365, -19.125179995212406 +0.27925517741979106, -18.755837000754966 +0.28203321005378645, -18.41109531613482 +0.28469262562165787, -18.077940228699802 +0.28737672176664336, -17.746006673991282 +0.29038344694926477, -17.39334299036547 +0.2926737449832167, -17.084564666310662 +0.2954764425826937, -16.812668418611295 +0.29818843111064697, -16.509869445927777 +0.3009790166768364, -16.239012527544027 +0.3037957178363549, -15.968155609160265 +0.306639413166462, -15.695466391686766 +0.30950716661321015, -15.430106370572238 +0.3123965711620451, -15.179404742175654 +0.3155575874495826, -14.906742470277004 +0.319688723668434, -14.690989252459778 +0.32865183560031125, -13.842982072429104 +0.3324105517508175, -13.565742046758858 +0.3364643102951843, -13.279148912663194 +0.3405665989851912, -12.994911591682909 +0.3433071458267973, -12.735656667955636 +0.3475473850343733, -12.502469663211004 +0.3518541856968126, -12.233552826216387 +0.35621656627237414, -11.959139091952542 +0.36016058464030876, -11.705881483313119 +0.36496911969974144, -11.44267026486593 +0.369138171473964, -11.17747106178542 +0.3740664197130681, -10.914608852688657 +0.37882567675282347, -10.651658963546746 +0.38365275918047925, -10.37191299941553 +0.3893138702290586, -10.10613382491446 +0.3942705864677256, -9.835396664641143 +0.3991470932284883, -9.587093192406135 +0.4040763934218002, -9.355280411978812 +0.4096950868435975, -9.09356343258389 +0.41538830017999934, -8.839542109365887 +0.4211684669457449, -8.5690300943402 +0.42701224140477045, -8.333423376974114 +0.4329465006713374, -8.07857751916573 +0.4391097642531306, -7.823652022213901 +0.4462203072773484, -7.567029988321165 +0.4532989753708334, -7.288641046887754 +0.4597418269935335, -7.053260073559848 +0.46718096237948503, -6.807076592057163 +0.47530552556729666, -6.528258481104336 +0.48263453018619235, -6.274413202308683 +0.4923073997979264, -5.987687136710429 +0.5001003638101689, -5.739081384117567 +0.5076006257119109, -5.490746067112278 +0.5194801159940909, -5.191733472608865 +0.5281294322953753, -4.953451304620028 +0.535854624261876, -4.725842033869174 +0.5453400378247008, -4.478708769456183 +0.5545746468160395, -4.235082279141423 +0.5648138831222511, -3.990200894912256 +0.5752397893804846, -3.748984108862574 +0.5858508777600719, -3.5187611173513513 +0.5966626381752747, -3.2812089294811564 +0.6076663869442186, -3.0546505361494205 +0.6188756284748052, -2.8244275446381977 +0.6306045664547784, -2.597887115023024 +0.641898985618576, -2.3905498984170226 +0.6672920923133849, -1.9090538612393981 +0.6567012468364305, -2.1467463371818223 +0.6884114648349446, -1.6064228920765249 +0.7106461217736716, -1.3799830592741245 +0.7346907078388645, -1.1662899531340045 +0.7595402699473752, -0.9625912056652082 +0.7862302745343676, -0.7716430442248878 +0.8252570283777096, -0.4630550866848182 +0.8545068569452148, -0.3501427853209371 +0.8843623688871748, -0.2994026348148253 +0.9120868431437682, -0.1591560502153948 +0.9437839002530807, -0.10983724962069896 +0.975518558192602, -0.07604259956442672 +1.0082770686248588, -0.08022651245918588 +1.0421579667960639, -0.06542114387842979 +1.0771311823787666, -0.08859433824870688 +1.1160927389622646, -0.15514500893070693 +1.1505531653303882, -0.20021816676825566 +1.1889189139121141, -0.40597401640839603 +1.2286425512196961, -0.5550761300373654 +1.269653313016065, -0.7321624479460445 +1.3119900481429703, -0.9382324060015677 +1.3557033311883944, -1.1672893890011355 +1.400857263779844, -1.4063407306720297 +1.44537057256005, -1.6286476022121121 +1.4912808298228266, -1.8613486067703722 +1.5288865242535277, -2.1166092086894164 +1.5723511547932745, -2.2923080343427635 +1.6131712762218147, -2.6126652658514082 +1.6397895873004198, -2.8942165834975206 +1.6741549259601598, -3.1431167077470477 +1.7066755019217648, -3.392224697859696 +1.7398288203991248, -3.6408091739467032 +1.7762560608476152, -3.9069852610423776 +1.8134266996695414, -4.182584600599586 +1.8486171378945437, -4.448706796545562 +1.8812761766416222, -4.706914692221556 +1.9067884700307238, -4.93576422928904 +1.9519334933989196, -5.247241356798135 +1.9974658525514508, -5.5465126288201 +2.039384552340547, -5.903471437076863 +2.0739372024237435, -6.127100461485712 +2.1118606089646783, -6.41674229490717 +2.1372437588965387, -6.646765119290942 +2.1745431766548924, -6.919077098716551 +2.2156539783123597, -7.2105328727042295 +2.25289165342661, -7.486917364857812 +2.283688033717999, -7.72646831559126 +2.319342551343599, -7.976005024186286 +2.3575631791923812, -8.249448717755564 +2.386113300139136, -8.46919442990336 +2.4179359286233186, -8.704318436542863 +2.4501614627160127, -8.94721662646313 +2.4828041656110837, -9.19451233419878 +2.5159371714953003, -9.42229405662867 +2.549460137223522, -9.668215540047013 +2.583434579823985, -9.912487954284588 +2.6147863677621483, -10.16349795981556 +2.651862861611859, -10.400990268630531 +2.6880485749661664, -10.661795888805 +2.730942055423787, -10.97374540762428 +2.764953476822113, -11.241716155546415 +2.804931861851221, -11.530769121230533 +2.8455330187824996, -11.805896613832607 +2.8799876262533592, -12.080879199121041 +2.9149056387597536, -12.341814158054786 +2.956082806351109, -12.62572471047658 +2.991846078562289, -12.909563408032112 +3.0271314952271497, -13.164226035931526 +3.058881593842395, -13.422376191089983 +3.0942773755610364, -13.68174274648449 +3.1307174352186506, -13.95152184187428 +3.171166070586415, -14.255393077353782 +3.2054205640182083, -14.534473956264515 +3.2424516648086392, -14.810331203466708 +3.280550207799639, -15.103472112250719 +3.314200563781684, -15.374113466035682 +3.3475130998018385, -15.635454747129854 +3.3775770953630664, -15.886025497020023 +3.407240588045831, -16.120883127405307 +3.437136165506052, -16.36306995414955 +3.4621634989429855, -16.586879898846675 +3.4925482003573, -16.827234426501185 +3.5230829824188286, -17.096905739591577 +3.5538773751674073, -17.368409351771717 +3.583299595719613, -17.66554975373691 +3.608814693004779, -17.967535226684504 +3.636540834857216, -18.281756556858845 +3.657028883529857, -18.62552820078443 +3.7031031967699066, -18.93577954959766 +3.726756971225696, -19.185996157646954 +3.74815248538932, -19.435404398450785 +3.7810314489700034, -19.679423524284772 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure78-B_max.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure78-B_max.csv new file mode 100644 index 00000000..892819d5 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure78-B_max.csv @@ -0,0 +1,153 @@ +0.27192437368524963, -19.97108872655918 +0.2753802033463755, -19.587316659692497 +0.2786332023834429, -19.313988925206615 +0.28126120116659514, -19.03341868161774 +0.2839103264328109, -18.77524382785593 +0.28732619381433283, -18.49912066881842 +0.2908475640781019, -18.21100397869317 +0.29434940404345356, -17.920083865662775 +0.29718815977892926, -17.646716139409357 +0.3007628446985795, -17.37599186899088 +0.3048085849980444, -17.065968132955618 +0.30825195168444275, -16.767569115040715 +0.31196007491260047, -16.494845256244815 +0.31615558669932153, -16.18948722642353 +0.3201411507274753, -15.879447938034225 +0.32406155640850826, -15.608127790279276 +0.3280315566956828, -15.328409371339177 +0.33205233287577307, -15.037493257485544 +0.3356867601706378, -14.76314973210394 +0.3401215853885741, -14.49251388792704 +0.3444064053557768, -14.196938288801043 +0.3486214320072267, -13.938215547823823 +0.3528860540269725, -13.689290789895942 +0.3573304319439496, -13.399780608848111 +0.3625545613667527, -13.117617359851884 +0.36664243337242597, -12.856366250459665 +0.371484129717761, -12.595506171683468 +0.3761539155486925, -12.346743158237672 +0.3813301419299036, -12.086368757260708 +0.3865752930321643, -11.836352224078759 +0.39189461145799426, -11.577377534965976 +0.39728379516179757, -11.332959849240794 +0.40335888474505205, -11.060762548717626 +0.4107630482007147, -10.770891553055918 +0.4181869322214249, -10.489244076673891 +0.4241262694489513, -10.236481563307464 +0.4305341101938382, -9.987920730464275 +0.43777699965246064, -9.706420011750424 +0.4458179801732082, -9.396953049990039 +0.4533206205283004, -9.105374405854022 +0.4601681879670527, -8.861914745138101 +0.46670051630883125, -8.621254790920645 +0.47500231169596197, -8.35181789185571 +0.48174587688792253, -8.10878266902023 +0.4890181946217242, -7.881746294177496 +0.4972386602370798, -7.622267708793608 +0.5063639299446308, -7.33986184307426 +0.5156522337902978, -7.072386237239627 +0.5245916955465044, -6.784051814157721 +0.534750565013598, -6.513173353257692 +0.5444113901600125, -6.244080868142362 +0.5545499900037483, -5.973556435374448 +0.5645679333990711, -5.706245401722626 +0.5750815725363486, -5.436738941219588 +0.5812328260310439, -5.2176467088238425 +0.5964090867616167, -4.795720674952662 +0.6110187431181275, -4.5000517617023945 +0.6231422183667342, -4.28765948342992 +0.6340377811871816, -4.035409632206878 +0.6469691237609874, -3.7496195742469993 +0.6590577929346542, -3.4787286714637347 +0.6721553716465114, -3.2122142011091697 +0.6844734130141651, -2.973665973801168 +0.6980747954567933, -2.710350844850474 +0.7203617115766521, -2.302363337888494 +0.7438714266047588, -1.908491910445754 +0.7586532417413658, -1.6449101697114088 +0.7737209559193876, -1.3989248066983322 +0.7902790455353934, -1.1417697430090072 +0.8071922314364335, -0.8830150086177397 +0.8281885039685999, -0.6286633678335534 +0.8548304672882929, -0.41639324623286456 +0.88407433381137, -0.25093083939806604 +0.927648933678342, -0.038128487154793334 +0.961315394068643, 0.01813330488685949 +0.99360369541103, 0.007337709017939176 +1.0286946246729327, 0.0014374915005390676 +1.0621625150436507, -0.12399641268324046 +1.0969463067174305, -0.3039734791622948 +1.131959746130954, -0.5124312946310567 +1.1645688833758747, -0.7483636159884313 +1.1945007734075865, -1.017895243028022 +1.2215474278728684, -1.2586656795527986 +1.2473205195923742, -1.5150049111841426 +1.2736467732642938, -1.75854677720001 +1.2972466512949263, -2.0431002008367045 +1.331590427679454, -2.306735897943611 +1.3640920138385964, -2.598061959928259 +1.3970280733846945, -2.8976482889863675 +1.4286220011577881, -3.1852090935426958 +1.4609250475769824, -3.479168580906766 +1.4911677529184404, -3.759895792183272 +1.5209212823671567, -4.00941542765343 +1.5483747163377741, -4.24117038671389 +1.5786716331998885, -4.496415176973329 +1.6087300926549037, -4.779378261320517 +1.6410074136859427, -5.05782760817042 +1.6756164317046773, -5.328830487902813 +1.70992737461368, -5.600248748794151 +1.7392080910366436, -5.848356874828696 +1.773994122730523, -6.1094751226820705 +1.8096092170399682, -6.412041201984053 +1.843229421175653, -6.6915153075805875 +1.8815685300153946, -6.981820638075305 +1.9224882317680358, -7.261149046391431 +1.957895726455299, -7.51903895880946 +1.9857603206377052, -7.756322779733473 +2.021576111412685, -8.012339411106595 +2.0580257265301904, -8.278620596150454 +2.095704125621354, -8.545415857188075 +2.1323382225918737, -8.801252646794396 +2.162026562480788, -9.027615746091946 +2.197342943958387, -9.290444308537467 +2.236935251897393, -9.577254600922807 +2.2772592932319045, -9.850067774666229 +2.3182890645650693, -10.138744349537163 +2.356542247954908, -10.408170220569232 +2.391846037370987, -10.667116915444723 +2.4772513783956938, -11.202715367318966 +2.4277006274395823, -10.910386837441273 +2.499267450741314, -11.503612719723066 +2.5269563970041915, -11.745370952906278 +2.557966661664695, -12.009369052376108 +2.594512631936519, -12.297044055646438 +2.6263481701133813, -12.56353053176371 +2.6577069252241694, -12.817102333080705 +2.689420602948691, -13.083271541175428 +2.721514904000638, -13.348041037405963 +2.7540210507251306, -13.594614279402002 +2.7868862636295244, -13.85938377563253 +2.8201459470780605, -14.12275355999887 +2.8538025633176987, -14.386123344365217 +2.8878399078033814, -14.662090535509279 +2.922302053028732, -14.926860031739814 +2.957158774616779, -15.201427511019688 +2.9924240279019703, -15.48019412589214 +3.0281415512900374, -15.740764486530097 +3.0642903364747265, -15.99853542343967 +3.1008081902309845, -16.29129915695404 +3.137796630890282, -16.564466924369718 +3.175223735131439, -16.839034403649592 +3.2130558410896497, -17.13599727275654 +3.2472201094838518, -17.398543226711382 +3.2852591733523457, -17.666907982844506 +3.328261452881204, -17.977734220348573 +3.369024627867396, -18.283257105122757 +3.4040979116940493, -18.55546373705836 +3.4344656924673695, -18.781451883238347 +3.4650969373927767, -19.011172594389514 +3.495948794588938, -19.267021260338936 +3.5919297456212336, -19.937528701408787 +3.527101869077049, -19.509805948889216 +3.548065319973722, -19.651755394743134 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure78-B_min.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure78-B_min.csv new file mode 100644 index 00000000..384d9c9d --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure78-B_min.csv @@ -0,0 +1,132 @@ +0.5001821933136144, -19.633154157209276 +0.49932799171483305, -19.90634898572099 +0.5055609612999111, -19.110008369895645 +0.5013598476282115, -19.374528462921297 +0.5089699171956923, -18.715382372777682 +0.5105387700163482, -18.4214526570628 +0.513153234975825, -18.12080654616465 +0.5155710828736071, -17.78216025774207 +0.5201031312320855, -17.36333847373858 +0.5228297209129632, -16.977111313345908 +0.5244796023488144, -16.721953171916162 +0.527392347863609, -16.41924881804819 +0.5304158742033026, -16.08622037317197 +0.5344192676048014, -15.706923452830694 +0.5376527047157871, -15.374478554495944 +0.5393471898230092, -15.126318972387153 +0.5430979339970857, -14.828306319382065 +0.5449974729614014, -14.540227621435974 +0.5495404404996101, -14.200359806691282 +0.5528591157624546, -13.8875553097525 +0.5552356903764967, -13.61095591541644 +0.5584011659337741, -13.332916150919182 +0.5619124129731312, -13.06640501321192 +0.5658304755790181, -12.736478929703253 +0.5690989965806467, -12.42144778001797 +0.5728647902966651, -12.146024476912558 +0.5760295753192035, -11.85218452049817 +0.580596464992038, -11.46911759844776 +0.5862548266753524, -11.145183836953237 +0.5907722379552119, -10.85605002287334 +0.5981291549094825, -10.22920306161366 +0.5953308540536039, -10.548253383937556 +0.6029877398752606, -9.872890076611867 +0.6086409828123424, -9.534019056673323 +0.6152317434194364, -9.166546904180514 +0.6212087191388582, -8.816495650380482 +0.6269446633410858, -8.504372346548934 +0.6323367166837282, -8.19503680218024 +0.6372150327444561, -7.890039586972833 +0.6438291143846989, -7.5630070189345275 +0.6584097259588667, -6.49232231218744 +0.6647359744048003, -6.1873600897766465 +0.6695473383783069, -5.865757292888986 +0.6736903654080582, -5.585926896999744 +0.6798157406768686, -5.268468691377244 +0.6857682875570952, -4.908590329210284 +0.6921219192163002, -4.542313728588553 +0.6988845015297139, -4.175331051093124 +0.7053568635365725, -3.8159285909599774 +0.7126063956245734, -3.446591287061892 +0.718385228494026, -3.113606833129964 +0.726192168070972, -2.817999351678182 +0.7330529347593377, -2.2461529016953676 +0.7325115094148954, -2.5512795902502035 +0.7438714266047588, -1.908491910445754 +0.7586532417413658, -1.6449101697114088 +0.7737209559193876, -1.3989248066983322 +0.7902790455353934, -1.1417697430090072 +0.8071922314364335, -0.8830150086177397 +0.8281885039685999, -0.6286633678335534 +0.8548304672882929, -0.41639324623286456 +0.8892442646798108, -0.23502691559753686 +0.9246501371748748, -0.047215979424223065 +0.9584315708926346, 0.017171321096554948 +0.9906288164504977, 0.016555447876314133 +1.023876390266708, -0.03715814243471982 +1.059652420446534, -0.12171664282876549 +1.0936671439398196, -0.28661196218499896 +1.130267690557526, -0.5020199832921364 +1.1645688833758747, -0.7483636159884313 +1.1945007734075865, -1.017895243028022 +1.2215474278728684, -1.2586656795527986 +1.2473205195923742, -1.5150049111841426 +1.2736467732642938, -1.75854677720001 +1.2972466512949263, -2.0431002008367045 +1.3160261219344893, -2.2965065816606725 +1.3215814037985294, -2.516243247054078 +1.3271426113590443, -2.731443985677096 +1.3378410067189863, -3.0888039388964827 +1.3500135074435355, -3.40027202205205 +1.3618461138751843, -3.7211898710498517 +1.3739335692272645, -4.024939787462721 +1.3866627178836874, -4.354825123803785 +1.3974179207818258, -4.649311702664136 +1.4114582380727476, -4.970017320603013 +1.4242051796736994, -5.302938151268378 +1.4359478801046552, -5.605898785713386 +1.448684746361747, -5.919602208716057 +1.4597186573598258, -6.2188186139243555 +1.4746400328560565, -6.55410279444915 +1.4857049880396451, -6.8742196972135545 +1.4992583076626955, -7.188083309462911 +1.5125469880144446, -7.5129844273791235 +1.525944272233963, -7.848336727214651 +1.5402157852308873, -8.200992576162378 +1.5538629850687666, -8.530932656789673 +1.5676240336133906, -8.868711123856457 +1.582282413380839, -9.22460186244588 +1.5955123002895726, -9.544827942735694 +1.6088441637460877, -9.874385435453462 +1.6230576598254884, -10.249054086318715 +1.6373779629968088, -10.643629750363587 +1.6485319035285186, -11.025726205521487 +1.6581708630523357, -11.334396886754696 +1.6678936563277384, -11.614451236542202 +1.6781069823936694, -11.880513133394004 +1.6854188846007676, -12.154940641487464 +1.6990995818268846, -12.46103163153731 +1.7189164837971636, -12.75513708885294 +1.7190519023551651, -13.053133745151001 +1.7252481390689274, -13.325547667748403 +1.7404093048924207, -13.635828017625421 +1.7468368940433976, -13.899667483083967 +1.756787652067719, -14.17847453407694 +1.7713302158997857, -14.497330451975259 +1.7765770461199881, -14.763813595445235 +1.7878236682848325, -15.065916739741063 +1.8024497003619864, -15.406979863982471 +1.8117984823032331, -15.696797537287452 +1.818326089237085, -15.97201088361323 +1.8344753458865872, -16.266118340517224 +1.839904642809407, -16.536920594882424 +1.8535127444789494, -16.855875736799547 +1.8661558852694473, -17.17877946588557 +1.877754428278341, -17.503911536259366 +1.891844455471495, -17.823748496650936 +1.902142318866099, -18.134029157575043 +1.9137792696289255, -18.40988903747619 +1.9221010148717603, -18.699713376075756 +1.9344628349628652, -19.01399379141357 +1.9498541466056112, -19.327858070192384 +1.972837276306722, -19.821807792628945 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure80-M0.093.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure80-M0.093.csv new file mode 100644 index 00000000..ac827652 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure80-M0.093.csv @@ -0,0 +1,158 @@ +0.21391214365936495, 0.08230691785875288 +0.29921696895008587, 0.08239720460535621 +0.4368696615829286, 0.08253692847893332 +0.5861871341804621, 0.08257345426283187 +0.7354997099993055, 0.08262754656130941 +0.8848122858181489, 0.08268167429462234 +1.0341248616369922, 0.08273583748598323 +1.183466818127977, 0.082684582986115 +1.3328871230780024, 0.08235298179089436 +1.4493841934450504, 0.08186199323909413 +1.604570198362702, 0.08171874819127634 +1.762044204796764, 0.08292648211233145 +1.9029015432789826, 0.08287543743367795 +2.052145564196165, 0.08317672433196073 +2.201332456028629, 0.08368624936770835 +2.3505417914300892, 0.08411695800893418 +2.508302307640422, 0.08463302558718233 +2.648951688837858, 0.08501738801972439 +2.7981975808030164, 0.08531953636077531 +2.9406934794773445, 0.08548310747016698 +3.109362461384295, 0.08591636096945163 +3.245916550722086, 0.08630244376283422 +3.3951360877458185, 0.08670823566158979 +3.534909811221196, 0.08862406816619134 +3.693232387284972, 0.08883676445919504 +3.842353988734901, 0.0896344782089713 +3.991460899848761, 0.09049700836477383 +4.152867579025553, 0.09307615786200565 +4.285725924763783, 0.09357197576600557 +4.43863387483653, 0.09373361654653432 +4.592999353029553, 0.09394900586764857 +4.746525770585617, 0.09439340700443602 +4.876627124878235, 0.09616999777288315 +5.034832225686635, 0.09836753242918364 +5.187809105206318, 0.10093108519913824 +5.481756319954313, 0.10299160855663037 +5.608280604773984, 0.10378988296138963 +5.766171019833299, 0.10600784021004142 +5.915106543693005, 0.10782663449906008 +6.064012686880568, 0.10981651208523606 +6.212923726846823, 0.11181935587215683 +6.361795592583556, 0.1140523843768114 +6.501500362160492, 0.1169216116518457 +6.657563065790674, 0.11718865718144418 +6.784867477851707, 0.11990969354034314 +6.904947030624346, 0.12261266070911758 +7.05194250034458, 0.1254217887905001 +7.200839710904086, 0.1277858825840376 +7.344247999040592, 0.13138409147541494 +7.498475036361484, 0.13356725845496928 +7.6472391729670335, 0.13687275585127298 +7.782576886490823, 0.13935746780650188 +7.944586265366603, 0.14486532913192457 +8.093232389605717, 0.14921236368933738 +8.236780858411132, 0.1524838018841783 +8.390844304902497, 0.15612159969142822 +8.537488012887023, 0.15808664316136856 +8.693860001143666, 0.16353735615136072 +8.837151497885149, 0.1678941162507816 +8.985822595695586, 0.17274493697980514 +9.134464312833884, 0.17796258679018723 +9.3013840725628, 0.1819298120695586 +9.562563683115643, 0.19520204325646798 +9.69123485098094, 0.20121826225034603 +9.8506279898199, 0.20556849226739649 +9.943772003791464, 0.21318306307568335 +10.093733464669116, 0.21701300866819334 +10.242228278446708, 0.22499704265925666 +10.390762266453825, 0.2328787219999921 +10.53930604801832, 0.24093411477727153 +10.687830242468058, 0.24948004152132527 +10.836344643360414, 0.25843886685846273 +10.988191098118945, 0.26843760031236225 +11.123287917335505, 0.2761817844582839 +11.281868258922719, 0.2875364529554816 +11.423154726422664, 0.2983926539166595 +11.578740363789345, 0.3106627068268543 +11.727181313001351, 0.32284567454493684 +11.875641849328114, 0.3352214506131693 +12.035970078580268, 0.34458952746630633 +12.17243070895701, 0.36349325153684503 +12.323215354050456, 0.3764204718327686 +12.469327297717092, 0.3923117238325825 +12.615546931980484, 0.39571409138377733 +12.755008607412618, 0.3965421450229411 +12.917078947583397, 0.39626909520882136 +13.066401316959618, 0.3963602535647718 +13.215723686335844, 0.3964514328909314 +13.365075436384208, 0.3960375400596185 +13.514427186432572, 0.3956240793298486 +13.663734865472724, 0.39596734984455545 +13.813027854176807, 0.39656355857258346 +13.962159249184117, 0.39995456164828075 +14.111672592929255, 0.3967460317478921 +14.261039033313692, 0.3960793386162683 +14.410361402689913, 0.39617045332031847 +14.559678875287448, 0.39634577407227334 +14.709035522114503, 0.39584789434908135 +14.858357891490725, 0.3959389558113341 +15.007670467309568, 0.39619832788638953 +15.156880210775919, 0.39823039517004694 +15.29364036981343, 0.3954882768142097 +15.455554330200508, 0.39790615900981646 +15.598887511742179, 0.40096499996392687 +15.747446411139295, 0.397485907130961 +16.14798332087556, 0.39632807763310374 +16.2972958966944, 0.3965877046144594 +16.446608472513248, 0.39684750167250965 +16.595994500012438, 0.39584414520842837 +16.745336456503424, 0.3955989214419817 +16.894653929100954, 0.39577398926896984 +17.043971401698492, 0.3959491345702443 +17.205294047369343, 0.39566035484558104 +17.342649530537912, 0.3955579499288786 +17.491945756556795, 0.39609791151714735 +17.62842060733191, 0.3982694276865604 +17.790637113145202, 0.395479577094049 +17.939939895406667, 0.3959068140799866 +18.089125154979563, 0.39836027139835306 +18.23857484060173, 0.39625729977735424 +18.387916797092714, 0.3960118200634073 +18.53730282459191, 0.3950105764677221 +18.686600710074686, 0.3955213167622243 +18.83593287300829, 0.3954442623537545 +18.98520627459761, 0.3963763425101698 +19.134504160080382, 0.39688884871118757 +19.283816735899222, 0.39714884304300474 +19.433181217572184, 0.3965151635997076 +19.73184540353143, 0.39636308823632777 +19.88122863287137, 0.3954089507669247 +20.030541208690217, 0.3956679756457618 +20.179853784509064, 0.3959271702068675 +20.329220224893497, 0.39526185309244755 +20.47857687172055, 0.3947653349638851 +20.627899241096777, 0.3948561473925014 +20.777211816915617, 0.395114810140368 +20.926524392734464, 0.3953736423332782 +21.075851658889377, 0.3953805967753937 +21.22524747994595, 0.39421343139961285 +21.374520881535275, 0.3951426104313502 +21.523882425141018, 0.394562417990654 +21.673195000959865, 0.39482088832197926 +21.822507576778705, 0.39507952797229967 +21.971702629908982, 0.3973590041531493 +22.120951501189893, 0.3987196661225507 +22.275796900172658, 0.39720682649252737 +22.419610976693377, 0.3986481978665781 +22.569129217217203, 0.3953661530708761 +22.718490760822945, 0.3947856323999506 +22.867803336641792, 0.3950442489547874 +23.017115912460632, 0.39530303492440777 +23.16649704318114, 0.39438735247539564 +23.38055953795945, 0.3958503489512621 +23.62807719606832, 0.3940129305548451 +23.77736039121502, 0.3947738811255579 +23.926623999246964, 0.3958725324424819 +24.27820356544904, 0.39631340871506615 +24.96334140261051, 0.3997086491606328 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure80-M0.209.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure80-M0.209.csv new file mode 100644 index 00000000..8f42b919 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure80-M0.209.csv @@ -0,0 +1,166 @@ +0.01191788615022027, 0.05087771883968323 +0.15708477312551317, 0.05069820361468981 +0.32579113377646607, 0.05099758201924726 +0.4751183999313797, 0.0509984790434649 +0.6244309757502231, 0.051031887176562235 +0.7737435515690665, 0.051065317194691824 +0.9230561273879099, 0.05109876911219007 +1.0724078774362749, 0.051045422314903395 +1.2217204532551182, 0.05107886119964453 +1.3712286670416285, 0.050680371734747966 +1.52020383149073, 0.0514613324443117 +1.6683322418596713, 0.05077589654049029 +1.846114416939555, 0.051228001687989314 +1.9953918991777861, 0.05133965939987006 +2.1446310233162773, 0.05153724722057791 +2.2939044249056, 0.05165872286208713 +2.454587320842883, 0.05229161056614223 +2.5923581892891328, 0.05211244031865035 +2.904199746611429, 0.052999370736225605 +3.0536539209473954, 0.052709318620797294 +3.2026926852244824, 0.053374081744463946 +3.339132588937707, 0.053880162033038706 +3.500970165575172, 0.05425619749533522 +3.65009666380379, 0.05473176580916608 +3.7992280588110994, 0.05519977549433554 +3.9483398667036482, 0.055719111693336126 +4.1068485061294915, 0.05624678291643617 +4.245471395909881, 0.056676067536337756 +4.395555319303389, 0.057605646770305885 +4.553153906313971, 0.05814193696620091 +4.69962650497426, 0.058209818111445065 +4.843156801289865, 0.0585670212885676 +4.980349383490811, 0.05984907490850082 +5.14069078740944, 0.06148646208893791 +5.289680175834736, 0.062395426837247296 +5.438684254596103, 0.06327749081657885 +5.567393634076307, 0.06398254484757439 +5.702553295286059, 0.06564917158005297 +5.912476973536414, 0.06706710747690521 +6.0615691943142025, 0.06775564283540074 +6.2104606471656965, 0.06905002364647508 +6.359381480689331, 0.07027949972828475 +6.508287623876896, 0.07157646686378588 +6.657164386392321, 0.0729903396549231 +6.806050942465125, 0.0744005252432215 +6.954908117865788, 0.07593467706482449 +7.103765293266452, 0.07750046336486742 +7.196669005190795, 0.07928887761749462 +7.332778278951638, 0.0806479974843392 +7.397847368867721, 0.08156902430780127 +7.523154800959638, 0.08250700502157343 +7.67191893756519, 0.08454887286725934 +7.820727145178951, 0.08647578721605599 +7.969496178563192, 0.08859705144718838 +8.118250521611364, 0.09082821491538498 +8.266980380766084, 0.09321451961497601 +8.415720033478184, 0.09562288489318836 +8.564440099075526, 0.09817686035584633 +8.713160164672866, 0.1007990495172559 +8.861841056040685, 0.10366729746394321 +9.010546431301954, 0.10650398070826038 +9.159202838776324, 0.10965096468262828 +9.307839659135931, 0.11298690037850549 +9.456476479495539, 0.11642432598830402 +9.605118196633837, 0.11994084793700663 +9.753720739542615, 0.12377374734663085 +9.902328179230084, 0.12770200304709745 +10.05091603180279, 0.13186693144322556 +10.199494090818115, 0.13622555994470475 +10.348067253054753, 0.1407581526865227 +10.49660124106187, 0.14568893138013234 +10.645135229068986, 0.15079243597317535 +10.79369370096955, 0.1559090336760121 +10.942193411525837, 0.16161068320831853 +11.090688225303433, 0.16755643363117462 +11.239207522974477, 0.1735365156470114 +11.38765336896517, 0.18030362906857045 +11.536118802070627, 0.18717551714839908 +11.684584235176084, 0.19430931257876544 +11.833034977945468, 0.20184358671886307 +11.99332473250791, 0.20783088717340245 +12.157049927091373, 0.2181499567268021 +12.371620303936188, 0.23571411792502267 +12.507492324467934, 0.24328612117636464 +12.656908198999146, 0.24235701310840346 +12.806225671596676, 0.24246426546259492 +12.95553824741552, 0.24262309918869526 +13.104850823234363, 0.242782036963747 +13.254163399053207, 0.24294107885591043 +13.403480871650741, 0.24304858968179047 +13.56085746261646, 0.24406528449311946 +13.702037468386765, 0.24409196834505845 +13.851496947566313, 0.24270025638994072 +14.000829110499916, 0.24265297417303103 +14.15014658309745, 0.2427603575014432 +14.299459158916294, 0.24291938519180342 +14.448771734735141, 0.24307851705817735 +14.598099000890054, 0.24308279269847155 +14.747426267044967, 0.2430870684139723 +14.896797604208095, 0.24262703853652393 +15.046002450895754, 0.24392326189992855 +15.195368891280188, 0.24351337257441852 +15.344754918779385, 0.24289769346485363 +15.494067494598228, 0.2430568111213899 +15.643414347867902, 0.24285464441111967 +15.792795478588404, 0.24229209437759708 +15.942112951185939, 0.24239931800273867 +16.09142552700478, 0.24255810918299403 +16.240738102823627, 0.24271700438432983 +16.390050678642467, 0.24287600367488807 +16.53937794479738, 0.24288027575306417 +16.68874438518182, 0.24247213906436685 +16.8380863416728, 0.2423219286042161 +16.987364640040816, 0.24284150118245368 +17.13672618364656, 0.24248493421257034 +17.28605344980147, 0.24248919941201288 +17.435424786964596, 0.24203030097115416 +17.58476184667689, 0.24193175129195288 +17.734069525717047, 0.24214166782921367 +17.88339189509327, 0.2421973704732332 +18.03270447091211, 0.24235602936150527 +18.182017046730955, 0.24251479218419558 +18.331452042017048, 0.2413883219492067 +18.470247915502497, 0.2411086401377597 +18.630052709761294, 0.24196154114833646 +18.779375079137516, 0.24201720235573554 +18.928687654956356, 0.24217574321930252 +19.078000230775203, 0.24233438793997197 +19.227361774380945, 0.2419785655702963 +19.37669393731455, 0.24193142395126818 +19.525991822797323, 0.24224423614942023 +19.675323985730927, 0.24219704277315804 +19.824670839000603, 0.24199559119009523 +19.973983414819443, 0.24215411789659874 +20.12330088741698, 0.2422612804618097 +20.272633050350585, 0.2422140837650199 +20.42200438751371, 0.24175570596649007 +20.550980641432517, 0.24163568907168 +20.991969839927783, 0.24380678719307508 +21.141399938435192, 0.24272587143747915 +21.29078596593439, 0.2421121833807819 +21.44017199343358, 0.24150004692230806 +21.589489466031118, 0.24160692003580944 +21.738802041849958, 0.24176519213123637 +21.888114617668805, 0.241923567907701 +22.03745657415979, 0.24177369728505166 +22.186788737093394, 0.24172659557791648 +22.336101312912234, 0.24188494607051353 +22.48547265007536, 0.24142719114828187 +22.634785225894205, 0.24158534550673488 +22.784122285606493, 0.24148697700409721 +22.933415274310576, 0.241850584365794 +23.082727850129423, 0.24200901608108646 +23.23210408407124, 0.2414997201657319 +23.3814558341196, 0.24124759595921363 +23.530768409938446, 0.24140563266827608 +23.680080985757286, 0.24156377290417924 +23.829393561576133, 0.24172201673474134 +23.978706137394973, 0.24188036422782538 +24.1280285067712, 0.24193600676116017 +24.277394947155635, 0.24152945682469446 +24.426702626195784, 0.2417390243037557 +24.576064169801533, 0.24138407611335636 +24.725376745620373, 0.24154220222797051 +24.874713805332675, 0.2414438512923742 +25.002478152940647, 0.2421696306528227 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure82-M0.093.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure82-M0.093.csv new file mode 100644 index 00000000..c2b4df09 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure82-M0.093.csv @@ -0,0 +1,163 @@ +1.0081298874286855, -19.180285859537776 +1.0070873076515507, -19.773305236771726 +1.0214651608789005, -17.60946803534118 +1.024349377307888, -18.265289366896702 +1.0129359259135233, -18.633624156374715 +1.0610467444990936, -14.231826908538892 +1.0396272396469124, -14.933423086641113 +1.0321838133762586, -15.339971222116347 +1.0246484197024994, -15.798830416477664 +1.0238652134308968, -16.24431814376561 +1.0297807941338393, -16.70680856720437 +1.0291162554791455, -17.084798153994143 +1.1147685635708715, -13.442532988188141 +1.1952243750803664, -12.039820298982583 +1.167517449454964, -12.72064057899037 +1.1305948680793811, -12.945581488798844 +1.2772644825511241, -11.423541140907105 +1.3102284295901816, -10.867913799357382 +1.4060841140873288, -10.35881351099313 +1.4737519492776832, -9.759348854719377 +1.5501976280908396, -9.270077048825996 +1.588485734686719, -8.924529289817436 +1.8090127387948538, -7.934223898564383 +1.8569400676952252, -7.4049774018522925 +1.973537909459453, -6.967891240126441 +2.1128498283219743, -6.574845270274928 +2.251057629771738, -6.119185604692049 +2.368126786074476, -5.6010628968248 +2.4789577593489964, -5.1475710736785345 +2.5700817149156228, -4.781826644707806 +2.693073752751584, -4.48031915997656 +2.8419135170907657, -4.020261203850197 +2.975683206446875, -3.781648674954461 +3.062773640195953, -3.4192656058627406 +3.216075998549293, -3.168669722267822 +3.355188718102845, -2.942054140907395 +3.5095483177892834, -2.531707778653832 +3.639807387518603, -2.3067125529818355 +3.801030506407791, -1.9472449530542093 +3.9495095862781007, -1.692344322820773 +4.106291297657824, -1.4989977991244032 +4.246464340104007, -1.1844803466461187 +4.460706909886953, -0.8687611995606446 +4.367792870269179, -1.0637214796053485 +4.582484730468098, -0.801536853006148 +4.68960534251195, -0.6323716835018516 +4.8337260827438175, -0.5479809311005255 +4.974605042857638, -0.36350316583473585 +5.102627389827688, -0.2625740274526507 +5.325085183156741, -0.028581181887652463 +5.47327946074647, 0.06432391115017566 +5.621464029167541, 0.15170642905632548 +5.769684197873687, 0.25933838911193163 +5.917820220451478, 0.31910803135973254 +6.066004788872551, 0.40649054926588946 +6.214085792827957, 0.4349655991009058 +6.36219268789978, 0.4781675159537073 +6.510257509907426, 0.49743827390260975 +6.6583223319150715, 0.5167090318515193 +6.806393626701821, 0.5396615065548644 +6.914096140049661, 0.5644874624421163 +7.640459760116039, 0.37466001074327693 +7.747954497254634, 0.281302858812829 +8.231825804630247, -0.05633386957463671 +8.379728807160289, -0.12910603048688074 +8.527580027457498, -0.23133192543469505 +8.675356810795009, -0.3758975630586292 +8.823065629951925, -0.5591212266042476 +8.970797103835705, -0.7294588815093022 +9.118518868550831, -0.9053191115460351 +9.266195323812228, -1.1069513588638813 +9.413852360736312, -1.3196287564450628 +9.561477033764875, -1.5507147377984865 +9.709066106508365, -1.802050161301345 +9.856622815356335, -2.071794168576446 +10.004156869477438, -2.354424184492096 +10.151632668586606, -2.6701896511977665 +10.299144067980846, -2.9657056757539806 +10.44656808485718, -3.3109248764952213 +10.593975919785754, -3.665348369122576 +10.714644241893678, -3.920115845043007 +11.069283093128652, -5.046991808044616 +11.203108124746102, -5.472768369493409 +11.330187297900967, -5.908316497189013 +11.443806102159456, -6.345576998596627 +11.557400183997757, -6.796899612608016 +11.670962621138212, -7.266221730752257 +11.777812426748817, -7.726415935803807 +11.864636181998804, -8.09560940415777 +11.937832741460976, -8.561406382074104 +12.011095754788617, -8.989404401311447 +12.091002120361189, -9.465936390903735 +12.17101223533598, -9.883455720517638 +12.237527807966142, -10.322125281208429 +12.297345186959841, -10.743454655045923 +12.343818392432059, -11.100404473357628 +12.530799720006947, -11.909061712398461 +12.678793341444447, -11.930289838748465 +12.826819326777468, -11.933109381326233 +12.974845312110489, -11.935928923904008 +13.12287129744351, -11.938748466481776 +13.250747521425282, -11.920934083831312 +13.472765274551765, -11.937236105487777 +13.930386090972465, -11.89706117993935 +14.0783570576831, -11.93117531492991 +14.226337733562392, -11.959766874788805 +14.374383137232726, -11.951541267103238 +14.522399413397089, -11.959883384812677 +14.67044158067787, -11.953498635504339 +14.81843520211537, -11.974726761854335 +15.011426000283446, -11.956106218397345 +15.492122887279507, -11.965262349578225 +15.814304631185813, -11.960559142951155 +15.962385635141217, -11.932084093116138 +16.11041485686379, -11.933062777316685 +16.25843760580726, -11.937723178271682 +16.399735137261505, -11.94041455982319 +17.00403217623105, -11.905349703037807 +17.146551444741206, -11.978571592642211 +17.29456772090557, -11.98691371035165 +17.44259370623859, -11.989733252929426 +17.59063587351937, -11.98334850362108 +17.738661858852392, -11.986168046198856 +17.886687844185413, -11.988987588776624 +18.034713829518434, -11.991807131354399 +18.182804542642497, -11.957809506387704 +18.28386242460096, -11.88517715750411 +19.07111256494957, -11.888206418124867 +19.219115895555724, -11.903911969343191 +19.36708362587681, -11.93986696271098 +19.51512579315759, -11.933482213402634 +19.663138832932404, -11.943665189489302 +19.811168054654978, -11.944643873689849 +19.959210221935756, -11.93825912438151 +20.107252389216537, -11.931874375073157 +20.25528161093911, -11.932853059273711 +20.403307596272132, -11.93567260185148 +20.551333581605153, -11.938492144429254 +20.69935956693817, -11.941311687007023 +20.84738555227119, -11.944131229584798 +20.995411537604213, -11.946950772162566 +21.143437522937234, -11.949770314740341 +21.291463508270255, -11.95258985731811 +21.439489493603276, -11.955409399895885 +21.587515478936297, -11.958228942473653 +21.735554409827525, -11.953685051542536 +21.883580395160546, -11.956504594120304 +22.03161932605178, -11.951960703189194 +22.179655020553454, -11.94925767063529 +22.327681005886475, -11.952077213213066 +22.475706991219496, -11.954896755790834 +22.623732976552517, -11.95771629836861 +22.771758961885535, -11.960535840946378 +22.919784947218556, -11.963355383524153 +23.067885369511274, -11.923835183425794 +23.202526366854574, -11.88549044001276 +24.05030436360327, -11.905729525715635 +24.19829798504077, -11.926957652065646 +24.346314261205137, -11.935299769775085 +24.49427875513667, -11.973095621520095 +24.64230474046969, -11.975915164097863 +24.79033072580271, -11.978734706675638 +24.89123973384178, -11.990781843144298 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure82-M0.116.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure82-M0.116.csv new file mode 100644 index 00000000..e809cccc --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure82-M0.116.csv @@ -0,0 +1,180 @@ +1.042296807685136, -14.421033392560027 +0.9087410115622285, -19.725145984845945 +1.0632356161773835, -13.825957537088364 +0.9487521719556344, -16.868616134894808 +0.9422123995877474, -17.52662047593099 +0.941502767238628, -17.930259356110064 +0.9191529082698748, -18.395586410263434 +0.9183697019982722, -18.84107413755138 +0.9175864957266686, -19.286561864839328 +0.9634362723971943, -16.17084525828121 +0.9708801224807653, -15.76405605801849 +0.9837347920824957, -15.15004726128106 +1.0850288765384368, -13.348365962136178 +1.2011071660470583, -12.131519738117191 +1.159868473919306, -12.697351889646697 +1.1371809208178627, -13.026707418422916 +1.2493178632101927, -11.330083272533798 +1.3633673320283837, -10.671876721878391 +1.4586010612887517, -10.084749700399506 +1.542045162809151, -9.50583566468692 +1.632087183829725, -9.001297744548587 +1.6900209841041152, -8.580370330293462 +1.7591713014686254, -8.158275873965856 +1.8706700250751416, -7.691531490309245 +1.9473077628621267, -7.083203020288366 +2.049210532320381, -6.640400759427649 +2.189032564678719, -6.349281864053175 +2.3153694984917133, -5.841731306223593 +2.4289713816270506, -5.438111491974965 +2.544139787183018, -4.993958775377251 +2.6827011824416642, -4.5482025202247485 +2.822281254428895, -4.08800129683128 +2.9436550863421074, -3.558747522778262 +3.0791978317143247, -3.00748850051599 +3.2242798429969834, -2.6800785781765555 +3.3751513082583298, -2.431272254406231 +3.5296792319307873, -2.3004060253052216 +3.6661738525035457, -2.108255148333633 +3.8146589428115973, -1.8499357811139205 +3.9609114765697893, -1.5857370036973535 +4.118710147348116, -1.3580170578539565 +4.243234357404578, -1.1080581424451736 +4.341199381983355, -0.8810067074903785 +4.522446532205265, -0.4518700855117359 +4.416335891567876, -0.6686125810674639 +4.6371710732762565, -0.31412688190673066 +4.732690312697343, -0.18278349919178538 +4.847773375519248, -0.09626463882032255 +4.96180951782654, 0.012947651022308548 +5.101255442314892, 0.23281980302641614 +5.258580614251054, 0.41634729728570363 +5.40678460100944, 0.5147749654551959 +5.555085679454388, 0.6684283849413646 +5.7033641031724684, 0.8091957957869838 +5.78419293223566, 0.8573610396568512 +5.898106036647038, 0.9359833136982019 +6.111535328714616, 1.0588070659764597 +6.3903784045088425, 1.2011122140972716 +6.538501481528426, 1.25351842283618 +6.686637504106217, 1.313288065083988 +6.83472821723028, 1.3472856900506756 +6.982802748406581, 1.3720790231312492 +7.130877279582883, 1.3968723562118228 +7.278971229096497, 1.4327108395557318 +7.427074887778769, 1.474071898031312 +7.57510087311179, 1.4712523554535437 +7.720075405438564, 1.3730260831824594 +7.870825968433071, 1.2796865741984789 +8.018842244597433, 1.2713444564890395 +8.166852047982696, 1.2593206220251503 +8.314784178018705, 1.2031161865079127 +8.462683944159195, 1.1285031672184545 +8.610548110014612, 1.0336407057795256 +8.758451112544654, 0.9608685448672958 +8.906302332841863, 0.8586426499194815 +9.034049505790245, 0.8030528047781829 +9.200989625913445, 0.7146537369137249 +9.349681228697674, 0.4525586127060137 +9.497375484101608, 0.261051086462885 +9.645178158555536, 0.13121231585673598 +9.792748614353412, -0.1307124263112982 +9.940633015349219, -0.21406513989643372 +10.088254451988227, -0.4469919796270716 +10.235888834185447, -0.6725553858488169 +10.383584707784156, -0.863142482903335 +10.531215853591824, -1.0905467475022945 +10.678788744387553, -1.3510864628912813 +10.826332507677314, -1.6281939036752675 +10.97385037985066, -1.920028211477046 +11.121332651738928, -2.2321119614282665 +11.268801978068993, -2.5515591448883725 +11.416258358840846, -2.8783697618573854 +11.563653248211214, -3.2401566879936325 +11.71858640804605, -3.566700626463536 +11.85825207996837, -4.072341184522259 +12.005536932093968, -4.496717295484089 +12.14612407604153, -4.903477090836027 +12.253197866779054, -5.236268555697279 +12.428388056298846, -5.862634211383501 +12.520518924046073, -6.274960273126062 +12.627390979834846, -6.722498576834212 +12.73428083576616, -7.1599121594676305 +12.847863050842768, -7.617984587528831 +12.947931496595391, -8.108143552526236 +13.027860069964849, -8.572043747253872 +13.10781237685768, -9.022444313881877 +13.187729083465445, -9.493094322659331 +13.267758524309269, -9.899621097963518 +13.335623051074652, -10.527823728359508 +13.40925185733142, -11.066698123450621 +13.487097814024107, -11.439433108163641 +13.593908378411395, -11.921947721039018 +13.741889054290688, -11.950539280897914 +13.889915039623709, -11.953358823475682 +14.037947497735832, -11.952496649299015 +14.186031738080793, -11.92218074108677 +14.334086850919782, -11.908432558269539 +14.482119309031905, -11.907570384092864 +14.630151767144028, -11.90670820991619 +14.778177752477049, -11.909527752493965 +14.92620373781007, -11.912347295071733 +15.074229723143091, -11.915166837649508 +15.222255708476112, -11.917986380227276 +15.37022667518675, -11.952100515217843 +15.491307405791883, -11.972290037926442 +16.27185244050063, -11.961910659228103 +16.419920498897827, -11.940799042901979 +16.567952957009954, -11.939936868725304 +16.71597570595342, -11.944597269680301 +16.864008164065545, -11.94373509550362 +17.012034149398566, -11.946554638081395 +17.160089262237555, -11.932806455264164 +17.308131429518337, -11.926421705955825 +17.456157414851358, -11.929241248533593 +17.60419958213214, -11.922856499225247 +17.752219094686055, -11.929357758557458 +17.90026449835639, -11.921132150871898 +18.048280774520755, -11.929474268581338 +18.19630028707467, -11.935975527913556 +18.344329508797244, -11.936954212114102 +18.492355494130265, -11.939773754691878 +18.640381479463286, -11.942593297269646 +18.788407464796304, -11.945412839847421 +18.936472286803948, -11.926142081898519 +19.084566236317563, -11.89030359855461 +19.232592221650584, -11.893123141132378 +19.380650570879126, -11.877534099937925 +19.46143085409904, -11.856981731726393 +19.75741809697404, -11.899437984426399 +19.905382590905564, -11.937233836171409 +20.053411812628138, -11.938212520371955 +20.20145397990892, -11.93182777106361 +20.34947996524194, -11.934647313641385 +20.49750595057496, -11.937466856219153 +20.645531935907982, -11.940286398796928 +20.79356439402011, -11.93942422462026 +20.94168423465014, -11.88885887425856 +21.06963813198116, -11.82686389055474 +21.560786137625673, -11.8527873708669 +21.708660012649744, -11.94212725717415 +21.849066817779487, -12.026211246848831 +22.044907941552616, -12.047941660857305 +22.475687572882183, -11.96594190605417 +22.623758867668933, -11.942989431350831 +22.771872235519858, -11.89610579774358 +22.919966185033473, -11.860267314399671 +23.068014825093357, -11.850200848336883 +23.216001973751755, -11.875110691441328 +23.363969704072836, -11.91106568480911 +23.511995689405857, -11.913885227386885 +23.66001843834933, -11.918545628341874 +23.807982932280858, -11.956341480086891 +23.95597331732881, -11.979410464814116 +24.104005775440932, -11.978548290637434 +24.252047942721713, -11.972163541329095 +24.40008040083384, -11.97130136715242 +24.54810638616686, -11.974120909730196 +24.696132371499882, -11.976940452307964 +24.844151884053794, -11.983441711640182 +24.951824983924904, -11.975346141318077 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure82-M0.163.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure82-M0.163.csv new file mode 100644 index 00000000..63a64a55 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure82-M0.163.csv @@ -0,0 +1,190 @@ +0.7366809501375533, -19.893074212457265 +0.7545205766265264, -18.908153618697085 +0.7359657080465434, -19.256102260930973 +0.7718472353714958, -17.983053154861743 +0.744260574468524, -18.36525496738134 +0.865846535734704, -15.121301613319595 +0.8362576444776826, -15.791867000717417 +0.8288059114738449, -16.203140006027517 +0.8146067377725279, -16.625084552791073 +0.8071840783348341, -17.01982051367913 +0.7999394203225023, -17.313309263819917 +0.9250002550930958, -14.431736749337126 +0.9426233686585119, -13.956194601812925 +1.0307795799094954, -13.161931541243732 +0.9679015652963354, -13.63098665724992 +1.075991941952049, -12.535039001338433 +1.1227272050782746, -11.953175736295307 +1.199029296074971, -11.527351572179619 +1.2623838870296176, -11.050103212383384 +1.3365745574825372, -10.602515974465199 +1.395646901621407, -10.171863597972823 +1.4882901015908407, -9.684336863284052 +1.5677723021551504, -9.224511531955521 +1.6203886758670265, -8.82099348931549 +1.7669473640407567, -8.058211855897959 +1.8126861585656746, -7.699328187467351 +1.9241893028669308, -7.21371344628686 +2.0429878991586827, -6.83097086543701 +2.156636617545602, -6.4007111600889885 +2.340153607767835, -5.584933990370253 +2.2560040253613636, -6.052522248294757 +2.4309226652008693, -5.211438178403995 +2.568036478538186, -4.796975278012006 +2.7028102577528292, -4.345403671418552 +2.837717538036496, -4.01488863537427 +2.92358898566078, -3.4905274084988136 +3.0701187418697398, -3.250895583337062 +3.2008760460649075, -3.070556541539702 +3.3246115118891417, -2.6332326716246612 +3.464894991473267, -2.2558985750837977 +3.627767032056621, -2.011024315514156 +3.7454825756841252, -1.573923991456418 +3.8994044967448485, -1.21419717141179 +3.9925970451913937, -0.7366452453885017 +4.15339061235473, -0.5429985086163569 +4.300610202415948, -0.23904113634080915 +4.426576060981512, -0.012457987045273455 +4.544950418204566, 0.19440087695240038 +4.693471398172868, 0.47313428292231663 +4.841727167164088, 0.601015685127372 +4.969448044447359, 0.8784027499686573 +5.111582876112866, 1.0040338442840167 +5.2690738821826795, 1.281887793764362 +5.408450262832243, 1.4622034102659214 +5.562174721069088, 1.5112813159894856 +5.69949220186961, 1.7962522741136766 +5.853377231690468, 1.9366632968240864 +6.001506781489155, 1.9927512223174517 +6.149879060504249, 2.186903526102533 +6.298160720611884, 2.3295117953253737 +6.44644561710907, 2.4739609229254356 +6.5947841452045495, 2.6489157036337616 +6.7428115175616625, 2.646885100360514 +6.890963722087216, 2.7158590344944358 +7.039106217444111, 2.7793103934966865 +7.187459078121892, 2.9624175470184397 +7.335498009013122, 2.966961437949557 +7.483634031590913, 3.026731080197365 +7.63174739944184, 3.0736147138046093 +7.779851058124109, 3.1149757722801894 +7.927935298469068, 3.145291680492427 +8.076006593255817, 3.1682441551957794 +8.224094069990329, 3.2004009217852385 +8.399007979722027, 3.1823418680846416 +8.546953055316246, 3.1335008660762895 +8.694979040649267, 3.1306813234985214 +8.843005025982288, 3.127861780920746 +8.990995411030237, 3.1047927961935287 +9.139001978025943, 3.090928103352411 +9.286982653905236, 3.0623365434935224 +9.434927729499455, 3.0134955414851774 +9.576132376573558, 2.9579715245073714 +9.918991278414461, 2.7852058007047518 +10.066878098996742, 2.703229347906401 +10.21469695539843, 2.5825948691863587 +10.362483447904598, 2.4435518066940958 +10.510392923213743, 2.3744613625362945 +10.658156760993046, 2.2225322914034678 +10.805844543617873, 2.0273430484058963 +10.95371680044717, 1.9370827329100422 +11.101571257133932, 1.8366976963394492 +11.24934480408189, 1.6902912003382937 +11.397063332407463, 1.5125901119243466 +11.544736551279307, 1.3091170062292719 +11.692364460697423, 1.0798718832530767 +11.840095934581203, 0.9095342283480221 +11.987879190697821, 0.7686503074785307 +12.133068374521894, 0.5030602056495894 +12.282963480887787, 0.21259456753332984 +12.430552553631276, -0.03874085596952881 +12.578138389985217, -0.29191713784962303 +12.72567244410632, -0.5745471537652804 +12.873190316279665, -0.8663814615670518 +13.020679060947039, -1.1747834947638296 +13.168141914497998, -1.4979123949783926 +13.315617713607168, -1.813677861684063 +13.46298994825067, -2.1883507964608597 +13.610326582609098, -2.583273173387113 +13.757663216967522, -2.978195550313373 +13.898273986558817, -3.371517079511584 +14.038824559304448, -3.799078574526149 +14.179395197665297, -4.215226747601925 +14.306450241738052, -4.664499497198825 +14.42682271674391, -5.087544804776826 +14.547187280575308, -5.515089988388048 +14.674192879807684, -5.992486963192519 +14.801274426314887, -6.426685128078155 +14.901366605590898, -6.903344464975909 +14.988097376286774, -7.3254275477059565 +15.08151761007301, -7.769816751911655 +15.17492767234923, -8.219991511017191 +15.261617757005023, -8.665216813346603 +15.354973571227795, -9.146247865251311 +15.448400586020718, -9.586780032857114 +15.495096293274639, -9.817170837734743 +15.601493678595773, -10.534701703435594 +15.656430851844071, -11.18037695374533 +15.712108079503274, -11.637065177995119 +15.841279938102396, -11.926095477888971 +15.989299450656311, -11.93259673722119 +16.137328672378885, -11.933575421421736 +16.285351421322353, -11.938235822376733 +16.433377406655374, -11.9410553649545 +16.581364555313773, -11.965965208058954 +16.729358176751273, -11.98719333440895 +16.87738416208429, -11.990012876986725 +17.02541014741731, -11.992832419564493 +17.17344907830854, -11.988288528633376 +17.321478300031114, -11.989267212833923 +17.469510758143237, -11.988405038657255 +17.617549689034465, -11.983861147726131 +17.765575674367486, -11.986680690303906 +17.913601659700507, -11.989500232881674 +18.06162764503353, -11.99231977545945 +18.209650393977, -11.99698017641444 +18.35767961569957, -11.997958860614993 +18.50570560103259, -12.000778403192761 +18.653731586365613, -12.003597945770537 +18.801757571698634, -12.006417488348305 +18.94978355703165, -12.00923703092608 +19.09789692488258, -11.962353397318829 +19.245942328552914, -11.954127789633262 +19.39400391417101, -11.93669789006158 +19.542039608672685, -11.933994857507685 +19.690052648447498, -11.944177833594345 +19.83808510655962, -11.943315659417678 +19.98612403745085, -11.938771768486554 +20.134169441121184, -11.930546160800986 +20.282195426454205, -11.933365703378755 +20.430221411787226, -11.93618524595653 +20.578247397120247, -11.939004788534298 +20.726273382453268, -11.941824331112073 +20.87429936778629, -11.944643873689849 +21.022325353119307, -11.947463416267617 +21.170351338452328, -11.950282958845392 +21.31837732378535, -11.95310250142316 +21.46640330911837, -11.955922044000936 +21.61442929445139, -11.958741586578704 +21.762471461732172, -11.952356837270365 +21.910549229298027, -11.92572264581257 +22.058614051305675, -11.906451887863668 +22.206640036638696, -11.909271430441436 +22.354666021971717, -11.912090973019211 +22.502692007304738, -11.91491051559698 +22.65071799263776, -11.917730058174755 +22.79874721436033, -11.918708742375301 +22.94677319969335, -11.921528284953077 +23.09482831253234, -11.907780102135838 +23.24285753425491, -11.908758786336392 +23.39088351958793, -11.91157832891416 +23.53890950492095, -11.914397871491936 +23.686935490253973, -11.917217414069704 +23.834961475586994, -11.920036956647479 +23.982987460920015, -11.922856499225247 +24.131013446253036, -11.925676041803023 +24.279039431586057, -11.92849558438079 +24.427065416919078, -11.931315126958566 +24.5750914022521, -11.934134669536334 +24.716467254333505, -11.892277278359053 +24.917663236339735, -11.922250647101095 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure82-M0.209.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure82-M0.209.csv new file mode 100644 index 00000000..126269ef --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure82-M0.209.csv @@ -0,0 +1,170 @@ +0.5845497844571383, -19.905722022826794 +0.6013432300434616, -19.283913203629908 +0.6321137431081176, -18.36649385730187 +0.6193697063954575, -18.888029212190197 +0.7212203576484288, -16.857307154155173 +0.7659813717766246, -16.448481987459374 +0.721262790311445, -16.137303686836546 +0.7960539034945491, -15.149365261534172 +0.8718875964547861, -14.661913952504314 +0.9300705814703072, -14.290508998753317 +1.028415767516977, -13.430829289763707 +0.9729518448501802, -13.928084616719374 +1.0907737242075513, -12.632211759459103 +1.0640767078750537, -13.126565558474603 +1.183036313009545, -11.82143306706687 +1.1519550391231066, -12.27773438094571 +1.266606943876475, -11.106761260260235 +1.356447823286386, -10.52526905190269 +1.4586921810660218, -10.032920771088392 +1.4954028559828387, -9.564010090524498 +1.567983926071972, -9.104139848067106 +1.6754408002189534, -8.630222280816653 +1.7590111001857975, -8.200330764570786 +1.847350240903718, -7.75664057783068 +1.9469066663169725, -7.311346735172201 +2.0295214845068266, -6.836122064867574 +2.1102323876257127, -6.376624007208676 +2.244426072909481, -5.977612960658867 +2.351995240402899, -5.481880880013776 +2.4837225433858388, -4.913832501758023 +2.6055769791475347, -4.4939385314146705 +2.7342420730826262, -4.027414919316115 +2.8922914058114815, -3.628255162444624 +3.0281036244770636, -3.45645366364986 +3.1668172533356884, -2.924106936829702 +3.2938350654436395, -2.4377390461897264 +3.458030517019999, -2.079863515759399 +3.5977709099548836, -1.6496151037791194 +3.732165828675445, -1.3867377164761763 +3.861515711816999, -0.9449130088579025 +4.005414979400726, -0.5115385328537485 +4.154091479033715, -0.14434554160971658 +4.308128758978974, 0.21024110943583452 +4.403278471566571, 0.5308781487407188 +4.556645262523773, 0.7227919620813807 +4.6807912239078195, 0.9151966155083429 +4.810001302726413, 1.1449543825895816 +4.977919062929246, 1.521511450895332 +5.126309373257557, 1.7259199656392283 +5.274591033365192, 1.8685282348620689 +5.410344326105205, 2.061137509018451 +5.57153948393716, 2.3728069201972772 +5.719879399056733, 2.548550640210131 +5.868193423059887, 2.709567493205192 +6.003091173974317, 2.8939536678779234 +6.4346651591395005, 3.427781884379435 +6.59219343315047, 3.530563442518037 +6.7197093726843455, 3.7219695097269323 +6.872891522480478, 3.91821008000025 +7.0817165222867935, 4.052415424377379 +7.229855781254136, 4.114025925002416 +7.378069477181176, 4.217976168303572 +7.526279936718666, 4.320085553227514 +7.674500105424812, 4.427717513283106 +7.822710564962302, 4.529826898207041 +7.970836878371438, 4.584073965323185 +8.119050574298479, 4.688024208624334 +8.267270743004623, 4.7956561686799475 +8.415348510570478, 4.822290360137735 +8.563423041746779, 4.847083693218316 +8.711575246272332, 4.916057627352231 +8.859840724432207, 5.049461604688965 +9.008012347295072, 5.129480689086215 +9.156142975890276, 5.186182234038654 +9.303993117390966, 5.083342719631766 +9.453727388995857, 5.031590347886095 +9.593152872866899, 4.984684361615017 +10.0033963179327, 4.867519551405962 +10.151409357707513, 4.857336575319302 +10.299412688313668, 4.84163102410097 +10.447403073361617, 4.818562039373738 +10.595380512851357, 4.788129621137628 +10.743351479561992, 4.754015486147061 +10.891264191260689, 4.686765900366495 +11.039199557686251, 4.632402323226472 +11.18715757883868, 4.590924754727027 +11.334957016903054, 4.459245125743642 +11.482801764421158, 4.353337514041392 +11.630646511939261, 4.247429902339135 +11.778471841120055, 4.130477140373543 +11.926319825027711, 4.026410387048507 +12.074193700051783, 3.937070500741264 +12.21515302879784, 3.7420094187699533 +12.853150592173186, 3.0441143757594986 +13.000995339691293, 2.9382067640572345 +13.14881743248253, 2.8194131437144208 +13.578519346091259, 2.2884070589023224 +13.819911933612225, 1.8106926590105843 +13.967523661082577, 1.5722432441482752 +14.115109497436517, 1.319066962268188 +14.262698570180007, 1.0677315387653152 +14.410232624301113, 0.7851015228496578 +14.557763442032666, 0.5006306485567862 +14.705278077816455, 0.20695548237778638 +14.852740931367418, -0.11617341783676949 +15.000207021307926, -0.4374614596741111 +15.147660165690226, -0.7661129350203382 +15.295093891735217, -1.1058095606299077 +15.442459653599613, -1.4841642121611542 +15.58982217907446, -1.8643597220696293 +15.737158813432888, -2.2592820989958824 +15.884482502233105, -2.661567909431035 +16.018408617084233, -3.0298483275645722 +16.152190173202037, -3.480353753214061 +16.28594871499413, -3.9439497273237976 +16.419726315524702, -4.396705090989897 +16.540188433384024, -4.768761543516256 +16.647105695884004, -5.19058626989176 +16.774097055002354, -5.676083021556018 +16.887718416265443, -6.111889098745749 +16.98120476486682, -6.518672196102457 +17.081355995409336, -6.9617431726094665 +17.181507225951854, -7.404814149116461 +17.27491728822807, -7.854988908222012 +17.388447614476476, -8.342575701765334 +17.50462674448041, -8.868977464620897 +17.628164507367032, -9.773425207437192 +17.71176386568622, -10.275645549017284 +17.781667003220427, -10.488478293296964 +18.02135401344745, -11.936325057985187 +18.16927967070436, -11.996211210256867 +18.31730889242693, -11.99718989445742 +18.465334877759947, -12.000009437035189 +18.613360863092968, -12.002828979612964 +18.76138684842599, -12.005648522190732 +18.90941283375901, -12.008468064768508 +19.05743881909203, -12.011287607346276 +19.205484222762365, -12.003061999660709 +19.35362348172971, -11.94145149903568 +19.501668885400044, -11.933225891350112 +19.64977901686142, -11.88818311612009 +19.797817947752648, -11.883639225188972 +19.94584393308567, -11.88645876776674 +20.09388326852559, -11.881684769538467 +20.24189590375171, -11.892097852922284 +20.389892761578764, -11.911485120895065 +20.53785725551029, -11.949280972640068 +20.618475719252597, -12.020771523289689 +21.587554315610923, -11.936138641946982 +21.7357453568111, -11.84507440728639 +21.883667777678454, -11.906801417935284 +22.018156305113965, -11.955181558071416 +22.448838485158127, -11.928612094404663 +22.596890361607567, -11.916704769964653 +22.744919583330137, -11.917683454165207 +22.89294556866316, -11.920502996742975 +23.04098773594394, -11.914118247434637 +23.18902990322472, -11.90773349812629 +23.337055888557742, -11.910553040704066 +23.485081873890763, -11.913372583281834 +23.633107859223784, -11.91619212585961 +23.781133844556805, -11.919011668437378 +23.929159829889826, -11.921831211015153 +24.077185815222848, -11.924650753592921 +24.22521180055587, -11.927470296170696 +24.37323778588889, -11.930289838748465 +24.521263771221907, -11.93310938132624 +24.669289756554928, -11.935928923904008 +24.81731574188795, -11.938748466481783 +24.938478769255983, -11.912127590455277 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure85-G1.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure85-G1.csv new file mode 100644 index 00000000..bd23e162 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure85-G1.csv @@ -0,0 +1,125 @@ +0.3402987009442946, -29.73243580474025 +0.35019525857233447, -29.152355185042815 +0.3589264881080276, -28.706499394427503 +0.367342878957542, -28.304722672206815 +0.37612264071832174, -27.893779059089844 +0.38604850350703596, -27.447197823905007 +0.3957555346958149, -27.03009539673387 +0.4053967579730522, -26.588661439570537 +0.4155638307676336, -26.17459499861191 +0.4254979145846255, -25.774128403895844 +0.4360302650469125, -25.33433715919974 +0.4468916126957555, -24.8962540414718 +0.45846703703400293, -24.480307974853424 +0.4708936836036186, -24.00954406645738 +0.4827955931589734, -23.59949926981639 +0.4940536415057475, -23.182015717427973 +0.507735747208707, -22.733220791423747 +0.5192115592297624, -22.339271146987848 +0.533527281021875, -21.90535801994576 +0.5458590632022026, -21.492543519435692 +0.5593707133410144, -21.08741644777586 +0.5717586674756521, -20.7019259763023 +0.5845021671391908, -20.318695779629852 +0.5901950901715672, -19.866038781045123 +0.5970087773325552, -19.431300745296515 +0.6029686962037756, -19.010968885472057 +0.6089881127478948, -18.58859333290623 +0.615067620928213, -18.1600867021163 +0.6212078206375461, -17.735667456809107 +0.6274093177574205, -17.317379289726013 +0.6336727242178568, -16.89704742990155 +0.6399986580577539, -16.478759262818453 +0.646387743485872, -16.062514788476733 +0.6528406109424271, -15.62992077220407 +0.6593578971612986, -15.19528306319004 +0.6659402452328593, -14.758601661434643 +0.672588304667432, -14.321920259679246 +0.6793027314593795, -13.889326243406579 +0.6860841881518349, -13.46081961261665 +0.6929333439020765, -13.02822559634399 +0.6998508745475587, -12.59358788732996 +0.7068374626725983, -12.160993871057293 +0.7134999374768176, -11.737048390885597 +0.7202252111179139, -11.314124757084588 +0.7278167371527753, -10.845394537339569 +0.7354882815855606, -10.393831336622032 +0.7428306367659459, -9.959193627608002 +0.7502462904351646, -9.526599611335339 +0.7577359743296059, -9.114442522476345 +0.7653004274905584, -8.694110662651891 +0.7729403963371357, -8.27377880282743 +0.7806566347399291, -7.849359557520234 +0.7884499040953948, -7.420852926730305 +0.7963209734009846, -6.984171524974908 +0.8042706193310266, -6.557708586926346 +0.8122996263133627, -6.131245648877783 +0.8204087866067523, -5.696607939863753 +0.8285989003790482, -5.276276080039292 +0.8362552224558768, -4.817064514062402 +0.8487095291634535, -4.38015228199737 +0.8674349463787812, -3.9675649198112186 +0.8833768330575315, -3.678331304589232 +0.9564414786646993, -3.2662113737800826 +0.9919198561748636, -3.2435821214256713 +1.028714273713436, -3.3095748179469098 +1.0668735486581538, -3.4625173511008587 +1.1064483092255704, -3.7325077412603846 +1.1399171252993654, -4.096646013136498 +1.1551153213912777, -4.470949665791103 +1.1653598601405184, -4.915025519465264 +1.1818752154105314, -5.410035769961773 +1.1920281222640952, -5.883471127768164 +1.2039280995686996, -6.2474063574433565 +1.2171553307876235, -6.686360902897903 +1.2274080879361353, -7.13388130779251 +1.2428122051775807, -7.5596048006492005 +1.2548036045312951, -7.995762273901807 +1.2673302673983562, -8.409257052555148 +1.2799819835263568, -8.80231490379482 +1.292760001317863, -9.191285369551753 +1.3056655816382028, -9.598649069980993 +1.316518593855397, -10.00564583466803 +1.3296613554189518, -10.38337599034745 +1.3447556446088529, -10.847102118630083 +1.356341799610321, -11.302076259422982 +1.3706383056544933, -11.698747731009888 +1.39044645752728, -12.13910777969975 +1.4029329474042662, -12.728906357443353 +1.4174076286038186, -13.229893480257118 +1.4319131144285957, -13.660061075875028 +1.445210570733138, -14.077085869263456 +1.459638060043905, -14.50488649710637 +1.474860567132898, -14.950496978239048 +1.4899540156358826, -15.364110662651889 +1.4979925099574656, -15.785984581544835 +1.5229993729140543, -16.31054012642279 +1.5382034252632395, -16.72735590578085 +1.5525307845123262, -17.168498131419906 +1.5734038929877407, -17.677663741004118 +1.5931502986648303, -18.192900975932687 +1.6085219705732579, -18.62946718773357 +1.624041957613948, -19.062354752599997 +1.6426098972476242, -19.51375445789822 +1.6693727709249893, -19.965476907400795 +1.7134045977445034, -20.444746538404047 +1.7626599828114025, -20.891308083720155 +1.8157598225537341, -21.40519580583851 +1.8720695957107614, -21.96128525649481 +1.927829076214447, -22.469751639011683 +1.9811589607836064, -22.939631104155417 +2.03201541048417, -23.36919939351229 +2.0914195573754966, -23.84454640027578 +2.1438904282113675, -24.287046099308256 +2.197823118265701, -24.688482441171274 +2.261684819630471, -25.17918229292436 +2.323842079730216, -25.621187776282916 +2.384685601462501, -26.083780724795524 +2.4523249208697875, -26.575314164128308 +2.5213767338969277, -27.01026096055694 +2.574755301290612, -27.431886206347095 +2.6431966583397535, -27.917334077714628 +2.7178956738650752, -28.373348281974074 +2.777792010893448, -28.791729344181768 +2.8462917733338724, -29.191451757075434 +2.9201200163188474, -29.536675616437293 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure86-St_1_prime.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure86-St_1_prime.csv new file mode 100644 index 00000000..001da2fa --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure86-St_1_prime.csv @@ -0,0 +1,160 @@ +10079.102972387203, 0.17754258781823296 +10334.465648836638, 0.17684922230294883 +10695.006458437525, 0.17811885771036892 +11141.59794800993, 0.1776942523055717 +11607.027310229661, 0.17761104265207697 +12091.899529051056, 0.1775278719635254 +12597.026810801206, 0.17744474022167067 +13123.255290932577, 0.17736164740827504 +13671.46645137898, 0.1772785935051093 +14242.604440360554, 0.17723335064851914 +14838.140707675655, 0.17794506235643798 +15457.989529929528, 0.17786173525503962 +16103.731930767086, 0.17777844717358254 +16776.51047110273, 0.17777096348167098 +17477.745065120806, 0.1781807499885073 +18208.092048053913, 0.1783632331465243 +18968.68287429436, 0.17824171507068826 +19761.009344534657, 0.17808231860675633 +20586.543545815985, 0.17803687063335694 +21446.604106737814, 0.17802937606295255 +22342.51502703457, 0.1779460094796114 +23275.851750181668, 0.17786268193469956 +24248.35369681323, 0.1779310283038416 +25261.12162093906, 0.17769614388704974 +26316.810045430677, 0.17795397412391406 +27416.26855137042, 0.17794648304308872 +28561.556367880534, 0.17786315527641927 +29754.579483481222, 0.17770409734767612 +30998.166656363086, 0.1780378182451854 +32293.084764535328, 0.17795444770858715 +33642.157854537894, 0.1779090323688216 +35047.58970417699, 0.1778636286193987 +36511.668501443906, 0.1777803396513274 +38036.90775917906, 0.1776970896853402 +39626.36570804572, 0.17787907750444135 +41281.86820861395, 0.17787158957643512 +43006.53396653412, 0.17786410196363778 +44803.252470747444, 0.1778566146660357 +46675.45738881217, 0.1780387658620579 +48625.367222014625, 0.1779933290036526 +50656.73631818578, 0.177947903741082 +52772.87195570614, 0.1778645753091362 +54977.60660456393, 0.17785708799160835 +57274.13844995037, 0.1777359147502106 +59666.81785791962, 0.17769055518173155 +62159.3408434806, 0.17760734725950497 +64858.30168580601, 0.17942008843856166 +69764.55416774347, 0.17927346822261503 +75710.0445173293, 0.17773655975646424 +78873.61630699722, 0.1778806698056361 +82168.48452114657, 0.17779737285761504 +85600.99263386948, 0.17771411491541494 +89461.08860586067, 0.1774757413792583 +96783.59191608094, 0.1775780876215486 +100511.94235567769, 0.1788196379742944 +105040.09058399795, 0.1777145878617564 +109423.2724015211, 0.17672502447612545 +114004.8721230136, 0.17857290292431804 +118754.91141258282, 0.1763130215611259 +123732.2947999874, 0.17901515544340632 +129339.37638250491, 0.17729183547888264 +133843.80588152786, 0.17660015152336428 +151903.0892155644, 0.1893372726030689 +158271.66536575573, 0.1925032528451019 +164908.1433888332, 0.1958473635337931 +171821.3362435729, 0.19903733625798126 +179286.85374397872, 0.20309344901472381 +192906.72152930935, 0.20876213561274037 +201626.39100363507, 0.211014526528509 +209422.3777717395, 0.21595355053590526 +215380.59598440392, 0.2197241151541342 +240706.7704303503, 0.2288240492860581 +250522.76280297333, 0.2316466224881271 +261582.7293135515, 0.23785966745110765 +272990.2472413338, 0.2401636809588331 +285320.7119613801, 0.24184724156273307 +296348.6323202384, 0.24710114920836568 +308763.60063393845, 0.25032433967966927 +346909.6754855274, 0.2623321881925166 +364384.11419177876, 0.27101905174382146 +379202.94939256867, 0.2766224183525455 +395689.79563156486, 0.2792220870507299 +428759.56053795875, 0.2778480114414054 +446681.71633849887, 0.27853301141840714 +465361.04023555765, 0.27978565533687744 +485113.0680031368, 0.27856924809627587 +505069.8802420563, 0.280614608322308 +526127.366187032, 0.27790797890692215 +548119.7463061935, 0.2786079722174479 +571024.1656983551, 0.27889330754476155 +594881.3802207796, 0.2789410155583325 +619727.4703133407, 0.27857278918217304 +645620.6654466204, 0.2786798349012369 +672594.4988514361, 0.27872750639777605 +700691.4765106272, 0.2785969854668744 +729962.1779438457, 0.2784665256555716 +760462.5335948471, 0.2786329130752412 +793368.9538260868, 0.2786790151683377 +825343.3636495619, 0.2791104261156628 +859811.246335832, 0.27859772689039713 +895729.0205975499, 0.2784672667319048 +933153.9975880783, 0.2785742719024049 +972139.1214776668, 0.2785625451489173 +1012754.7958394883, 0.27861019658165154 +1055065.4661978916, 0.27859846831589274 +1099139.794613259, 0.27846800781020986 +1145049.744471109, 0.27817945089292895 +1192842.6749908428, 0.27694511479432893 +1242734.1452790545, 0.2784328424498516 +1294695.1330369634, 0.2794913603410668 +1348809.1252379883, 0.2800759235511876 +1405159.4071707914, 0.2800641335847601 +1463866.5362711474, 0.2801120418820352 +1524973.8559606248, 0.2790276801196453 +1588669.5000091447, 0.27871874016423126 +1655037.6183539082, 0.2786476090042823 +1724165.8113478625, 0.27833908986429884 +1796213.9670854867, 0.27862414981674233 +1871269.4220215688, 0.2788500602314903 +1956362.208005146, 0.2810827793101456 +2024336.404754037, 0.2804897385062525 +2115748.2205900466, 0.2789931865589704 +2204131.5341436104, 0.27886254121687437 +2296206.974217101, 0.27873195705263587 +2392133.116317793, 0.2786608225196351 +2492107.357675029, 0.27912463593335457 +2596212.706250542, 0.27899392903689335 +2704666.953989106, 0.2788632833471143 +2817651.7719017686, 0.27873269883535523 +2935356.4201284423, 0.27860217547296845 +3057978.0649663806, 0.27847171323131914 +3185722.1091421554, 0.27834131208178614 +3318802.5358804194, 0.2782109719957615 +3457498.7296946486, 0.2786146453633359 +3601912.7519574184, 0.2783061627207557 +3752413.1796207204, 0.2784724543214576 +3909180.7582524894, 0.278460731854043 +4072490.3523457022, 0.2783896665397935 +4242676.241916249, 0.2787341824067155 +4419966.034237869, 0.2790196469917296 +4604639.214771775, 0.27912686442252366 +4796993.516460249, 0.2789961564825183 +4997383.231055648, 0.2788655097496834 +5206144.030076696, 0.27873492419535717 +5423625.607391685, 0.27860439979089147 +5650192.264988402, 0.2784739365076515 +5886351.691528197, 0.27905637175023346 +6132348.422650462, 0.2794612717601768 +6388428.547695005, 0.2788545128432606 +6655407.590419041, 0.27925911996373176 +6933430.736163084, 0.279128350091854 +7223068.027024353, 0.2789976414561481 +7524804.632561114, 0.2788669940279382 +7839145.989815594, 0.2787364077785626 +8166722.379166847, 0.2790218746426825 +8507879.222745104, 0.2788912158666939 +8863528.800301878, 0.2796532857466662 +9233777.296181368, 0.2794627592094103 +9619526.77041665, 0.279391438170095 +9854892.929329835, 0.278986875576402 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure87.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure87.csv new file mode 100644 index 00000000..4f0b3d49 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure87.csv @@ -0,0 +1,62 @@ +0.4748453697731536, 0.9627061541003156 +0.5779822991814649, 0.9543051005857622 +0.6811332818571723, 0.945520680842594 +0.7842842645328796, 0.9368171220632588 +0.8874422738422831, 0.9279696064744569 +0.9905897432011415, 0.9195386048133337 +1.093744239193696, 0.9109642351968639 +1.1969022485031005, 0.90236088019627 +1.3000356645945637, 0.8945944172788342 +1.403186647270271, 0.8863596369591554 +1.5063306033122803, 0.8784127140663858 +1.6094850993048357, 0.8702218287171615 +1.7126325686636932, 0.8623154903713036 +1.8157765247057025, 0.854584142478781 +1.9189204807477127, 0.8469221123022251 +2.0220468702054797, 0.8398355442810664 +2.1252013661980333, 0.8320043772849002 +2.228373428774833, 0.8237488739608809 +2.434629721007213, 0.8099234344101649 +2.5377771903660706, 0.802564932824281 +2.64092114640808, 0.7953692964576741 +2.7440861823511815, 0.7876674513554409 +2.847230138393191, 0.7806053828224685 +2.9503740944352, 0.7736066313808379 +3.0535145371603614, 0.766763186338921 +3.1566655198360687, 0.7597050980312346 +3.25980596256123, 0.7529846281237302 +3.3629674851874816, 0.7457832333889398 +3.4661149545463408, 0.7390074730238689 +3.569262423905198, 0.7322932733462335 +3.6724063799472075, 0.7257276785971976 +3.775567902573459, 0.7187869638888977 +3.8787118586154685, 0.7123424640040092 +3.9818593279743277, 0.7058705273636238 +4.085013823966883, 0.6992885363832485 +4.188168319959437, 0.6927679201218715 +4.291322815951992, 0.6863081062821207 +4.394480825261396, 0.6798264552468807 +4.497624781303407, 0.6737312674754176 +4.600772250662266, 0.6676101301066886 +4.703933773288518, 0.6612252400355282 +4.807084755964225, 0.6551386330901352 +4.910232225323083, 0.6491864177747723 +5.01338320799879, 0.6432106287092026 +5.1165412173081934, 0.6371360001287024 +5.219702739934445, 0.6310425585559236 +5.322860749243849, 0.6250828480184765 +5.426018758553252, 0.6191794223531173 +5.529173254545808, 0.6134057950161276 +5.632324237221515, 0.6077593681312603 +5.7354892731646165, 0.6018742170025633 +5.838657822424568, 0.5959741043889141 +5.941801778466577, 0.5906307199925823 +6.044980867677071, 0.5846290610922733 +6.148142390303325, 0.579037785407342 +6.251300399612728, 0.5735692198653138 +6.35446192223898, 0.5680837182950249 +6.457623444865233, 0.5626506789671917 +6.560763887590395, 0.5576733832162021 +6.663904330315554, 0.5527401174005152 +6.767048286357563, 0.5477843602681265 +6.828083383310347, 0.5432617567220622 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure88-G2-alpha0.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure88-G2-alpha0.csv new file mode 100644 index 00000000..9e5220a0 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure88-G2-alpha0.csv @@ -0,0 +1,140 @@ +15970.087021491256, 125.65629502572898 +16396.547639910805, 126.45956873315363 +16663.820931547085, 127.09783876500858 +17005.03852810282, 127.72203871600098 +17341.192619313628, 128.38205341827984 +17647.654247195725, 129.06892918402352 +18020.541555128948, 129.82103896103897 +18358.113273598938, 130.4565909090909 +18707.611951676798, 131.21653516295027 +19135.98468506806, 131.89701543739278 +19500.795730024103, 132.5800539083558 +19826.930470513198, 133.1970909090909 +20272.35143475466, 133.91831046312177 +20626.041725103332, 134.58759862778732 +21003.04903308872, 135.19644939965696 +21436.88299627237, 135.97542024013723 +21863.573874478523, 136.57531732418525 +22393.656648650096, 137.4035334476844 +22715.546886174052, 137.99984905660378 +23248.184726371517, 138.706295025729 +23590.727656088515, 139.2623190394511 +24109.23506947055, 139.97682332761576 +24527.11388989166, 140.50598627787306 +24994.53583258162, 141.20885077186963 +25430.575528368896, 141.88261578044597 +26039.405685208472, 142.57876500857634 +26410.419994309843, 143.1383704974271 +27000.37834738168, 143.75617495711833 +27441.73377902924, 144.32831560891938 +28085.090732189736, 145.04550600343052 +28499.10706185771, 145.5800411663808 +29121.164651262836, 146.2632075471698 +29652.912969397225, 146.9257804459691 +30304.85416360343, 147.6214819897084 +30868.48444456774, 148.24197255574614 +31532.875736115784, 148.86246312178386 +32288.12535346731, 149.52861749571184 +32983.4437077104, 150.1155317324185 +33693.279932430916, 150.74273756432245 +34500.52262690928, 151.38740308747856 +35326.8508923823, 152.0535574614065 +36172.84024156089, 152.73045626072042 +36952.298240470715, 153.27842195540308 +37836.6557781744, 153.99919382504288 +38834.7366264896, 154.72891938250427 +39670.9813005613, 155.3198627787307 +40525.23318198552, 155.91080617495712 +41397.97333862605, 156.49503430531732 +42288.47913317213, 157.15178730703258 +43261.2230477024, 157.73198627787306 +44128.28446868624, 158.403512864494 +45078.842473123426, 158.97296740994852 +46048.79677337267, 159.61226072041165 +47040.51206598289, 160.19514579759863 +48052.71862397673, 160.83175300171527 +49231.37210918093, 161.59863636363636 +50982.153920304554, 162.4828130360206 +52040.23681718862, 163.3140441768474 +54722.871941562036, 164.43134481299145 +53562.653733686995, 163.83865719186474 +56782.178576931576, 164.95867352773013 +58214.84228712814, 165.85835334476843 +59896.2819497384, 166.44481989708405 +61772.90790392892, 167.06965939720658 +63861.70102753887, 167.64909090909092 +66337.23754276041, 168.2340651801029 +69568.6337754064, 168.8969094027756 +74869.33179919011, 169.77495221759372 +78361.74768577679, 170.20821768283173 +82580.86336885499, 170.56962108217684 +87030.49526757504, 170.81625448308125 +91723.79205394055, 170.9359083112428 +96427.22796810175, 170.88688217442933 +101894.09412790278, 170.86020895056916 +107401.1762531668, 170.64043661312957 +113210.5397837129, 170.298568532668 +118768.25305849896, 169.88154373927958 +124246.1713657315, 169.36640823327616 +129856.67184817245, 168.75755746140652 +135848.22703886204, 168.19398676794904 +140420.13981432412, 167.70583490566037 +144608.61448306125, 167.08500857632933 +148083.5930942513, 166.67571183533448 +151732.9887533824, 166.17173241852487 +155803.8525083394, 165.59421955403087 +160369.52353046276, 164.9629845626072 +164675.80973955136, 164.31831903945113 +168285.55612067494, 163.78109777015436 +171980.941622675, 163.1310600343053 +178723.05594594585, 162.45819039451115 +180972.00246406803, 161.81062484685125 +183555.68571999366, 161.2695883361921 +189910.1945728008, 160.71669811320754 +193246.42109981686, 160.09656419052646 +196212.06682053095, 159.55495711835334 +200218.33735226264, 158.6551114922813 +205104.79568508425, 157.9992538593482 +209006.23291054805, 157.3827924528302 +212466.82307420982, 156.86168782161235 +217859.89725593693, 156.2116500857633 +223183.6597394358, 155.46567998039694 +228394.02440482198, 154.83968501481365 +235658.14717188114, 153.93204116638077 +245753.72428339624, 153.18623966942147 +254309.40225438538, 152.1795602682052 +261857.06146936875, 151.20244547904926 +266150.85801688535, 150.65517350573953 +275081.1287147119, 150.0909090909091 +287097.979164723, 148.54843287073132 +278338.31327016064, 149.33717137065335 +291695.1514020491, 147.99350771869638 +296442.4751567703, 147.3510806174957 +303198.8084809977, 146.64821612349914 +310116.58392555837, 145.87372212692966 +317434.32280787517, 145.1986140651801 +332501.45240755426, 143.79309269893355 +326358.6723717225, 144.4545626072041 +339343.37882631825, 142.81405264546774 +345867.46317324426, 142.31910806174957 +350782.796415798, 141.79979416809604 +357220.85936653183, 141.17175692232297 +365788.9911618066, 140.3821269296741 +373527.20224549633, 139.70463121783877 +386534.6121712455, 138.83750098957645 +398729.33657064004, 138.16459691252143 +405081.248905065, 137.40062607204118 +416292.6151880857, 136.28730703259004 +429304.7954470145, 135.43491595197256 +419116.2617714475, 135.9204116638079 +434601.9195733975, 134.5992384219554 +444147.95369097486, 133.93174099485418 +449934.0341793281, 133.33408233276157 +458338.85231423937, 132.76731389365352 +468189.881398289, 132.05280960548885 +477547.9404329647, 131.46052315608918 +485709.45239824185, 130.80108404802743 +495674.8131064486, 130.0865797598628 +503473.430902628, 129.5409164420485 +560113.7467128999, 126.14203259005146 +580189.1638947661, 125.1548885077187 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure88-G2-alpha6.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure88-G2-alpha6.csv new file mode 100644 index 00000000..515e0f68 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure88-G2-alpha6.csv @@ -0,0 +1,90 @@ +278136.5952401709, 126.0789090909091 +284259.5785734193, 126.69134133790736 +290240.16801799665, 127.30041595197255 +295537.3585829643, 127.988730703259 +302124.5707182007, 128.74979416809606 +306869.6315311644, 129.30223670668954 +312274.89571496873, 129.9563036020583 +318997.37257521634, 130.56470668953688 +325610.18660584814, 131.12699828473413 +332091.05174596055, 131.72913379073756 +351039.70295342687, 133.18227662560423 +339239.5078568106, 132.34290909090907 +358830.2276725649, 133.88089683901003 +365923.8659484874, 134.53835334476844 +373791.9433140259, 135.22107204116637 +381837.34722449636, 135.84021955403085 +399633.40411171527, 137.07996382348352 +412619.6275696948, 137.97433104631216 +421734.719621837, 138.7197255574614 +430816.1102476286, 139.3106689536878 +440089.8799690893, 139.9231012006861 +449565.70930296456, 140.51941680960547 +460333.20067694644, 141.1864665523156 +473591.4465779767, 142.01020583190393 +489185.90028998745, 142.771269296741 +506431.4793307743, 143.78684391080617 +518161.2906741104, 144.54186106346484 +529309.2918752816, 145.18786963979417 +540717.1247847106, 145.72374785591768 +553680.6680049187, 146.3214065180103 +569665.1162860442, 146.94816466552317 +586112.7880295335, 147.5659691252144 +610274.8732371066, 148.22121627943238 +627885.4875280559, 148.8843996569468 +672674.0210083671, 150.0315909090909 +700426.7537943105, 150.59231560891936 +734565.8318855292, 151.17349134570404 +775626.3040183682, 151.6597231070816 +817587.2004488849, 152.10397935232592 +858826.0844862629, 152.35727110228402 +906738.1497299948, 152.59122641509435 +954909.1834917029, 152.60445345392174 +1010573.9223329611, 152.60977333986767 +1056228.2462508758, 152.42375175424917 +1111630.6176123247, 152.13354532260195 +1164418.7860209316, 151.66588732022694 +1201586.0342989094, 151.37128644939966 +1263646.1963504057, 150.8206346483705 +1319427.880021468, 150.25319468267583 +1374412.1734328964, 149.62531732418523 +1428290.3345554192, 148.957628032345 +1505808.8197152764, 147.95012713147008 +1466542.5884435612, 148.51729845626073 +1542544.638508201, 147.46971698113208 +1583894.0643891508, 146.95935677530017 +1622493.9492979313, 146.4064665523156 +1666064.1031290889, 145.7573241852487 +1702592.4360411796, 145.20667238421956 +1739968.7120973393, 144.5754373927959 +1778121.4060141179, 144.0180703259005 +1817145.0876622517, 143.40429502572897 +1857009.2998606865, 142.81603773584905 +1902312.2351530998, 142.1892795883362 +1953491.6840746189, 141.39508747855916 +1996337.1446583874, 140.8216037735849 +2040164.6304977036, 140.1863396226415 +2084911.0678503597, 139.61285591766722 +2130679.259117927, 138.9829639794168 +2177405.0424608956, 138.417538593482 +2225161.5405725576, 137.8440548885077 +2274028.0027128016, 137.18864493996568 +2323925.7089198725, 136.58695711835333 +2374906.51544358, 136.00004288164666 +2421211.734545058, 135.41581475128646 +2474388.089463962, 134.75503259005146 +2534886.4537619473, 133.9706895368782 +2590497.518743428, 133.38108919382503 +2647397.814351189, 132.71359176672382 +2705469.8680035817, 132.1320497427101 +2758232.7468978856, 131.5343910806175 +2818762.7072689855, 130.9246449399657 +2887602.86679809, 130.22088507718695 +2950982.5223322655, 129.60039451114923 +3005550.2242730036, 128.9077628032345 +3066408.866060245, 128.16332761578045 +3137862.277539195, 127.46493996569467 +3203798.735299375, 126.72626072041166 +3271055.8447452015, 126.04667581475128 +3338133.889378112, 125.36306174957117 +3426018.2604732327, 124.71436706689536 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure89.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure89.csv new file mode 100644 index 00000000..7646f51c --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure89.csv @@ -0,0 +1,129 @@ +0.18260209914632308, -42.54347107438019 +0.18616533125398865, -41.90560802833531 +0.18966803110390612, -41.26813016528928 +0.19302431412942017, -40.62371900826449 +0.19701038444251395, -40.03795196280993 +0.20078256604580813, -39.350400309917376 +0.2051179159330765, -38.65273760330578 +0.20879797808875433, -38.012370867768595 +0.21338809227869507, -37.26415289256198 +0.21764640581718986, -36.55637913223143 +0.22181471594869479, -35.882308884297544 +0.22606234280202342, -35.2014979338843 +0.23039418891325625, -34.55776084710746 +0.23480530745364842, -33.86683884297523 +0.23987801088192973, -33.20287964876033 +0.24397715817046584, -32.61884592680046 +0.24856883805306312, -31.996293904958677 +0.25307409666807973, -31.382408500590316 +0.2581878156052667, -30.725671487603307 +0.26313495665475434, -30.078564049586774 +0.2682711064620116, -29.4564935064935 +0.2763336224627245, -28.820299586776827 +0.28001306522940667, -28.397240259740244 +0.28389537243043655, -27.548553719008268 +0.28884494820770945, -26.956655844155833 +0.2948803912400475, -26.267820247933884 +0.2995809812656732, -25.72407024793388 +0.3079866723309998, -24.75940082644628 +0.3151467354033214, -24.119783057851237 +0.32041785757043595, -23.495144628099155 +0.32655461901673877, -22.822871900826428 +0.33468233324383145, -22.191942148760333 +0.3424546803612577, -21.48012396694216 +0.3498658271728656, -20.92469008264463 +0.3582877877129371, -20.30005165289255 +0.36778311205652003, -19.58733471074379 +0.3757396653854319, -19.010330578512395 +0.384921476339251, -18.424852420306976 +0.3937360793634629, -17.792510330578494 +0.4014697489627558, -17.188414994096817 +0.41057967702584874, -16.62989964580872 +0.4181595612283354, -15.979710743801661 +0.42417151837936407, -15.613016528925613 +0.4490681053413197, -13.96058146399055 +0.47659816866009863, -12.494318181818187 +0.5057426180472182, -10.597933884297518 +0.5179053848200632, -9.907685950413224 +0.5291048467033939, -9.303719008264466 +0.5418324143425023, -8.629648760330582 +0.5558194973352744, -7.963282172373084 +0.573098986004455, -7.25454545454545 +0.5821342635336781, -6.6384100024307315 +0.6161169110233358, -5.349173553719012 +0.6440469431349443, -4.458502066115699 +0.672924551050595, -3.587603305785123 +0.6974481609997447, -2.9910511363636374 +0.7333155869214467, -2.259684917355372 +0.7608464490665636, -1.7579840613931594 +0.783418484384122, -1.3467599549211116 +0.9094666608244443, -0.20009391435011992 +0.9356765754918469, 0.0531243082201911 +0.9775583962238239, 0.13347107438016792 +1.0352052712981252, 0.0646318557475638 +1.0934648912503517, -0.047080135773313714 +1.1476892514502937, -0.24151069518715929 +1.213129236394918, -0.589829075882804 +1.2729550445009485, -1.014152892561981 +1.3357822610236294, -1.55191115702479 +1.3923684423469778, -2.1855371900826412 +1.4568867718584326, -2.7209415584415524 +1.5106088961627993, -3.3584194214875964 +1.571418915314829, -4.160563016528926 +1.6359887005254414, -4.969447314049589 +1.6881616114159044, -5.551394628099175 +1.737861201376662, -6.198502066115708 +1.789040212727976, -6.872572314049592 +1.8197525656198084, -7.5342846074380105 +1.8564005191836896, -8.150309917355372 +1.8998775149153742, -8.800413223140495 +1.956879710792087, -9.48755634861007 +2.0586689578233353, -11.130449380165288 +2.0705607530306858, -10.419979338842978 +2.1236084003829925, -12.038518299881943 +2.171403853240218, -12.751962809917345 +2.2305895511919576, -13.429028925619832 +2.2812296568631028, -14.17387654958678 +2.3319752136554017, -14.777169421487585 +2.392916313633422, -15.370351239669404 +2.4540553824151687, -16.176539256198325 +2.507770489916143, -16.812861570247918 +2.5618744331773127, -17.41952479338842 +2.637579537706853, -17.978553719008232 +2.6803388980690737, -18.70025826446279 +2.7539811869404254, -19.374328512396673 +2.8397040341292827, -19.94988080101716 +2.9082469849544283, -20.60972890745616 +2.958318291464275, -21.182762691853583 +3.0170745101997323, -21.89535123966941 +3.0755196656106136, -22.53860684769775 +3.15169845598287, -23.25547520661155 +3.2161325909169145, -23.968117252066094 +3.279168782183906, -24.598372933884278 +3.3422711528371702, -25.207925029515934 +3.4090300099586273, -25.90943956611568 +3.513710552248368, -26.645299586776844 +3.62202937451813, -27.728305785123936 +3.699332423153728, -28.677995867768573 +3.7749372690367515, -29.370790289256178 +3.8767414368827966, -30.005764462809907 +3.962075097379827, -30.525697314049566 +4.000016863714242, -31.34003837072018 +4.100947102676588, -32.04107142857141 +4.175272529368018, -32.950103305785106 +4.324659414853411, -34.01064049586773 +4.475619657751913, -34.70807851239667 +4.526401367915814, -35.430681818181796 +4.6144774668533275, -36.258825265643424 +4.6888643286168605, -36.917488193624536 +4.785251367022955, -37.617665289256195 +4.883113719157373, -38.34940599173552 +5.01249309164478, -39.04100206611568 +5.15045005965451, -39.43386606708796 +5.235081070343995, -39.95144628099172 +5.250221826362573, -40.83479929161746 +5.372328015785741, -41.57820247933881 +5.482355761644609, -42.39607438016526 +5.594380539157113, -43.07800878099172 +5.704043346964392, -43.71500516528923 +5.813770811471624, -44.30529811097989 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure91-tip.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure91-tip.csv new file mode 100644 index 00000000..b4f764fe --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure91-tip.csv @@ -0,0 +1,13 @@ +1.2401721540542965, 42.47045219036755 +1.584306020291701, 45.91662036133181 +1.9820989414369934, 48.61985072161235 +2.4801140830728974, 50.7319747097782 +3.147569623346996, 52.255695556189664 +3.995481645521921, 52.89275684442913 +5.0014471518503765, 53.23156171625095 +6.2615564489090785, 52.97926021595811 +7.951632683313081, 51.84300238785352 +10.0282864505485, 50.26206316548277 +12.471821918208114, 48.38286752669444 +16.070391849980226, 45.03266403352012 +20.13392559438178, 41.67705407962518 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure95-0Psi.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure95-0Psi.csv new file mode 100644 index 00000000..964beeff --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure95-0Psi.csv @@ -0,0 +1,152 @@ +0.20551596271370642, 0.1158908937909841 +0.2102323697917107, 0.11686102112823273 +0.21505701418340936, 0.11781779080457164 +0.21999237983810577, 0.11877156802435197 +0.22504100770951263, 0.1197658096015731 +0.23020549706395224, 0.12065835150216189 +0.23548850681857847, 0.12159078710201958 +0.24089275691030979, 0.12260862847563084 +0.24642102969617827, 0.12347733129267302 +0.2520761713858152, 0.12443155168470818 +0.2573297508350023, 0.12540767429233743 +0.27602466922359564, 0.12812407189225833 +0.2823591878976681, 0.12907890284959353 +0.2888390780957606, 0.13006455652910465 +0.29546767596400886, 0.13096221094004076 +0.30224839421011124, 0.13191414437009547 +0.3091847238603477, 0.13286088720659758 +0.3162802360569216, 0.13374126680509116 +0.3235385838965477, 0.13468884624279337 +0.33096350431123517, 0.13556898168447354 +0.3385588199922321, 0.1364921845149513 +0.34632844135812335, 0.13738410402020423 +0.3542763685680943, 0.1382944559294808 +0.36240669358139677, 0.13921084012760646 +0.37072360226407897, 0.14013329658649581 +0.379074960467678, 0.1413064839831905 +0.38793439661567186, 0.1421260673182081 +0.3968371431947698, 0.1428333184940195 +0.4059441998256266, 0.14374047022546568 +0.4152602552407453, 0.14465338338759579 +0.42479010577483556, 0.14554556105700828 +0.43453865783418855, 0.1465634169827126 +0.46084969481404253, 0.1494039434798627 +0.47976416367281927, 0.1507313105775924 +0.49077432107101326, 0.1512468535845744 +0.502037151709753, 0.15219356859401795 +0.5135584542133618, 0.1529788014532757 +0.5253441602793911, 0.15386622182550755 +0.5369571216783292, 0.15478163603043385 +0.5497331936486186, 0.15594053679353037 +0.5623490775502992, 0.15643111786287572 +0.5752544846760811, 0.15726687921362606 +0.5892969896869593, 0.15754975192664733 +0.6403872573510969, 0.16100088501259693 +0.6550835707340232, 0.1619643623288992 +0.6701171513323259, 0.16274066505998575 +0.6854957391262024, 0.16352068864621364 +0.7012272517214573, 0.16425953115931965 +0.717319788425848, 0.165046834741493 +0.7337816344189843, 0.16568683010248536 +0.7506212650179189, 0.16642029114715354 +0.7678473500406316, 0.16706561230387842 +0.7854687582696526, 0.16774401059973815 +0.8034945620181178, 0.16839446468924688 +0.8219340418006167, 0.1690320341255187 +0.8407966911112268, 0.1696874827311758 +0.860092221311203, 0.17023682629198353 +0.8798305666288342, 0.17091252354602263 +0.9000218892740408, 0.17140333236596883 +0.9206765846703501, 0.1719895794372381 +0.941805286806938, 0.17259356172053425 +0.9634188737134982, 0.17318387970724963 +0.9855284730607516, 0.17366538195996162 +1.008145467889487, 0.17433879710902173 +1.0312815024710713, 0.17483944514524868 +1.0549484883024596, 0.17545343540927855 +1.0791586102387818, 0.1759572843479173 +1.10392433276667, 0.1765591072016131 +1.2727729125720022, 0.1799156997211124 +1.3019819097432292, 0.18041591841849 +1.3318612272106551, 0.18098349780486767 +1.3624262482240652, 0.1815197710157586 +1.393692709065037, 0.18200785989433046 +1.4256767071486998, 0.18254716839823698 +1.4583947093114267, 0.1830046573955818 +1.4918635602887218, 0.18354691951571905 +1.5261004913876652, 0.18395660774355116 +1.5611231293583874, 0.18450169059306928 +1.5969495054691274, 0.18499779756120988 +1.6335980647895645, 0.18542762401325807 +1.6734757356668029, 0.18538416726379392 +1.7109074636677124, 0.1860269385431972 +1.7486677006817835, 0.18691040332258768 +1.7887980565513275, 0.1874471531908074 +1.8718427704562806, 0.18826771447787954 +1.9147998837379834, 0.18856759430624787 +1.958742824254016, 0.18912633999574505 +2.0036942158555093, 0.1895830372562274 +2.049677201590694, 0.18995425202494604 +2.0967154556200067, 0.1904997429014822 +2.144833195404643, 0.19078578828929116 +2.194055194174816, 0.19121163412590897 +2.244406793684161, 0.19167336689924777 +2.2959139172568395, 0.19196117454524392 +2.3486030831340563, 0.19242471728887106 +2.4025014181268802, 0.19299489204097212 +2.4576366715823688, 0.19347856450999606 +2.5140372296702145, 0.19369845237362243 +2.5717321299972538, 0.19395394224320028 +2.630751076557363, 0.19420976910604087 +2.691124455024451, 0.19467874169606528 +2.7528833483963924, 0.19497106207045767 +2.816059552997997, 0.19529941872408796 +2.880685594851219, 0.19566399216891445 +2.9467947464210535, 0.19604711380601209 +3.0144210437457386, 0.19641308300395177 +3.083599303960069, 0.19660046491981778 +3.154365143220867, 0.1969674670810048 +3.2267549950438204, 0.19731716932082766 +3.300806129061134, 0.197577432308154 +3.376556670209661, 0.19782000773255756 +3.454045618359367, 0.19804482963462738 +3.5333128683922683, 0.19830605241195928 +3.6143992307421504, 0.19849524025759802 +3.69734645240567, 0.1988295320861411 +3.7821972384356206, 0.19914623517101104 +3.8689952739274704, 0.1994089107114052 +3.957785246510459, 0.19949002741898117 +4.04861286935485, 0.19969854521742914 +4.141524904707181, 0.19992550207225362 +4.2365691879656175, 0.2002074522712224 +4.333794652307825, 0.2002523870346442 +4.43325135388402, 0.2004251634154217 +4.534990497588188, 0.20063465866874175 +4.639064463420723, 0.2008809875986608 +4.745526833456062, 0.2010176600399694 +4.854432419429208, 0.20111776092797232 +4.965837290955338, 0.2011079033805349 +5.079798804397022, 0.2013548133360068 +5.196375632393934, 0.20141836277508857 +5.315627794070217, 0.20170241832013788 +5.437616685935096, 0.2017660774665637 +5.56240511349264, 0.2017561881426635 +5.69005732357692, 0.2019670746552329 +5.820639037429254, 0.20214133045668367 +5.954217484534514, 0.2021314227402053 +6.090861437233972, 0.20219521728438897 +6.23064124613247, 0.20231434338126694 +6.373628876318165, 0.20235975101746395 +6.519897944413451, 0.20234983259536204 +6.669523756476204, 0.20246904978597988 +6.822583346770813, 0.20245912600672905 +6.979155517428957, 0.20246765550663343 +7.139320879020595, 0.20245773179572157 +7.303161892055981, 0.20242935758729452 +7.470762909440149, 0.20247479103739646 +8.61343878846522, 0.20156568856333384 +8.811109485823483, 0.2014639773639627 +9.013316548453936, 0.20112387122059866 +9.220164081872248, 0.20093079430401845 +9.43175858072235, 0.20092094592052737 +9.559067083514492, 0.20091512664808536 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure95-14Psi.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure95-14Psi.csv new file mode 100644 index 00000000..f4255c16 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure95-14Psi.csv @@ -0,0 +1,153 @@ +0.2072186509383286, 0.08160700226831218 +0.2117388271287582, 0.08208139097848936 +0.21683874948434348, 0.08309972751560439 +0.22220752710378625, 0.08402944256563669 +0.23558567543194325, 0.08552116892369319 +0.24089275691030979, 0.08635433996387698 +0.24642102969617827, 0.0870454752779608 +0.2520761713858152, 0.08773414530892638 +0.2578610935068109, 0.0883799190212897 +0.2642455560211751, 0.08936377297479899 +0.2693132822615688, 0.09011182959116786 +0.27602466922359564, 0.09075029043187537 +0.2823591878976681, 0.09122682504082305 +0.2888390780957606, 0.09191506029694801 +0.29546767596400886, 0.09260004746384558 +0.30224839421011124, 0.09329013942442221 +0.3091847238603477, 0.09398537422160741 +0.3162802360569216, 0.09465990370595623 +0.3235385838965477, 0.0953479642249155 +0.33096350431123517, 0.09605853474157373 +0.3385588199922321, 0.09672149296570406 +0.34632844135812335, 0.09752226354040558 +0.3542763685680943, 0.09818637437620611 +0.36240669358139677, 0.09872894810685848 +0.37072360226407897, 0.09943752204198794 +0.3792313765440615, 0.10010555108085648 +0.38793439661567186, 0.10077806799097933 +0.3968371431947698, 0.10138115400806852 +0.4059441998256266, 0.10200644184847045 +0.4152602552407453, 0.102654297134038 +0.42479010577483556, 0.10331568316266299 +0.43453865783418855, 0.103962377660055 +0.4445109304227203, 0.10459405218137706 +0.47582200504770344, 0.10664819490102724 +0.48674169344000323, 0.1071300679960542 +0.4979119788902783, 0.1075160796478116 +0.5102399354712656, 0.10764907286099941 +0.6465129641574365, 0.11434903167743737 +0.6618747453395678, 0.11521978826996852 +0.6770641773060784, 0.11576149067938693 +0.6926021931173268, 0.11631634089505705 +0.7084967924600082, 0.11684189798715157 +0.7247561586064551, 0.11749827007704873 +0.7615380500075445, 0.11883186805132014 +0.7790146654577448, 0.11911882008876909 +0.7968923535629373, 0.11956982374327466 +0.815180318580951, 0.12003347475863779 +0.8338879759990798, 0.1205758271354639 +0.8530249573816086, 0.1209992578085424 +0.8726011153285873, 0.12145738111284853 +0.8926265285484027, 0.12193946492919022 +0.9131115070467626, 0.12238999243943915 +0.9340665974347621, 0.12280860025545924 +0.9555025883587647, 0.12326233894409772 +0.9774305160548945, 0.12369520394186952 +0.9998616700309998, 0.12408434281922923 +1.0228075988790117, 0.12446336135042727 +1.046280116220691, 0.12490044402381431 +1.0702913067898276, 0.12530479473703227 +1.094853532654015, 0.12566463202199238 +1.1199794395792146, 0.12599104810192108 +1.1456819635403777, 0.12638740958929762 +1.171974337381484, 0.1267734628918827 +1.1988700976284166, 0.12713751774539203 +1.2263830914581908, 0.1274909975340542 +1.2545274838281193, 0.12789207778674674 +1.283317764768584, 0.12827103551512575 +1.3127687568431743, 0.12855734450555192 +1.342895622780022, 0.12895002592515864 +1.373713873278275, 0.12928497587322213 +1.40523937499372, 0.12963261050573097 +1.4374883587076674, 0.130028576350518 +1.4704774276833077, 0.13030693109644886 +1.504223566213833, 0.13068113299666853 +1.5387441483667375, 0.1309966983242567 +1.5740569469287857, 0.13130105787238652 +1.6101801425562627, 0.13152218594915477 +1.6471323331352177, 0.13163566238564944 +1.7414685961451184, 0.1326918396820178 +1.7814337390202866, 0.13290319618687624 +1.8223160460915635, 0.13326055985928767 +1.864136565454918, 0.1335093228186697 +1.9069168282412488, 0.13378293485165857 +1.9506788597016032, 0.1340571076211039 +1.9954451905467951, 0.13433184227617082 +2.041238868547248, 0.13461940910860626 +2.088083470399051, 0.1348461257209034 +2.136003113862332, 0.13506091365280917 +2.1850224701781875, 0.13536237807678206 +2.23516677677058, 0.1356027047028118 +2.2864618502397205, 0.13584345801229672 +2.3389340996536494, 0.1361342607904449 +2.39261054014484, 0.1363883882053626 +2.4475188068188323, 0.13654339323851383 +2.503687168982065, 0.13682322325057913 +2.5611445446962087, 0.137016181800735 +2.619920515666524, 0.13723442627879667 +2.6800453424718813, 0.13746554692048193 +2.7415499801443097, 0.13772215950188732 +2.804466094106063, 0.13784098523287586 +2.8688260764724482, 0.1380605434885672 +2.9346630627287738, 0.13830566052238308 +3.0020109487900264, 0.13855121274469484 +3.070904408452054, 0.13879720092814993 +3.1413789112432275, 0.1388536616546033 +3.2134707406857914, 0.13908750929948482 +3.2872170129762956, 0.13929635651329716 +3.3626556960947194, 0.13946737742598111 +3.4398256293521454, 0.13957498697059087 +3.5187665433870188, 0.13972087831853472 +3.5995190806203143, 0.13991792336298212 +3.6821248161801283, 0.13994932668345522 +3.766626279306469, 0.14010837871352544 +3.853066975247277, 0.14022926325802046 +3.9414914076569194, 0.1404526256519108 +4.0319451015087315, 0.14048414898150735 +4.124474626533369, 0.14059254304165097 +4.2191276211950495, 0.14071384531979483 +4.315952817218037, 0.1409508257561632 +4.415000064675969, 0.1410081625465537 +4.516320357656978, 0.1410912394474701 +4.619965860517798, 0.14118723302243735 +4.725989934740384, 0.141257540115841 +4.834447166404851, 0.1414825403874125 +4.94964558715206, 0.14128956842667617 +5.047236548091029, 0.1417865196407708 +5.4264120573543195, 0.14187331737604328 +5.550943348732041, 0.14204750214892944 +5.678332521591724, 0.142040539859849 +5.808645161750993, 0.14209831993043176 +5.941948360163184, 0.14229871782445852 +6.078310747458853, 0.1423047127969945 +6.2178025292800045, 0.14240153197704825 +6.36049552242517, 0.14256337093178137 +6.50646319182402, 0.142569377054018 +6.655780688360489, 0.1425883788571146 +6.808524887563917, 0.14275043016281994 +6.964774429188126, 0.14283453354469686 +7.124609757698767, 0.1428275326802102 +7.288113163689856, 0.1428205321588626 +7.455368826250756, 0.1429046768422959 +7.626462856305465, 0.14298887110072833 +7.80148334094647, 0.14303399970929168 +7.980520388786055, 0.1430139536656859 +8.163666176348364, 0.14301997877074377 +8.35101499552612, 0.14299993469215572 +8.542663302126453, 0.14297989342272133 +8.738709765530775, 0.1429077449506791 +8.939255319494332, 0.14295284795508006 +9.144403214111565, 0.14294584129155355 +9.354259068973997, 0.14303005980258815 +9.568930927548084, 0.14306216161411675 +9.788529312800959, 0.14302907484286959 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure96-0Psi.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure96-0Psi.csv new file mode 100644 index 00000000..f969fd7d --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure96-0Psi.csv @@ -0,0 +1,124 @@ +0.1125329277799472, 139.93476310435227 +0.11638431969510715, 140.32399723114196 +0.12036067019933908, 140.5800843192481 +0.1244736728204126, 140.85115044920613 +0.12872640165003224, 141.1072375373123 +0.13312476900360856, 141.36931624215921 +0.13767412680227287, 141.64337818048767 +0.14237931753759764, 141.92343173555685 +0.14724210726341266, 142.15255654832956 +0.15227312552662703, 142.4146352531765 +0.15747584357385797, 142.673718149653 +0.16285527972771474, 142.91782200427767 +0.16841847951589575, 143.16192585890226 +0.17417305924892978, 143.42400456374918 +0.18012564804506734, 143.7040581188184 +0.1862811969170514, 143.9781200571468 +0.1926471032940694, 144.25218199547524 +0.19923055585756044, 144.5262439338037 +0.2060395168975742, 144.80629748887284 +0.21307981798897058, 145.07137200209016 +0.22036181309050087, 145.34842974878896 +0.2278917942018575, 145.61650007037665 +0.23567908221563175, 145.8845703919643 +0.2437312205093476, 146.14065748007044 +0.25206072618750125, 146.41771522676927 +0.2606725546391209, 146.67380231487542 +0.2695789575237298, 146.93288521135196 +0.2787925230467558, 147.21593457479153 +0.2883180311498568, 147.47501747126805 +0.2981743455705046, 147.7760416849299 +0.3069600685694588, 148.05668141128356 +0.32480585428477154, 148.50905889959768 +0.3358914509026416, 148.68425916170358 +0.34736607873322656, 148.9313588246986 +0.3592368417107278, 149.205420763027 +0.37151184393771874, 149.47049527624432 +0.3842067711043753, 149.738565597832 +0.3973380417809778, 150.02161496127152 +0.4109144227634486, 150.28369366611847 +0.4249535972538959, 150.5397807542246 +0.43947411894598815, 150.8048552674419 +0.4544908019873971, 151.06992978065918 +0.470021804404815, 151.34099591061727 +0.48608166884182175, 151.60307461546418 +0.5026889841061163, 151.8591617035703 +0.5198650318193573, 152.1212404084172 +0.5376265789661104, 152.37732749652338 +0.5559970986006543, 152.64240200974064 +0.5749953327211382, 152.90747652295795 +0.5946404445986345, 153.1635636110641 +0.6576996360788591, 153.94680391723446 +0.6801721403259127, 154.20888262208138 +0.7034151963117963, 154.4799487520394 +0.7274487933361637, 154.73903164851592 +0.7523093296351117, 155.01608939521478 +0.7780154867560815, 155.28116390843206 +0.8045969221347244, 155.53725099653823 +0.8320929268969612, 155.81131293486663 +0.8605230577737528, 156.07039583134315 +0.8899245613368684, 156.32947872781972 +0.9203318055972288, 156.5915574326666 +0.9517950865820364, 156.89557745469884 +1.0463125575005403, 157.61918385377916 +1.0820189587241795, 157.7853966907739 +1.1189797141930589, 158.02650473702812 +1.157207462245976, 158.27660020839355 +1.197819397043265, 158.59870930341546 +1.2376388219007906, 158.80195594143552 +1.2917113638206588, 159.14030395008783 +1.3358487072847118, 159.4053784633051 +1.3814853592911516, 159.6554739346705 +1.4286829284312303, 159.90856521440628 +1.4774948654493565, 160.16465230251245 +1.5279744959409944, 160.4207393906186 +1.5801767733168877, 160.67383067035433 +1.632206744700665, 160.9740125935686 +1.687986053819805, 161.24927285524518 +1.7477861352847404, 161.50799971882117 +1.807454139377084, 161.70417063951973 +1.8692094506833803, 161.96325353599624 +1.9330772332011723, 162.22533224084316 +1.999119588086452, 162.47842352057893 +2.0674235355068507, 162.73750641705547 +2.138061224870956, 162.99658931353198 +2.2167114084196506, 163.06803809289374 +2.2866624313979313, 163.51775091485544 +2.3647878295264517, 163.77383800296158 +2.445591835417286, 164.0389125161789 +2.5291601273482334, 164.30698283776655 +2.61558738149753, 164.5780489677246 +2.7049126068318006, 164.80118216375658 +2.7674928533582683, 164.8974874596031 +2.9105632205834784, 165.310377852118 +3.0101276391869494, 165.66203122723925 +3.112978701351275, 165.9241099320862 +3.2193357644093323, 166.18019702019234 +3.329343651697685, 166.44826734178 +3.443097383633086, 166.7073502382565 +3.5607286170928707, 166.9604415179923 +3.682402235826278, 167.22851183957997 +3.808218925430821, 167.4875947360565 +3.938329349962511, 167.74368182416265 +4.072911177333688, 168.0147479541207 +4.2120757879091, 168.2768266589676 +4.355989841306703, 168.53590955544416 +4.504809465290305, 168.78900083517993 +4.658725354409579, 169.04808373165645 +4.817906262486399, 169.31016243650333 +4.9821750380072, 169.40747168097937 +5.097234167103203, 169.4086600610663 +5.442003496433254, 169.40937052311563 +5.576285884609125, 169.46216603251224 +5.980655982419762, 169.4439409970085 +6.137346664267959, 169.41378190974524 +6.592569721362353, 169.44541644866842 +6.7550746341433445, 169.44009327567971 +7.222964470204694, 169.44118254390514 +7.412253761427326, 169.42700110128393 +7.961904003818676, 169.41869152860204 +8.15813333993587, 169.40498009217626 +8.749742209490831, 169.39035002671696 +8.979140926058093, 169.40163295524397 +9.615956639761682, 169.4638660094248 +9.900375069051924, 169.49204530327026 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure96-14Psi.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure96-14Psi.csv new file mode 100644 index 00000000..260f5ab2 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure96-14Psi.csv @@ -0,0 +1,108 @@ +0.12217984676706929, 125.83073180075561 +0.12635452921291473, 126.09281050560253 +0.1306708491463444, 126.33691436022713 +0.1351344431187676, 126.57802240648138 +0.1397515835602277, 126.8371053029579 +0.14452573725118695, 127.08420496595295 +0.14946279272895102, 127.32830882057755 +0.15456909403446292, 127.58140010031335 +0.15985046326687072, 127.84347880516023 +0.16531122914705254, 128.09057846815526 +0.17095963929555286, 128.35265717300217 +0.17679946065182697, 128.59376521925643 +0.18283853059430522, 128.83187745714028 +0.18908533501973204, 129.08796454524645 +0.19554531529599636, 129.3410558249822 +0.20222625577933984, 129.5971429130884 +0.20913545519936208, 129.8532300011945 +0.2162798809004146, 130.10032966418953 +0.22366837243214704, 130.34742932718456 +0.23130867480664008, 130.58853737343878 +0.23921118864687957, 130.84162865317458 +0.24738463767728952, 131.10370735802147 +0.25583670434180505, 131.3597944461276 +0.3017042560500024, 132.5864464661503 +0.31201298940412103, 132.84852517099722 +0.3226714746522804, 133.09262902562185 +0.33369405790803336, 133.33673288024647 +0.3450958296624816, 133.59881158509342 +0.3568876382572226, 133.8638860983107 +0.3690800047009126, 134.11398156967607 +0.3816879214194061, 134.35808542430073 +0.3947280466295416, 134.61117670403647 +0.4082131564349999, 134.86127217540187 +0.4221589585779245, 135.11136764676726 +0.4375201227954081, 135.45700083369255 +0.6513400825909186, 138.34477505445386 +0.6735935654709304, 138.60086214256 +0.6966055689811614, 138.85095761392537 +0.716021432999465, 139.06966537140715 +0.7611355103478388, 139.58083789006398 +0.7871119931729718, 139.7530423437995 +0.8140042169634241, 140.00912943190568 +0.8418141536030425, 140.26222071164142 +0.870573083691889, 140.51231618300685 +0.900313352781335, 140.75941584600181 +0.9310731790506921, 141.01550293410796 +0.9628901041268354, 141.28656906406604 +0.9957866324600371, 141.53966034380178 +1.0298044110472697, 141.78676000679684 +1.0649829308409455, 142.03086386142144 +1.101791386801456, 142.2348716400478 +1.2161703822554026, 142.79839221116535 +1.2597403237425744, 143.24539151780382 +1.3027785511320364, 143.4984827975396 +1.3472888783158636, 143.75456988564576 +1.3933235016896426, 144.01664859049268 +1.4409310516890868, 144.2787272953396 +1.4901690909383372, 144.54679761692725 +1.5410797706838384, 144.79988889666302 +1.5937440744463807, 145.07395083499145 +1.6481869927981772, 145.3180546896161 +1.7045006212404006, 145.57713758609265 +1.7627270263707284, 145.82124144071724 +1.8229448036918343, 146.06834110371227 +1.8852221388266877, 146.31843657507764 +1.9496320526531443, 146.57452366318378 +2.0162451587460173, 146.83360655966035 +2.085128892940703, 147.08669783939612 +2.1563577080883167, 147.33080169402072 +2.230028298466819, 147.58389297375652 +2.3062098884055193, 147.8309926367515 +2.384993972065745, 148.07809229974654 +2.466488415060654, 148.34316681296383 +2.550751155940074, 148.5932622843292 +2.637885808953188, 148.83736613895385 +2.727993520609653, 149.07847418520808 +2.8212009140569183, 149.33755708168462 +2.9175966637959876, 149.59963578653154 +3.0172706335462394, 149.84973125789693 +3.120345771335711, 150.09683092089196 +3.2269379982697717, 150.34093477551656 +3.3371629061950823, 150.57904701340044 +3.4324616432335846, 150.93125400364454 +3.5692193354802324, 151.1751038239834 +3.6741659144406853, 151.31531503297546 +4.008389098903174, 152.029537880249 +4.145179151168056, 152.19575071724375 +4.286780085533257, 152.43985457186835 +4.433206803517089, 152.6779668097522 +4.584670369697731, 152.93405389785838 +4.741296644129227, 153.18414936922377 +4.903248620376036, 153.42226160710766 +5.070349230915326, 153.4836211511391 +5.163734474721055, 153.44982047811226 +5.487933643923063, 153.47096434189976 +5.623209600924136, 153.46564116891105 +6.031055052116803, 153.47557673208885 +6.189128281524547, 153.46888481039358 +6.648099844287501, 153.46806475863767 +6.811975303802782, 153.463340747323 +7.3060200827550785, 153.466685532086 +7.486124765438618, 153.46555649081577 +8.029029937417032, 153.45931468879357 +8.239461052044124, 153.45012626012294 +8.85050138025064, 153.45479852371273 +9.082462262819462, 153.44561009504213 +9.696816509581428, 153.45356042731981 +9.905658510666726, 153.4525725162084 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi0-h_over_deltastar0p25.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi0-h_over_deltastar0p25.csv new file mode 100644 index 00000000..7bc25c27 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi0-h_over_deltastar0p25.csv @@ -0,0 +1,112 @@ +0.17387577242435007, -29.338640931990696 +0.1789630581766478, -28.850036763454398 +0.18420004498254888, -28.349877694980933 +0.18958922369285977, -27.863584506432062 +0.19541875176191126, -27.338816653805466 +0.20142650569698023, -26.826654146564863 +0.2076175166931173, -26.33171894468518 +0.21400007987744565, -25.822077506521808 +0.22026071472375852, -25.340406277947807 +0.22638018849069347, -24.857526218717794 +0.2303379855173751, -24.492517917542173 +0.23898427931944846, -23.865494225538214 +0.2454226822594713, -23.442598685737437 +0.25259763578421696, -23.00971481245378 +0.26036220430955365, -22.50742649243223 +0.2668212171914836, -22.110716338075235 +0.27621870470904, -21.50413874757814 +0.28471111539758465, -20.986513924003617 +0.29304069473478805, -20.50253171544219 +0.3016167709762666, -19.995439707006412 +0.3099971896712911, -19.507424136693203 +0.3186097669150355, -19.024800853017368 +0.3279347529001614, -18.513086884606693 +0.3375298353303361, -18.022171736082953 +0.34740792275497345, -17.515079727647176 +0.3575731055064816, -17.021853599135994 +0.36856702611938774, -16.50254806284333 +0.3799001212609559, -15.975679319319056 +0.39101348308689, -15.498630050719953 +0.40245456791409273, -15.005403922208785 +0.41422810867366733, -14.526043673622212 +0.4269643736319206, -14.004217068252345 +0.44072656047047376, -13.461983460524706 +0.454274500742019, -12.956963982336205 +0.46824230896493224, -12.433876842427736 +0.4826382460775249, -11.917722642481593 +0.49747509881490387, -11.409972006126111 +0.512768660258704, -10.8992801225139 +0.5277698571944774, -10.417608893939914 +0.5432139594960353, -9.91744982546642 +0.5591094818683128, -9.419601736980383 +0.5762869662748114, -8.955759720386169 +0.5948526594259117, -8.453443039714259 +0.6131363647609236, -7.956827125116433 +0.6310709141070632, -7.486710796479613 +0.6495385139379625, -6.984240748018706 +0.6695014878764222, -6.493507327934324 +0.6910836218158768, -5.942870156616024 +0.7123300705330192, -5.429026936657294 +0.7331660860345541, -4.9589106080204886 +0.7557137786278598, -4.420486964559046 +0.7789423888602262, -3.9219802481533037 +0.8028916355571843, -3.4028848009504173 +0.8275821893115693, -2.8688730283740824 +0.8530233746825944, -2.360071946569775 +0.8805193101569471, -1.815737447944457 +0.9105027815760545, -1.4728719354393718 +0.9358286280792989, -1.1509937345942802 +0.9648457255908998, -0.780296199230861 +0.9964754933571723, -0.4405763194740757 +1.0137556202487346, -0.42174815176993263 +1.0687931302081373, -0.717344602456464 +1.0930900279888272, -1.289717793184792 +1.1024982375130963, -1.8537228219664712 +1.1117567639331483, -2.424854922836971 +1.121091303861592, -2.9998386570198647 +1.130502466468854, -3.578674024515138 +1.1399837986859775, -4.176767558572408 +1.1495464307886454, -4.77100945931727 +1.1591874815006882, -5.369102993374526 +1.1689166363795382, -5.9517899941822066 +1.178738409627834, -6.511367195115511 +1.188635341319022, -7.086350929298419 +1.198622800162541, -7.645928130231738 +1.2086829388805722, -8.228615131039433 +1.2188369578744964, -8.792043965285146 +1.2290800893637353, -9.34776953290607 +1.2393900961663302, -9.942011433650919 +1.249780776624609, -10.547808234332976 +1.2602624757745136, -11.145901768390232 +1.2708498090649094, -11.709330602635958 +1.2807270691054193, -12.297442053130169 +1.291474885974437, -12.88288022058957 +1.3031242273374197, -13.44583670512182 +1.3140655281024989, -14.020820439304714 +1.3251130698097318, -14.568842740300866 +1.3362307098768293, -15.15923300773332 +1.3474541560768938, -15.726513475291426 +1.358750813692024, -16.332310275973455 +1.3701506729430326, -16.922700543405938 +1.381659024195622, -17.489981010964044 +1.3932618786436002, -18.061113111834544 +1.4049578163868066, -18.63994847932983 +1.4167409590187856, -19.238042013387087 +1.4286207107933038, -19.839987180756737 +1.4396919991869912, -20.48367219761549 +1.4526911511640845, -21.024619348934067 +1.4648905170638136, -21.59575144980458 +1.477174015757615, -22.19769661717423 +1.4895789831186108, -22.768828718044716 +1.5020811407612036, -23.351515718852397 +1.514685882572957, -23.938054352972472 +1.5273774601922188, -24.555406053591696 +1.537999330628427, -25.127456892683497 +1.5531214541371354, -25.724631688519466 +1.566173919580281, -26.280357256140377 +1.5793311829250714, -26.84378609038609 +1.592579233544731, -27.438027991130966 +1.6059433917841592, -28.02456662525104 +1.6194222053796143, -28.607253626058736 +1.6330192094433869, -29.1822373602416 +1.6468145981500077, -29.63011719511553 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi0-h_over_deltastar0p43.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi0-h_over_deltastar0p43.csv new file mode 100644 index 00000000..4d1da44d --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi0-h_over_deltastar0p43.csv @@ -0,0 +1,107 @@ +0.3703999540606767, -29.087368804870536 +0.3779834689889374, -28.545869797646247 +0.3846159806278393, -28.024228408433316 +0.3913636605047004, -27.51029028584513 +0.39822972127578826, -26.996352163256958 +0.40521435580408316, -26.49396894060598 +0.4123227733321917, -25.98388245133019 +0.4195545888536253, -25.481499228679212 +0.42691787613012044, -24.952154572841465 +0.43440702470118825, -24.442068083565673 +0.44203029085927076, -23.916575061040334 +0.44978524397828923, -23.402636938452147 +0.45767554022861684, -22.892550449176383 +0.4652986614464568, -22.41239766267364 +0.4738767418227489, -21.85697093737525 +0.48218965988571244, -21.346884448099473 +0.49064612496813675, -20.84835285876086 +0.4992578601145178, -20.315156569610735 +0.5077680771661726, -19.831970937375246 +0.5154438567652561, -19.32158156736716 +0.5244883988145169, -18.799940178154202 +0.5336949547627129, -18.262892255691668 +0.5430605921857741, -17.73739923316633 +0.5525914405069267, -17.208054577328582 +0.5622878147174795, -16.686413188115623 +0.5721525586789237, -16.172475065527465 +0.5821912713990064, -15.654685309626885 +0.5924070366385544, -15.133043920413925 +0.6028020588758563, -14.611402531200952 +0.6133775823259412, -14.097464408612794 +0.6241396094190761, -13.579674652712228 +0.6350924303723655, -13.054181630186875 +0.6468496876427197, -12.548067926516424 +0.65567610223407, -12.083716427817663 +0.6671740748124683, -11.589036471791474 +0.6788778849558323, -11.078949982515695 +0.6907880781716339, -10.565011859927509 +0.7029148486944786, -10.024112304152595 +0.7152478534598805, -9.506322548252015 +0.7288435971522573, -8.977159620853655 +0.7426943215963902, -8.459551593392462 +0.7557241065791005, -7.945613470804304 +0.7689824853341862, -7.431675348216132 +0.7824758936510455, -6.910033959003158 +0.7962060720783795, -6.388392569790213 +0.8101771752436837, -5.866751180577253 +0.8231997000576731, -5.387296029361252 +0.8364380262272153, -4.888582711583268 +0.8511164023493729, -4.363089689057915 +0.8634681164099848, -3.8911430456903844 +0.8773857672274353, -3.454063599538287 +0.8923188727969898, -2.79649190756696 +0.9286047198959859, -1.5310856155899586 +0.9547356760815542, -0.9429310090630878 +0.9895439598757528, -0.5862351054628192 +1.0224956319936085, -0.44174654048522655 +1.055165212511616, -0.578100692704723 +1.082548424906529, -0.9682358570557597 +1.0989187468352513, -1.6311879345932283 +1.1115517461579287, -2.3747577285702306 +1.121091303861592, -2.9998386570198647 +1.130502466468854, -3.578674024515138 +1.1399837986859775, -4.176767558572408 +1.1495464307886454, -4.77100945931727 +1.1591874815006882, -5.369102993374526 +1.1689166363795382, -5.9517899941822066 +1.178738409627834, -6.511367195115511 +1.188635341319022, -7.086350929298419 +1.198622800162541, -7.645928130231738 +1.2086829388805722, -8.228615131039433 +1.2188369578744964, -8.792043965285146 +1.2290800893637353, -9.34776953290607 +1.2393900961663302, -9.942011433650919 +1.249780776624609, -10.547808234332976 +1.2602624757745136, -11.145901768390232 +1.270841930852339, -11.724737135885519 +1.2807236664808042, -12.304044853094283 +1.291474885974437, -12.88288022058957 +1.3031242273374197, -13.44583670512182 +1.3140655281024989, -14.020820439304714 +1.3251130698097318, -14.568842740300866 +1.3362307098768293, -15.15923300773332 +1.3474541560768938, -15.726513475291426 +1.358750813692024, -16.332310275973455 +1.3701506729430326, -16.922700543405938 +1.381659024195622, -17.489981010964044 +1.3932618786436002, -18.061113111834544 +1.4049578163868066, -18.63994847932983 +1.4167409590187856, -19.238042013387087 +1.4286207107933038, -19.839987180756737 +1.4396919991869912, -20.48367219761549 +1.4526911511640845, -21.024619348934067 +1.4648905170638136, -21.59575144980458 +1.477174015757615, -22.19769661717423 +1.4895766745753303, -22.772680351357124 +1.5020811407612036, -23.351515718852397 +1.514685882572957, -23.938054352972472 +1.5273774601922188, -24.555406053591696 +1.537999330628427, -25.127456892683497 +1.5531214541371354, -25.724631688519466 +1.566173919580281, -26.280357256140377 +1.5793311829250714, -26.84378609038609 +1.592579233544731, -27.438027991130966 +1.6059433917841592, -28.02456662525104 +1.6194222053796143, -28.607253626058736 +1.6330192094433869, -29.1822373602416 +1.6451692333656143, -29.741693408882014 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi0-h_over_deltastar0p50.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi0-h_over_deltastar0p50.csv new file mode 100644 index 00000000..cd11fa14 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi0-h_over_deltastar0p50.csv @@ -0,0 +1,103 @@ +0.5142815594855304, -29.13820905670005 +0.5218589378157413, -28.52260519206429 +0.5291708750628704, -27.951732222486967 +0.5355592206756173, -27.392171848261015 +0.5420224486777092, -26.842882496201426 +0.549000691851448, -26.291768287729738 +0.5562583455710247, -25.684460616994727 +0.5644272314182294, -25.04382546488131 +0.5718868259878831, -24.445183969099205 +0.5792503796284539, -23.89053909675782 +0.586436252377224, -23.304057673442728 +0.5938540383127279, -22.79794493129839 +0.6087993115243667, -21.565211985566933 +0.6035564467423613, -22.180407175372196 +0.6202446082226324, -20.833160024694635 +0.6285511363476676, -20.198012398382147 +0.6353533139950547, -19.66012217902599 +0.64268056021206, -19.127135923240814 +0.6502343828804421, -18.55951092884972 +0.6578685788585356, -18.023661909285863 +0.6655916318646724, -17.49070161470631 +0.6743869832289664, -16.896682078899076 +0.6840691677233532, -16.269615647058444 +0.6918310756738807, -15.713174103039776 +0.7018828791483789, -15.099097047937931 +0.7107485744305615, -14.51193776071726 +0.7190907408635492, -13.984754916106283 +0.7277765686063317, -13.409146069745333 +0.737975210464077, -12.833137589084828 +0.7471401744157569, -12.213275343728995 +0.7576109494595785, -11.634699107526899 +0.7658119594756918, -11.089839265986413 +0.774634851654473, -10.585327585046414 +0.7846094738615588, -10.029077865491558 +0.7943462053915239, -9.432325420010088 +0.8054668970545793, -8.889697761390323 +0.8146045818315131, -8.338391728454852 +0.8214274543144007, -7.881563922050162 +0.8326225855806688, -7.331840489479532 +0.8423529905779681, -6.758095993754381 +0.8530049041702388, -6.225249279449443 +0.8619960096900448, -5.673362666216917 +0.8717357013716379, -5.036345861945165 +0.8916556127948867, -4.312994996799489 +0.9044094392396256, -3.6692136794002153 +0.9194839280057191, -2.6881043379638214 +0.9324145163336787, -2.1490796139218276 +0.9549696492500198, -1.0975918909527564 +0.9426460759941665, -1.6828660971069382 +0.9826062142776181, -0.7000717469802566 +1.0166571872967676, -0.43681784493237785 +1.049156188718658, -0.5353559609938117 +1.077946930581162, -0.8773148472289733 +1.0954745810843738, -1.3652700937963118 +1.1024982375130963, -1.8537228219664712 +1.1117567639331483, -2.424854922836971 +1.121091303861592, -2.9998386570198647 +1.130502466468854, -3.578674024515138 +1.1399837986859775, -4.176767558572408 +1.1495464307886454, -4.77100945931727 +1.1591874815006882, -5.369102993374526 +1.1689166363795382, -5.9517899941822066 +1.178738409627834, -6.511367195115511 +1.188635341319022, -7.086350929298419 +1.198622800162541, -7.645928130231738 +1.2086829388805722, -8.228615131039433 +1.2188369578744964, -8.792043965285146 +1.2290800893637353, -9.34776953290607 +1.2393900961663302, -9.942011433650919 +1.249780776624609, -10.547808234332976 +1.2602624757745136, -11.145901768390232 +1.2708498090649094, -11.709330602635958 +1.2807270691054193, -12.297442053130169 +1.291474885974437, -12.88288022058957 +1.3031242273374197, -13.44583670512182 +1.3140655281024989, -14.020820439304714 +1.3251130698097318, -14.568842740300866 +1.3362307098768293, -15.15923300773332 +1.3474541560768938, -15.726513475291426 +1.358750813692024, -16.332310275973455 +1.3701506729430326, -16.922700543405938 +1.381659024195622, -17.489981010964044 +1.3932618786436002, -18.061113111834544 +1.4049578163868066, -18.63994847932983 +1.4167409590187856, -19.238042013387087 +1.4286207107933038, -19.839987180756737 +1.4396919991869912, -20.48367219761549 +1.4526911511640845, -21.024619348934067 +1.4648905170638136, -21.59575144980458 +1.477174015757615, -22.19769661717423 +1.4895766745753303, -22.772680351357124 +1.5020811407612036, -23.351515718852397 +1.514685882572957, -23.938054352972472 +1.5273774601922188, -24.555406053591696 +1.537999330628427, -25.127456892683497 +1.5531214541371354, -25.724631688519466 +1.566173919580281, -26.280357256140377 +1.5793311829250714, -26.84378609038609 +1.592579233544731, -27.438027991130966 +1.6059433917841592, -28.02456662525104 +1.6194222053796143, -28.607253626058736 +1.6330192094433869, -29.1822373602416 +1.6444544588675942, -29.635327753313504 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi0-h_over_deltastar0p54.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi0-h_over_deltastar0p54.csv new file mode 100644 index 00000000..29f0e9ec --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi0-h_over_deltastar0p54.csv @@ -0,0 +1,103 @@ +0.5814820618389084, -29.361267637097043 +0.5874726583710137, -28.802127089219454 +0.5926632449001352, -28.294801862619792 +0.5980355245154099, -27.73137879753088 +0.6040683220005763, -27.191745571674815 +0.6102953920474721, -26.617198490547636 +0.6165818762709528, -26.06190957598244 +0.622296746685317, -25.504565038732906 +0.62981959099178, -24.876315761480058 +0.6358655480805334, -24.267013116321664 +0.64162802050607, -23.709092384536177 +0.6490556511337859, -23.068810629334322 +0.6567088301092334, -22.408746435445778 +0.6684688440294948, -21.828335505679604 +0.6721338307211979, -21.146366586148986 +0.6772330978776508, -20.666617352164792 +0.6832190879379242, -20.150818532277867 +0.6892641831622235, -19.61268023917907 +0.6953616874775148, -19.07839357939264 +0.7025431976462493, -18.456663990188673 +0.7106781202371348, -17.808954085027196 +0.7171169869482701, -17.25653568654512 +0.7236061805563268, -16.731628954580145 +0.7319763669639183, -16.113218974259397 +0.7395254221500003, -15.527116993195037 +0.747159569754068, -14.916942303928238 +0.7548625808615647, -14.339506497816771 +0.7615392143860492, -13.809071471342747 +0.7682689482918795, -13.297894611430706 +0.7750569517792303, -12.790569384831059 +0.7828742733982785, -12.25478779228736 +0.7901397184057448, -11.668280888529708 +0.7990993061465702, -11.101841996720637 +0.8065678261431848, -10.556943117219106 +0.815796595219653, -10.043012061848003 +0.8242005292334649, -9.485797330626596 +0.8349020156342855, -8.744801638263695 +0.8462413305147265, -7.961895834171443 +0.8561767819949962, -7.426046814607588 +0.8777453751246587, -5.675660382117115 +0.8637334592290604, -6.941831387882289 +0.8876630188637893, -5.038643577845363 +0.8963737509300878, -4.496774803727092 +0.9214446609317533, -2.900284572203489 +0.9019534678306482, -3.9162322708098287 +0.9125849103535563, -3.4227380429251753 +0.9321074250016279, -2.3077332065592344 +0.9479322279820779, -1.7041997751389886 +0.9593410301038716, -1.2739218982161589 +0.972260234595403, -0.8664287346734767 +1.0050699244043944, -0.4521711445986938 +1.0372257020780513, -0.48558164283240046 +1.0687931302081373, -0.717344602456464 +1.0930900279888272, -1.289717793184792 +1.1024982375130963, -1.8537228219664712 +1.1117567639331483, -2.424854922836971 +1.121091303861592, -2.9998386570198647 +1.130502466468854, -3.578674024515138 +1.1399837986859775, -4.176767558572408 +1.1495464307886454, -4.77100945931727 +1.1591874815006882, -5.369102993374526 +1.1689166363795382, -5.9517899941822066 +1.178738409627834, -6.511367195115511 +1.188635341319022, -7.086350929298419 +1.198622800162541, -7.645928130231738 +1.2086829388805722, -8.228615131039433 +1.2188369578744964, -8.792043965285146 +1.2290800893637353, -9.34776953290607 +1.2393900961663302, -9.942011433650919 +1.249780776624609, -10.547808234332976 +1.2602624757745136, -11.145901768390232 +1.2708498090649094, -11.709330602635958 +1.2807270691054193, -12.297442053130169 +1.291474885974437, -12.88288022058957 +1.3031242273374197, -13.44583670512182 +1.3140655281024989, -14.020820439304714 +1.3251130698097318, -14.568842740300866 +1.3362307098768293, -15.15923300773332 +1.3474541560768938, -15.726513475291426 +1.358750813692024, -16.332310275973455 +1.3701506729430326, -16.922700543405938 +1.381659024195622, -17.489981010964044 +1.3932618786436002, -18.061113111834544 +1.4049578163868066, -18.63994847932983 +1.4167409590187856, -19.238042013387087 +1.4286207107933038, -19.839987180756737 +1.4396919991869912, -20.48367219761549 +1.4526911511640845, -21.024619348934067 +1.4648905170638136, -21.59575144980458 +1.477174015757615, -22.19769661717423 +1.4895766745753303, -22.772680351357124 +1.5020811407612036, -23.351515718852397 +1.514685882572957, -23.938054352972472 +1.5273774601922188, -24.555406053591696 +1.537999330628427, -25.127456892683497 +1.5531214541371354, -25.724631688519466 +1.566173919580281, -26.280357256140377 +1.5793311829250714, -26.84378609038609 +1.592579233544731, -27.438027991130966 +1.6059433917841592, -28.02456662525104 +1.6194222053796143, -28.607253626058736 +1.6330192094433869, -29.1822373602416 +1.6467252725801655, -29.764924361049296 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi0-h_over_deltastar1p20.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi0-h_over_deltastar1p20.csv new file mode 100644 index 00000000..715bbed3 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi0-h_over_deltastar1p20.csv @@ -0,0 +1,95 @@ +0.7597071920552536, -28.854503978909676 +0.7636938181195133, -28.142089397394983 +0.7676283677678299, -27.573551109424315 +0.770650620334218, -26.959958014464007 +0.7811045868046581, -25.5056761783337 +0.7846775720003718, -24.840659127270243 +0.7888082182889667, -24.24910655502758 +0.801815229920217, -21.62046972993153 +0.7918166883241854, -23.686259504188484 +0.7970612066947804, -23.097909942430718 +0.8013720649842866, -22.347344938990602 +0.8110826170093904, -20.88627857445681 +0.8172239945065928, -19.934733321831857 +0.8112162305831265, -20.476904976682434 +0.820974566803962, -19.232278394971928 +0.8251978250233771, -18.68302028289645 +0.8284245060852055, -18.136115467573575 +0.8321700947080115, -17.602053949131502 +0.8359416871397842, -17.041030997502688 +0.8402548944090759, -16.45345463630217 +0.8431485717102841, -15.875015898337281 +0.849158976679323, -15.226242004412853 +0.8550207715045977, -14.342991645443092 +0.8627461286488652, -13.343427681519557 +0.8564236210124344, -13.82782483668423 +0.8685024723443219, -12.578307683057986 +0.8715432109829504, -12.027389265345406 +0.8745941309143005, -11.477791407625617 +0.8801556574488945, -10.977417726518965 +0.8860101647672596, -10.09329194608027 +0.8939742317246505, -9.208506654866042 +0.9006637499512085, -8.476321089937386 +0.9064771461593485, -7.909377829594561 +0.9111252869543026, -7.40092502129724 +0.9146716790178426, -6.898258965733859 +0.91881149231321, -6.352642547354591 +0.9229574548686219, -5.840920502124419 +0.9271321833058616, -5.3022370237074625 +0.9313368607789811, -4.734024356562173 +0.9358185366616146, -4.192552692737351 +0.9480008677732671, -2.4789741568852435 +0.9437674201332883, -3.1027878179280606 +0.9411444486929551, -3.613187283960542 +0.9645124284449472, -1.0706932821868236 +0.9565177723058793, -1.731698615490771 +0.9907412341207132, -0.5469948414976784 +1.0224956319936085, -0.44174654048522655 +1.055165212511616, -0.578100692704723 +1.0815635661194936, -0.857517805364111 +1.0989187468352513, -1.6311879345932283 +1.1115517461579287, -2.3747577285702306 +1.121091303861592, -2.9998386570198647 +1.130502466468854, -3.578674024515138 +1.1399837986859775, -4.176767558572408 +1.1495464307886454, -4.77100945931727 +1.1591874815006882, -5.369102993374526 +1.1689166363795382, -5.9517899941822066 +1.178738409627834, -6.511367195115511 +1.188635341319022, -7.086350929298419 +1.198622800162541, -7.645928130231738 +1.2086829388805722, -8.228615131039433 +1.2188369578744964, -8.792043965285146 +1.2290800893637353, -9.34776953290607 +1.2393900961663302, -9.942011433650919 +1.249780776624609, -10.547808234332976 +1.2602624757745136, -11.145901768390232 +1.2708498090649094, -11.709330602635958 +1.2807270691054193, -12.297442053130169 +1.291474885974437, -12.88288022058957 +1.3031242273374197, -13.44583670512182 +1.3140655281024989, -14.020820439304714 +1.3251130698097318, -14.568842740300866 +1.3362307098768293, -15.15923300773332 +1.3474541560768938, -15.726513475291426 +1.358750813692024, -16.332310275973455 +1.3701506729430326, -16.922700543405938 +1.381659024195622, -17.489981010964044 +1.3932618786436002, -18.061113111834544 +1.4049578163868066, -18.63994847932983 +1.4167409590187856, -19.238042013387087 +1.4286207107933038, -19.839987180756737 +1.4396919991869912, -20.48367219761549 +1.4506326016647646, -20.98977292068315 +1.4586040096930994, -21.60676116442363 +1.4761052901643723, -22.2168639195165 +1.4896390064997242, -22.668686251922495 +1.5413382686749726, -25.07655778562078 +1.55283573240556, -25.673434027592037 +1.566173919580281, -26.280357256140377 +1.5793311829250714, -26.84378609038609 +1.59035498840713, -27.352340003156456 +1.6056507965262385, -27.96896709768089 +1.6194222053796143, -28.607253626058736 +1.633337765846735, -29.205923354651958 +1.6398490264882613, -29.487061577238833 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi14-h_over_deltastar0p25.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi14-h_over_deltastar0p25.csv new file mode 100644 index 00000000..f94db8ea --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi14-h_over_deltastar0p25.csv @@ -0,0 +1,119 @@ +0.11531540688073041, -14.235230777850227 +0.11901203725537667, -14.013867348118957 +0.12282686226539874, -13.798725896472469 +0.1267638624497299, -13.585658437520884 +0.1308271653222163, -13.370516985874389 +0.13502071375455305, -13.155375534227886 +0.13934891492681575, -12.936086097191549 +0.14381574032392017, -12.718870652850121 +0.14842513116875936, -12.512025171983318 +0.15318238374531115, -12.303105698421575 +0.15809250882242823, -12.087964246775073 +0.16316015957428984, -11.87074880243366 +0.16838941167775753, -11.66597731426176 +0.17378712934983775, -11.448761869920347 +0.17935712329606224, -11.241916389053529 +0.18510594782542794, -11.030922922796876 +0.19103887670541903, -10.82200344923514 +0.1971616363941962, -10.617231961063247 +0.20348113812751661, -10.406238494806594 +0.210002669930045, -10.201467006634694 +0.216733396219025, -9.99462152576789 +0.2236800332168759, -9.785702052206155 +0.2308487433719573, -9.583004556729186 +0.2382477988455976, -9.374085083167444 +0.24588482507753237, -9.15686963882603 +0.25376559848275587, -8.950024157959213 +0.26189633668113493, -8.768066589431463 +0.27028736129923997, -8.58818301359863 +0.27895536706011, -8.335709693443533 +0.28789271434459895, -8.157900110305626 +0.29737243291530413, -7.972073622420801 +0.30664761540485613, -7.704803287368492 +0.31647482191758897, -7.506253777281366 +0.32661805202218974, -7.299408296414555 +0.33708609851113625, -7.094636808242662 +0.3478896439004534, -6.8898653200707685 +0.3590412362725955, -6.672649875729348 +0.3705484396542841, -6.467878387557448 +0.3824263590623718, -6.250662943216035 +0.39468338012499665, -6.043817462349217 +0.407332907442863, -5.839045974177331 +0.4203882000703597, -5.632200493310513 +0.4338622851675983, -5.423281019748785 +0.44776786212786884, -5.216435538881967 +0.4621187370044729, -5.011664050710078 +0.47692995218008194, -4.804818569843263 +0.4922162869535623, -4.595899096281531 +0.5079934188995022, -4.382831637329954 +0.5242727636457913, -4.186356119937749 +0.5410778608187582, -3.9712146682912497 +0.5584193034185247, -3.7664431801193565 +0.5763170162763901, -3.559597699252542 +0.5947878671108755, -3.3548262110806526 +0.613851728406021, -3.1459067375189207 +0.633525031632294, -2.9432092420419487 +0.6538293884857465, -2.7384377538700555 +0.6747850585020122, -2.5315922730032447 +0.6964106305568438, -2.3309687702211974 +0.7187250678304435, -2.1448632163036017 +0.7417681063448032, -1.9131298230977265 +0.7655422711940647, -1.7062843422309122 +0.790079730905894, -1.4952908759742591 +0.8154029952745132, -1.2863714024125201 +0.843181128949621, -1.151004747509429 +0.8707920664101203, -0.983424170218477 +0.9546379042658424, -0.47406121643506793 +0.985169001162585, -0.4331351511619772 +1.0166816233360907, -0.3797651297193596 +1.0491830030453133, -0.3720229475650214 +1.082624133693019, -0.5924199618520589 +1.11067165983028, -1.0072945110398521 +1.1272151920833964, -1.584600150411724 +1.1358531261236882, -2.162677401934907 +1.1437206922206329, -2.780733360130821 +1.154980614109118, -3.3148448440508034 +1.1630026850633535, -3.8857900581815734 +1.1727439653448892, -4.483470956502636 +1.1825776798192433, -5.0583379351795585 +1.1925066067209489, -5.606588674271663 +1.2025060352627324, -6.181455652948586 +1.2125837528761867, -6.7677295914475835 +1.222742191183877, -7.361608169827953 +1.2329932677539066, -7.940277468445572 +1.2433264865547584, -8.52655140694457 +1.2537405569112066, -9.124232305265629 +1.2645142544231622, -9.69422765039102 +1.2768273033712068, -9.985109391732543 +1.2936616690941887, -11.201085336534796 +1.3017545871311689, -11.697825589519383 +1.3089659839267551, -12.18652124832579 +1.3199508237857982, -12.744658019263682 +1.3329523492537483, -13.266411963376427 +1.3572861738589441, -14.515125683793663 +1.362813888910488, -15.078227368832124 +1.3722769772938812, -15.653735366891723 +1.3854731325117333, -16.243153542433667 +1.3973547438476617, -16.856060784032557 +1.4090632568419572, -17.446137042472245 +1.420874218165509, -18.028608661030553 +1.4327907482771107, -18.599673319766787 +1.4447939739427027, -19.193551898147156 +1.4568999828802818, -19.783628156586843 +1.4691321209291965, -20.33187889567894 +1.4814148979318014, -20.9675829934069 +1.4958811305483994, -21.698464534257567 +1.5084359448255105, -22.254319913231043 +1.521077537502935, -22.84059385173004 +1.533822730655638, -23.430670110169714 +1.5467243454264268, -23.940897649854925 +1.5574673243942818, -24.51184286398569 +1.5705222289500536, -25.094314482544 +1.5836817219180728, -25.684390740983687 +1.5969514790084234, -26.274466999423367 +1.6103398056793852, -26.85313629804098 +1.6238329323339036, -27.443212556480667 +1.6374266090514795, -28.0523004146238 +1.651149220410492, -28.63857435312279 +1.664979203392674, -29.236255251443865 +1.6671149951200166, -29.605199730296214 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi14-h_over_deltastar0p43.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi14-h_over_deltastar0p43.csv new file mode 100644 index 00000000..32ccd02a --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi14-h_over_deltastar0p43.csv @@ -0,0 +1,124 @@ +0.10501417805208024, -26.43534621461975 +0.10838573390377348, -26.09576520127795 +0.11186628184316827, -25.739592246376787 +0.11545927282069769, -25.368901342611167 +0.11916786435790579, -24.994062453455705 +0.12299475706896996, -24.635815505859618 +0.12694539095088697, -24.260976616704156 +0.13102259295704066, -23.892359705633467 +0.13523074557175496, -23.523742794562764 +0.13957440361104106, -23.148903905407302 +0.14405746137824482, -22.776139008946764 +0.14868476048185605, -22.399226127096377 +0.1534606940039099, -22.022313245246004 +0.1583895082347515, -21.653696334175294 +0.16347716993907455, -21.27678345232492 +0.1687282534628483, -20.899870570474533 +0.17414800811167236, -20.522957688624146 +0.17974200160718615, -20.14397081407885 +0.18551568572085386, -19.764983939533543 +0.1914745133253906, -19.39014505037808 +0.19762490522733195, -19.013232168527693 +0.20397302511902962, -18.63424529398239 +0.2105247088105587, -18.259406404826926 +0.21728647264895817, -17.888715501061313 +0.22426578885223217, -17.513876611905843 +0.23146966891786688, -17.134889737360552 +0.23890535070207386, -16.751754877425398 +0.24657927820693937, -16.374841995575018 +0.25449970150261464, -15.99792911372463 +0.26267322481146127, -15.63346018804377 +0.2711094752950506, -15.266917269668006 +0.27687067561312384, -14.545862762267099 +0.27981923730765235, -14.877560431648085 +0.2888092937188057, -14.484055608238336 +0.29808694125878044, -14.100920748303182 +0.3076641604422867, -13.705341932198507 +0.3175467037011178, -13.328429050348127 +0.3277480519177402, -12.941146205023138 +0.33827543202315763, -12.566307315867675 +0.3491409551968112, -12.191468426712206 +0.3603554827103046, -11.81662953755675 +0.3719299147259403, -11.443864641096205 +0.3838757915877197, -11.073173737330592 +0.3962063441971949, -10.696260855480205 +0.40893296900238274, -10.319347973629824 +0.422067684792111, -9.94658307716928 +0.43562391780869447, -9.575892173403666 +0.4496178067080835, -9.192757313468519 +0.4640596852354592, -8.81791842431305 +0.47896663941785106, -8.436857557072834 +0.4943503885298363, -8.066166653307207 +0.510229092964121, -7.691327764151751 +0.5266169490480768, -7.320636860386131 +0.5435311605099052, -6.94994595662051 +0.5609914384298879, -6.566811096685363 +0.5790121239913694, -6.185750229445141 +0.597607204090553, -5.823355296459205 +0.6168015248190652, -5.452664392693585 +0.6366128712774679, -5.079899496233047 +0.6570583575054539, -4.715430570552197 +0.6781570806637764, -4.363405601040874 +0.6999449694074205, -3.9699007776311106 +0.7232718169965617, -3.6540973847275637 +0.7471350632024157, -3.137051531212016 +0.7710780114238274, -2.940634083170238 +0.796435760149012, -2.4655161574380564 +0.8219197819697193, -1.994124601425078 +0.8473873340519296, -1.6354406483874229 +0.8744180837209008, -1.2860589338506578 +0.8982340312194467, -1.0206574895195217 +0.9558420281270988, -0.5403647427135709 +1.0141937024286758, -0.3755542809373722 +1.0491830030453133, -0.3720229475650214 +1.082624133693019, -0.5924199618520589 +1.11067165983028, -1.0072945110398521 +1.1272151920833964, -1.584600150411724 +1.1358531261236882, -2.162677401934907 +1.1437206922206329, -2.780733360130821 +1.154980614109118, -3.3148448440508034 +1.1630026850633535, -3.8857900581815734 +1.1727439653448892, -4.483470956502636 +1.1825776798192433, -5.0583379351795585 +1.1925066067209489, -5.606588674271663 +1.2025060352627324, -6.181455652948586 +1.2125837528761867, -6.7677295914475835 +1.222742191183877, -7.361608169827953 +1.2329932677539066, -7.940277468445572 +1.2433264865547584, -8.52655140694457 +1.2537405569112066, -9.124232305265629 +1.2642515137919892, -9.702901603883248 +1.274846695333506, -10.289175542382239 +1.2855267423616734, -10.883054120762608 +1.2963022036908216, -11.465525739320917 +1.3071699837050745, -12.044195037938536 +1.318118805535343, -12.641875936259595 +1.3291573035226998, -13.24335915452135 +1.3402902905726477, -13.841040052842416 +1.3515062020101885, -14.457732550866929 +1.362813888910488, -15.078227368832124 +1.3722769772938812, -15.653735366891723 +1.3854731325117333, -16.243153542433667 +1.3973547438476617, -16.856060784032557 +1.4090632568419572, -17.446137042472245 +1.420874218165509, -18.028608661030553 +1.4327907482771107, -18.599673319766787 +1.4447939739427027, -19.193551898147156 +1.456904435033699, -19.776023516705465 +1.4691074287390002, -20.37370441502653 +1.4813967897951001, -20.998001552932415 +1.4938026483671496, -21.59948477119417 +1.5063377164910114, -22.159142470108343 +1.518961724763848, -22.745416408607326 +1.5316868490582785, -23.339294986987703 +1.5445303780661912, -23.914161965664633 +1.5577835213307356, -24.515119058878497 +1.5772822438677074, -25.083265856538333 +1.5860015779372207, -25.60085914689398 +1.6030139707636937, -26.505646345465784 +1.6170685892403827, -27.153877907171854 +1.6306205882541678, -27.74015184567086 +1.6443012355120703, -28.303611864525713 +1.6534193504010464, -28.778619171545643 +1.6770093149242646, -30.065029609448167 +1.667298408775813, -29.331432694566566 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi14-h_over_deltastar0p50.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi14-h_over_deltastar0p50.csv new file mode 100644 index 00000000..ee4f0762 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi14-h_over_deltastar0p50.csv @@ -0,0 +1,118 @@ +0.12171773362862881, -29.25388056981719 +0.12563028075198793, -28.820969885203922 +0.12966913481959236, -28.37768923711605 +0.13383716365525702, -27.946852545197707 +0.1381400888510139, -27.499423911719994 +0.14258076087768856, -27.062365241716883 +0.14716430606459677, -26.623232579018854 +0.15189519852578734, -26.184099916320825 +0.15677739105727273, -25.757411209792316 +0.16181691087170189, -25.324500525179054 +0.16701884077038298, -24.88536786248102 +0.17238770981717647, -24.45038318517284 +0.17792916271563994, -24.01539850786464 +0.18364721664929362, -23.601153757505678 +0.18955155752195546, -23.15372512402795 +0.19564539950444418, -22.710444475940086 +0.20193565566804011, -22.26094184976745 +0.20842745697774667, -21.819735194374495 +0.21512885234592724, -21.368158575506932 +0.22204478683404322, -20.92695192011398 +0.22918324489627953, -20.483671272026108 +0.2365511953245959, -20.040390623938237 +0.2441566264677022, -19.59088799776559 +0.2520061621372985, -19.145533356982796 +0.2601067564824692, -18.712622672369534 +0.268468858558039, -18.269342024281656 +0.27551007187494636, -17.90735816688597 +0.2895140714817313, -17.118779193756538 +0.30064404815303397, -16.571842345324576 +0.30910679542070124, -16.300384571967285 +0.3190417934585607, -15.875769858133701 +0.32882684446883725, -15.440873135489532 +0.33891064839608076, -15.015931577780997 +0.34980561249702524, -14.576798915082968 +0.3610544280590804, -14.112778340045878 +0.37266621788923193, -13.640461794229104 +0.3846447197574915, -13.211699095005677 +0.3970098975210363, -12.772566432307649 +0.4097739448480436, -12.325137798829935 +0.42294730456526525, -11.883931143436982 +0.43654379591671005, -11.444798480738953 +0.4505803780173294, -10.989073876481541 +0.46440163009900287, -10.544014589632262 +0.47863782439605584, -10.14582753768822 +0.49402212906290877, -9.719138831159711 +0.5099047384344068, -9.273784190376922 +0.5262979672004772, -8.82842954959412 +0.5432177788324828, -8.385148901506255 +0.5606801390706855, -7.948090231503144 +0.5787033646536417, -7.513105554194958 +0.5973044586136318, -7.084342854971531 +0.6165080664480507, -6.636914221493811 +0.6363312002809806, -6.181189617236413 +0.6567846090030531, -5.752426918012986 +0.6778954456937177, -5.323664218789567 +0.6996865912828009, -4.888679541481373 +0.7221776176794064, -4.4557688568681115 +0.7458238585273347, -4.003825217303753 +0.7718476951563531, -3.537847922457111 +0.7966585480626064, -3.104159490583246 +0.8207907582241852, -2.6931356725966893 +0.9016053558639586, -1.4366858357268484 +0.916897642263474, -1.1966142107045528 +0.9601315105114301, -0.43098514826357714 +0.9908275679124481, -0.41702098802447196 +1.0225228951809104, -0.3595029811920156 +1.0551899028356995, -0.40153662371579557 +1.0888079751897066, -0.655117521121575 +1.1153995013961417, -1.1141178031955619 +1.127771519134326, -1.6278262999543642 +1.1358531261236882, -2.162677401934907 +1.1437206922206329, -2.780733360130821 +1.154980614109118, -3.3148448440508034 +1.1630026850633535, -3.8857900581815734 +1.1727439653448892, -4.483470956502636 +1.1825776798192433, -5.0583379351795585 +1.1925066067209489, -5.606588674271663 +1.2025060352627324, -6.181455652948586 +1.2125837528761867, -6.7677295914475835 +1.222742191183877, -7.361608169827953 +1.2329932677539066, -7.940277468445572 +1.2433264865547584, -8.52655140694457 +1.2537405569112066, -9.124232305265629 +1.264247650366522, -9.710506243764627 +1.274846695333506, -10.289175542382239 +1.2855267423616734, -10.883054120762608 +1.2963022036908216, -11.465525739320917 +1.3071699837050745, -12.044195037938536 +1.318118805535343, -12.641875936259595 +1.3291573035226998, -13.24335915452135 +1.3402902905726477, -13.841040052842416 +1.3515062020101885, -14.457732550866929 +1.362813888910488, -15.078227368832124 +1.3722769772938812, -15.653735366891723 +1.3854731325117333, -16.243153542433667 +1.3973547438476617, -16.856060784032557 +1.4090632568419572, -17.446137042472245 +1.420874218165509, -18.028608661030553 +1.4327907482771107, -18.599673319766787 +1.4447939739427027, -19.193551898147156 +1.4568999828802818, -19.783628156586843 +1.4691051840150156, -20.377506734967213 +1.4813967897951001, -20.998001552932415 +1.4938026483671496, -21.59948477119417 +1.5063377164910114, -22.159142470108343 +1.518961724763848, -22.745416408607326 +1.5316868490582785, -23.339294986987703 +1.5445303780661912, -23.914161965664633 +1.5574673243942818, -24.51184286398569 +1.5705222289500536, -25.094314482544 +1.5836817219180728, -25.684390740983687 +1.5969514790084234, -26.274466999423367 +1.6103398056793852, -26.85313629804098 +1.6238329323339036, -27.443212556480667 +1.6374266090514795, -28.0523004146238 +1.651149220410492, -28.63857435312279 +1.664979203392674, -29.236255251443865 +1.6789198953270754, -29.84154078964631 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi14-h_over_deltastar0p54.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi14-h_over_deltastar0p54.csv new file mode 100644 index 00000000..2942ebcc --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi14-h_over_deltastar0p54.csv @@ -0,0 +1,104 @@ +0.21570138298262298, -28.99055950776563 +0.2220074698536935, -28.463388931771654 +0.2278418118471089, -27.97377222234087 +0.23416589862829365, -27.465516845808146 +0.24101376228841537, -26.91809027449377 +0.2473472923724451, -26.43145204901652 +0.2534829396002058, -25.95977691469855 +0.26014312995165584, -25.482834605070067 +0.26698076245483426, -24.98307837579744 +0.2739978369879028, -24.485857026485277 +0.28119905535507594, -23.991170557133565 +0.2885880665001817, -23.509158487584166 +0.2961736507405027, -23.00686737835108 +0.3039570751856228, -22.517250668920305 +0.3110483545346796, -22.073022909566852 +0.3192330317637483, -21.5027509286669 +0.3276265206895346, -20.98225477244506 +0.3333435954647428, -20.641479313048592 +0.3500745137678027, -19.782759468547084 +0.3608308888297983, -19.213053220733016 +0.3708377848848635, -18.76183264331064 +0.3805837656368212, -18.2696810539194 +0.39058428886897, -17.787668984369986 +0.4008484104784999, -17.300587154899667 +0.4113856142116002, -16.793226285745668 +0.4221998120891458, -16.285865416591662 +0.4332951959287397, -15.796248707160885 +0.444680806836271, -15.314236637611465 +0.4563725682574102, -14.794201368655173 +0.46837030379025174, -14.281770739580246 +0.4806849208469721, -13.761735470623947 +0.49332030464364535, -13.256909481430405 +0.5062867933229203, -12.757153252157785 +0.5195935654333498, -12.259931902845615 +0.5332506235771097, -11.760175673572995 +0.5472649730452079, -11.268024084181754 +0.5616487775930944, -10.770802734869584 +0.5764088712549038, -10.281186025438807 +0.5915556540670058, -9.796639075928937 +0.6071023169294179, -9.304487486537695 +0.6230588306794043, -8.807266137225525 +0.6394334279255398, -8.315114547834284 +0.6562376971827776, -7.8254978384035 +0.6734828955192154, -7.338416008933173 +0.6911826866517204, -6.846264419541924 +0.7093505359277914, -6.343973310308847 +0.7279907391605329, -5.8594263607989845 +0.7471215278028325, -5.3723445313286575 +0.7667566144259507, -4.880192941937409 +0.7835191894460118, -4.4497875777610325 +0.8029760427797461, -3.9129257008235037 +0.8264206375587234, -3.47796138339125 +0.8493630374934165, -2.958362419035474 +0.8843355330629598, -2.2020033438387614 +0.91061467739827, -1.6985062232796864 +1.0343002794004144, -0.33349663300176857 +1.0673026258291223, -0.4709339394919425 +1.0996977640720127, -0.803414513968761 +1.1240703055264096, -1.418960343780796 +1.1342897276923487, -2.031149780179213 +1.1410740359861833, -2.614182788383207 +1.1503476171937146, -3.1482878734850424 +1.162792508884233, -3.8271086298672934 +1.1677569993173067, -4.410868543813134 +1.1957762714870204, -5.911013158737767 +1.2060681897571317, -6.447330812959905 +1.2176523785489022, -7.064668880637768 +1.2278551554454245, -7.654745139077448 +1.2381528811311235, -8.225809797813689 +1.2485178944634008, -8.834897655956823 +1.2589850662249351, -9.413566954574435 +1.2695322322208624, -10.007445532954812 +1.2801755814194498, -10.58611483157243 +1.2909042161429891, -11.172388770071414 +1.3017545871311689, -11.697825589519383 +1.3089659839267551, -12.18652124832579 +1.3199508237857982, -12.744658019263682 +1.3310384239234314, -13.28302272650999 +1.3402902905726477, -13.841040052842416 +1.3515062020101885, -14.457732550866929 +1.362813888910488, -15.078227368832124 +1.3722769772938812, -15.653735366891723 +1.3854731325117333, -16.243153542433667 +1.3973547438476617, -16.856060784032557 +1.4090632568419572, -17.446137042472245 +1.420874218165509, -18.028608661030553 +1.4327907482771107, -18.599673319766787 +1.4447939739427027, -19.193551898147156 +1.4568999828802818, -19.783628156586843 +1.4691051840150156, -20.377506734967213 +1.4813967897951001, -20.998001552932415 +1.4938026483671496, -21.59948477119417 +1.5063377164910114, -22.159142470108343 +1.518961724763848, -22.745416408607326 +1.5316868490582785, -23.339294986987703 +1.5445303780661912, -23.914161965664633 +1.5574673243942818, -24.51184286398569 +1.5705222289500536, -25.094314482544 +1.5836817219180728, -25.684390740983687 +1.5969514790084234, -26.274466999423367 +1.6103398056793852, -26.85313629804098 +1.6238329323339036, -27.443212556480667 +1.6377397350697656, -28.084908791916206 +1.6547393873007343, -28.572212921068925 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi14-h_over_deltastar0p62.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi14-h_over_deltastar0p62.csv new file mode 100644 index 00000000..12fab7d4 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi14-h_over_deltastar0p62.csv @@ -0,0 +1,104 @@ +0.3757538297691322, -28.698546920743787 +0.38288554537457653, -28.17809549161447 +0.3895942707597765, -27.662413314946278 +0.3964205430120171, -27.1467311382781 +0.40336703805261365, -26.62724664166923 +0.41043400259000007, -26.11536678494174 +0.41762414178095203, -25.60728924815494 +0.4249415391475651, -25.09160707148675 +0.4323864875551403, -24.57972721475926 +0.4399632154628355, -24.06024271815039 +0.4476706586525184, -23.55216518136359 +0.455515907785092, -23.028878364814027 +0.4634979335658451, -22.50939386820515 +0.47162054935711045, -21.986107051655587 +0.4798840442575478, -21.470424874987415 +0.48829158181737986, -20.95854501825992 +0.49685097385986016, -20.423851241888286 +0.505554998469588, -19.915773705101493 +0.5144138614915058, -19.396289208492618 +0.5234247596878951, -18.8920139916465 +0.5310296861136814, -18.58712168247566 +0.5497898157928509, -17.608989808308948 +0.5578493988002985, -16.984702624120175 +0.5676263535649959, -16.457613487629935 +0.5775737782439682, -15.93432667108037 +0.5876910377236605, -15.430051454234253 +0.5992763602375305, -14.89838858472634 +0.6085927578782282, -14.388383581716802 +0.6200111918250655, -13.891272197279513 +0.631818294070246, -13.215468839144883 +0.6428955683658264, -12.673170422891872 +0.6532147898300857, -12.196912929001392 +0.6637004580800486, -11.71761357915836 +0.6753294792459809, -11.201931402490182 +0.6871622581939534, -10.686249225822003 +0.6992012967171093, -10.174369369094507 +0.7114523454843378, -9.65868719242632 +0.7239202631117264, -9.135400375876763 +0.7366021740208566, -8.627322839089956 +0.7495131227649618, -8.09643138265902 +0.762643379137772, -7.58835384587222 +0.7760072134402837, -7.068869349263345 +0.7896052228135437, -6.549384852654477 +0.8034415107178698, -6.0299003560456015 +0.8175202525187004, -5.510415859436733 +0.8318444257272288, -4.994733682768548 +0.8464169932251777, -4.486656145981748 +0.8599853622236813, -4.06134973929651 +0.9046778348479421, -2.55296742808153 +0.9488510769326416, -1.368446473600148 +0.9879026940653152, -0.655653384438164 +1.0175542926607877, -0.43487920945718983 +1.0521830432000774, -0.3847057929454891 +1.0857116518200425, -0.6237687414868134 +1.113822456872183, -1.0759751591831979 +1.127771519134326, -1.6278262999543642 +1.1358531261236882, -2.162677401934907 +1.1437206922206329, -2.780733360130821 +1.154980614109118, -3.3148448440508034 +1.1630026850633535, -3.8857900581815734 +1.1727439653448892, -4.483470956502636 +1.1825776798192433, -5.0583379351795585 +1.1925066067209489, -5.606588674271663 +1.2025060352627324, -6.181455652948586 +1.2125837528761867, -6.7677295914475835 +1.222742191183877, -7.361608169827953 +1.2329932677539066, -7.940277468445572 +1.2433264865547584, -8.52655140694457 +1.2537405569112066, -9.124232305265629 +1.264247650366522, -9.710506243764627 +1.274846695333506, -10.289175542382239 +1.2855267423616734, -10.883054120762608 +1.2963022036908216, -11.465525739320917 +1.3071719809996496, -12.04039271799784 +1.318118805535343, -12.641875936259595 +1.3291573035226998, -13.24335915452135 +1.3402902905726477, -13.841040052842416 +1.3515062020101885, -14.457732550866929 +1.362813888910488, -15.078227368832124 +1.3722769772938812, -15.653735366891723 +1.3854731325117333, -16.243153542433667 +1.3973547438476617, -16.856060784032557 +1.4090632568419572, -17.446137042472245 +1.420874218165509, -18.028608661030553 +1.4327907482771107, -18.599673319766787 +1.4447939739427027, -19.193551898147156 +1.4568999828802818, -19.783628156586843 +1.4691051840150156, -20.377506734967213 +1.4813967897951001, -20.998001552932415 +1.4938026483671496, -21.59948477119417 +1.5063377164910114, -22.159142470108343 +1.5189686874818245, -22.734009448785258 +1.5319810919981274, -23.369730610028284 +1.5503850652445754, -24.159464214343892 +1.5639799603575872, -24.804979833235194 +1.577091864439423, -25.383649131852806 +1.590332648013315, -25.93266033493304 +1.5991485597282709, -26.412230425881795 +1.6125853659638256, -26.944511421222998 +1.6261261298930803, -27.490480768350686 +1.6374266090514795, -28.0523004146238 +1.651149220410492, -28.63857435312279 +1.664979203392674, -29.236255251443865 +1.676679311590016, -29.60567750871808 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi14-h_over_deltastar1p20.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi14-h_over_deltastar1p20.csv new file mode 100644 index 00000000..29793fc2 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure97-Psi14-h_over_deltastar1p20.csv @@ -0,0 +1,93 @@ +0.7068013875603847, -26.869918265109057 +0.7131614495797154, -26.22868653647256 +0.7195169902263636, -25.504427535413875 +0.7259276911653565, -24.78523829427612 +0.7323992399352506, -24.053374653336057 +0.73892848170128, -23.321511012395995 +0.7455151713808225, -22.592182251416403 +0.7521628722872317, -21.85524885055542 +0.7588698502265405, -21.118315449694443 +0.7656342940589052, -20.388986688714844 +0.772459821909966, -19.65712304777479 +0.7793382597832206, -18.950608206439334 +0.7862667343843794, -18.2795816845503 +0.7932648849548937, -17.583206363056682 +0.8003375510982623, -16.848807842156162 +0.8074584711582659, -16.160037160543922 +0.8146493874773431, -15.450987439248003 +0.8219118783639501, -14.719123798307947 +0.829234045255508, -14.00246943713065 +0.8360557659440934, -13.2741701748934 +0.8423984985979034, -12.770270924162588 +0.8510895474474724, -12.141442854222667 +0.8632595380128573, -10.976798228619721 +0.8573466689068527, -11.708575604011386 +0.8715834693731667, -10.270090948753229 +0.8771819887848551, -9.702793534954488 +0.8838658957312924, -9.116764173504784 +0.8909661225023017, -8.526857981431931 +0.898489980164686, -7.938289568940306 +0.9055352696160668, -7.313710883035817 +0.9135637920592995, -6.702254040217596 +0.9216601159848405, -6.09992276525702 +0.9298307497058593, -5.490747314403215 +0.9394061125775106, -4.908877895730807 +0.9450486988231883, -4.242618872552761 +0.9537697070339981, -3.7551517868311493 +0.9636877713672475, -3.0943899172277867 +0.9717956022258277, -2.413500920623491 +0.9811515195849804, -1.7041940616352456 +1.0004372162870838, -0.6000680361354256 +0.9909434484495012, -1.1428820143079435 +1.031345210647035, -0.335331736485756 +1.0642630238597957, -0.4499551233317902 +1.0981344694383857, -0.784421735839512 +1.1240806107267751, -1.3961464241366563 +1.1383171106103778, -2.1088889744849197 +1.144395008479817, -2.500352079373453 +1.1544636566238613, -3.2425609503092083 +1.1630026850633535, -3.8857900581815734 +1.1727439653448892, -4.483470956502636 +1.1825776798192433, -5.0583379351795585 +1.1925066067209489, -5.606588674271663 +1.2025060352627324, -6.181455652948586 +1.2091526546907292, -6.700950103274586 +1.2141318030014858, -7.151883350062697 +1.2295279023115668, -7.8259689810139506 +1.240095429398993, -8.392162006198653 +1.2535128882519249, -9.067723631203172 +1.264247650366522, -9.710506243764627 +1.274846695333506, -10.289175542382239 +1.2855267423616734, -10.883054120762608 +1.2963022036908216, -11.465525739320917 +1.3071699837050745, -12.044195037938536 +1.318118805535343, -12.641875936259595 +1.3291573035226998, -13.24335915452135 +1.3402902905726477, -13.841040052842416 +1.3515062020101885, -14.457732550866929 +1.362813888910488, -15.078227368832124 +1.3722769772938812, -15.653735366891723 +1.3854731325117333, -16.243153542433667 +1.3973547438476617, -16.856060784032557 +1.4090632568419572, -17.446137042472245 +1.420874218165509, -18.028608661030553 +1.4327907482771107, -18.599673319766787 +1.4447939739427027, -19.193551898147156 +1.4568999828802818, -19.783628156586843 +1.4691051840150156, -20.377506734967213 +1.4813967897951001, -20.998001552932415 +1.4938026483671496, -21.59948477119417 +1.5063377164910114, -22.159142470108343 +1.518961724763848, -22.745416408607326 +1.5316868490582785, -23.339294986987703 +1.5445303780661912, -23.914161965664633 +1.5574673243942818, -24.51184286398569 +1.5705222289500536, -25.094314482544 +1.5836817219180728, -25.684390740983687 +1.5969514790084234, -26.274466999423367 +1.6103398056793852, -26.85313629804098 +1.6238329323339036, -27.443212556480667 +1.6374266090514795, -28.0523004146238 +1.651149220410492, -28.63857435312279 +1.664979203392674, -29.236255251443865 +1.678971202292745, -29.765494390832515 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure98-a-TBL-TE-suction.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure98-a-TBL-TE-suction.csv new file mode 100644 index 00000000..08678029 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure98-a-TBL-TE-suction.csv @@ -0,0 +1,19 @@ +0.19999999999999982, 54.785276073619634 +0.2486523931334979, 56.467824043858506 +0.31594505029697023, 58.15298263934212 +0.4014490813831109, 59.83814123482574 +0.5045697947407928, 61.337945437932376 +0.634179251046298, 62.837749641039025 +0.8058068247167196, 63.41861375799504 +1.001828976845588, 62.708523691424084 +1.2591700035052644, 61.26354261845711 +1.6174520477738452, 59.63712309098028 +2.010916612288221, 58.006787625636335 +2.5274632060617885, 56.56180655266936 +3.176695751062076, 54.748727320193176 +4.03640313370572, 52.75290432058477 +5.018306494237403, 50.75447069573163 +6.376407955487519, 48.75864769612323 +8.102051650590377, 46.39472653700561 +10.07297266105253, 44.02819475264326 +12.523343790695101, 41.293564808771706 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure98-b-bluntness.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure98-b-bluntness.csv new file mode 100644 index 00000000..fed42922 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure98-b-bluntness.csv @@ -0,0 +1,14 @@ +0.3088227179989663, 39.825126553152316 +0.3921776373865684, 41.69236079153244 +0.4980310394995792, 43.19374137137598 +0.6188651590288712, 45.05752416014725 +0.7859042155364313, 46.558904739990794 +0.9765831820806095, 48.0568338702255 +1.2401745815251595, 49.55821445006903 +1.574912430279955, 51.425448688449144 +1.9570234670535507, 52.923377818683846 +2.4852473438230063, 54.42475839852738 +3.156045118497447, 56.29199263690751 +4.0078991794311065, 57.793373216751036 +4.980310394995792, 59.29130234698574 +6.324555320336747, 54.57317073170732 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure98-c-bluntness.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure98-c-bluntness.csv new file mode 100644 index 00000000..e6a8cccd --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure98-c-bluntness.csv @@ -0,0 +1,12 @@ +0.392735443323626, 40.8343959082498 +0.4986194369496742, 43.053911947161595 +0.6192527919104482, 45.99722059055199 +0.794708090411764, 48.58207137637994 +0.9979104544745524, 51.16348371753101 +1.2395031911454977, 53.743176836343665 +1.6078956647621192, 56.693362369087765 +1.9971649746379956, 59.273055487900436 +2.4806758444186032, 61.85274860671309 +3.1488586334000406, 64.61768793249146 +5.108908145983431, 51.05775154371764 +3.9996578987147675, 65.56454963538121 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure98-d-bluntness.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure98-d-bluntness.csv new file mode 100644 index 00000000..c301c1c4 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure98-d-bluntness.csv @@ -0,0 +1,9 @@ +0.7849061712986825, 43.632441760138036 +0.9844805942366371, 47.87575496117344 +1.2347998727349885, 52.11906816220882 +1.5823566265854805, 57.09749784296811 +1.9845636201515835, 61.523727351164794 +2.489004498896005, 65.94995685936152 +3.1235264015857895, 68.72993960310615 +3.9860346388974763, 55.23209663503022 +4.980049040825702, 40.267471958585006 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure99-b-TBL-TE-suction.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure99-b-TBL-TE-suction.csv new file mode 100644 index 00000000..c4d24e34 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure99-b-TBL-TE-suction.csv @@ -0,0 +1,17 @@ +0.19888373359389414, 45.33849381465674 +0.24697069235315255, 47.20494827461479 +0.3134606295749702, 48.705924907762466 +0.39352730388205115, 50.38964045431527 +0.49417695368446257, 51.33719163712655 +0.6207758196502704, 51.364537365260816 +0.797249531297717, 50.290240902843095 +0.9912000118610859, 48.84395572596401 +1.2324158122800868, 47.21362945814951 +1.5831880076211426, 45.403168631990184 +1.9900966489802605, 43.5901034507705 +2.4744012800845496, 41.959777182955975 +3.1443333713626367, 40.148014179266454 +3.9961788121099207, 37.96816899370617 +5.023605497442693, 35.97106272155108 +6.316448405514776, 33.421833176589786 +8.029270565386138, 30.689864718223305 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure99-b-bluntness.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure99-b-bluntness.csv new file mode 100644 index 00000000..89a66994 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure99-b-bluntness.csv @@ -0,0 +1,11 @@ +0.39195718815617164, 31.432105910439134 +0.4974806759264461, 32.93308254358678 +0.6178460083864385, 34.43145482167404 +0.7840792359404558, 36.30051363669247 +0.9844863436141147, 37.61614700137457 +1.2359518866419605, 39.299862547927404 +1.585827422365149, 40.8021413586053 +1.9910250740626105, 42.30181581422269 +2.4725883667492887, 43.98422918324533 +3.1393091820237666, 44.56500036171599 +4.006576751725049, 30.7905664472257 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure99-c-bluntness.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure99-c-bluntness.csv new file mode 100644 index 00000000..31a78cb6 --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure99-c-bluntness.csv @@ -0,0 +1,11 @@ +0.24326243001204642, 30.511567567567624 +0.3088470867765021, 32.735135135135124 +0.3963794007371903, 35.14291891891895 +0.4977632031041067, 37.54810810810815 +0.6250784120054128, 39.953297297297354 +0.8022358538345494, 42.361081081081096 +0.9965857669069371, 44.58205405405411 +1.2378546011813674, 47.16886486486493 +1.6061790599389314, 49.39502702702708 +1.9955574257243194, 51.25016216216221 +2.4882342108564943, 43.2276756756757 diff --git a/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure99-d-bluntness.csv b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure99-d-bluntness.csv new file mode 100644 index 00000000..0cad892f --- /dev/null +++ b/test/bpm_data/brooks_airfoil_self_noise_and_prediction_1989/19890016302-figure99-d-bluntness.csv @@ -0,0 +1,10 @@ +0.3117247474485876, 32.205797768319314 +0.39490952907466825, 35.536063499367316 +0.4949542113736202, 38.68169791786494 +0.6203437833736429, 41.827332336362616 +0.7859886659052311, 44.974692281145735 +0.9851076553996511, 48.120326699643385 +1.2213346151802933, 51.26423559185554 +1.5812257372739074, 54.597952375474506 +1.974209677466171, 48.04785459565167 +2.479596231916002, 33.26699643391231 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure21a-loading.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure21a-loading.csv new file mode 100644 index 00000000..b070f763 --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure21a-loading.csv @@ -0,0 +1,32 @@ +27.46780855834909, 44.44024425005671 +28.35297928483881, 42.02008647121904 +29.237775626416717, 39.35443915735159 +30.1679037410663, 36.13611948831418 +31.019411024235758, 33.08882686952545 +31.901555472688344, 29.945852163989816 +32.82479646489776, 26.942385978939853 +33.709663003646625, 24.322767952890494 +34.55616288862062, 22.09211245115486 +35.44142721133829, 19.733327056074636 +36.28092297858718, 17.640809558629655 +37.190846007527504, 15.366240712372154 +37.311552642896004, -44.57133292689413 +38.00580786352433, 13.271336511114377 +38.243885468692916, -42.55932155637804 +38.891165782469955, 10.973923499791596 +39.25729082716326, -40.372278554145865 +39.77614931650377, 8.431020953439038 +40.19034382393636, -37.88804078638499 +40.66103925430963, 5.826746023329051 +41.154100283320716, -35.140623796511306 +41.50499124196715, 2.8715654637353083 +41.99022008662526, -32.19285739526039 +42.227975304786455, 0.0740678064621676 +42.66779697941149, -29.44089430288615 +42.949940208679166, -3.3917069183920248 +43.278931989890395, -26.101334091425926 +43.5101318322416, -6.963760160086316 +43.728796019795695, -22.538687270640878 +43.86882117660312, -10.200270924570788 +44.06468168317467, -14.23520431160432 +44.017618379885874, -18.602591500325232 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure21a-thickness.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure21a-thickness.csv new file mode 100644 index 00000000..a4b42867 --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure21a-thickness.csv @@ -0,0 +1,33 @@ +45.675301173153116, -44.329413419416284 +45.84517832688696, 44.35344043407556 +46.543437386155475, -42.78066326459607 +46.800795814282274, 42.71018483080271 +47.538903467601585, -41.00264914940615 +47.825268926708006, 40.800500879218134 +48.44206806891518, -39.19330703963155 +48.757580953343144, 39.01420349785441 +49.403281830773494, -37.16700553074055 +49.64752508745845, 36.885534457362766 +50.27199912035772, -35.237235160092894 +50.543584175133304, 34.98185737797929 +51.17849592071278, -32.92499828904772 +51.41873230554644, 32.612913449443795 +52.11590374198088, -30.52887245597769 +52.33422820989278, 30.207888175032593 +52.94244769787097, -27.97286086650773 +53.18882026874184, 27.606381019092048 +53.882436175135346, -24.914833428917333 +54.07645006279466, 24.590944545031448 +54.71974803039867, -21.62696641415532 +54.933150203352, 21.164012254777553 +55.49295964231696, -17.982235701455878 +55.66835204044608, 17.546986025552066 +56.14497523192301, -14.329388858704007 +56.18895297956364, 14.507448522793688 +56.58819392964369, 11.368511825949724 +56.59425792525692, -11.147932732590164 +56.946137104076804, 7.6427267798434 +56.92257269375263, -7.808793704155747 +57.16989344641056, 4.237696006930399 +57.211991989785524, -3.4812785085426157 +57.2600307737612, 1.5257453020058662 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-BVS.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-BVS.csv new file mode 100644 index 00000000..75c86e18 --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-BVS.csv @@ -0,0 +1,8 @@ +5010.349561349019, 13.116329845509398 +6334.487056773419, 18.74400387387881 +8076.718403208972, 24.87084821630927 +10073.104384257105, 30.4000034640466 +12629.47291760871, 33.98914772255189 +16183.851993194035, 35.78805734671567 +20150.968433735346, 27.13891545330977 +25217.712560009088, 14.609574540831204 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-LBLVS.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-LBLVS.csv new file mode 100644 index 00000000..9ee71058 --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-LBLVS.csv @@ -0,0 +1,9 @@ +198.42897216086706, 18.483400097993652 +248.6573977210179, 17.59518736455899 +313.3097431905787, 16.4086612056036 +402.45881688342297, 15.33468861357688 +497.44090206077436, 14.48334458688683 +626.7892339988555, 13.446063660996117 +807.355300418456, 12.3721795892737 +1000.6631194242536, 11.670169315952627 +1247.032872006364, 10.483289075780007 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-TBL-TE-pressure-2.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-TBL-TE-pressure-2.csv new file mode 100644 index 00000000..5f10bacd --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-TBL-TE-pressure-2.csv @@ -0,0 +1,13 @@ +2013.676498773692, 11.941395528354839 +2511.296793612552, 17.07256348791973 +3166.0568401523524, 20.811130020098304 +4035.1922454063997, 23.405837179998343 +5030.569628232357, 25.452603656226813 +6340.558901400064, 27.002240103456963 +8019.520714421171, 27.79160900202556 +10070.488536286177, 28.161324968076613 +16163.968731498817, 25.191645799124423 +20250.3021756469, 22.064754569719767 +25370.413605592672, 19.1866053954229 +31780.789565639818, 15.139368562119472 +40470.91236116183, 10.445933507361687 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-TBL-TE-pressure.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-TBL-TE-pressure.csv new file mode 100644 index 00000000..f9053ae1 --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-TBL-TE-pressure.csv @@ -0,0 +1,23 @@ +2010.8876869005044, 11.860510100292665 +2146.9242301096574, 13.69930116578243 +2363.3573266586254, 15.783375906042195 +2683.2460874591607, 18.41265549514766 +3006.059628226959, 19.949529019290416 +3557.7008901273443, 22.105098238166462 +4263.972253348358, 24.153833751407852 +4849.044100926952, 25.067649929050695 +5652.165317410403, 26.24521446100796 +6368.701667608679, 27.208016590672152 +7174.081479418778, 27.53645462243493 +9262.140705145814, 28.315381891406155 +12759.498651554895, 27.358038614595827 +14191.029118838314, 26.356543497060343 +16202.993569330958, 24.883661830223488 +18241.874276810493, 23.486004386500568 +20744.004088345788, 21.596172145101768 +23319.767178201688, 20.425528197837068 +26903.6447818636, 18.005793779860532 +29715.54122783614, 16.44394214928142 +32309.383369317067, 14.945880880961255 +35509.787253687995, 13.122470371876311 +40027.73573824793, 10.456239799934792 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-TBL-TE-suction-2.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-TBL-TE-suction-2.csv new file mode 100644 index 00000000..388a2139 --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-TBL-TE-suction-2.csv @@ -0,0 +1,15 @@ +626.6083825809217, 10.958643109918356 +790.065753409601, 15.617555245995703 +1242.1697918773516, 24.26342188814217 +1600.8258416394856, 27.554960883561215 +2006.8311506861367, 30.049640099592303 +2501.857182585286, 32.07153237030998 +3153.2277908381757, 33.272929940389254 +3995.9323298352647, 34.05164305739392 +5035.79850404155, 34.40731764010674 +6345.720882690218, 34.016766057496234 +7995.183143191944, 32.3327557883253 +12550.270321868575, 27.22318678301177 +16160.330781047569, 23.251457769283775 +20131.787659197125, 18.930427634753173 +25194.401747478736, 14.99822809458616 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-TBL-TE-suction.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-TBL-TE-suction.csv new file mode 100644 index 00000000..abbdf58c --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-TBL-TE-suction.csv @@ -0,0 +1,23 @@ +623.5041083679228, 10.979919648752386 +797.3723896068367, 15.86659236878451 +914.6844243506171, 18.65840282047281 +1052.665621053777, 21.223457597568775 +1273.3768782596662, 24.56892758838797 +1465.645287624041, 26.45766319134912 +1630.5250159716036, 27.80429307403105 +2058.366163753664, 30.28924685929541 +2389.5664065334568, 31.74669236026473 +2562.2905545671856, 32.146922162813 +3101.543119091579, 33.197776202031065 +3520.4584860909235, 33.64958383522327 +4040.1675853536376, 34.02712293310037 +5008.1689377971115, 34.44445190776429 +6193.860969528456, 34.05578580763557 +7890.307309560729, 32.421878030703425 +9123.276529496332, 30.993797665350137 +10183.762077144207, 29.6541313799405 +12619.745619231042, 27.347734851174273 +15866.75704575442, 23.42498707249716 +19694.355062369308, 19.41476647977887 +23223.470138410667, 16.397861728477928 +28300.50548445084, 12.076123431512862 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-separation-2.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-separation-2.csv new file mode 100644 index 00000000..4d116cbc --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-separation-2.csv @@ -0,0 +1,17 @@ +313.17415114286615, 12.677530378986965 +401.234553108405, 15.505170443387051 +497.6304247432492, 17.766739714309466 +627.1909107319838, 18.96813728438874 +795.29099498784, 19.896822388555364 +996.2144404153433, 20.72420308126705 +1255.4822350652917, 21.229122897044533 +1599.84677972037, 22.28162931527637 +1994.4760200394119, 24.278647380483285 +2514.0376721195903, 26.47501317099365 +3168.9818833078452, 28.770875783547126 +4047.2768364576204, 30.53165882504313 +5034.142105600009, 31.571658211878095 +6343.633618441638, 31.181106629267596 +8080.168668226837, 28.55223063190435 +10065.781721656165, 24.131703675330648 +12536.00881281385, 17.422749811765406 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-separation.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-separation.csv new file mode 100644 index 00000000..aae8c705 --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-separation.csv @@ -0,0 +1,25 @@ +313.1687286816831, 12.528285145922304 +435.0033956057982, 16.41921282587721 +503.14068094163923, 17.767093795526705 +606.7970463744182, 18.792955602161584 +662.7043433039073, 19.119152923539573 +786.1221862286804, 19.945489964262386 +1001.7205732222211, 20.774128532897222 +1118.353743242615, 20.926914578134237 +1274.066987137666, 21.329091827377297 +1551.2591652562228, 22.22093979464225 +1721.8661099419892, 23.03021602204793 +2029.3238092221713, 24.421342111029098 +2534.920258102742, 26.587212656705077 +3134.2347313834, 28.65681104856634 +3913.3790254410314, 30.390923809976066 +4267.271237022486, 30.820120828296247 +5045.15429584945, 31.422483795056877 +5437.452912111732, 31.424891547334077 +6484.691537748657, 30.908198531083514 +7399.467469502746, 29.34537255851135 +8366.20863897123, 27.83199992927971 +9717.992699750635, 24.787249640920024 +10929.20283449256, 21.597190322360603 +12453.970452561225, 17.78072592239026 +13635.30214525935, 14.24156612905135 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-tip_vortex_shedding.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-tip_vortex_shedding.csv new file mode 100644 index 00000000..62210ae9 --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure22b-tip_vortex_shedding.csv @@ -0,0 +1,9 @@ +8020.001266277251, 11.587845432945429 +10053.821213623798, 13.883531004890287 +12469.888098144867, 15.58153141637775 +16059.356034825221, 16.684490473829875 +19930.193683318867, 16.940175015676665 +25128.22692997341, 17.203122396604954 +31782.034789984347, 16.50603042174179 +40181.98219065483, 15.131985968740118 +50181.631852600156, 13.28849751932642 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure23c-BVS.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure23c-BVS.csv new file mode 100644 index 00000000..f30f8bf9 --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure23c-BVS.csv @@ -0,0 +1,7 @@ +9941.972169538814, 14.470046082949303 +12403.632741625106, 20.86929883251517 +15830.837188848589, 27.55034919298457 +19775.415289360157, 31.904962374361943 +24709.593226327903, 34.648965200983305 +31181.5527071823, 30.711917667135268 +39606.63614707291, 14.00929176596177 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure23c-LBLVS.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure23c-LBLVS.csv new file mode 100644 index 00000000..b1347a8f --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure23c-LBLVS.csv @@ -0,0 +1,11 @@ +3143.5208349573836, 11.026679997895073 +4014.7674141702964, 13.770682824516435 +4994.385283181881, 16.753294592583124 +6266.520776168983, 20.809646597153836 +7963.3934537958, 27.2520880161779 +9945.931140487071, 32.62078919869795 +12373.77280867454, 35.126183083873975 +15793.735477476384, 32.79974590478195 +19887.81327391852, 24.269476248111204 +24790.462887453356, 15.321640943911113 +31290.54531844659, 10.072244232113732 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure23c-TBL-TE-pressure.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure23c-TBL-TE-pressure.csv new file mode 100644 index 00000000..e2cd4bd3 --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure23c-TBL-TE-pressure.csv @@ -0,0 +1,13 @@ +2511.0253377277877, 12.367806586929888 +3148.373548383108, 15.99220423842852 +4032.4887730018436, 18.53432916607153 +4993.338394193654, 20.6605160087505 +6299.041717758706, 22.24034980513281 +8004.396359258761, 23.374692717691197 +9999.749237827325, 24.07858909495493 +12451.696713757881, 23.88173671826253 +15856.625696493944, 23.100292435029054 +19752.693310797957, 21.44593710767473 +30942.437754178933, 17.07143984784358 +39904.05891719062, 14.193548387096776 +49909.949830771715, 10.7373271889401 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure23c-TBL-TE-suction.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure23c-TBL-TE-suction.csv new file mode 100644 index 00000000..56f2f318 --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure23c-TBL-TE-suction.csv @@ -0,0 +1,16 @@ +1259.7826091164259, 15.145503341577651 +1610.6354124861155, 19.8883473823145 +2009.2285326524916, 23.22697168116313 +2496.359179643009, 25.822335248891953 +3144.2351077626236, 27.726847640598102 +3958.8106442089597, 29.199788003397963 +4989.057778188725, 30.37786514911179 +6280.970541728588, 30.921658986175117 +7988.7339715648395, 30.237551106323707 +9922.509916107076, 29.517922519215546 +12364.933955515506, 28.257654269411816 +15628.52333447935, 25.963599732373083 +19747.913064098357, 22.87759075634674 +24844.02188391758, 19.81544267446494 +31291.803738793275, 15.787517975142485 +39683.66648990339, 11.14598446861774 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure23c-separation.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure23c-separation.csv new file mode 100644 index 00000000..35261d34 --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure23c-separation.csv @@ -0,0 +1,21 @@ +203.77934681456463, 14.406973335037328 +252.4935887805937, 15.083032002465778 +319.5369537859144, 14.987588425887651 +403.1950712414183, 14.894603107779979 +501.1625746117447, 15.162568316280883 +633.0252599344444, 15.083032002465778 +798.7686898591635, 15.083032002465778 +1012.5711596465026, 15.301756865457342 +1249.0723902746463, 15.117118994100828 +1607.2978922786547, 14.277726825087768 +2009.0498928609716, 14.307552942768439 +2516.192500741679, 14.957074446891852 +3161.9748226694383, 18.51632449011811 +4001.553096351974, 22.688692011035855 +4972.824318246206, 25.743935168131344 +6223.003920347921, 27.510581036077014 +7988.490396464756, 27.530465114530784 +9993.994150489743, 26.41695672111922 +12449.804303674979, 24.780781122636924 +15858.968460654405, 21.778274536673585 +19865.565160546397, 16.70127810109465 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure23c-tip_vortex_shedding.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure23c-tip_vortex_shedding.csv new file mode 100644 index 00000000..1f8c1b7b --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure23c-tip_vortex_shedding.csv @@ -0,0 +1,9 @@ +7942.21491376868, 12.188489035565809 +9909.524963524653, 14.454323538603461 +12420.008734379138, 16.109050450680726 +15967.660934189358, 17.158929793040194 +19839.670190897188, 17.439295299238466 +24900.721371992255, 17.628194044549353 +31188.040614858644, 16.991903534028467 +39434.66113042424, 15.303636267957692 +49436.27555862587, 13.603077709534595 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure24b-BVS.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure24b-BVS.csv new file mode 100644 index 00000000..b641ab95 --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure24b-BVS.csv @@ -0,0 +1,6 @@ +4994.115408307409, 1.602885530561565 +6276.071191304018, 6.65125568875149 +8010.780804897988, 12.603706271849575 +9909.749176933228, 18.60237506951657 +12477.560399890495, 19.73699649061186 +15895.162583471803, 14.993235066428056 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure24b-LBLVS.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure24b-LBLVS.csv new file mode 100644 index 00000000..b0c785c1 --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure24b-LBLVS.csv @@ -0,0 +1,20 @@ +201.2812406499209, 7.253951720427828 +250.73843437497516, 6.283038663828478 +316.4108150398763, 5.048560666390117 +400.9818712388363, 4.047077982702362 +500.61716728644495, 3.369454192744847 +635.3540946068531, 2.420578519153274 +799.2259394818263, 2.1580710039622346 +1012.5194339840486, 2.5320987392646686 +1274.4160056606802, 3.6608802639560523 +1601.9825706643053, 5.269353362179551 +1988.6534224049879, 7.835985813068795 +2502.06970904748, 10.6977091578175 +3157.401528408497, 13.850344832458767 +3984.3751657069133, 20.393341952883162 +4972.583170580966, 27.12028511129212 +6224.629985938435, 28.57590788722453 +7988.9198181633865, 24.846749652543327 +9973.993080264081, 16.9298382774627 +12422.325321243601, 8.172375352124739 +15843.63370467617, 2.5952494740627756 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure24b-TBL-TE-pressure.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure24b-TBL-TE-pressure.csv new file mode 100644 index 00000000..c4e065fb --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure24b-TBL-TE-pressure.csv @@ -0,0 +1,12 @@ +2498.3079772475066, 3.327135634773356 +3135.854244300608, 6.765335405456966 +4007.8854957267504, 9.587163935965016 +5014.870201077561, 11.84269321568759 +6299.520235957786, 12.76474289551605 +7971.986558368031, 12.86356786785241 +9933.672243983749, 12.451578619075448 +12400.778213751988, 10.976681291640553 +15950.448199203756, 8.082785401470161 +19976.885057958996, 4.957396815207581 +22370.16029559359, 2.9190776677960883 +24994.16617513613, 1.0421580768914893 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure24b-TBL-TE-suction.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure24b-TBL-TE-suction.csv new file mode 100644 index 00000000..038e247c --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure24b-TBL-TE-suction.csv @@ -0,0 +1,14 @@ +1002.4140941030279, 3.174494913557389 +1247.9004597288588, 7.680288381472579 +1595.506400444829, 11.630774164766628 +1995.993712824503, 14.970514881844544 +2481.880879461515, 17.22123174780046 +3132.9521163195836, 18.791616831740136 +3974.587999586483, 19.63236648529277 +4968.843754337062, 19.87515026176584 +6264.5808190245025, 18.94340682660272 +7942.056667599996, 16.996938495373804 +9961.175115173151, 14.509564605073564 +12401.974294177207, 11.136972115655382 +15921.245759931284, 6.196374464936902 +19921.47255969292, 0.947909506838613 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure24b-separation.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure24b-separation.csv new file mode 100644 index 00000000..3a537b24 --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure24b-separation.csv @@ -0,0 +1,19 @@ +201.2812406499209, 5.00774952032306 +250.27937681046888, 3.57508066949881 +315.83152300394363, 2.238236686378606 +401.8723526500628, 1.3351943839696574 +501.62246632164727, 1.6294855218814632 +629.2638178388403, 1.726487923714629 +804.84699761042, 2.5293735888515556 +999.5178792857503, 3.3513647452337665 +1247.635702973381, 3.891661140667267 +1599.3581030374878, 4.959897393040293 +2002.0347659536415, 8.34454093495539 +2524.856749019957, 11.081835509921056 +3144.0309002275517, 13.315489906345661 +3984.3751657069133, 15.177941219514906 +4974.501911432466, 15.886644845277068 +6265.789340573026, 14.764839705643382 +7988.9198181633865, 11.93108700194091 +9955.732469427745, 7.84771405299513 +12422.325321243601, 1.2673640023779456 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure24b-tip_vortex_shedding.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure24b-tip_vortex_shedding.csv new file mode 100644 index 00000000..fba793d6 --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure24b-tip_vortex_shedding.csv @@ -0,0 +1,8 @@ +4953.10200887433, 1.3814538122330475 +6235.646127072764, 3.040240883110222 +7903.849333016873, 4.104494378620295 +9893.51440860238, 4.843250862207306 +12410.589479475359, 4.837320632113773 +15855.863039523641, 3.8768776202237234 +19744.53588711629, 2.859483927163815 +24639.136197855423, 1.2968103460166986 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure25b-BVS.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure25b-BVS.csv new file mode 100644 index 00000000..861ee51a --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure25b-BVS.csv @@ -0,0 +1,5 @@ +12486.277716697496, 20.72611960373807 +16015.174911059583, 26.923531269371573 +20110.028047857428, 30.085498076000885 +25087.074219642876, 32.096837389910995 +31453.58207603152, 19.412390788196348 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure25b-LBLVS.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure25b-LBLVS.csv new file mode 100644 index 00000000..466dc779 --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure25b-LBLVS.csv @@ -0,0 +1,6 @@ +5010.814073825407, 16.001181300366085 +6336.914670212687, 22.754501723495522 +8026.293681229403, 28.29881051240365 +10002.58016893442, 29.145136200423394 +12570.730850095759, 25.47772488567118 +16028.318263246156, 15.039708066761008 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure25b-TBL-TE-pressure.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure25b-TBL-TE-pressure.csv new file mode 100644 index 00000000..c2e4b126 --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure25b-TBL-TE-pressure.csv @@ -0,0 +1,12 @@ +2514.149262896887, 16.18685598661972 +3162.261593238226, 19.256950373688575 +4002.5270624573864, 21.401536860080242 +5036.602899286703, 23.20214271511948 +6349.475309461834, 24.701926338319744 +8016.087750707262, 25.6187791670078 +10103.483114819483, 25.839717423595594 +12562.18604186773, 25.388601036269428 +16032.413333720913, 24.18952268447584 +20045.722006232605, 22.504064375021933 +24953.198529465128, 20.98445595854922 +31748.287693059454, 18.220622463420625 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure25b-TBL-TE-suction.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure25b-TBL-TE-suction.csv new file mode 100644 index 00000000..028af24b --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure25b-TBL-TE-suction.csv @@ -0,0 +1,14 @@ +1595.7553512787126, 15.110235207429326 +1991.7047093099825, 19.165545795857255 +2484.9634030819257, 22.427426051766687 +3139.3190442720397, 24.75482169382098 +3990.5801054184594, 26.49331571129487 +5006.766745499279, 27.910911238727937 +6411.902608999668, 28.975871062819447 +8112.809755313637, 29.10281991602241 +10065.475612866834, 28.73635948958468 +12453.132287485305, 27.903858524661104 +15904.290067362292, 25.900887729681045 +19918.145890734908, 23.502964946958443 +25037.18244333652, 21.09784909765026 +31524.212599115745, 17.358167931788685 diff --git a/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure25b-separation.csv b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure25b-separation.csv new file mode 100644 index 00000000..4e8c144f --- /dev/null +++ b/test/bpm_data/pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021/figure25b-separation.csv @@ -0,0 +1,17 @@ +200.8497572110692, 19.017438800453803 +251.1971097486726, 18.75173978643025 +315.5580550387623, 17.80437198095884 +400.6506030074118, 17.049731575807904 +502.2945716438663, 16.873413724137123 +629.6620858014053, 16.48551445046141 +798.6408930727855, 16.252774886255978 +1002.5834729624327, 16.203405887788158 +1253.78806288201, 15.744979473444133 +3147.449707316153, 16.591305161463872 +4002.7043129699496, 19.271336506859726 +5022.701448886523, 20.992198739166533 +6298.999380023496, 21.556415864513035 +8027.929957418758, 21.50469596135627 +9964.14219636752, 20.945040292868917 +12484.806710398032, 19.588568287348387 +15965.44097879352, 16.760570299067822 diff --git a/test/bpm_itr_tests.jl b/test/bpm_itr_tests.jl new file mode 100644 index 00000000..945597f4 --- /dev/null +++ b/test/bpm_itr_tests.jl @@ -0,0 +1,35 @@ +module BPMITRTests + +using SafeTestsets: @safetestset +using Test: @testset + +@testset "BPM.jl comparisons" begin + @safetestset "figure 22b" begin + include("itr_figure22b_bpmjl.jl") + end + + @safetestset "figure 23c" begin + include("itr_figure23c_bpmjl.jl") + end + + @safetestset "figure 24b" begin + include("itr_figure24b_bpmjl.jl") + end + +end + +@testset "PAS/ROTONET/BARC comparisons" begin + @safetestset "figure 22b" begin + include("itr_figure22b_barc.jl") + end + + @safetestset "figure 23c" begin + include("itr_figure23c_barc.jl") + end + + @safetestset "figure 24b" begin + include("itr_figure24b_barc.jl") + end +end + +end # module diff --git a/test/bpm_shape_function_tests.jl b/test/bpm_shape_function_tests.jl new file mode 100644 index 00000000..fc92e206 --- /dev/null +++ b/test/bpm_shape_function_tests.jl @@ -0,0 +1,514 @@ +module BPMShapeFunctionTests + +using AcousticAnalogies: AcousticAnalogies +using AcousticMetrics: AcousticMetrics +using DelimitedFiles: DelimitedFiles +using FLOWMath: linear +using Test + +@testset "shape functions" begin + + @testset "TBL-TE" begin + @testset "St_1" begin + @test isapprox(AcousticAnalogies.St_1(0.093), 0.081; atol=0.0022) + @test isapprox(AcousticAnalogies.St_1(0.116), 0.071; atol=0.002) + @test isapprox(AcousticAnalogies.St_1(0.163), 0.059; atol=0.0004) + @test isapprox(AcousticAnalogies.St_1(0.209), 0.051; atol=0.0002) + end + + @testset "K_1" begin + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure77.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + Re_c_bpm = bpm[:, 1] + K_1_bpm = bpm[:, 2] + + Re_c_jl = range(minimum(Re_c_bpm), maximum(Re_c_bpm); length=50) + K_1_jl = AcousticAnalogies.K_1.(Re_c_jl) + + K_1_interp = linear(Re_c_bpm, K_1_bpm, Re_c_jl) + + vmin, vmax = extrema(K_1_bpm) + err = abs.(K_1_jl .- K_1_interp)./(vmax - vmin) + @test maximum(err) < 0.012 + end + + @testset "A" begin + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure78-A_min.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + St_St_peak_bpm = bpm[:, 1] + A = bpm[:, 2] + + St_St_peak_jl = range(minimum(St_St_peak_bpm), maximum(St_St_peak_bpm); length=50) + A_jl = AcousticAnalogies.A.(St_St_peak_jl, 9.5e4) + + # Interpolate: + A_interp = linear(St_St_peak_bpm, A, St_St_peak_jl) + + # Check error. + vmin, vmax = extrema(A) + err = abs.(A_jl .- A_interp)./(vmax - vmin) + @test maximum(err) < 0.057 + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure78-A_max.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + St_St_peak_bpm = bpm[:, 1] + A = bpm[:, 2] + + St_St_peak_jl = range(minimum(St_St_peak_bpm), maximum(St_St_peak_bpm); length=50) + A_jl = AcousticAnalogies.A.(St_St_peak_jl, 8.58e5) + + # Interpolate: + A_interp = linear(St_St_peak_bpm, A, St_St_peak_jl) + + # Check error. + vmin, vmax = extrema(A) + err = abs.(A_jl .- A_interp)./(vmax - vmin) + @test maximum(err) < 0.021 + end + + @testset "B" begin + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure78-B_min.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + St_St_peak_bpm = bpm[:, 1] + B = bpm[:, 2] + + St_St_peak_jl = range(minimum(St_St_peak_bpm), maximum(St_St_peak_bpm); length=50) + B_jl = AcousticAnalogies.B.(St_St_peak_jl, 9.5e4) + + # Interpolate: + B_interp = linear(St_St_peak_bpm, B, St_St_peak_jl) + + # Check error. + vmin, vmax = extrema(B) + err = abs.(B_jl .- B_interp)./(vmax - vmin) + @test maximum(err) < 0.057 + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure78-B_max.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + St_St_peak_bpm = bpm[:, 1] + B = bpm[:, 2] + + St_St_peak_jl = range(minimum(St_St_peak_bpm), maximum(St_St_peak_bpm); length=50) + B_jl = AcousticAnalogies.B.(St_St_peak_jl, 8.58e5) + + # Interpolate: + B_interp = linear(St_St_peak_bpm, B, St_St_peak_jl) + + # Check error. + vmin, vmax = extrema(B) + err = abs.(B_jl .- B_interp)./(vmax - vmin) + @test maximum(err) < 0.020 + end + + @testset "St_2" begin + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure80-M0.093.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + alpha_deg = bpm[:, 1] + St_2 = bpm[:, 2] + + alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=50) + St_2_jl = AcousticAnalogies.St_2.(AcousticAnalogies.St_1(0.093), alpha_deg_jl.*pi/180) + + # Interpolate: + St_2_interp = linear(alpha_deg, St_2, alpha_deg_jl) + + # Check error. + vmin, vmax = extrema(St_2) + err = abs.(St_2_jl .- St_2_interp)./(vmax - vmin) + @test maximum(err) < 0.023 + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure80-M0.209.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + alpha_deg = bpm[:, 1] + St_2 = bpm[:, 2] + + alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=50) + St_2_jl = AcousticAnalogies.St_2.(AcousticAnalogies.St_1(0.209), alpha_deg_jl.*pi/180) + + # Interpolate: + St_2_interp = linear(alpha_deg, St_2, alpha_deg_jl) + + # Check error. + vmin, vmax = extrema(St_2) + err = abs.(St_2_jl .- St_2_interp)./(vmax - vmin) + @test maximum(err) < 0.011 + + end + + @testset "K_2" begin + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure82-M0.093.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + alpha_deg = bpm[:, 1] + K_2_K_1 = bpm[:, 2] + + alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=200) + K_2_K_1_jl = AcousticAnalogies.K_2.(1e6, 0.093, alpha_deg_jl.*pi/180) .- AcousticAnalogies.K_1(1e6) + + # Interpolate: + K_2_K_1_interp = linear(alpha_deg, K_2_K_1, alpha_deg_jl) + + # Check error. + vmin, vmax = extrema(K_2_K_1) + err = abs.(K_2_K_1_jl .- K_2_K_1_interp)./(vmax - vmin) + # The curve is almost vertical at low angles of attack, so a small error in the digitization results in big differences. + @test maximum(err[2:end]) < 0.027 + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure82-M0.116.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + alpha_deg = bpm[:, 1] + K_2_K_1 = bpm[:, 2] + + alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=200) + K_2_K_1_jl = AcousticAnalogies.K_2.(1e6, 0.116, alpha_deg_jl.*pi/180) .- AcousticAnalogies.K_1(1e6) + + # Interpolate: + K_2_K_1_interp = linear(alpha_deg, K_2_K_1, alpha_deg_jl) + + # Check error. + vmin, vmax = extrema(K_2_K_1) + err = abs.(K_2_K_1_jl .- K_2_K_1_interp)./(vmax - vmin) + # There's a branch for low angles of attack that sets K_2 - K_1 to + # -1000, but I can't see that in the digitized plots, so the first + # point is bad. + @test K_2_K_1_jl[1] ≈ -1000 + @test maximum(err[2:end]) < 0.022 + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure82-M0.163.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + alpha_deg = bpm[:, 1] + K_2_K_1 = bpm[:, 2] + + alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=200) + K_2_K_1_jl = AcousticAnalogies.K_2.(1e6, 0.163, alpha_deg_jl.*pi/180) .- AcousticAnalogies.K_1(1e6) + + # Interpolate: + K_2_K_1_interp = linear(alpha_deg, K_2_K_1, alpha_deg_jl) + + # Check error. + vmin, vmax = extrema(K_2_K_1) + err = abs.(K_2_K_1_jl .- K_2_K_1_interp)./(vmax - vmin) + # There's a branch for low angles of attack that sets K_2 - K_1 to + # -1000, but I can't see that in the digitized plots, so the first + # point is bad. + @test K_2_K_1_jl[1] ≈ -1000.0 + @test maximum(err[2:end]) < 0.020 + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure82-M0.209.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + alpha_deg = bpm[:, 1] + K_2_K_1 = bpm[:, 2] + + alpha_deg_jl = range(minimum(alpha_deg), maximum(alpha_deg); length=200) + K_2_K_1_jl = AcousticAnalogies.K_2.(1e6, 0.209, alpha_deg_jl.*pi/180) .- AcousticAnalogies.K_1(1e6) + + # Interpolate: + K_2_K_1_interp = linear(alpha_deg, K_2_K_1, alpha_deg_jl) + + # Check error. + vmin, vmax = extrema(K_2_K_1) + err = abs.(K_2_K_1_jl .- K_2_K_1_interp)./(vmax - vmin) + @test maximum(err) < 0.024 + end + + end + + @testset "LBL-VS" begin + @testset "St_1_prime" begin + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure86-St_1_prime.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + Re_c_bpm = bpm[:, 1] + St_1_prime_bpm = bpm[:, 2] + + Re_c_jl = 10.0.^(range(4, 7; length=100)) + St_1_prime_jl = AcousticAnalogies.St_1_prime.(Re_c_jl) + + St_1_prime_interp = linear(Re_c_bpm, St_1_prime_bpm, Re_c_jl) + vmin, vmax = extrema(St_1_prime_bpm) + err = abs.(St_1_prime_interp .- St_1_prime_jl)./(vmax - vmin) + @test maximum(err) < 0.04 + end + + @testset "G1" begin + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure85-G1.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + e_bpm = bpm[:, 1] + G1_bpm = bpm[:, 2] + + e_jl = 10.0.^(range(-1, 1; length=101)) + G1_jl = AcousticAnalogies.G1.(e_jl) + + G1_interp = linear(e_jl, G1_jl, e_bpm) + vmin, vmax = extrema(G1_bpm) + err = abs.(G1_interp .- G1_bpm)./(vmax - vmin) + @test maximum(err) < 0.033 + end + + @testset "St_peak_prime_alphastar" begin + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure87.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + alphastar_bpm = bpm[:, 1] + St_peak_ratio_bpm = bpm[:, 2] + + St_1_prime = 0.25 # Just make up a value, since we're multiplying and then dividing by it anyway. + alphastar_jl = range(0.0*pi/180, 7.0*pi/180; length=21) + St_peak_ratio_jl = AcousticAnalogies.St_peak_prime.(St_1_prime, alphastar_jl)./St_1_prime + + St_peak_ratio_interp = linear(alphastar_jl.*180/pi, St_peak_ratio_jl, alphastar_bpm) + vmin, vmax = extrema(St_peak_ratio_bpm) + err = abs.(St_peak_ratio_interp .- St_peak_ratio_bpm)./(vmax - vmin) + @test maximum(err) < 0.031 + end + + @testset "G2" begin + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure89.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + Re_ratio_bpm = bpm[:, 1] + G2_bpm = bpm[:, 2] + + Re_ratio_jl = 10.0.^range(-1, 1, length=51) + G2_jl = AcousticAnalogies.G2.(Re_ratio_jl) + + G2_interp = linear(Re_ratio_jl, G2_jl, Re_ratio_bpm) + vmin, vmax = extrema(G2_interp) + err = abs.(G2_interp .- G2_bpm)./(vmax - vmin) + @test maximum(err) < 0.024 + end + + @testset "G2 + G3" begin + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure88-G2-alpha0.csv") + alphastar = 0.0*pi/180 + bpm = DelimitedFiles.readdlm(fname, ',') + Re_c_bpm = bpm[:, 1] + G2_bpm = bpm[:, 2] + + Re_c_jl = 10.0.^range(log10(first(Re_c_bpm)), log10(last(Re_c_bpm)), length=51) + Re_c0 = AcousticAnalogies.Re_c0(alphastar) + Re_ratio_jl = Re_c_jl./Re_c0 + G2_jl = AcousticAnalogies.G2.(Re_ratio_jl) .+ AcousticAnalogies.G3.(alphastar) + + G2_interp = linear(Re_c_jl, G2_jl, Re_c_bpm) + vmin, vmax = extrema(G2_interp) + err = abs.(G2_interp .- G2_bpm)./(vmax - vmin) + @test maximum(err) < 0.013 + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure88-G2-alpha6.csv") + alphastar = 6.0*pi/180 + bpm = DelimitedFiles.readdlm(fname, ',') + Re_c_bpm = bpm[:, 1] + G2_bpm = bpm[:, 2] + + Re_c_jl = 10.0.^range(log10(first(Re_c_bpm)), log10(last(Re_c_bpm)), length=51) + Re_c0 = AcousticAnalogies.Re_c0(alphastar) + Re_ratio_jl = Re_c_jl./Re_c0 + G2_jl = AcousticAnalogies.G2.(Re_ratio_jl) .+ AcousticAnalogies.G3.(alphastar) + + G2_interp = linear(Re_c_jl, G2_jl, Re_c_bpm) + vmin, vmax = extrema(G2_interp) + err = abs.(G2_interp .- G2_bpm)./(vmax - vmin) + @test maximum(err) < 0.030 + end + + end + + @testset "TEB-VS" begin + @testset "St_3prime_peak" begin + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure95-0Psi.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + h_over_deltastar_0Psi = bpm[:, 1] + St_3prime_peak_0Psi = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure95-14Psi.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + h_over_deltastar_14Psi = bpm[:, 1] + St_3prime_peak_14Psi = bpm[:, 2] + + h_over_deltastar_jl = 10.0.^(range(-1, 1; length=101)) + St_3prime_peak_0Psi_jl = AcousticAnalogies.St_3prime_peak.(h_over_deltastar_jl, 0.0*pi/180) + St_3prime_peak_14Psi_jl = AcousticAnalogies.St_3prime_peak.(h_over_deltastar_jl, 14.0*pi/180) + + St_3prime_peak_0Psi_interp = linear(h_over_deltastar_jl, St_3prime_peak_0Psi_jl, h_over_deltastar_0Psi) + vmin, vmax = extrema(St_3prime_peak_0Psi) + err = abs.(St_3prime_peak_0Psi_interp .- St_3prime_peak_0Psi)./(vmax - vmin) + @test maximum(err) < 0.070 + + St_3prime_peak_14Psi_interp = linear(h_over_deltastar_jl, St_3prime_peak_14Psi_jl, h_over_deltastar_14Psi) + vmin, vmax = extrema(St_3prime_peak_14Psi) + err = abs.(St_3prime_peak_14Psi_interp .- St_3prime_peak_14Psi)./(vmax - vmin) + @test maximum(err) < 0.049 + end + + @testset "G4" begin + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure96-0Psi.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + h_over_deltastar_0Psi = bpm[:, 1] + G4_0Psi = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure96-14Psi.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + h_over_deltastar_14Psi = bpm[:, 1] + G4_14Psi = bpm[:, 2] + + h_over_deltastar_jl = 10.0.^(range(-1, 1; length=51)) + G4_0Psi_jl = AcousticAnalogies.G4.(h_over_deltastar_jl, 0.0*pi/180) + G4_14Psi_jl = AcousticAnalogies.G4.(h_over_deltastar_jl, 14.0*pi/180) + + G4_0Psi_interp = linear(h_over_deltastar_jl, G4_0Psi_jl, h_over_deltastar_0Psi) + vmin, vmax = extrema(G4_0Psi) + err = abs.(G4_0Psi_interp .- G4_0Psi)./(vmax - vmin) + @test maximum(err) < 0.033 + + G4_14Psi_interp = linear(h_over_deltastar_jl, G4_14Psi_jl, h_over_deltastar_14Psi) + vmin, vmax = extrema(G4_14Psi) + err = abs.(G4_14Psi_interp .- G4_14Psi)./(vmax - vmin) + @test maximum(err) < 0.024 + + end + + @testset "G5, Psi = 14°" begin + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure97-Psi14-h_over_deltastar0p25.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + St_3prime_over_St_3prime_peak_0p25 = bpm[:, 1] + G5_14Psi_h_over_deltastar_avg0p25 = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure97-Psi14-h_over_deltastar0p43.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + St_3prime_over_St_3prime_peak_0p43 = bpm[:, 1] + G5_14Psi_h_over_deltastar_avg0p43 = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure97-Psi14-h_over_deltastar0p50.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + St_3prime_over_St_3prime_peak_0p50 = bpm[:, 1] + G5_14Psi_h_over_deltastar_avg0p50 = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure97-Psi14-h_over_deltastar0p54.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + St_3prime_over_St_3prime_peak_0p54 = bpm[:, 1] + G5_14Psi_h_over_deltastar_avg0p54 = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure97-Psi14-h_over_deltastar0p62.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + St_3prime_over_St_3prime_peak_0p62 = bpm[:, 1] + G5_14Psi_h_over_deltastar_avg0p62 = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure97-Psi14-h_over_deltastar1p20.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + St_3prime_over_St_3prime_peak_1p20 = bpm[:, 1] + G5_14Psi_h_over_deltastar_avg1p20 = bpm[:, 2] + + St_3prime_over_St_3prime_peak_jl = 10.0.^(range(-1, 10; length=1001)) + G5_14Psi_h_over_deltastar_avg0p25_jl = AcousticAnalogies.G5_Psi14.(0.25, St_3prime_over_St_3prime_peak_jl) + G5_14Psi_h_over_deltastar_avg0p43_jl = AcousticAnalogies.G5_Psi14.(0.43, St_3prime_over_St_3prime_peak_jl) + G5_14Psi_h_over_deltastar_avg0p50_jl = AcousticAnalogies.G5_Psi14.(0.50, St_3prime_over_St_3prime_peak_jl) + G5_14Psi_h_over_deltastar_avg0p54_jl = AcousticAnalogies.G5_Psi14.(0.54, St_3prime_over_St_3prime_peak_jl) + G5_14Psi_h_over_deltastar_avg0p62_jl = AcousticAnalogies.G5_Psi14.(0.62, St_3prime_over_St_3prime_peak_jl) + G5_14Psi_h_over_deltastar_avg1p20_jl = AcousticAnalogies.G5_Psi14.(1.20, St_3prime_over_St_3prime_peak_jl) + + interp = linear(St_3prime_over_St_3prime_peak_jl, G5_14Psi_h_over_deltastar_avg0p25_jl, St_3prime_over_St_3prime_peak_0p25) + vmin, vmax = extrema(G5_14Psi_h_over_deltastar_avg0p25) + err = abs.(interp .- G5_14Psi_h_over_deltastar_avg0p25)/(vmax - vmin) + @test maximum(err) < 0.074 + + interp = linear(St_3prime_over_St_3prime_peak_jl, G5_14Psi_h_over_deltastar_avg0p43_jl, St_3prime_over_St_3prime_peak_0p43) + vmin, vmax = extrema(G5_14Psi_h_over_deltastar_avg0p43) + err = abs.(interp .- G5_14Psi_h_over_deltastar_avg0p43)/(vmax - vmin) + @test maximum(err) < 0.072 + + interp = linear(St_3prime_over_St_3prime_peak_jl, G5_14Psi_h_over_deltastar_avg0p50_jl, St_3prime_over_St_3prime_peak_0p50) + vmin, vmax = extrema(G5_14Psi_h_over_deltastar_avg0p50) + err = abs.(interp .- G5_14Psi_h_over_deltastar_avg0p50)/(vmax - vmin) + @test maximum(err) < 0.072 + + interp = linear(St_3prime_over_St_3prime_peak_jl, G5_14Psi_h_over_deltastar_avg0p54_jl, St_3prime_over_St_3prime_peak_0p54) + vmin, vmax = extrema(G5_14Psi_h_over_deltastar_avg0p54) + err = abs.(interp .- G5_14Psi_h_over_deltastar_avg0p54)/(vmax - vmin) + @test maximum(err) < 0.074 + + interp = linear(St_3prime_over_St_3prime_peak_jl, G5_14Psi_h_over_deltastar_avg0p62_jl, St_3prime_over_St_3prime_peak_0p62) + vmin, vmax = extrema(G5_14Psi_h_over_deltastar_avg0p62) + err = abs.(interp .- G5_14Psi_h_over_deltastar_avg0p62)/(vmax - vmin) + @test maximum(err) < 0.073 + + interp = linear(St_3prime_over_St_3prime_peak_jl, G5_14Psi_h_over_deltastar_avg1p20_jl, St_3prime_over_St_3prime_peak_1p20) + vmin, vmax = extrema(G5_14Psi_h_over_deltastar_avg1p20) + err = abs.(interp .- G5_14Psi_h_over_deltastar_avg1p20)/(vmax - vmin) + # The lower end of this case is really bad. + # Not sure why. :-( + @test maximum(err[1:22]) < 0.31 + @test maximum(err[23:end]) < 0.087 + end + + @testset "G5, Psi = 0°" begin + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure97-Psi0-h_over_deltastar0p25.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + St_3prime_over_St_3prime_peak_0p25 = bpm[:, 1] + G5_0Psi_h_over_deltastar_avg0p25 = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure97-Psi0-h_over_deltastar0p43.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + St_3prime_over_St_3prime_peak_0p43 = bpm[:, 1] + G5_0Psi_h_over_deltastar_avg0p43 = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure97-Psi0-h_over_deltastar0p50.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + St_3prime_over_St_3prime_peak_0p50 = bpm[:, 1] + G5_0Psi_h_over_deltastar_avg0p50 = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure97-Psi0-h_over_deltastar0p54.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + St_3prime_over_St_3prime_peak_0p54 = bpm[:, 1] + G5_0Psi_h_over_deltastar_avg0p54 = bpm[:, 2] + + # fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure97-Psi0-h_over_deltastar0p62.csv") + # bpm = DelimitedFiles.readdlm(fname, ',') + # St_3prime_over_St_3prime_peak_0p62 = bpm[:, 1] + # G5_0Psi_h_over_deltastar_avg0p62 = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure97-Psi0-h_over_deltastar1p20.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + St_3prime_over_St_3prime_peak_1p20 = bpm[:, 1] + G5_0Psi_h_over_deltastar_avg1p20 = bpm[:, 2] + + St_3prime_over_St_3prime_peak_jl = 10.0.^(range(-1, 10; length=1001)) + G5_0Psi_h_over_deltastar_avg0p25_jl = AcousticAnalogies.G5_Psi0.(0.25, St_3prime_over_St_3prime_peak_jl) + G5_0Psi_h_over_deltastar_avg0p43_jl = AcousticAnalogies.G5_Psi0.(0.43, St_3prime_over_St_3prime_peak_jl) + G5_0Psi_h_over_deltastar_avg0p50_jl = AcousticAnalogies.G5_Psi0.(0.50, St_3prime_over_St_3prime_peak_jl) + G5_0Psi_h_over_deltastar_avg0p54_jl = AcousticAnalogies.G5_Psi0.(0.54, St_3prime_over_St_3prime_peak_jl) + # G5_0Psi_h_over_deltastar_avg0p62_jl = AcousticAnalogies.G5_Psi0.(0.62, St_3prime_over_St_3prime_peak_jl) + G5_0Psi_h_over_deltastar_avg1p20_jl = AcousticAnalogies.G5_Psi0.(1.20, St_3prime_over_St_3prime_peak_jl) + + interp = linear(St_3prime_over_St_3prime_peak_jl, G5_0Psi_h_over_deltastar_avg0p25_jl, St_3prime_over_St_3prime_peak_0p25) + vmin, vmax = extrema(G5_0Psi_h_over_deltastar_avg0p25) + err = abs.(interp .- G5_0Psi_h_over_deltastar_avg0p25)/(vmax - vmin) + @test maximum(err) < 0.030 + + interp = linear(St_3prime_over_St_3prime_peak_jl, G5_0Psi_h_over_deltastar_avg0p43_jl, St_3prime_over_St_3prime_peak_0p43) + vmin, vmax = extrema(G5_0Psi_h_over_deltastar_avg0p43) + err = abs.(interp .- G5_0Psi_h_over_deltastar_avg0p43)/(vmax - vmin) + @test maximum(err) < 0.026 + + interp = linear(St_3prime_over_St_3prime_peak_jl, G5_0Psi_h_over_deltastar_avg0p50_jl, St_3prime_over_St_3prime_peak_0p50) + vmin, vmax = extrema(G5_0Psi_h_over_deltastar_avg0p50) + err = abs.(interp .- G5_0Psi_h_over_deltastar_avg0p50)/(vmax - vmin) + @test maximum(err) < 0.037 + + interp = linear(St_3prime_over_St_3prime_peak_jl, G5_0Psi_h_over_deltastar_avg0p54_jl, St_3prime_over_St_3prime_peak_0p54) + vmin, vmax = extrema(G5_0Psi_h_over_deltastar_avg0p54) + err = abs.(interp .- G5_0Psi_h_over_deltastar_avg0p54)/(vmax - vmin) + @test maximum(err) < 0.037 + + # interp = linear(St_3prime_over_St_3prime_peak_jl, G5_0Psi_h_over_deltastar_avg0p62_jl, St_3prime_over_St_3prime_peak_0p62) + # vmin, vmax = extrema(G5_0Psi_h_over_deltastar_avg0p62) + # err = abs.(interp .- G5_0Psi_h_over_deltastar_avg0p62)/(vmax - vmin) + # @test maximum(err) < 0.073 + + interp = linear(St_3prime_over_St_3prime_peak_jl, G5_0Psi_h_over_deltastar_avg1p20_jl, St_3prime_over_St_3prime_peak_1p20) + vmin, vmax = extrema(G5_0Psi_h_over_deltastar_avg1p20) + err = abs.(interp .- G5_0Psi_h_over_deltastar_avg1p20)/(vmax - vmin) + @test maximum(err) < 0.045 + end + + end + +end + +end # module diff --git a/test/bpm_writevtk_test.jl b/test/bpm_writevtk_test.jl new file mode 100644 index 00000000..72479dde --- /dev/null +++ b/test/bpm_writevtk_test.jl @@ -0,0 +1,305 @@ +module BPMWriteVTKTest + +using AcousticAnalogies +using CCBlade + +""" + XROTORAirfoilConfig(A0, DCLDA, CLMAX, CLMIN, DCL_STALL, DCLDA_STALL, CDMIN, CLDMIN, DCDCL2, REREF, REXP, MCRIT) + +`struct` that holds all the required parameters for XROTOR's approach to handling airfoil lift and drag polars. + +# Arguments +- `A0`: zero lift angle of attack, radians. +- `DCLDA`: lift curve slope, 1/radians. +- `CLMAX`: stall Cl. +- `CLMIN`: negative stall Cl. +- `DCL_STALL`: CL increment from incipient to total stall. +- `DCLDA_STALL`: stalled lift curve slope, 1/radian. +- `CDMIN`: minimum Cd. +- `CLDMIN`: Cl at minimum Cd. +- `DCDCL2`: d(Cd)/d(Cl**2). +- `REREF`: Reynolds Number at which Cd values apply. +- `REXP`: Exponent for Re scaling of Cd: Cd ~ Re**exponent +- `MCRIT`: Critical Mach number. +""" +struct XROTORAirfoilConfig{TF} + A0::TF # = 0. # zero lift angle of attack radians + DCLDA::TF # = 6.28 # lift curve slope /radian + CLMAX::TF # = 1.5 # stall Cl + CLMIN::TF # = -0.5 # negative stall Cl + DCL_STALL::TF # = 0.1 # CL increment from incipient to total stall + DCLDA_STALL::TF # = 0.1 # stalled lift curve slope /radian + CDMIN::TF # = 0.013 # minimum Cd + CLDMIN::TF # = 0.5 # Cl at minimum Cd + DCDCL2::TF # = 0.004 # d(Cd)/d(Cl**2) + REREF::TF # = 200000. # Reynolds Number at which Cd values apply + REXP::TF # = -0.4 # Exponent for Re scaling of Cd: Cd ~ Re**exponent + MCRIT::TF # = 0.8 # Critical Mach number +end + + +function XROTORAirfoilConfig(; A0, DCLDA, CLMAX, CLMIN, DCL_STALL, DCLDA_STALL, CDMIN, CLDMIN, DCDCL2, REREF, REXP, MCRIT) + return XROTORAirfoilConfig(A0, DCLDA, CLMAX, CLMIN, DCL_STALL, DCLDA_STALL, CDMIN, CLDMIN, DCDCL2, REREF, REXP, MCRIT) +end + +""" + af_xrotor(alpha, Re, Mach, config::XROTORAirfoilConfig) + +Return a tuple of the lift and drag coefficients for a given angle of attach +`alpha` (in radians), Reynolds number `Re`, and Mach number `Mach`. +""" +function af_xrotor(alpha, Re, Mach, config::XROTORAirfoilConfig) +# C------------------------------------------------------------ +# C CL(alpha) function +# C Note that in addition to setting CLIFT and its derivatives +# C CLMAX and CLMIN (+ and - stall CL's) are set in this routine +# C In the compressible range the stall CL is reduced by a factor +# C proportional to Mcrit-Mach. Stall limiting for compressible +# C cases begins when the compressible drag added CDC > CDMstall +# C------------------------------------------------------------ +# C CD(alpha) function - presently CD is assumed to be a sum +# C of profile drag + stall drag + compressibility drag +# C In the linear lift range drag is CD0 + quadratic function of CL-CLDMIN +# C In + or - stall an additional drag is added that is proportional +# C to the extent of lift reduction from the linear lift value. +# C Compressible drag is based on adding drag proportional to +# C (Mach-Mcrit_eff)^MEXP +# C------------------------------------------------------------ +# C CM(alpha) function - presently CM is assumed constant, +# C varying only with Mach by Prandtl-Glauert scaling +# C------------------------------------------------------------ +# C + # INCLUDE 'XROTOR.INC' + # LOGICAL STALLF + # DOUBLE PRECISION ECMIN, ECMAX +# C +# C---- Factors for compressibility drag model, HHY 10/23/00 +# C Mcrit is set by user +# C Effective Mcrit is Mcrit_eff = Mcrit - CLMFACTOR*(CL-CLDmin) - DMDD +# C DMDD is the delta Mach to get CD=CDMDD (usually 0.0020) +# C Compressible drag is CDC = CDMFACTOR*(Mach-Mcrit_eff)^MEXP +# C CDMstall is the drag at which compressible stall begins +# + A0 = config.A0 + DCLDA = config.DCLDA + CLMAX = config.CLMAX + CLMIN = config.CLMIN + DCL_STALL = config.DCL_STALL + DCLDA_STALL = config.DCLDA_STALL + CDMIN = config.CDMIN + CLDMIN = config.CLDMIN + DCDCL2 = config.DCDCL2 + REREF = config.REREF + REXP = config.REXP + MCRIT = config.MCRIT + + CDMFACTOR = 10.0 + CLMFACTOR = 0.25 + MEXP = 3.0 + CDMDD = 0.0020 + CDMSTALL = 0.1000 +# C +# C---- Prandtl-Glauert compressibility factor + # MSQ = W*W*VEL^2/VSO^2 + # MSQ_W = 2.0*W*VEL^2/VSO^2 + # if (MSQ>1.0) + # # WRITE(*,*) + # # & 'CLFUNC: Local Mach number limited to 0.99, was ', MSQ + # MSQ = 0.99 + # # MSQ_W = 0. + # end + MSQ = Mach*Mach + if MSQ > 1.0 + MSQ = 0.99 + Mach = sqrt(MSQ) + end + PG = 1.0 / sqrt(1.0 - MSQ) + # PG_W = 0.5*MSQ_W * PG^3 +# C +# C---- Mach number and dependence on velocity + # Mach = sqrt(MSQ) + # MACH_W = 0.0 + # IF(Mach.NE.0.0) MACH_W = 0.5*MSQ_W/Mach + # if ! (mach ≈ 0.0) + # MACH_W = 0.5*MSQ_W/Mach + # end +# C +# C +# C------------------------------------------------------------ +# C--- Generate CL from dCL/dAlpha and Prandtl-Glauert scaling + CLA = DCLDA*PG *(alpha-A0) + # CLA_ALF = DCLDA*PG + # CLA_W = DCLDA*PG_W*(ALF-A0) +# C +# C--- Effective CLmax is limited by Mach effects +# C reduces CLmax to match the CL of onset of serious compressible drag + CLMX = CLMAX + CLMN = CLMIN + DMSTALL = (CDMSTALL/CDMFACTOR)^(1.0/MEXP) + CLMAXM = max(0.0, (MCRIT+DMSTALL-Mach)/CLMFACTOR) + CLDMIN + CLMAX = min(CLMAX,CLMAXM) + CLMINM = min(0.0,-(MCRIT+DMSTALL-Mach)/CLMFACTOR) + CLDMIN + CLMIN = max(CLMIN,CLMINM) +# C +# C--- CL limiter function (turns on after +-stall + ECMAX = exp( min(200.0, (CLA-CLMAX)/DCL_STALL) ) + ECMIN = exp( min(200.0, (CLMIN-CLA)/DCL_STALL) ) + CLLIM = DCL_STALL * log( (1.0+ECMAX)/(1.0+ECMIN) ) + CLLIM_CLA = ECMAX/(1.0+ECMAX) + ECMIN/(1.0+ECMIN) +# c +# c if(CLLIM.GT.0.001) then +# c write(*,999) 'cla,cllim,ecmax,ecmin ',cla,cllim,ecmax,ecmin +# c endif +# c 999 format(a,2(1x,f10.6),3(1x,d12.6)) +# C +# C--- Subtract off a (nearly unity) fraction of the limited CL function +# C This sets the dCL/dAlpha in the stalled regions to 1-FSTALL of that +# C in the linear lift range + FSTALL = DCLDA_STALL/DCLDA + CLIFT = CLA - (1.0-FSTALL)*CLLIM + + # CL_ALF = CLA_ALF - (1.0-FSTALL)*CLLIM_CLA*CLA_ALF + # CL_W = CLA_W - (1.0-FSTALL)*CLLIM_CLA*CLA_W +# C + # STALLF = false + # IF(CLIFT.GT.CLMAX) STALLF = .TRUE. + # IF(CLIFT.LT.CLMIN) STALLF = .TRUE. + # STALLF = (CLIFT > CLMAX) || (CLIFT < CLMIN) + +# C +# C +# C------------------------------------------------------------ +# C--- CM from CMCON and Prandtl-Glauert scaling + # CMOM = PG*CMCON + # CM_AL = 0.0 + # CM_W = PG_W*CMCON +# C +# C +# C------------------------------------------------------------ +# C--- CD from profile drag, stall drag and compressibility drag +# C +# C---- Reynolds number scaling factor + if (Re < 0.0) + RCORR = 1.0 + # RCORR_REY = 0.0 + else + RCORR = (Re/REREF)^REXP + # RCORR_REY = REXP/Re + end +# C +# C--- In the basic linear lift range drag is a function of lift +# C CD = CD0 (constant) + quadratic with CL) + CDRAG = (CDMIN + DCDCL2*(CLIFT-CLDMIN)^2 ) * RCORR + # CD_ALF = ( 2.0*DCDCL2*(CLIFT-CLDMIN)*CL_ALF) * RCORR + # CD_W = ( 2.0*DCDCL2*(CLIFT-CLDMIN)*CL_W ) * RCORR + # CD_REY = CDRAG*RCORR_REY +# C +# C--- Post-stall drag added + FSTALL = DCLDA_STALL/DCLDA + DCDX = (1.0-FSTALL)*CLLIM/(PG*DCLDA) +# c write(*,*) 'cla,cllim,fstall,pg,dclda ',cla,cllim,fstall,pg,dclda + DCD = 2.0* DCDX^2 + # DCD_ALF = 4.0* DCDX * (1.0-FSTALL)*CLLIM_CLA*CLA_ALF/(PG*DCLDA) + # DCD_W = 4.0* DCDX * ( (1.0-FSTALL)*CLLIM_CLA*CLA_W/(PG*DCLDA) - DCD/PG*PG_W ) +# c write(*,*) 'alf,cl,dcd,dcd_alf,dcd_w ',alf,clift,dcd,dcd_alf,dcd_w +# C +# C--- Compressibility drag (accounts for drag rise above Mcrit with CL effects +# C CDC is a function of a scaling factor*(M-Mcrit(CL))^MEXP +# C DMDD is the Mach difference corresponding to CD rise of CDMDD at MCRIT + DMDD = (CDMDD/CDMFACTOR)^(1.0/MEXP) + CRITMACH = MCRIT-CLMFACTOR*abs(CLIFT-CLDMIN) - DMDD + # CRITMACH_ALF = -CLMFACTOR*ABS(CL_ALF) + # CRITMACH_W = -CLMFACTOR*ABS(CL_W) + if (Mach < CRITMACH) + CDC = 0.0 + # CDC_ALF = 0.0 + # CDC_W = 0.0 + else + CDC = CDMFACTOR*(Mach-CRITMACH)^MEXP + # CDC_W = MEXP*MACH_W*CDC/Mach - MEXP*CRITMACH_W *CDC/CRITMACH + # CDC_ALF = - MEXP*CRITMACH_ALF*CDC/CRITMACH + end +# c write(*,*) 'critmach,mach ',critmach,mach +# c write(*,*) 'cdc,cdc_w,cdc_alf ',cdc,cdc_w,cdc_alf +# C + FAC = 1.0 + # FAC_W = 0.0 +# C--- Although test data does not show profile drag increases due to Mach # +# C you could use something like this to add increase drag by Prandtl-Glauert +# C (or any function you choose) +# cc FAC = PG +# cc FAC_W = PG_W +# C--- Total drag terms + CDRAG = FAC*CDRAG + DCD + CDC + # CD_ALF = FAC*CD_ALF + DCD_ALF + CDC_ALF + # CD_W = FAC*CD_W + FAC_W*CDRAG + DCD_W + CDC_W + # CD_REY = FAC*CD_REY +# C + return CLIFT, CDRAG +end + +function main(; positive_x_rotation) + # Define the blade geometry. + B = 2 + Rhub = 0.10 + Rtip = 1.1684 # meters + radii = Rhub .+ range(0.0, 1.0, length=31).*(Rtip - Rhub) + radii = 0.5.*(radii[2:end] .+ radii[1:end-1]) + + cs_area_over_chord_squared = 0.064 + chord = [ + 0.35044 , 0.28260 , 0.22105 , 0.17787 , 0.14760, + 0.12567 , 0.10927 , 0.96661E-01 , 0.86742E-01 , + 0.78783E-01 , 0.72287E-01 , 0.66906E-01 , 0.62387E-01 , + 0.58541E-01 , 0.55217E-01 , 0.52290E-01 , 0.49645E-01 , + 0.47176E-01 , 0.44772E-01 , 0.42326E-01 , 0.39732E-01 , + 0.36898E-01 , 0.33752E-01 , 0.30255E-01 , 0.26401E-01 , + 0.22217E-01 , 0.17765E-01 , 0.13147E-01 , 0.85683E-02 , + 0.47397E-02].*Rtip + + theta = [ + 40.005, 34.201, 28.149, 23.753, 20.699, 18.516, 16.890, 15.633, + 14.625, 13.795, 13.094, 12.488, 11.956, 11.481, 11.053, 10.662, + 10.303, 9.9726, 9.6674, 9.3858, 9.1268, 8.8903, 8.6764, 8.4858, + 8.3193, 8.1783, 8.0638, 7.9769, 7.9183, 7.8889].*(pi/180) + + # Define the operating point. + rpm = 2200.0 + omega = rpm*(2*pi/60.0) + rho = 1.226 # kg/m^3 + c0 = 340.0 # m/s + mu = 0.1780e-4 # kg/(m*s) + pitch = 0.0 # rad + Vinf = 5.0 # m/s + + # Create an airfoil interpolation object. + xrotor_config = XROTORAirfoilConfig( + A0=0.0, DCLDA=6.2800, CLMAX=1.5, CLMIN=-0.5, DCLDA_STALL=0.1, + DCL_STALL=0.1, MCRIT=0.8, CDMIN=0.13e-1, CLDMIN=0.5, DCDCL2=0.4e-2, REREF=0.2e6, REXP=-0.4) + airfoil_interp(a, r, m) = af_xrotor(a, r, m, xrotor_config) + + # Create the CCBlade.jl structs. + rotor = Rotor(Rhub, Rtip, B) + sections = Section.(radii, chord, theta, Ref(airfoil_interp)) + ops = OperatingPoint.(Vinf, omega.*radii, rho, pitch, mu, c0) + outs = solve.(Ref(rotor), sections, ops) + + # Create the AcousticAnalogies.jl source elements. + bpp = 60/(rpm*B) + period = 2*bpp + num_source_times = 64 + alphastar0 = 12.5*pi/180 + ses = tblte_source_elements_ccblade(rotor, sections, ops, outs, fill(TrippedN0012BoundaryLayer(), length(radii)), period, num_source_times, positive_x_rotation) + @show size(ses) + + if positive_x_rotation + name = "two_blade_example_tblte_pos_x_rotation" + else + name = "two_blade_example_tblte_neg_x_rotation" + end + outfiles = AcousticAnalogies.to_paraview_collection(name, ses) + + return outfiles +end + +end diff --git a/test/broadband_source_element_tests.jl b/test/broadband_source_element_tests.jl new file mode 100644 index 00000000..6fe866ac --- /dev/null +++ b/test/broadband_source_element_tests.jl @@ -0,0 +1,2764 @@ +module BroadbandSourceElementTests + +using AcousticAnalogies +using AcousticAnalogies: calculate_bpm_test +using AcousticMetrics: AcousticMetrics +using CCBlade +using DelimitedFiles: DelimitedFiles +using FileIO: load +using FLOWMath: linear +using KinematicCoordinateTransformations: KinematicCoordinateTransformations, compose +using StaticArrays +using JLD2 +using Test +using LinearAlgebra: norm, dot, cross + +include("gen_test_data/gen_ccblade_data/constants.jl") +using .CCBladeTestCaseConstants +ccbc = CCBladeTestCaseConstants + +@testset "Twist and rotation tests" begin + # So, the way this should work: first do the twist, then do the theta rotation. + # The twist could be either about the positive y axis or negative y axis. + # Then the theta rotation is always about the x axis. + c0 = 1.1 + nu = 1.2 + r = 2.0 + Δr = 0.1 + chord = 1.3 + h = 1.4 + Psi = 1.5 + vn = 2.0 + vr = 3.0 + vc = 4.0 + τ = 0.1 + Δτ = 0.02 + bl = 2.0 # should be a boundary layer struct, but doesn't matter for these tests. + blade_tip = 3.0 # should be a blade tip struct, but doesn't matter for these tests. + for setype in [TBLTESourceElement, LBLVSSourceElement, TEBVSSourceElement, TipVortexSourceElement, CombinedNoTipBroadbandSourceElement, CombinedWithTipBroadbandSourceElement] + for twist_about_positive_y in [true, false] + if setype == CombinedWithTipBroadbandSourceElement + se_0twist0theta = setype(c0, nu, r, 0.0, Δr, chord, 0.0, h, Psi, vn, vr, vc, τ, Δτ, bl, blade_tip, twist_about_positive_y) + elseif setype == TipVortexSourceElement + se_0twist0theta = setype(c0, r, 0.0, Δr, chord, 0.0, vn, vr, vc, τ, Δτ, bl, blade_tip, twist_about_positive_y) + elseif setype in (TEBVSSourceElement, CombinedNoTipBroadbandSourceElement) + se_0twist0theta = setype(c0, nu, r, 0.0, Δr, chord, 0.0, h, Psi, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) + else + se_0twist0theta = setype(c0, nu, r, 0.0, Δr, chord, 0.0, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) + end + for θ in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + trans_theta = KinematicCoordinateTransformations.SteadyRotXTransformation(τ, 0.0, -θ) + + for ϕ in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + # The angle of attack depends on the twist and the fluid velocity + if twist_about_positive_y + alpha_check = ϕ - atan(-vn, -vc) + else + alpha_check = ϕ - atan(-vn, vc) + end + if setype == CombinedWithTipBroadbandSourceElement + se = setype(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, vn, vr, vc, τ, Δτ, bl, blade_tip, twist_about_positive_y) |> trans_theta + elseif setype == TipVortexSourceElement + se = setype(c0, r, θ, Δr, chord, ϕ, vn, vr, vc, τ, Δτ, bl, blade_tip, twist_about_positive_y) |> trans_theta + elseif setype in (TEBVSSourceElement, CombinedNoTipBroadbandSourceElement) + se = setype(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) |> trans_theta + else + se = setype(c0, nu, r, θ, Δr, chord, ϕ, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) |> trans_theta + end + # Adjust the angles of attack to always be between -pi and pi. + alpha_check = rem2pi(alpha_check+pi, RoundNearest) - pi + alpha = rem2pi(AcousticAnalogies.angle_of_attack(se)+pi, RoundNearest) - pi + @test alpha ≈ alpha_check + + for field in fieldnames(setype) + # The twist changes the unit vector in the chord direction, but nothing else, so ignore that for now. + if field != :chord_uvec + @test getproperty(se, field) ≈ getproperty(se_0twist0theta, field) + end + end + + if twist_about_positive_y + # If we're applying the twist about the positive y axis, then we need to do a negative rotation about the y axis to undo it. + trans_phi = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, -ϕ) + chord_uvec_check = @SVector [0.0, 0.0, -1.0] + else + # If we're applying the twist about the negative y axis, then we need to do a positive rotation about the y axis to undo it. + trans_phi = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, ϕ) + chord_uvec_check = @SVector [0.0, 0.0, 1.0] + end + se_no_twist = se |> trans_phi + @test se_no_twist.chord_uvec ≈ chord_uvec_check + + # Make sure we get the same thing if we specify the velocity via a velocity magnitude and angle of attack. + # But need to make sure we use vr == 0. + if setype == CombinedWithTipBroadbandSourceElement + se_no_vr = setype(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, vn, 0.0, vc, τ, Δτ, bl, blade_tip, twist_about_positive_y) + elseif setype == TipVortexSourceElement + se_no_vr = setype(c0, r, θ, Δr, chord, ϕ, vn, 0.0, vc, τ, Δτ, bl, blade_tip, twist_about_positive_y) + elseif setype in (TEBVSSourceElement, CombinedNoTipBroadbandSourceElement) + se_no_vr = setype(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, vn, 0.0, vc, τ, Δτ, bl, twist_about_positive_y) + else + se_no_vr = setype(c0, nu, r, θ, Δr, chord, ϕ, vn, 0.0, vc, τ, Δτ, bl, twist_about_positive_y) + end + # Removing vr, the radial velocity component, shouldn't change the angle of attack. + alpha_no_vr = rem2pi(AcousticAnalogies.angle_of_attack(se_no_vr)+pi, RoundNearest) - pi + @test alpha_no_vr ≈ alpha_check + # Now create a source element using the velocity magnitude and angle of attack, check that we get the same thing. + U = sqrt(vn^2 + vc^2) + if setype == CombinedWithTipBroadbandSourceElement + se_from_U_α = setype(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, U, alpha_no_vr, τ, Δτ, bl, blade_tip, twist_about_positive_y) + elseif setype == TipVortexSourceElement + se_from_U_α = setype(c0, r, θ, Δr, chord, ϕ, U, alpha_no_vr, τ, Δτ, bl, blade_tip, twist_about_positive_y) + elseif setype in (TEBVSSourceElement, CombinedNoTipBroadbandSourceElement) + se_from_U_α = setype(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, U, alpha_no_vr, τ, Δτ, bl, twist_about_positive_y) + else + se_from_U_α = setype(c0, nu, r, θ, Δr, chord, ϕ, U, alpha_no_vr, τ, Δτ, bl, twist_about_positive_y) + end + for field in fieldnames(setype) + @test getproperty(se_from_U_α, field) ≈ getproperty(se_no_vr, field) + end + + end + end + end + end +end + +@testset "TBLTESourceElement twist and rotation tests, CCBlade" begin + # Create the CCBlade objects. + τ = 0.1 + Δτ = 0.02 + bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() + + # ccblade_fname = joinpath(@__DIR__, "gen_test_data", "gen_ccblade_data", "ccblade_omega11.jld2") + # out, section_loaded, Δr, op, rotor0precone = nothing, nothing, nothing, nothing, nothing + # jldopen(ccblade_fname, "r") do f + # out = f["outs"][1] + # section_loaded = f["sections"][1] + # Δr = f["sections"][2].r - f["sections"][1].r + # op = f["ops"][1] + # rotor0precone = f["rotor"] + # @test rotor0precone.precone ≈ 0.0 + # end + + ccblade_fname = joinpath(@__DIR__, "gen_test_data", "gen_ccblade_data", "ccblade_omega11-outputs.jld2") + outs_d = load(ccblade_fname) + section_loaded = CCBlade.Section(first(ccbc.radii), first(ccbc.chord), first(ccbc.theta)*pi/180, nothing) + Δr = ccbc.radii[2] - ccbc.radii[1] + op = CCBlade.OperatingPoint(ccbc.v, outs_d["omega"]*first(ccbc.radii), ccbc.rho, ccbc.pitch, ccbc.mu, ccbc.c0) + rotor0precone = CCBlade.Rotor(ccbc.Rhub, ccbc.Rtip, ccbc.num_blades) + out = CCBlade.Outputs(outs_d["Np"][1], outs_d["Tp"][1], outs_d["a"][1], outs_d["ap"][1], outs_d["u"][1], outs_d["v"][1], outs_d["phi"][1], outs_d["alpha"][1], outs_d["W"][1], outs_d["cl"][1], outs_d["cd"][1], outs_d["cn"][1], outs_d["ct"][1], outs_d["F"][1], outs_d["G"][1]) + @test rotor0precone.precone ≈ 0.0 + + for positive_x_rotation in [true, false] + for twist in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + section = CCBlade.Section(section_loaded.r, section_loaded.chord, twist, section_loaded.af) + se_0theta0precone = TBLTESourceElement(rotor0precone, section, op, out, 0.0, Δr, τ, Δτ, bl, positive_x_rotation) + for precone in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + rotor = CCBlade.Rotor(rotor0precone.Rhub, rotor0precone.Rtip, rotor0precone.B; turbine=rotor0precone.turbine, precone=precone) + # This is tricky: in my "normal" coordinate system, the blade is rotating around the x axis, moving axially in the positive x direction, and is initially aligned with the y axis. + # That means that the precone should be a rotation around the negative z axis. + # And so to undo it, we want a positive rotation around the positive z axis. + trans_precone = KinematicCoordinateTransformations.SteadyRotZTransformation(τ, 0.0, precone) + for θ in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + trans_theta = KinematicCoordinateTransformations.SteadyRotXTransformation(τ, 0.0, -θ) + # Create a transformation that reverses the theta and precone rotations. + # The precone happens first, then theta. + # So to reverse it we need to do theta, then precone. + trans = KinematicCoordinateTransformations.compose(τ, trans_precone, trans_theta) + # Create a source element with the theta and precone rotations, then undo it. + se = TBLTESourceElement(rotor, section, op, out, θ, Δr, τ, Δτ, bl, positive_x_rotation) |> trans + # Check that we got the same thing: + for field in fieldnames(TBLTESourceElement) + # The twist changes the unit vector in the chord direction, but nothing else, so ignore that for now. + if !(field in (:chord_uvec, :bl)) + @test getproperty(se, field) ≈ getproperty(se_0theta0precone, field) + end + end + + if positive_x_rotation + # If we're doing a positive-x rotation, we're applying the twist about the positive y axis. + # If we're applying the twist about the positive y axis, then we need to do a negative rotation about the y axis to undo it. + trans_phi = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, -twist) + chord_uvec_check = @SVector [0.0, 0.0, -1.0] + else + # If we're doing a negative-x rotation, we're applying the twist about the negative y axis. + # If we're applying the twist about the negative y axis, then we need to do a positive rotation about the y axis to undo it. + trans_phi = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, twist) + chord_uvec_check = @SVector [0.0, 0.0, 1.0] + end + se_no_twist = se |> trans_phi + @test se_no_twist.chord_uvec ≈ chord_uvec_check + end + end + end + end +end + +@testset "CCBlade TBLTESourceElement complete test" begin + for positive_x_rotation in [true, false] + omega = 2200*(2*pi/60) + + # Create the CCBlade objects. + rotor = Rotor(ccbc.Rhub, ccbc.Rtip, ccbc.num_blades; turbine=false) + sections = Section.(ccbc.radii, ccbc.chord, ccbc.theta, nothing) + ops = simple_op.(ccbc.v, omega, ccbc.radii, ccbc.rho; asound=ccbc.c0) + # What actually matters in the output structs are just W and phi. + phi = range(45.0, 10.0; length=length(sections)) .* (pi/180) + W = range(10.0, 11.0; length=length(sections)) + outs = Outputs.(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, phi, 0.0, W, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) + + # Set the source time stuff. + num_blade_passes = 3 + steps_per_blade_pass = 8 + num_src_times = num_blade_passes*steps_per_blade_pass + bpp = 2*pi/omega/ccbc.num_blades + src_time_range = num_blade_passes*bpp + + # Finally get all the source elements. + bls = [AcousticAnalogies.TrippedN0012BoundaryLayer()] + ses_helper = tblte_source_elements_ccblade(rotor, sections, ops, outs, bls, src_time_range, num_src_times, positive_x_rotation) + + # Now need to get the source elements the "normal" way. + # First get the transformation objects. + rot_axis = @SVector [1.0, 0.0, 0.0] + blade_axis = @SVector [0.0, 1.0, 0.0] + y0_hub = @SVector [0.0, 0.0, 0.0] # m + v0_hub = ccbc.v.*rot_axis + t0 = 0.0 + if positive_x_rotation + rot_trans = KinematicCoordinateTransformations.SteadyRotXTransformation(t0, omega, 0.0) + else + rot_trans = KinematicCoordinateTransformations.SteadyRotXTransformation(t0, -omega, 0.0) + end + const_vel_trans = KinematicCoordinateTransformations.ConstantVelocityTransformation(t0, y0_hub, v0_hub) + + # Need the source times. + dt = src_time_range/num_src_times + src_times = t0 .+ (0:num_src_times-1).*dt + + # This is just an array of the angular offsets of each blade. + θs = 2*pi/ccbc.num_blades.*(0:(ccbc.num_blades-1)) + + # Radial spacing. + dradii = get_dradii(ccbc.radii, ccbc.Rhub, ccbc.Rtip) + + # Need the kinematic viscosity. + nus = getproperty.(ops, :mu) ./ getproperty.(ops, :rho) + + # Also need the velocity in each direction. + if positive_x_rotation + vn = @. -W*sin(phi) + vr = zeros(eltype(vn), length(vn)) + vc = @. -W*cos(phi) + else + vn = @. -W*sin(phi) + vr = zeros(eltype(vn), length(vn)) + vc = @. W*cos(phi) + end + + # Reshape stuff for broadcasting. + radii_rs = reshape(ccbc.radii, 1, :, 1) + dradii_rs = reshape(dradii, 1, :, 1) + phi_rs = reshape(phi, 1, :, 1) + W_rs = reshape(W, 1, :, 1) + src_times_rs = reshape(src_times, :, 1, 1) # This isn't really necessary. + θs_rs = reshape(θs, 1, 1, :) + nus_rs = reshape(nus, 1, :, 1) + twist_rs = reshape(getproperty.(sections, :theta), 1, :, 1) + chord_rs = reshape(getproperty.(sections, :chord), 1, :, 1) + vn_rs = reshape(vn, 1, :, 1) + vr_rs = reshape(vr, 1, :, 1) + vc_rs = reshape(vc, 1, :, 1) + + # Get all the transformations. + trans = compose.(src_times, Ref(const_vel_trans), Ref(rot_trans)) + + # Transform the source elements. + ses = TBLTESourceElement.(ccbc.c0, nus_rs, radii_rs, θs_rs, dradii_rs, chord_rs, twist_rs, vn_rs, vr_rs, vc_rs, src_times_rs, dt, bls, positive_x_rotation) .|> trans + + # Now check that we got the same thing. + for field in fieldnames(TBLTESourceElement) + if !(field in (:bl,)) + @test all(getproperty.(ses_helper, field) .≈ getproperty.(ses, field)) + end + end + end +end + +@testset "LBLVSSourceElement twist and rotation tests" begin + # So, the way this should work: first do the twist, then do the theta rotation. + # The twist could be either about the positive y axis or negative y axis. + # Then the theta rotation is always about the x axis. + c0 = 1.1 + nu = 1.2 + r = 2.0 + Δr = 0.1 + chord = 1.3 + vn = 2.0 + vr = 3.0 + vc = 4.0 + τ = 0.1 + Δτ = 0.02 + bl = 2.0 # should be a boundary layer struct, but doesn't matter for these tests. + for twist_about_positive_y in [true, false] + se_0twist0theta = LBLVSSourceElement(c0, nu, r, 0.0, Δr, chord, 0.0, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) + for θ in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + trans_theta = KinematicCoordinateTransformations.SteadyRotXTransformation(τ, 0.0, -θ) + + for ϕ in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + # The angle of attack depends on the twist and the fluid velocity + if twist_about_positive_y + alpha_check = ϕ - atan(-vn, -vc) + else + alpha_check = ϕ - atan(-vn, vc) + end + se = LBLVSSourceElement(c0, nu, r, θ, Δr, chord, ϕ, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) |> trans_theta + # Adjust the angles of attack to always be between -pi and pi. + alpha_check = rem2pi(alpha_check+pi, RoundNearest) - pi + alpha = rem2pi(AcousticAnalogies.angle_of_attack(se)+pi, RoundNearest) - pi + @test alpha ≈ alpha_check + + for field in fieldnames(LBLVSSourceElement) + # The twist changes the unit vector in the chord direction, but nothing else, so ignore that for now. + if field != :chord_uvec + @test getproperty(se, field) ≈ getproperty(se_0twist0theta, field) + end + end + + if twist_about_positive_y + # If we're applying the twist about the positive y axis, then we need to do a negative rotation about the y axis to undo it. + trans_phi = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, -ϕ) + chord_uvec_check = @SVector [0.0, 0.0, -1.0] + else + # If we're applying the twist about the negative y axis, then we need to do a positive rotation about the y axis to undo it. + trans_phi = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, ϕ) + chord_uvec_check = @SVector [0.0, 0.0, 1.0] + end + se_no_twist = se |> trans_phi + @test se_no_twist.chord_uvec ≈ chord_uvec_check + end + end + end +end + +@testset "LBLVSSourceElement twist and rotation tests, CCBlade" begin + # Create the CCBlade objects. + τ = 0.1 + Δτ = 0.02 + bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() + + # ccblade_fname = joinpath(@__DIR__, "gen_test_data", "gen_ccblade_data", "ccblade_omega11.jld2") + # out, section_loaded, Δr, op, rotor0precone = nothing, nothing, nothing, nothing, nothing + # jldopen(ccblade_fname, "r") do f + # out = f["outs"][1] + # section_loaded = f["sections"][1] + # Δr = f["sections"][2].r - f["sections"][1].r + # op = f["ops"][1] + # rotor0precone = f["rotor"] + # @test rotor0precone.precone ≈ 0.0 + # end + + ccblade_fname = joinpath(@__DIR__, "gen_test_data", "gen_ccblade_data", "ccblade_omega11-outputs.jld2") + outs_d = load(ccblade_fname) + section_loaded = CCBlade.Section(first(ccbc.radii), first(ccbc.chord), first(ccbc.theta)*pi/180, nothing) + Δr = ccbc.radii[2] - ccbc.radii[1] + op = CCBlade.OperatingPoint(ccbc.v, outs_d["omega"]*first(ccbc.radii), ccbc.rho, ccbc.pitch, ccbc.mu, ccbc.c0) + rotor0precone = CCBlade.Rotor(ccbc.Rhub, ccbc.Rtip, ccbc.num_blades) + out = CCBlade.Outputs(outs_d["Np"][1], outs_d["Tp"][1], outs_d["a"][1], outs_d["ap"][1], outs_d["u"][1], outs_d["v"][1], outs_d["phi"][1], outs_d["alpha"][1], outs_d["W"][1], outs_d["cl"][1], outs_d["cd"][1], outs_d["cn"][1], outs_d["ct"][1], outs_d["F"][1], outs_d["G"][1]) + @test rotor0precone.precone ≈ 0.0 + + for positive_x_rotation in [true, false] + for twist in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + section = CCBlade.Section(section_loaded.r, section_loaded.chord, twist, section_loaded.af) + se_0theta0precone = LBLVSSourceElement(rotor0precone, section, op, out, 0.0, Δr, τ, Δτ, bl, positive_x_rotation) + for precone in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + rotor = CCBlade.Rotor(rotor0precone.Rhub, rotor0precone.Rtip, rotor0precone.B; turbine=rotor0precone.turbine, precone=precone) + # This is tricky: in my "normal" coordinate system, the blade is rotating around the x axis, moving axially in the positive x direction, and is initially aligned with the y axis. + # That means that the precone should be a rotation around the negative z axis. + # And so to undo it, we want a positive rotation around the positive z axis. + trans_precone = KinematicCoordinateTransformations.SteadyRotZTransformation(τ, 0.0, precone) + for θ in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + trans_theta = KinematicCoordinateTransformations.SteadyRotXTransformation(τ, 0.0, -θ) + # Create a transformation that reverses the theta and precone rotations. + # The precone happens first, then theta. + # So to reverse it we need to do theta, then precone. + trans = KinematicCoordinateTransformations.compose(τ, trans_precone, trans_theta) + # Create a source element with the theta and precone rotations, then undo it. + se = LBLVSSourceElement(rotor, section, op, out, θ, Δr, τ, Δτ, bl, positive_x_rotation) |> trans + # Check that we got the same thing: + for field in fieldnames(LBLVSSourceElement) + # The twist changes the unit vector in the chord direction, but nothing else, so ignore that for now. + if !(field in (:chord_uvec, :bl)) + @test getproperty(se, field) ≈ getproperty(se_0theta0precone, field) + end + end + + if positive_x_rotation + # If we're doing a positive-x rotation, we're applying the twist about the positive y axis. + # If we're applying the twist about the positive y axis, then we need to do a negative rotation about the y axis to undo it. + trans_phi = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, -twist) + chord_uvec_check = @SVector [0.0, 0.0, -1.0] + else + # If we're doing a negative-x rotation, we're applying the twist about the negative y axis. + # If we're applying the twist about the negative y axis, then we need to do a positive rotation about the y axis to undo it. + trans_phi = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, twist) + chord_uvec_check = @SVector [0.0, 0.0, 1.0] + end + se_no_twist = se |> trans_phi + @test se_no_twist.chord_uvec ≈ chord_uvec_check + end + end + end + end +end + +@testset "CCBlade LBLVSSourceElement complete test" begin + for positive_x_rotation in [true, false] + omega = 2200*(2*pi/60) + + # Create the CCBlade objects. + rotor = Rotor(ccbc.Rhub, ccbc.Rtip, ccbc.num_blades; turbine=false) + sections = Section.(ccbc.radii, ccbc.chord, ccbc.theta, nothing) + ops = simple_op.(ccbc.v, omega, ccbc.radii, ccbc.rho; asound=ccbc.c0) + # What actually matters in the output structs are just W and phi. + phi = range(45.0, 10.0; length=length(sections)) .* (pi/180) + W = range(10.0, 11.0; length=length(sections)) + outs = Outputs.(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, phi, 0.0, W, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) + + # Set the source time stuff. + num_blade_passes = 3 + steps_per_blade_pass = 8 + num_src_times = num_blade_passes*steps_per_blade_pass + bpp = 2*pi/omega/ccbc.num_blades + src_time_range = num_blade_passes*bpp + + # Finally get all the source elements. + bls = [AcousticAnalogies.TrippedN0012BoundaryLayer()] + ses_helper = lblvs_source_elements_ccblade(rotor, sections, ops, outs, bls, src_time_range, num_src_times, positive_x_rotation) + + # Now need to get the source elements the "normal" way. + # First get the transformation objects. + rot_axis = @SVector [1.0, 0.0, 0.0] + blade_axis = @SVector [0.0, 1.0, 0.0] + y0_hub = @SVector [0.0, 0.0, 0.0] # m + v0_hub = ccbc.v.*rot_axis + t0 = 0.0 + if positive_x_rotation + rot_trans = KinematicCoordinateTransformations.SteadyRotXTransformation(t0, omega, 0.0) + else + rot_trans = KinematicCoordinateTransformations.SteadyRotXTransformation(t0, -omega, 0.0) + end + const_vel_trans = KinematicCoordinateTransformations.ConstantVelocityTransformation(t0, y0_hub, v0_hub) + + # Need the source times. + dt = src_time_range/num_src_times + src_times = t0 .+ (0:num_src_times-1).*dt + + # This is just an array of the angular offsets of each blade. + θs = 2*pi/ccbc.num_blades.*(0:(ccbc.num_blades-1)) + + # Radial spacing. + dradii = get_dradii(ccbc.radii, ccbc.Rhub, ccbc.Rtip) + + # Need the kinematic viscosity. + nus = getproperty.(ops, :mu) ./ getproperty.(ops, :rho) + + # Also need the velocity in each direction. + if positive_x_rotation + vn = @. -W*sin(phi) + vr = zeros(eltype(vn), length(vn)) + vc = @. -W*cos(phi) + else + vn = @. -W*sin(phi) + vr = zeros(eltype(vn), length(vn)) + vc = @. W*cos(phi) + end + + # Reshape stuff for broadcasting. + radii_rs = reshape(ccbc.radii, 1, :, 1) + dradii_rs = reshape(dradii, 1, :, 1) + phi_rs = reshape(phi, 1, :, 1) + W_rs = reshape(W, 1, :, 1) + src_times_rs = reshape(src_times, :, 1, 1) # This isn't really necessary. + θs_rs = reshape(θs, 1, 1, :) + nus_rs = reshape(nus, 1, :, 1) + twist_rs = reshape(getproperty.(sections, :theta), 1, :, 1) + chord_rs = reshape(getproperty.(sections, :chord), 1, :, 1) + vn_rs = reshape(vn, 1, :, 1) + vr_rs = reshape(vr, 1, :, 1) + vc_rs = reshape(vc, 1, :, 1) + + # Get all the transformations. + trans = compose.(src_times, Ref(const_vel_trans), Ref(rot_trans)) + + # Transform the source elements. + ses = LBLVSSourceElement.(ccbc.c0, nus_rs, radii_rs, θs_rs, dradii_rs, chord_rs, twist_rs, vn_rs, vr_rs, vc_rs, src_times_rs, dt, bls, positive_x_rotation) .|> trans + + # Now check that we got the same thing. + for field in fieldnames(LBLVSSourceElement) + if !(field in (:bl,)) + @test all(getproperty.(ses_helper, field) .≈ getproperty.(ses, field)) + end + end + end +end + +@testset "TEBVSSourceElement twist and rotation tests" begin + # So, the way this should work: first do the twist, then do the theta rotation. + # The twist could be either about the positive y axis or negative y axis. + # Then the theta rotation is always about the x axis. + c0 = 1.1 + nu = 1.2 + r = 2.0 + Δr = 0.1 + chord = 1.3 + vn = 2.0 + vr = 3.0 + vc = 4.0 + τ = 0.1 + Δτ = 0.02 + h = 0.1 + Psi = 0.2 + bl = 2.0 # should be a boundary layer struct, but doesn't matter for these tests. + for twist_about_positive_y in [true, false] + se_0twist0theta = TEBVSSourceElement(c0, nu, r, 0.0, Δr, chord, 0.0, h, Psi, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) + for θ in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + trans_theta = KinematicCoordinateTransformations.SteadyRotXTransformation(τ, 0.0, -θ) + + for ϕ in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + # The angle of attack depends on the twist and the fluid velocity + if twist_about_positive_y + alpha_check = ϕ - atan(-vn, -vc) + else + alpha_check = ϕ - atan(-vn, vc) + end + se = TEBVSSourceElement(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) |> trans_theta + # Adjust the angles of attack to always be between -pi and pi. + alpha_check = rem2pi(alpha_check+pi, RoundNearest) - pi + alpha = rem2pi(AcousticAnalogies.angle_of_attack(se)+pi, RoundNearest) - pi + @test alpha ≈ alpha_check + + for field in fieldnames(TEBVSSourceElement) + # The twist changes the unit vector in the chord direction, but nothing else, so ignore that for now. + if field != :chord_uvec + @test getproperty(se, field) ≈ getproperty(se_0twist0theta, field) + end + end + + if twist_about_positive_y + # If we're applying the twist about the positive y axis, then we need to do a negative rotation about the y axis to undo it. + trans_phi = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, -ϕ) + chord_uvec_check = @SVector [0.0, 0.0, -1.0] + else + # If we're applying the twist about the negative y axis, then we need to do a positive rotation about the y axis to undo it. + trans_phi = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, ϕ) + chord_uvec_check = @SVector [0.0, 0.0, 1.0] + end + se_no_twist = se |> trans_phi + @test se_no_twist.chord_uvec ≈ chord_uvec_check + end + end + end +end + +@testset "TEBVSSourceElement twist and rotation tests, CCBlade" begin + # Create the CCBlade objects. + τ = 0.1 + Δτ = 0.02 + h = 0.1 + Psi = 0.2 + bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() + # ccblade_fname = joinpath(@__DIR__, "gen_test_data", "gen_ccblade_data", "ccblade_omega11.jld2") + # out, section_loaded, Δr, op, rotor0precone = nothing, nothing, nothing, nothing, nothing + # jldopen(ccblade_fname, "r") do f + # out = f["outs"][1] + # section_loaded = f["sections"][1] + # Δr = f["sections"][2].r - f["sections"][1].r + # op = f["ops"][1] + # rotor0precone = f["rotor"] + # @test rotor0precone.precone ≈ 0.0 + # end + + ccblade_fname = joinpath(@__DIR__, "gen_test_data", "gen_ccblade_data", "ccblade_omega11-outputs.jld2") + outs_d = load(ccblade_fname) + section_loaded = CCBlade.Section(first(ccbc.radii), first(ccbc.chord), first(ccbc.theta)*pi/180, nothing) + Δr = ccbc.radii[2] - ccbc.radii[1] + op = CCBlade.OperatingPoint(ccbc.v, outs_d["omega"]*first(ccbc.radii), ccbc.rho, ccbc.pitch, ccbc.mu, ccbc.c0) + rotor0precone = CCBlade.Rotor(ccbc.Rhub, ccbc.Rtip, ccbc.num_blades) + out = CCBlade.Outputs(outs_d["Np"][1], outs_d["Tp"][1], outs_d["a"][1], outs_d["ap"][1], outs_d["u"][1], outs_d["v"][1], outs_d["phi"][1], outs_d["alpha"][1], outs_d["W"][1], outs_d["cl"][1], outs_d["cd"][1], outs_d["cn"][1], outs_d["ct"][1], outs_d["F"][1], outs_d["G"][1]) + @test rotor0precone.precone ≈ 0.0 + + for positive_x_rotation in [true, false] + for twist in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + section = CCBlade.Section(section_loaded.r, section_loaded.chord, twist, section_loaded.af) + se_0theta0precone = TEBVSSourceElement(rotor0precone, section, op, out, 0.0, Δr, h, Psi, τ, Δτ, bl, positive_x_rotation) + for precone in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + rotor = CCBlade.Rotor(rotor0precone.Rhub, rotor0precone.Rtip, rotor0precone.B; turbine=rotor0precone.turbine, precone=precone) + # This is tricky: in my "normal" coordinate system, the blade is rotating around the x axis, moving axially in the positive x direction, and is initially aligned with the y axis. + # That means that the precone should be a rotation around the negative z axis. + # And so to undo it, we want a positive rotation around the positive z axis. + trans_precone = KinematicCoordinateTransformations.SteadyRotZTransformation(τ, 0.0, precone) + for θ in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + trans_theta = KinematicCoordinateTransformations.SteadyRotXTransformation(τ, 0.0, -θ) + # Create a transformation that reverses the theta and precone rotations. + # The precone happens first, then theta. + # So to reverse it we need to do theta, then precone. + trans = KinematicCoordinateTransformations.compose(τ, trans_precone, trans_theta) + # Create a source element with the theta and precone rotations, then undo it. + se = TEBVSSourceElement(rotor, section, op, out, θ, Δr, h, Psi, τ, Δτ, bl, positive_x_rotation) |> trans + # Check that we got the same thing: + for field in fieldnames(TEBVSSourceElement) + # The twist changes the unit vector in the chord direction, but nothing else, so ignore that for now. + if !(field in (:chord_uvec, :bl)) + @test getproperty(se, field) ≈ getproperty(se_0theta0precone, field) + end + end + + if positive_x_rotation + # If we're doing a positive-x rotation, we're applying the twist about the positive y axis. + # If we're applying the twist about the positive y axis, then we need to do a negative rotation about the y axis to undo it. + trans_phi = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, -twist) + chord_uvec_check = @SVector [0.0, 0.0, -1.0] + else + # If we're doing a negative-x rotation, we're applying the twist about the negative y axis. + # If we're applying the twist about the negative y axis, then we need to do a positive rotation about the y axis to undo it. + trans_phi = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, twist) + chord_uvec_check = @SVector [0.0, 0.0, 1.0] + end + se_no_twist = se |> trans_phi + @test se_no_twist.chord_uvec ≈ chord_uvec_check + end + end + end + end +end + +@testset "CCBlade TEBVSSourceElement complete test" begin + for positive_x_rotation in [true, false] + omega = 2200*(2*pi/60) + + # Create the CCBlade objects. + rotor = Rotor(ccbc.Rhub, ccbc.Rtip, ccbc.num_blades; turbine=false) + sections = Section.(ccbc.radii, ccbc.chord, ccbc.theta, nothing) + ops = simple_op.(ccbc.v, omega, ccbc.radii, ccbc.rho; asound=ccbc.c0) + # What actually matters in the output structs are just W and phi. + phi = range(45.0, 10.0; length=length(sections)) .* (pi/180) + W = range(10.0, 11.0; length=length(sections)) + outs = Outputs.(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, phi, 0.0, W, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) + + # Set the source time stuff. + num_blade_passes = 3 + steps_per_blade_pass = 8 + num_src_times = num_blade_passes*steps_per_blade_pass + bpp = 2*pi/omega/ccbc.num_blades + src_time_range = num_blade_passes*bpp + + # Finally get all the source elements. + bls = [AcousticAnalogies.TrippedN0012BoundaryLayer()] + hs = range(0.1, 0.2; length=length(sections)) + Psis = range(0.2, 0.3; length=length(sections)) + ses_helper = tebvs_source_elements_ccblade(rotor, sections, ops, outs, hs, Psis, bls, src_time_range, num_src_times, positive_x_rotation) + + # Now need to get the source elements the "normal" way. + # First get the transformation objects. + rot_axis = @SVector [1.0, 0.0, 0.0] + blade_axis = @SVector [0.0, 1.0, 0.0] + y0_hub = @SVector [0.0, 0.0, 0.0] # m + v0_hub = ccbc.v.*rot_axis + t0 = 0.0 + if positive_x_rotation + rot_trans = KinematicCoordinateTransformations.SteadyRotXTransformation(t0, omega, 0.0) + else + rot_trans = KinematicCoordinateTransformations.SteadyRotXTransformation(t0, -omega, 0.0) + end + const_vel_trans = KinematicCoordinateTransformations.ConstantVelocityTransformation(t0, y0_hub, v0_hub) + + # Need the source times. + dt = src_time_range/num_src_times + src_times = t0 .+ (0:num_src_times-1).*dt + + # This is just an array of the angular offsets of each blade. + θs = 2*pi/ccbc.num_blades.*(0:(ccbc.num_blades-1)) + + # Radial spacing. + dradii = get_dradii(ccbc.radii, ccbc.Rhub, ccbc.Rtip) + + # Need the kinematic viscosity. + nus = getproperty.(ops, :mu) ./ getproperty.(ops, :rho) + + # Also need the velocity in each direction. + if positive_x_rotation + vn = @. -W*sin(phi) + vr = zeros(eltype(vn), length(vn)) + vc = @. -W*cos(phi) + else + vn = @. -W*sin(phi) + vr = zeros(eltype(vn), length(vn)) + vc = @. W*cos(phi) + end + + # Reshape stuff for broadcasting. + radii_rs = reshape(ccbc.radii, 1, :, 1) + dradii_rs = reshape(dradii, 1, :, 1) + phi_rs = reshape(phi, 1, :, 1) + W_rs = reshape(W, 1, :, 1) + src_times_rs = reshape(src_times, :, 1, 1) # This isn't really necessary. + θs_rs = reshape(θs, 1, 1, :) + nus_rs = reshape(nus, 1, :, 1) + twist_rs = reshape(getproperty.(sections, :theta), 1, :, 1) + chord_rs = reshape(getproperty.(sections, :chord), 1, :, 1) + vn_rs = reshape(vn, 1, :, 1) + vr_rs = reshape(vr, 1, :, 1) + vc_rs = reshape(vc, 1, :, 1) + h_rs = reshape(hs, 1, :, 1) + Psi_rs = reshape(Psis, 1, :, 1) + + # Get all the transformations. + trans = compose.(src_times, Ref(const_vel_trans), Ref(rot_trans)) + + # Transform the source elements. + ses = TEBVSSourceElement.(ccbc.c0, nus_rs, radii_rs, θs_rs, dradii_rs, chord_rs, twist_rs, h_rs, Psi_rs, vn_rs, vr_rs, vc_rs, src_times_rs, dt, bls, positive_x_rotation) .|> trans + + # Now check that we got the same thing. + for field in fieldnames(TEBVSSourceElement) + if !(field in (:bl,)) + @test all(getproperty.(ses_helper, field) .≈ getproperty.(ses, field)) + end + end + end +end + +@testset "TipVortexSourceElement twist and rotation tests" begin + # So, the way this should work: first do the twist, then do the theta rotation. + # The twist could be either about the positive y axis or negative y axis. + # Then the theta rotation is always about the x axis. + c0 = 1.1 + # nu = 1.2 + r = 2.0 + Δr = 0.1 + chord = 1.3 + vn = 2.0 + vr = 3.0 + vc = 4.0 + τ = 0.1 + Δτ = 0.02 + bl = 2.0 # should be a boundary layer struct, but doesn't matter for these tests. + blade_tip = 3.0 # should be a blade tip struct, but doesn't matter for these tests. + for twist_about_positive_y in [true, false] + se_0twist0theta = TipVortexSourceElement(c0, r, 0.0, Δr, chord, 0.0, vn, vr, vc, τ, Δτ, bl, blade_tip, twist_about_positive_y) + for θ in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + trans_theta = KinematicCoordinateTransformations.SteadyRotXTransformation(τ, 0.0, -θ) + + for ϕ in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + # The angle of attack depends on the twist and the fluid velocity + if twist_about_positive_y + alpha_check = ϕ - atan(-vn, -vc) + else + alpha_check = ϕ - atan(-vn, vc) + end + se = TipVortexSourceElement(c0, r, θ, Δr, chord, ϕ, vn, vr, vc, τ, Δτ, bl, blade_tip, twist_about_positive_y) |> trans_theta + # Adjust the angles of attack to always be between -pi and pi. + alpha_check = rem2pi(alpha_check+pi, RoundNearest) - pi + alpha = rem2pi(AcousticAnalogies.angle_of_attack(se)+pi, RoundNearest) - pi + @test alpha ≈ alpha_check + + for field in fieldnames(TipVortexSourceElement) + # The twist changes the unit vector in the chord direction, but nothing else, so ignore that for now. + if field != :chord_uvec + @test getproperty(se, field) ≈ getproperty(se_0twist0theta, field) + end + end + + if twist_about_positive_y + # If we're applying the twist about the positive y axis, then we need to do a negative rotation about the y axis to undo it. + trans_phi = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, -ϕ) + chord_uvec_check = @SVector [0.0, 0.0, -1.0] + else + # If we're applying the twist about the negative y axis, then we need to do a positive rotation about the y axis to undo it. + trans_phi = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, ϕ) + chord_uvec_check = @SVector [0.0, 0.0, 1.0] + end + se_no_twist = se |> trans_phi + @test se_no_twist.chord_uvec ≈ chord_uvec_check + end + end + end +end + +@testset "TipVortexSourceElement twist and rotation tests, CCBlade" begin + # Create the CCBlade objects. + τ = 0.1 + Δτ = 0.02 + bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() + blade_tip = AcousticAnalogies.RoundedTip() + # ccblade_fname = joinpath(@__DIR__, "gen_test_data", "gen_ccblade_data", "ccblade_omega11.jld2") + # out, section_loaded, Δr, op, rotor0precone = nothing, nothing, nothing, nothing, nothing + # jldopen(ccblade_fname, "r") do f + # out = f["outs"][1] + # section_loaded = f["sections"][1] + # Δr = f["sections"][2].r - f["sections"][1].r + # op = f["ops"][1] + # rotor0precone = f["rotor"] + # @test rotor0precone.precone ≈ 0.0 + # end + + ccblade_fname = joinpath(@__DIR__, "gen_test_data", "gen_ccblade_data", "ccblade_omega11-outputs.jld2") + outs_d = load(ccblade_fname) + section_loaded = CCBlade.Section(first(ccbc.radii), first(ccbc.chord), first(ccbc.theta)*pi/180, nothing) + Δr = ccbc.radii[2] - ccbc.radii[1] + op = CCBlade.OperatingPoint(ccbc.v, outs_d["omega"]*first(ccbc.radii), ccbc.rho, ccbc.pitch, ccbc.mu, ccbc.c0) + rotor0precone = CCBlade.Rotor(ccbc.Rhub, ccbc.Rtip, ccbc.num_blades) + out = CCBlade.Outputs(outs_d["Np"][1], outs_d["Tp"][1], outs_d["a"][1], outs_d["ap"][1], outs_d["u"][1], outs_d["v"][1], outs_d["phi"][1], outs_d["alpha"][1], outs_d["W"][1], outs_d["cl"][1], outs_d["cd"][1], outs_d["cn"][1], outs_d["ct"][1], outs_d["F"][1], outs_d["G"][1]) + @test rotor0precone.precone ≈ 0.0 + + for positive_x_rotation in [true, false] + for twist in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + section = CCBlade.Section(section_loaded.r, section_loaded.chord, twist, section_loaded.af) + se_0theta0precone = TipVortexSourceElement(rotor0precone, section, op, out, 0.0, Δr, τ, Δτ, bl, blade_tip, positive_x_rotation) + for precone in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + rotor = CCBlade.Rotor(rotor0precone.Rhub, rotor0precone.Rtip, rotor0precone.B; turbine=rotor0precone.turbine, precone=precone) + # This is tricky: in my "normal" coordinate system, the blade is rotating around the x axis, moving axially in the positive x direction, and is initially aligned with the y axis. + # That means that the precone should be a rotation around the negative z axis. + # And so to undo it, we want a positive rotation around the positive z axis. + trans_precone = KinematicCoordinateTransformations.SteadyRotZTransformation(τ, 0.0, precone) + for θ in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + trans_theta = KinematicCoordinateTransformations.SteadyRotXTransformation(τ, 0.0, -θ) + # Create a transformation that reverses the theta and precone rotations. + # The precone happens first, then theta. + # So to reverse it we need to do theta, then precone. + trans = KinematicCoordinateTransformations.compose(τ, trans_precone, trans_theta) + # Create a source element with the theta and precone rotations, then undo it. + se = TipVortexSourceElement(rotor, section, op, out, θ, Δr, τ, Δτ, bl, blade_tip, positive_x_rotation) |> trans + # Check that we got the same thing: + for field in fieldnames(TipVortexSourceElement) + # The twist changes the unit vector in the chord direction, but nothing else, so ignore that for now. + if !(field in (:chord_uvec, :bl, :blade_tip)) + @test getproperty(se, field) ≈ getproperty(se_0theta0precone, field) + end + end + + if positive_x_rotation + # If we're doing a positive-x rotation, we're applying the twist about the positive y axis. + # If we're applying the twist about the positive y axis, then we need to do a negative rotation about the y axis to undo it. + trans_phi = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, -twist) + chord_uvec_check = @SVector [0.0, 0.0, -1.0] + else + # If we're doing a negative-x rotation, we're applying the twist about the negative y axis. + # If we're applying the twist about the negative y axis, then we need to do a positive rotation about the y axis to undo it. + trans_phi = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, twist) + chord_uvec_check = @SVector [0.0, 0.0, 1.0] + end + se_no_twist = se |> trans_phi + @test se_no_twist.chord_uvec ≈ chord_uvec_check + end + end + end + end +end + +@testset "CCBlade TipVortexSourceElement complete test" begin + for positive_x_rotation in [true, false] + omega = 2200*(2*pi/60) + + # Create the CCBlade objects. + rotor = Rotor(ccbc.Rhub, ccbc.Rtip, ccbc.num_blades; turbine=false) + sections = Section.(ccbc.radii, ccbc.chord, ccbc.theta, nothing) + ops = simple_op.(ccbc.v, omega, ccbc.radii, ccbc.rho; asound=ccbc.c0) + # What actually matters in the output structs are just W and phi. + phi = range(45.0, 10.0; length=length(sections)) .* (pi/180) + W = range(10.0, 11.0; length=length(sections)) + outs = Outputs.(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, phi, 0.0, W, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) + + # Radial spacing. + dradii = get_dradii(ccbc.radii, ccbc.Rhub, ccbc.Rtip) + + # Set the source time stuff. + num_blade_passes = 3 + steps_per_blade_pass = 8 + num_src_times = num_blade_passes*steps_per_blade_pass + bpp = 2*pi/omega/ccbc.num_blades + src_time_range = num_blade_passes*bpp + + # Finally get all the source elements. + bl = AcousticAnalogies.TrippedN0012BoundaryLayer() + blade_tip = AcousticAnalogies.RoundedTip() + ses_helper = tip_vortex_source_elements_ccblade(rotor, sections[end], ops[end], outs[end], dradii[end], bl, blade_tip, src_time_range, num_src_times, positive_x_rotation) + + # Now need to get the source elements the "normal" way. + # First get the transformation objects. + rot_axis = @SVector [1.0, 0.0, 0.0] + blade_axis = @SVector [0.0, 1.0, 0.0] + y0_hub = @SVector [0.0, 0.0, 0.0] # m + v0_hub = ccbc.v.*rot_axis + t0 = 0.0 + if positive_x_rotation + rot_trans = KinematicCoordinateTransformations.SteadyRotXTransformation(t0, omega, 0.0) + else + rot_trans = KinematicCoordinateTransformations.SteadyRotXTransformation(t0, -omega, 0.0) + end + const_vel_trans = KinematicCoordinateTransformations.ConstantVelocityTransformation(t0, y0_hub, v0_hub) + + # Need the source times. + dt = src_time_range/num_src_times + src_times = t0 .+ (0:num_src_times-1).*dt + + # This is just an array of the angular offsets of each blade. + θs = 2*pi/ccbc.num_blades.*(0:(ccbc.num_blades-1)) + + # Need the kinematic viscosity. + # nus = getproperty.(ops, :mu) ./ getproperty.(ops, :rho) + + # Also need the velocity in each direction. + if positive_x_rotation + vn = @. -W*sin(phi) + vr = zeros(eltype(vn), length(vn)) + vc = @. -W*cos(phi) + else + vn = @. -W*sin(phi) + vr = zeros(eltype(vn), length(vn)) + vc = @. W*cos(phi) + end + + # Reshape stuff for broadcasting. + θs_rs = reshape(θs, 1, 1, :) + + # Get all the transformations. + trans = compose.(src_times, Ref(const_vel_trans), Ref(rot_trans)) + + # Transform the source elements. + ses = TipVortexSourceElement.(ccbc.c0, ccbc.radii[end], θs_rs, dradii[end], sections[end].chord, sections[end].theta, vn[end], vr[end], vc[end], src_times, dt, Ref(bl), Ref(blade_tip), positive_x_rotation) .|> trans + + # Now check that we got the same thing. + for field in fieldnames(TipVortexSourceElement) + if !(field in (:bl, :blade_tip)) + @test all(getproperty.(ses_helper, field) .≈ getproperty.(ses, field)) + end + end + end +end + +@testset "CombinedNoTipBroadbandSourceElement twist and rotation tests" begin + # So, the way this should work: first do the twist, then do the theta rotation. + # The twist could be either about the positive y axis or negative y axis. + # Then the theta rotation is always about the x axis. + c0 = 1.1 + nu = 1.2 + r = 2.0 + Δr = 0.1 + chord = 1.3 + vn = 2.0 + vr = 3.0 + vc = 4.0 + τ = 0.1 + Δτ = 0.02 + h = 0.1 + Psi = 0.2 + bl = 2.0 # should be a boundary layer struct, but doesn't matter for these tests. + for twist_about_positive_y in [true, false] + se_0twist0theta = CombinedNoTipBroadbandSourceElement(c0, nu, r, 0.0, Δr, chord, 0.0, h, Psi, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) + for θ in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + trans_theta = KinematicCoordinateTransformations.SteadyRotXTransformation(τ, 0.0, -θ) + + for ϕ in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + # The angle of attack depends on the twist and the fluid velocity + if twist_about_positive_y + alpha_check = ϕ - atan(-vn, -vc) + else + alpha_check = ϕ - atan(-vn, vc) + end + se = CombinedNoTipBroadbandSourceElement(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, vn, vr, vc, τ, Δτ, bl, twist_about_positive_y) |> trans_theta + # Adjust the angles of attack to always be between -pi and pi. + alpha_check = rem2pi(alpha_check+pi, RoundNearest) - pi + alpha = rem2pi(AcousticAnalogies.angle_of_attack(se)+pi, RoundNearest) - pi + @test alpha ≈ alpha_check + + for field in fieldnames(CombinedNoTipBroadbandSourceElement) + # The twist changes the unit vector in the chord direction, but nothing else, so ignore that for now. + if field != :chord_uvec + @test getproperty(se, field) ≈ getproperty(se_0twist0theta, field) + end + end + + if twist_about_positive_y + # If we're applying the twist about the positive y axis, then we need to do a negative rotation about the y axis to undo it. + trans_phi = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, -ϕ) + chord_uvec_check = @SVector [0.0, 0.0, -1.0] + else + # If we're applying the twist about the negative y axis, then we need to do a positive rotation about the y axis to undo it. + trans_phi = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, ϕ) + chord_uvec_check = @SVector [0.0, 0.0, 1.0] + end + se_no_twist = se |> trans_phi + @test se_no_twist.chord_uvec ≈ chord_uvec_check + end + end + end +end + +@testset "CombinedNoTipBroadbandSourceElement twist and rotation tests, CCBlade" begin + # Create the CCBlade objects. + τ = 0.1 + Δτ = 0.02 + h = 0.1 + Psi = 0.2 + bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() + # ccblade_fname = joinpath(@__DIR__, "gen_test_data", "gen_ccblade_data", "ccblade_omega11.jld2") + # out, section_loaded, Δr, op, rotor0precone = nothing, nothing, nothing, nothing, nothing + # jldopen(ccblade_fname, "r") do f + # out = f["outs"][1] + # section_loaded = f["sections"][1] + # Δr = f["sections"][2].r - f["sections"][1].r + # op = f["ops"][1] + # rotor0precone = f["rotor"] + # @test rotor0precone.precone ≈ 0.0 + # end + + ccblade_fname = joinpath(@__DIR__, "gen_test_data", "gen_ccblade_data", "ccblade_omega11-outputs.jld2") + outs_d = load(ccblade_fname) + section_loaded = CCBlade.Section(first(ccbc.radii), first(ccbc.chord), first(ccbc.theta)*pi/180, nothing) + Δr = ccbc.radii[2] - ccbc.radii[1] + op = CCBlade.OperatingPoint(ccbc.v, outs_d["omega"]*first(ccbc.radii), ccbc.rho, ccbc.pitch, ccbc.mu, ccbc.c0) + rotor0precone = CCBlade.Rotor(ccbc.Rhub, ccbc.Rtip, ccbc.num_blades) + out = CCBlade.Outputs(outs_d["Np"][1], outs_d["Tp"][1], outs_d["a"][1], outs_d["ap"][1], outs_d["u"][1], outs_d["v"][1], outs_d["phi"][1], outs_d["alpha"][1], outs_d["W"][1], outs_d["cl"][1], outs_d["cd"][1], outs_d["cn"][1], outs_d["ct"][1], outs_d["F"][1], outs_d["G"][1]) + @test rotor0precone.precone ≈ 0.0 + + for positive_x_rotation in [true, false] + for twist in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + section = CCBlade.Section(section_loaded.r, section_loaded.chord, twist, section_loaded.af) + se_0theta0precone = CombinedNoTipBroadbandSourceElement(rotor0precone, section, op, out, 0.0, Δr, h, Psi, τ, Δτ, bl, positive_x_rotation) + for precone in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + rotor = CCBlade.Rotor(rotor0precone.Rhub, rotor0precone.Rtip, rotor0precone.B; turbine=rotor0precone.turbine, precone=precone) + # This is tricky: in my "normal" coordinate system, the blade is rotating around the x axis, moving axially in the positive x direction, and is initially aligned with the y axis. + # That means that the precone should be a rotation around the negative z axis. + # And so to undo it, we want a positive rotation around the positive z axis. + trans_precone = KinematicCoordinateTransformations.SteadyRotZTransformation(τ, 0.0, precone) + for θ in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + trans_theta = KinematicCoordinateTransformations.SteadyRotXTransformation(τ, 0.0, -θ) + # Create a transformation that reverses the theta and precone rotations. + # The precone happens first, then theta. + # So to reverse it we need to do theta, then precone. + trans = KinematicCoordinateTransformations.compose(τ, trans_precone, trans_theta) + # Create a source element with the theta and precone rotations, then undo it. + se = CombinedNoTipBroadbandSourceElement(rotor, section, op, out, θ, Δr, h, Psi, τ, Δτ, bl, positive_x_rotation) |> trans + # Check that we got the same thing: + for field in fieldnames(CombinedNoTipBroadbandSourceElement) + # The twist changes the unit vector in the chord direction, but nothing else, so ignore that for now. + if !(field in (:chord_uvec, :bl)) + @test getproperty(se, field) ≈ getproperty(se_0theta0precone, field) + end + end + + if positive_x_rotation + # If we're doing a positive-x rotation, we're applying the twist about the positive y axis. + # If we're applying the twist about the positive y axis, then we need to do a negative rotation about the y axis to undo it. + trans_phi = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, -twist) + chord_uvec_check = @SVector [0.0, 0.0, -1.0] + else + # If we're doing a negative-x rotation, we're applying the twist about the negative y axis. + # If we're applying the twist about the negative y axis, then we need to do a positive rotation about the y axis to undo it. + trans_phi = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, twist) + chord_uvec_check = @SVector [0.0, 0.0, 1.0] + end + se_no_twist = se |> trans_phi + @test se_no_twist.chord_uvec ≈ chord_uvec_check + end + end + end + end +end + +@testset "CombinedWithTipBroadbandSourceElement twist and rotation tests" begin + # So, the way this should work: first do the twist, then do the theta rotation. + # The twist could be either about the positive y axis or negative y axis. + # Then the theta rotation is always about the x axis. + c0 = 1.1 + nu = 1.2 + r = 2.0 + Δr = 0.1 + chord = 1.3 + vn = 2.0 + vr = 3.0 + vc = 4.0 + τ = 0.1 + Δτ = 0.02 + h = 0.1 + Psi = 0.2 + bl = 2.0 # should be a boundary layer struct, but doesn't matter for these tests. + blade_tip = 3.0 # should be a blade tip struct, but doesn't matter for these tests. + for twist_about_positive_y in [true, false] + se_0twist0theta = CombinedWithTipBroadbandSourceElement(c0, nu, r, 0.0, Δr, chord, 0.0, h, Psi, vn, vr, vc, τ, Δτ, bl, blade_tip, twist_about_positive_y) + for θ in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + trans_theta = KinematicCoordinateTransformations.SteadyRotXTransformation(τ, 0.0, -θ) + + for ϕ in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + # The angle of attack depends on the twist and the fluid velocity + if twist_about_positive_y + alpha_check = ϕ - atan(-vn, -vc) + else + alpha_check = ϕ - atan(-vn, vc) + end + se = CombinedWithTipBroadbandSourceElement(c0, nu, r, θ, Δr, chord, ϕ, h, Psi, vn, vr, vc, τ, Δτ, bl, blade_tip, twist_about_positive_y) |> trans_theta + # Adjust the angles of attack to always be between -pi and pi. + alpha_check = rem2pi(alpha_check+pi, RoundNearest) - pi + alpha = rem2pi(AcousticAnalogies.angle_of_attack(se)+pi, RoundNearest) - pi + @test alpha ≈ alpha_check + + for field in fieldnames(CombinedWithTipBroadbandSourceElement) + # The twist changes the unit vector in the chord direction, but nothing else, so ignore that for now. + if field != :chord_uvec + @test getproperty(se, field) ≈ getproperty(se_0twist0theta, field) + end + end + + if twist_about_positive_y + # If we're applying the twist about the positive y axis, then we need to do a negative rotation about the y axis to undo it. + trans_phi = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, -ϕ) + chord_uvec_check = @SVector [0.0, 0.0, -1.0] + else + # If we're applying the twist about the negative y axis, then we need to do a positive rotation about the y axis to undo it. + trans_phi = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, ϕ) + chord_uvec_check = @SVector [0.0, 0.0, 1.0] + end + se_no_twist = se |> trans_phi + @test se_no_twist.chord_uvec ≈ chord_uvec_check + end + end + end +end + +@testset "CombinedWithTipBroadbandSourceElement twist and rotation tests, CCBlade" begin + # Create the CCBlade objects. + τ = 0.1 + Δτ = 0.02 + h = 0.1 + Psi = 0.2 + bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() + blade_tip = AcousticAnalogies.RoundedTip() + # ccblade_fname = joinpath(@__DIR__, "gen_test_data", "gen_ccblade_data", "ccblade_omega11.jld2") + # out, section_loaded, Δr, op, rotor0precone = nothing, nothing, nothing, nothing, nothing + # jldopen(ccblade_fname, "r") do f + # out = f["outs"][1] + # section_loaded = f["sections"][1] + # Δr = f["sections"][2].r - f["sections"][1].r + # op = f["ops"][1] + # rotor0precone = f["rotor"] + # @test rotor0precone.precone ≈ 0.0 + # end + + ccblade_fname = joinpath(@__DIR__, "gen_test_data", "gen_ccblade_data", "ccblade_omega11-outputs.jld2") + outs_d = load(ccblade_fname) + section_loaded = CCBlade.Section(first(ccbc.radii), first(ccbc.chord), first(ccbc.theta)*pi/180, nothing) + Δr = ccbc.radii[2] - ccbc.radii[1] + op = CCBlade.OperatingPoint(ccbc.v, outs_d["omega"]*first(ccbc.radii), ccbc.rho, ccbc.pitch, ccbc.mu, ccbc.c0) + rotor0precone = CCBlade.Rotor(ccbc.Rhub, ccbc.Rtip, ccbc.num_blades) + out = CCBlade.Outputs(outs_d["Np"][1], outs_d["Tp"][1], outs_d["a"][1], outs_d["ap"][1], outs_d["u"][1], outs_d["v"][1], outs_d["phi"][1], outs_d["alpha"][1], outs_d["W"][1], outs_d["cl"][1], outs_d["cd"][1], outs_d["cn"][1], outs_d["ct"][1], outs_d["F"][1], outs_d["G"][1]) + @test rotor0precone.precone ≈ 0.0 + + for positive_x_rotation in [true, false] + for twist in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + section = CCBlade.Section(section_loaded.r, section_loaded.chord, twist, section_loaded.af) + se_0theta0precone = CombinedWithTipBroadbandSourceElement(rotor0precone, section, op, out, 0.0, Δr, h, Psi, τ, Δτ, bl, blade_tip, positive_x_rotation) + for precone in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + rotor = CCBlade.Rotor(rotor0precone.Rhub, rotor0precone.Rtip, rotor0precone.B; turbine=rotor0precone.turbine, precone=precone) + # This is tricky: in my "normal" coordinate system, the blade is rotating around the x axis, moving axially in the positive x direction, and is initially aligned with the y axis. + # That means that the precone should be a rotation around the negative z axis. + # And so to undo it, we want a positive rotation around the positive z axis. + trans_precone = KinematicCoordinateTransformations.SteadyRotZTransformation(τ, 0.0, precone) + for θ in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + trans_theta = KinematicCoordinateTransformations.SteadyRotXTransformation(τ, 0.0, -θ) + # Create a transformation that reverses the theta and precone rotations. + # The precone happens first, then theta. + # So to reverse it we need to do theta, then precone. + trans = KinematicCoordinateTransformations.compose(τ, trans_precone, trans_theta) + # Create a source element with the theta and precone rotations, then undo it. + se = CombinedWithTipBroadbandSourceElement(rotor, section, op, out, θ, Δr, h, Psi, τ, Δτ, bl, blade_tip, positive_x_rotation) |> trans + # Check that we got the same thing: + for field in fieldnames(CombinedWithTipBroadbandSourceElement) + # The twist changes the unit vector in the chord direction, but nothing else, so ignore that for now. + if !(field in (:chord_uvec, :bl, :blade_tip)) + @test getproperty(se, field) ≈ getproperty(se_0theta0precone, field) + end + end + + if positive_x_rotation + # If we're doing a positive-x rotation, we're applying the twist about the positive y axis. + # If we're applying the twist about the positive y axis, then we need to do a negative rotation about the y axis to undo it. + trans_phi = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, -twist) + chord_uvec_check = @SVector [0.0, 0.0, -1.0] + else + # If we're doing a negative-x rotation, we're applying the twist about the negative y axis. + # If we're applying the twist about the negative y axis, then we need to do a positive rotation about the y axis to undo it. + trans_phi = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, twist) + chord_uvec_check = @SVector [0.0, 0.0, 1.0] + end + se_no_twist = se |> trans_phi + @test se_no_twist.chord_uvec ≈ chord_uvec_check + end + end + end + end +end + +@testset "CCBlade combined broadband source elements complete test" begin + for positive_x_rotation in [true, false] + omega = 2200*(2*pi/60) + + # Create the CCBlade objects. + rotor = Rotor(ccbc.Rhub, ccbc.Rtip, ccbc.num_blades; turbine=false) + sections = Section.(ccbc.radii, ccbc.chord, ccbc.theta, nothing) + ops = simple_op.(ccbc.v, omega, ccbc.radii, ccbc.rho; asound=ccbc.c0) + # What actually matters in the output structs are just W and phi. + phi = range(45.0, 10.0; length=length(sections)) .* (pi/180) + W = range(10.0, 11.0; length=length(sections)) + outs = Outputs.(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, phi, 0.0, W, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) + + # Set the source time stuff. + num_blade_passes = 3 + steps_per_blade_pass = 8 + num_src_times = num_blade_passes*steps_per_blade_pass + bpp = 2*pi/omega/ccbc.num_blades + src_time_range = num_blade_passes*bpp + + # Finally get all the source elements. + # bls = [AcousticAnalogies.TrippedN0012BoundaryLayer()] + # bl = AcousticAnalogies.TrippedN0012BoundaryLayer() + # bls = Fill(AcousticAnalogies.TrippedN0012BoundaryLayer(), num_radial) + bls = fill(AcousticAnalogies.TrippedN0012BoundaryLayer(), length(sections)) + hs = range(0.1, 0.2; length=length(sections)) + Psis = range(0.2, 0.3; length=length(sections)) + blade_tip = AcousticAnalogies.RoundedTip() + ses_no_tip_helper, ses_with_tip_helper = combined_broadband_source_elements_ccblade(rotor, sections, ops, outs, hs, Psis, bls, blade_tip, src_time_range, num_src_times, positive_x_rotation) + + # Now need to get the source elements the "normal" way. + # First get the transformation objects. + rot_axis = @SVector [1.0, 0.0, 0.0] + blade_axis = @SVector [0.0, 1.0, 0.0] + y0_hub = @SVector [0.0, 0.0, 0.0] # m + v0_hub = ccbc.v.*rot_axis + t0 = 0.0 + if positive_x_rotation + rot_trans = KinematicCoordinateTransformations.SteadyRotXTransformation(t0, omega, 0.0) + else + rot_trans = KinematicCoordinateTransformations.SteadyRotXTransformation(t0, -omega, 0.0) + end + const_vel_trans = KinematicCoordinateTransformations.ConstantVelocityTransformation(t0, y0_hub, v0_hub) + + # Need the source times. + dt = src_time_range/num_src_times + src_times = t0 .+ (0:num_src_times-1).*dt + + # This is just an array of the angular offsets of each blade. + θs = 2*pi/ccbc.num_blades.*(0:(ccbc.num_blades-1)) + + # Radial spacing. + dradii = get_dradii(ccbc.radii, ccbc.Rhub, ccbc.Rtip) + + # Need the kinematic viscosity. + nus = getproperty.(ops, :mu) ./ getproperty.(ops, :rho) + + # Also need the velocity in each direction. + if positive_x_rotation + vn = @. -W*sin(phi) + vr = zeros(eltype(vn), length(vn)) + vc = @. -W*cos(phi) + else + vn = @. -W*sin(phi) + vr = zeros(eltype(vn), length(vn)) + vc = @. W*cos(phi) + end + + # Reshape stuff for broadcasting. + radii_rs = reshape(ccbc.radii, 1, :, 1) + dradii_rs = reshape(dradii, 1, :, 1) + phi_rs = reshape(phi, 1, :, 1) + W_rs = reshape(W, 1, :, 1) + # src_times_rs = reshape(src_times, :, 1, 1) # This isn't really necessary. + θs_rs = reshape(θs, 1, 1, :) + nus_rs = reshape(nus, 1, :, 1) + twist_rs = reshape(getproperty.(sections, :theta), 1, :, 1) + chord_rs = reshape(getproperty.(sections, :chord), 1, :, 1) + hs_rs = reshape(hs, 1, :, 1) + Psis_rs = reshape(Psis, 1, :, 1) + vn_rs = reshape(vn, 1, :, 1) + vr_rs = reshape(vr, 1, :, 1) + vc_rs = reshape(vc, 1, :, 1) + bls_rs = reshape(bls, 1, :, 1) + + # Get all the transformations. + trans = compose.(src_times, Ref(const_vel_trans), Ref(rot_trans)) + + # Now need to split things into the with tip and no tip stuff. + radii_rs_no_tip = @view radii_rs[:, begin:end-1, :] + dradii_rs_no_tip = @view dradii_rs[:, begin:end-1, :] + phi_rs_no_tip = @view phi_rs[:, begin:end-1, :] + W_rs_no_tip = @view W_rs[:, begin:end-1, :] + nus_rs_no_tip = @view nus_rs[:, begin:end-1, :] + twist_rs_no_tip = @view twist_rs[:, begin:end-1, :] + chord_rs_no_tip = @view chord_rs[:, begin:end-1, :] + hs_rs_no_tip = @view hs_rs[:, begin:end-1, :] + Psis_rs_no_tip = @view Psis_rs[:, begin:end-1, :] + vn_rs_no_tip = @view vn_rs[:, begin:end-1, :] + vr_rs_no_tip = @view vr_rs[:, begin:end-1, :] + vc_rs_no_tip = @view vc_rs[:, begin:end-1, :] + bls_rs_no_tip = @view bls_rs[:, begin:end-1, :] + + radii_rs_with_tip = @view radii_rs[:, end:end, :] + dradii_rs_with_tip = @view dradii_rs[:, end:end, :] + phi_rs_with_tip = @view phi_rs[:, end:end, :] + W_rs_with_tip = @view W_rs[:, end:end, :] + nus_rs_with_tip = @view nus_rs[:, end:end, :] + twist_rs_with_tip = @view twist_rs[:, end:end, :] + chord_rs_with_tip = @view chord_rs[:, end:end, :] + hs_rs_with_tip = @view hs_rs[:, end:end, :] + Psis_rs_with_tip = @view Psis_rs[:, end:end, :] + vn_rs_with_tip = @view vn_rs[:, end:end, :] + vr_rs_with_tip = @view vr_rs[:, end:end, :] + vc_rs_with_tip = @view vc_rs[:, end:end, :] + bls_rs_with_tip = @view bls_rs[:, end:end, :] + + # Transform the source elements. + ses_no_tip = CombinedNoTipBroadbandSourceElement.(ccbc.c0, nus_rs_no_tip, radii_rs_no_tip, θs_rs, dradii_rs_no_tip, chord_rs_no_tip, twist_rs_no_tip, hs_rs_no_tip, Psis_rs_no_tip, vn_rs_no_tip, vr_rs_no_tip, vc_rs_no_tip, src_times, dt, bls_rs_no_tip, positive_x_rotation) .|> trans + + ses_with_tip = CombinedWithTipBroadbandSourceElement.(ccbc.c0, nus_rs_with_tip, radii_rs_with_tip, θs_rs, dradii_rs_with_tip, chord_rs_with_tip, twist_rs_with_tip, hs_rs_with_tip, Psis_rs_with_tip, vn_rs_with_tip, vr_rs_with_tip, vc_rs_with_tip, src_times, dt, bls_rs_with_tip, Ref(blade_tip), positive_x_rotation) .|> trans + + # Now check that we got the same thing. + for field in fieldnames(CombinedNoTipBroadbandSourceElement) + if !(field in (:bl,)) + @test all(getproperty.(ses_no_tip_helper, field) .≈ getproperty.(ses_no_tip, field)) + end + end + for field in fieldnames(CombinedWithTipBroadbandSourceElement) + if !(field in (:bl, :blade_tip)) + @test all(getproperty.(ses_with_tip_helper, field) .≈ getproperty.(ses_with_tip, field)) + end + end + end +end + +@testset "directivity function tests" begin + # None of this stuff matters for the directivity functions. + c0 = 2.0 + nu = 3.0 + dr = 0.1 + chord = 1.1 + τ = 0.2 + dτ = 0.01 + bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() + chord_cross_span_to_get_top_uvec = true + + # This stuff actually matters. + # Need the fluid velocity to be zero so we can ignore the denominator. + y1dot = @SVector [0.0, 0.0, 0.0] + y1dot_fluid = @SVector [0.0, 0.0, 0.0] + y0dot = @SVector [0.0, 0.0, 0.0] + chord_uvec = [1.0, 0.0, 0.0] + span_uvec = [0.0, 1.0, 0.0] + + # Create a source element. + se = AcousticAnalogies.TBLTESourceElement(c0, nu, dr, chord, y0dot, y1dot, y1dot_fluid, τ, dτ, span_uvec, chord_uvec, bl, chord_cross_span_to_get_top_uvec) + + # Now, create an observer at different places, and check that we get the correct directivity function. + for x_er in [-5.0, -3.0, 1.5, 4.0] + for y_er in [-5.0, -3.0, 1.5, 4.0] + for z_er in [-5.0, -3.0, 1.5, 4.0] + x = @SVector [x_er, y_er, z_er] + obs = AcousticAnalogies.StationaryAcousticObserver(x) + r_er_check = sqrt(x_er^2 + y_er^2 + z_er^2) + Θ_er = acos(x_er/r_er_check) + Φ_er = acos(y_er/sqrt(y_er^2 + z_er^2)) + + # Observer time doesn't matter since the observer is stationary. + t_obs = 7.0 + x_obs = obs(t_obs) + Dl_check = (sin(Θ_er)^2) * (sin(Φ_er)^2) + Dh_check = 2*(sin(0.5*Θ_er)^2) * (sin(Φ_er)^2) + top_is_suction = true + r_er, Dl, Dh = AcousticAnalogies.directivity(se, obs(t_obs), top_is_suction) + @test r_er ≈ r_er_check + @test Dl ≈ Dl_check + @test Dh ≈ Dh_check + + # Now, rotate and translate both the source and the observer. + # The directivity functions should be the same. + # Time parameter for the steady rotations doesn't matter because the rotation rate is zero. + trans1 = KinematicCoordinateTransformations.SteadyRotXTransformation(t_obs, 0.0, 3.0*pi/180) + trans2 = KinematicCoordinateTransformations.SteadyRotYTransformation(t_obs, 0.0, 4.0*pi/180) + trans3 = KinematicCoordinateTransformations.SteadyRotZTransformation(t_obs, 0.0, 5.0*pi/180) + # Time parameter for the constant velocity transformations doesn't matter because the velocity is zero. + x_trans = @SVector [2.0, 3.0, 4.0] + v_trans = @SVector [0.0, 0.0, 0.0] + trans4 = KinematicCoordinateTransformations.ConstantVelocityTransformation(t_obs, x_trans, v_trans) + + # Transform the source and observer. + trans = compose(t_obs, trans4, compose(t_obs, trans3, compose(t_obs, trans2, trans1))) + se_trans = trans(se) + obs_trans = AcousticAnalogies.StationaryAcousticObserver(trans(t_obs, obs(t_obs))) + + # Check that the directivity functions didn't change. + r_er, Dl, Dh = AcousticAnalogies.directivity(se_trans, obs_trans(t_obs), top_is_suction) + @test r_er ≈ r_er_check + @test Dl ≈ Dl_check + @test Dh ≈ Dh_check + end + end + end + +end + +@testset "angle of attack test" begin + + @testset "TBLTESourceElement" begin + for twist_about_positive_y in [true, false] + # None of this stuff matters for the angle of attack. + c0 = 2.0 + nu = 3.0 + dr = 0.1 + chord = 1.1 + dτ = 0.01 + r = 0.5 + omega = 101.0 + bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() + + # We'll create a random transformation to check that rotating and displacing the source doesn't change the angle of attack. + # Time parameter for the steady rotations doesn't matter because the rotation rate is zero. + τ = 0.2 + trans1 = KinematicCoordinateTransformations.SteadyRotXTransformation(τ, 0.0, 3.0*pi/180) + trans2 = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, 4.0*pi/180) + trans3 = KinematicCoordinateTransformations.SteadyRotZTransformation(τ, 0.0, 5.0*pi/180) + # Time parameter for the constant velocity transformations doesn't matter because the velocity is zero. + x_trans = @SVector [2.0, 3.0, 4.0] + v_trans = @SVector [0.0, 0.0, 0.0] + trans4 = KinematicCoordinateTransformations.ConstantVelocityTransformation(τ, x_trans, v_trans) + # Combine all the transformations into one. + trans = compose(τ, trans4, compose(τ, trans3, compose(τ, trans2, trans1))) + + # This stuff does matter for angle of attack. + Vx = 5.5 + u = 0.1*Vx + Vy = omega*r + v = 0.05*Vy + # So, let's say I'm in the usual frame of reference: moving axially in the positive x direction, rotating about the positive x axis if `twist_about_positive_y` is `true`, negative x axis if `twist_about_positive_y` is `false`, initially aligned with the y axis. + # Then, from the perspective of the blade element, the fluid velocity in the axial direction (`x`) is `-(Vx + u)`, and the velocity in the tangential direction is `(-Vy + v)`. + # + # vr shouldn't matter at all, so check that. + for use_induction in [true, false] + for vr in [0.0, 2.1, -2.1] + for θ in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + for twist in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + for vn_sign in [1, -1] + for vc_sign in [1, -1] + vn = -(Vx + u)*vn_sign + vc = (-Vy + v)*vc_sign + se = AcousticAnalogies.TBLTESourceElement{AcousticAnalogies.BrooksBurleyDirectivity,use_induction,AcousticAnalogies.NoMachCorrection,true}(c0, nu, r, θ, dr, chord, twist, vn, vr, vc, τ, dτ, bl, twist_about_positive_y) + # And then the angle of attack will be `twist - atan(-vn, -vc)`, where `twist` is the twist of the blade, `vn` is the velocity in the axial direction, and `vc` is the velocity in the circumferential/tangential direction. + # But we need to switch the direction of the velocity vector, since I'm thinking of them in opposite directions (eg the angle of attack is zero when the velocity and chordwise vector from trailing edge to leading edge are exactly opposite). + # The rem2pi will give us back an equivalent angle in the interval [-π, π]. + if twist_about_positive_y + # If the twist is about the positive y axis, then the assumption is that the twist and velocity angles are zero when they are aligned with positive z axis. + # In the "usual" operation, the axial component of the blade-fixed frame velocity will be in the negative x direction, and the circumferential component of the blade-fixed frame velocity will be in the negative z direction. + # So we need to switch both of those signs to get the correct angle. + angle_of_attack_check = rem2pi(twist - atan(-vn, -vc), RoundNearest) + else + # If the twist is about the negative y axis, then the assumption is the twist and velocity angles are zero when they are aligned with the negative z axis. + # In then "usual" operation, the axial component of the blade-fixed frame velocity will be in the negative x direction, and the circumferential component of the blade fixed frame velocity will be in the positive z direction. + # So we need to switch the sign of the axial component, but not the circumferential. + angle_of_attack_check = rem2pi(twist - atan(-vn, vc), RoundNearest) + end + + @test AcousticAnalogies.angle_of_attack(se) ≈ angle_of_attack_check + + if use_induction + # Flow speed normal to span, including induction: + U_check = sqrt(vn^2 + vc^2) + else + # Flow speed normal to span, not including induction: + U_check = sqrt(Vx^2 + Vy^2) + end + + if use_induction + # If we're including induction in the flow speed normal to span calculation, we can check it now. + @test AcousticAnalogies.speed_normal_to_span(se) ≈ U_check + end + + # Apply the random transformation we created. + se_trans = trans(se) + + # Make sure we get the same angle of attack as before. + @test AcousticAnalogies.angle_of_attack(se_trans) ≈ angle_of_attack_check + + # Now, instead of doing a transformation that just displaces the source element, let's do one that changes the velocity. + # So, how are we going to transform the source element into the fluid frame? + # Well, first we say we're rotating around the x axix at a rate ω or -ω, depending on the value of `twist_about_positive_y` + # Oh, but wait. + # We're switching the sign. + # Hmm... what to do about that? + # Well, the definition of the fluid frame is one that has the "freestream velocity" as zero. + # So that, I think, means we need to remove the axial and circumferential (rotational) velocity. + # So remove Vx and Vy. + # I should be able to do that. + # So, first, let's think about getting rid of Vy. + # If we rotate about the positive x axis, then that will increase the velocity in the z direction (since the blade is initially aligned with the y axis). + # If we rotate about the negative x axis, then that will decrease the velocity in the z direction (again, since the blade is initially aligned with the y axis). + # OK, then. + trans_rot = KinematicCoordinateTransformations.SteadyRotXTransformation(τ, omega*vc_sign, 0.0) + + # Now, for the x velocity, we just want to remove the Vx. + x0 = @SVector [0.0, 0.0, 0.0] + v0 = @SVector [Vx*vn_sign, 0.0, 0.0] + trans_freestream = KinematicCoordinateTransformations.ConstantVelocityTransformation(τ, x0, v0) + + # Now compose the two transformations, and apply them to the source element. + trans_global = compose(τ, trans_freestream, trans_rot) + se_global = trans_global(se) + + # The angle of attack should be the same. + @test AcousticAnalogies.angle_of_attack(se_global) ≈ angle_of_attack_check + + # Also, we should know what the source element and fluid velocities are, right? + y1dot_check = @SVector [Vx*vn_sign, Vy*vc_sign*(-sin(θ)), Vy*vc_sign*(cos(θ))] + y1dot_fluid_check = @SVector [-u*vn_sign, vr*cos(θ) + v*vc_sign*(-sin(θ)), vr*sin(θ) + v*vc_sign*(cos(θ))] + + @test se_global.y1dot ≈ y1dot_check + @test se_global.y1dot_fluid ≈ y1dot_fluid_check + + # The flow speed normal to span, including induction or not, shouldn't have changed, so check that. + @test AcousticAnalogies.speed_normal_to_span(se_global) ≈ U_check + end + end + end + end + end + end + end + end + + @testset "TBLTESourceElement, CCBlade" begin + # Create the CCBlade objects. + τ = 0.1 + Δτ = 0.02 + bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() + # ccblade_fname = joinpath(@__DIR__, "gen_test_data", "gen_ccblade_data", "ccblade_omega11.jld2") + # out, section, Δr, op, rotor = nothing, nothing, nothing, nothing, nothing + # jldopen(ccblade_fname, "r") do f + # out = f["outs"][1] + # section = f["sections"][1] + # Δr = f["sections"][2].r - f["sections"][1].r + # op = f["ops"][1] + # rotor = f["rotor"] + # @test rotor.precone ≈ 0.0 + # @test op.pitch ≈ 0.0 + # end + + ccblade_fname = joinpath(@__DIR__, "gen_test_data", "gen_ccblade_data", "ccblade_omega11-outputs.jld2") + outs_d = load(ccblade_fname) + section = CCBlade.Section(first(ccbc.radii), first(ccbc.chord), first(ccbc.theta)*pi/180, nothing) + Δr = ccbc.radii[2] - ccbc.radii[1] + op = CCBlade.OperatingPoint(ccbc.v, outs_d["omega"]*first(ccbc.radii), ccbc.rho, ccbc.pitch, ccbc.mu, ccbc.c0) + rotor = CCBlade.Rotor(ccbc.Rhub, ccbc.Rtip, ccbc.num_blades) + out = CCBlade.Outputs(outs_d["Np"][1], outs_d["Tp"][1], outs_d["a"][1], outs_d["ap"][1], outs_d["u"][1], outs_d["v"][1], outs_d["phi"][1], outs_d["alpha"][1], outs_d["W"][1], outs_d["cl"][1], outs_d["cd"][1], outs_d["cn"][1], outs_d["ct"][1], outs_d["F"][1], outs_d["G"][1]) + @test rotor.precone ≈ 0.0 + @test op.pitch ≈ 0.0 + + for positive_x_rotation in [true, false] + for θ in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + se = AcousticAnalogies.TBLTESourceElement(rotor, section, op, out, θ, Δr, τ, Δτ, bl, positive_x_rotation) + # The `chord_uvec` vector points from leading edge to trailing edge. + # So we should be able to use that to figure out the angle it makes with the tangential/rotation direction. + # The tangential/rotation direction can be found by crossing the the rotation axis with the position vector. + # Then I can dot the chord with that direction, and the forward velocity axis, then use the arctan function to get the angle. + if positive_x_rotation + rot_axis = @SVector [1, 0, 0] + else + rot_axis = @SVector [-1, 0, 0] + end + tan_axis_tmp = cross(rot_axis, se.y0dot) + tan_axis = tan_axis_tmp / norm(tan_axis_tmp) + forward_axis = @SVector [1, 0, 0] + # I'm visualizing the chord vector as going from trailing edge to leading edge, but it's leading edge to trailing edge in the TBLTESourceElement struct, so switch that. + te_to_le = -se.chord_uvec + twist_check = atan(dot(te_to_le, forward_axis), dot(te_to_le, tan_axis)) + @test twist_check ≈ section.theta + + # The angle of attack that AcousticAnalogies.jl calculates should match what CCBlade.jl has. + @test AcousticAnalogies.angle_of_attack(se) ≈ out.alpha + + # Now, rotate and translate the source, which shouldn't change the twist or angle of attack, as long as we don't do anything that would change the velocity. + # Time parameter for the steady rotations doesn't matter because the rotation rate is zero. + trans1 = KinematicCoordinateTransformations.SteadyRotXTransformation(τ, 0.0, 3.0*pi/180) + trans2 = KinematicCoordinateTransformations.SteadyRotYTransformation(τ, 0.0, 4.0*pi/180) + trans3 = KinematicCoordinateTransformations.SteadyRotZTransformation(τ, 0.0, 5.0*pi/180) + # Time parameter for the constant velocity transformations doesn't matter because the velocity is zero. + x_trans = @SVector [2.0, 3.0, 4.0] + v_trans = @SVector [0.0, 0.0, 0.0] + trans4 = KinematicCoordinateTransformations.ConstantVelocityTransformation(τ, x_trans, v_trans) + + # Transform the source. + trans = compose(τ, trans4, compose(τ, trans3, compose(τ, trans2, trans1))) + se_trans = trans(se) + + # Angle of attack should still be the same. + @test AcousticAnalogies.angle_of_attack(se_trans) ≈ out.alpha + + # It'd be nice to check the twist too, but if that was wrong, the angle of attack would be wrong too. + # And there are other tests already for `chord_uvec`. + + # Could I put the source element in the "fluid/global" frame now? + # I'd need to know the forward velocity and rotation rate. + # Well, the forward velocity would be Vx. + Vx = op.Vx + # And the rotation rate would be Vy/r. + omega = op.Vy / section.r + # Now, need to undo the rotation, which depends on `positive_x_rotation`. + if positive_x_rotation + # If we're rotating about the positive x axis, need to apply a rotation around the negative x axis to undo it. + trans_rot = KinematicCoordinateTransformations.SteadyRotXTransformation(τ, -omega, 0.0) + else + # If we're rotating about the negative x axis, need to apply a rotation around the positive x axis to undo it. + trans_rot = KinematicCoordinateTransformations.SteadyRotXTransformation(τ, omega, 0.0) + end + # Now, I'm assuming that the freestream/axial velocity is in the -x direction, so to undo that, move it in the positive x direction. + x0 = @SVector [0.0, 0.0, 0.0] + v0 = @SVector [Vx, 0.0, 0.0] + trans_freestream = KinematicCoordinateTransformations.ConstantVelocityTransformation(τ, x0, v0) + + # Now compose the two transformations, and apply them to the original source element. + trans_global = compose(τ, trans_freestream, trans_rot) + se_global = trans_global(se) + + # The angle of attack should be the same. + @test AcousticAnalogies.angle_of_attack(se_global) ≈ out.alpha + end + end + end +end + +@testset "BPM Report tests" begin + + @testset "BPM Figure 11a" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 45.72e-2 # span in meters + chord = 30.48e-2 # chord in meters + U = 71.3 # freestream velocity in m/s + M = 0.209 # Mach number, corresponds to U = 71.3 m/s in BPM report + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + M_c = 0.8*M + alphastar = 0.0 + bl = AcousticAnalogies.TrippedN0012BoundaryLayer() + + # Now, need to get the data from the BPM report. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure11-a-TBL-TE-suction.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_s = bpm[:, 1] # This is in kHz. + SPL_s = bpm[:, 2] + + # At zero angle of attack the pressure and suction side predictions are the same. + f_p = f_s + SPL_p = SPL_s + + for angle_of_attack_sign in [1, -1] + for use_Ualpha in [false, true] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl; use_Ualpha=use_Ualpha) + + # Now compare... + SPL_s_jl_interp = linear(freqs, SPL_s_jl, f_s.*1e3) + vmin, vmax = extrema(SPL_s) + err = abs.(SPL_s_jl_interp .- SPL_s)./(vmax - vmin) + @test maximum(err) < 0.029 + + SPL_p_jl_interp = linear(freqs, SPL_p_jl, f_p.*1e3) + vmin, vmax = extrema(SPL_p) + err = abs.(SPL_p_jl_interp .- SPL_p)./(vmax - vmin) + @test maximum(err) < 0.029 + + # These should all be very negative, since alphastar is zero: + @test all(SPL_alpha_jl .< -100) + end + end + end + + @testset "BPM Figure 11d" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 45.72e-2 # span in meters + chord = 30.48e-2 # chord in meters + U = 31.7 # freestream velocity in m/s + M = 0.093 # Mach number, corresponds to U = 31.7 m/s in BPM report + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + alphastar = 0.0 + bl = AcousticAnalogies.TrippedN0012BoundaryLayer() + + # Now, need to get the data from the BPM report. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure11-d-TBL-TE-suction.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_s = bpm[:, 1] # This is in kHz. + SPL_s = bpm[:, 2] + + # At zero angle of attack the pressure and suction side predictions are the same. + f_p = f_s + SPL_p = SPL_s + + for angle_of_attack_sign in [1, -1] + for use_Ualpha in [false, true] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl; use_Ualpha=use_Ualpha) + + # Now compare... + SPL_s_jl_interp = linear(freqs, SPL_s_jl, f_s.*1e3) + vmin, vmax = extrema(SPL_s) + err = abs.(SPL_s_jl_interp .- SPL_s)./(vmax - vmin) + @test maximum(err) < 0.015 + + SPL_p_jl_interp = linear(freqs, SPL_p_jl, f_p.*1e3) + vmin, vmax = extrema(SPL_p) + err = abs.(SPL_p_jl_interp .- SPL_p)./(vmax - vmin) + @test maximum(err) < 0.015 + + # These should all be very negative, since alphastar is zero: + @test all(SPL_alpha_jl .< -100) + end + end + end + + @testset "BPM Figure 12a" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 45.72e-2 # span in meters + chord = 30.48e-2 # chord in meters + U = 71.3 # freestream velocity in m/s + M = 0.209 # Mach number, corresponds to U = 71.3 m/s in BPM report + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + alphastar = 1.5*pi/180 + bl = AcousticAnalogies.TrippedN0012BoundaryLayer() + + # Now, need to get the data from the BPM report. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure12-U71.3-TBL-TE-suction.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_s = bpm[:, 1] + SPL_s = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure12-U71.3-TBL-TE-pressure.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_p = bpm[:, 1] + SPL_p = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure12-U71.3-separation.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_alpha = bpm[:, 1] + SPL_alpha = bpm[:, 2] + + for angle_of_attack_sign in [1, -1] + for use_Ualpha in [false, true] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl; use_Ualpha=use_Ualpha) + + # Now compare... + SPL_s_jl_interp = linear(freqs, SPL_s_jl, f_s.*1e3) + vmin, vmax = extrema(SPL_s) + err = abs.(SPL_s_jl_interp .- SPL_s)./(vmax - vmin) + @test maximum(err) < 0.022 + + SPL_p_jl_interp = linear(freqs, SPL_p_jl, f_p.*1e3) + vmin, vmax = extrema(SPL_p) + err = abs.(SPL_p_jl_interp .- SPL_p)./(vmax - vmin) + @test maximum(err) < 0.017 + + SPL_alpha_jl_interp = linear(freqs, SPL_alpha_jl, f_alpha.*1e3) + vmin, vmax = extrema(SPL_alpha) + err = abs.(SPL_alpha_jl_interp .- SPL_alpha)./(vmax - vmin) + @test maximum(err) < 0.037 + end + end + end + + @testset "BPM Figure 26a" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 45.72e-2 # span in meters + chord = 10.16e-2 # chord in meters + U = 71.3 # freestream velocity in m/s + M = 0.209 # Mach number, corresponds to U = 71.3 m/s in BPM report + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + alphastar = 0.0 + bl = AcousticAnalogies.TrippedN0012BoundaryLayer() + + # Now, need to get the data from the BPM report. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure26-a-TBL-TE-suction.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_s = bpm[:, 1] + SPL_s = bpm[:, 2] + + # At zero angle of attack the pressure and suction side predictions are the same. + f_p = f_s + SPL_p = SPL_s + + for angle_of_attack_sign in [1, -1] + for use_Ualpha in [false, true] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl; use_Ualpha=use_Ualpha) + + # Now compare... + SPL_s_jl_interp = linear(freqs, SPL_s_jl, f_s.*1e3) + vmin, vmax = extrema(SPL_s) + err = abs.(SPL_s_jl_interp .- SPL_s)./(vmax - vmin) + @test maximum(err) < 0.015 + + SPL_p_jl_interp = linear(freqs, SPL_p_jl, f_p.*1e3) + vmin, vmax = extrema(SPL_p) + err = abs.(SPL_p_jl_interp .- SPL_p)./(vmax - vmin) + @test maximum(err) < 0.015 + + # These should all be very negative, since alphastar is zero: + @test all(SPL_alpha_jl .< -100) + end + end + end + + @testset "BPM Figure 26d" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 45.72e-2 # span in meters + chord = 10.16e-2 # chord in meters + U = 31.7 # freestream velocity in m/s + M = 0.093 # Mach number, corresponds to U = 31.7 m/s in BPM report + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + alphastar = 0.0 + bl = AcousticAnalogies.TrippedN0012BoundaryLayer() + + # Now, need to get the data from the BPM report. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure26-d-TBL-TE-suction.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_s = bpm[:, 1] + SPL_s = bpm[:, 2] + + # At zero angle of attack the pressure and suction side predictions are the same. + f_p = f_s + SPL_p = SPL_s + + for angle_of_attack_sign in [1, -1] + for use_Ualpha in [false, true] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl, use_Ualpha=use_Ualpha) + + # Now compare... + SPL_s_jl_interp = linear(freqs, SPL_s_jl, f_s.*1e3) + vmin, vmax = extrema(SPL_s) + err = abs.(SPL_s_jl_interp .- SPL_s)./(vmax - vmin) + @test maximum(err) < 0.032 + + SPL_p_jl_interp = linear(freqs, SPL_p_jl, f_p.*1e3) + vmin, vmax = extrema(SPL_p) + err = abs.(SPL_p_jl_interp .- SPL_p)./(vmax - vmin) + @test maximum(err) < 0.032 + + # These should all be very negative, since alphastar is zero: + @test all(SPL_alpha_jl .< -100) + end + end + end + + @testset "BPM Figure 28a" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 45.72e-2 # span in meters + chord = 10.16e-2 # chord in meters + U = 71.3 # freestream velocity in m/s + M = 0.209 # Mach number, corresponds to U = 71.3 m/s in BPM report + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + alphastar = 6.7*pi/180 + # Using the tripped boundary layer in this case. + bl = AcousticAnalogies.TrippedN0012BoundaryLayer() + + # Now, need to get the data from the BPM report. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure28-a-TBL-TE-suction.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_s = bpm[:, 1] + SPL_s = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure28-a-TBL-TE-pressure.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_p = bpm[:, 1] + SPL_p = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure28-a-separation.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_alpha = bpm[:, 1] + SPL_alpha = bpm[:, 2] + + for angle_of_attack_sign in [1, -1] + for use_Ualpha in [false, true] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl; use_Ualpha=use_Ualpha) + + # Now compare... + SPL_s_jl_interp = linear(freqs, SPL_s_jl, f_s.*1e3) + vmin, vmax = extrema(SPL_s) + err = abs.(SPL_s_jl_interp .- SPL_s)./(vmax - vmin) + @test maximum(err) < 0.036 + + SPL_p_jl_interp = linear(freqs, SPL_p_jl, f_p.*1e3) + vmin, vmax = extrema(SPL_p) + err = abs.(SPL_p_jl_interp .- SPL_p)./(vmax - vmin) + @test maximum(err) < 0.075 + + SPL_alpha_jl_interp = linear(freqs, SPL_alpha_jl, f_alpha.*1e3) + vmin, vmax = extrema(SPL_alpha) + err = abs.(SPL_alpha_jl_interp .- SPL_alpha)./(vmax - vmin) + @test maximum(err) < 0.039 + end + end + end + + @testset "BPM Figure 28d" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 45.72e-2 # span in meters + chord = 10.16e-2 # chord in meters + U = 31.7 # freestream velocity in m/s + M = 0.093 # mach number, corresponds to u = 31.7 m/s in bpm report + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + alphastar = 6.7*pi/180 + # Using the tripped boundary layer in this case. + bl = AcousticAnalogies.TrippedN0012BoundaryLayer() + + # Now, need to get the data from the BPM report. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure28-d-TBL-TE-suction.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_s = bpm[:, 1] + SPL_s = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure28-d-TBL-TE-pressure.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_p = bpm[:, 1] + SPL_p = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure28-d-separation.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_alpha = bpm[:, 1] + SPL_alpha = bpm[:, 2] + + for angle_of_attack_sign in [1, -1] + for use_Ualpha in [false, true] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl; use_Ualpha=use_Ualpha) + + # Now compare... + SPL_s_jl_interp = linear(freqs, SPL_s_jl, f_s.*1e3) + vmin, vmax = extrema(SPL_s) + err = abs.(SPL_s_jl_interp .- SPL_s)./(vmax - vmin) + @test maximum(err) < 0.021 + + SPL_p_jl_interp = linear(freqs, SPL_p_jl, f_p.*1e3) + vmin, vmax = extrema(SPL_p) + err = abs.(SPL_p_jl_interp .- SPL_p)./(vmax - vmin) + @test maximum(err) < 0.042 + + SPL_alpha_jl_interp = linear(freqs, SPL_alpha_jl, f_alpha.*1e3) + vmin, vmax = extrema(SPL_alpha) + err = abs.(SPL_alpha_jl_interp .- SPL_alpha)./(vmax - vmin) + @test maximum(err) < 0.040 + end + end + end + + @testset "BPM Figure 38d" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 45.72e-2 # span in meters + chord = 2.54e-2 # chord in meters + U = 31.7 # freestream velocity in m/s + M = 0.093 # mach number, corresponds to u = 31.7 m/s in bpm report + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + alphastar = 0.0*pi/180 + # Using the tripped boundary layer in this case. + bl = AcousticAnalogies.TrippedN0012BoundaryLayer() + + # Now, need to get the data from the BPM report. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure38-d-TBL-TE-suction.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_s = bpm[:, 1] + SPL_s = bpm[:, 2] + + # At zero angle of attack the pressure and suction side predictions are the same. + f_p = f_s + SPL_p = SPL_s + + for angle_of_attack_sign in [1, -1] + for use_Ualpha in [false, true] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl; use_Ualpha=use_Ualpha) + + # Now compare... + SPL_s_jl_interp = linear(freqs, SPL_s_jl, f_s.*1e3) + vmin, vmax = extrema(SPL_s) + err = abs.(SPL_s_jl_interp .- SPL_s)./(vmax - vmin) + @test maximum(err) < 0.026 + + SPL_p_jl_interp = linear(freqs, SPL_p_jl, f_p.*1e3) + vmin, vmax = extrema(SPL_p) + err = abs.(SPL_p_jl_interp .- SPL_p)./(vmax - vmin) + @test maximum(err) < 0.026 + + # These should all be very negative, since alphastar is zero: + @test all(SPL_alpha_jl .< -100) + end + end + end + + + @testset "BPM Figure 39d" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 45.72e-2 # span in meters + chord = 2.54e-2 # chord in meters + U = 31.7 # freestream velocity in m/s + M = 0.093 # mach number, corresponds to u = 31.7 m/s in bpm report + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + alphastar = 4.8*pi/180 + # Using the tripped boundary layer in this case. + bl = AcousticAnalogies.TrippedN0012BoundaryLayer() + + # Now, need to get the data from the BPM report. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure39-d-TBL-TE-suction.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_s = bpm[:, 1] + SPL_s = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure39-d-TBL-TE-pressure.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_p = bpm[:, 1] + SPL_p = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure39-d-separation.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_alpha = bpm[:, 1] + SPL_alpha = bpm[:, 2] + + for angle_of_attack_sign in [1, -1] + for use_Ualpha in [false, true] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl; use_Ualpha=use_Ualpha) + + # Now compare... + SPL_s_jl_interp = linear(freqs, SPL_s_jl, f_s.*1e3) + vmin, vmax = extrema(SPL_s) + err = abs.(SPL_s_jl_interp .- SPL_s)./(vmax - vmin) + @test maximum(err) < 0.036 + + SPL_p_jl_interp = linear(freqs, SPL_p_jl, f_p.*1e3) + vmin, vmax = extrema(SPL_p) + err = abs.(SPL_p_jl_interp .- SPL_p)./(vmax - vmin) + @test maximum(err) < 0.043 + + SPL_alpha_jl_interp = linear(freqs, SPL_alpha_jl, f_alpha.*1e3) + vmin, vmax = extrema(SPL_alpha) + err = abs.(SPL_alpha_jl_interp .- SPL_alpha)./(vmax - vmin) + @test maximum(err) < 0.039 + end + end + end + + @testset "BPM Figure 45a" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 45.72e-2 # span in meters + chord = 30.48e-2 # chord in meters + U = 71.3 # freestream velocity in m/s + M = 0.209 # Mach number, corresponds to U = 71.3 m/s in BPM report + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + alphastar = 1.5*pi/180 + bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() + + # Now, need to get the data from the BPM report. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure45-a-TBL-TE-suction.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_s = bpm[:, 1] + SPL_s = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure45-a-TBL-TE-pressure.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_p = bpm[:, 1] + SPL_p = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure45-a-separation.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_alpha = bpm[:, 1] + SPL_alpha = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure45-a-LBL-VS.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_lbl_vs = bpm[:, 1] + SPL_lbl_vs = bpm[:, 2] + + for angle_of_attack_sign in [1, -1] + for use_Ualpha in [false, true] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_lbl_vs_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl; do_lblvs=true, use_Ualpha=use_Ualpha) + + # Now compare... + # The agreement with these ones aren't so great. + # Might be better if I grabbed the listing in the BPM appendix? + SPL_s_jl_interp = linear(freqs, SPL_s_jl, f_s.*1e3) + vmin, vmax = extrema(SPL_s) + err = abs.(SPL_s_jl_interp .- SPL_s)./(vmax - vmin) + @test maximum(err) < 0.037 + + SPL_p_jl_interp = linear(freqs, SPL_p_jl, f_p.*1e3) + vmin, vmax = extrema(SPL_p) + err = abs.(SPL_p_jl_interp .- SPL_p)./(vmax - vmin) + @test maximum(err) < 0.058 + + SPL_alpha_jl_interp = linear(freqs, SPL_alpha_jl, f_alpha.*1e3) + vmin, vmax = extrema(SPL_alpha) + err = abs.(SPL_alpha_jl_interp .- SPL_alpha)./(vmax - vmin) + @test maximum(err) < 0.091 + + SPL_lbl_vs_jl_interp = linear(freqs, SPL_lbl_vs_jl, f_lbl_vs.*1e3) + vmin, vmax = extrema(SPL_lbl_vs) + err = abs.(SPL_lbl_vs_jl_interp .- SPL_lbl_vs)./(vmax - vmin) + @test maximum(err) < 0.053 + end + end + end + + @testset "BPM Figure 48c" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 45.72e-2 # span in meters + chord = 22.86e-2 # chord in meters + U = 39.6 # freestream velocity in m/s + M = 0.116 # Mach number, corresponds to U = 39.6 m/s in BPM report + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + alphastar = 0.0*pi/180 + bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure48-c-LBL-VS.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_lbl_vs = bpm[:, 1] + SPL_lbl_vs = bpm[:, 2] + + for angle_of_attack_sign in [1, -1] + for use_Ualpha in [false, true] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_lbl_vs_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl; do_lblvs=true, use_Ualpha=use_Ualpha) + + # Now compare... + SPL_lbl_vs_jl_interp = linear(freqs, SPL_lbl_vs_jl, f_lbl_vs.*1e3) + vmin, vmax = extrema(SPL_lbl_vs) + err = abs.(SPL_lbl_vs_jl_interp .- SPL_lbl_vs)./(vmax - vmin) + @test maximum(err) < 0.083 + end + end + end + + @testset "BPM Figure 54a" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 45.72e-2 # span in meters + chord = 15.24e-2 # chord in meters + U = 71.3 # freestream velocity in m/s + M = 0.209 # Mach number, corresponds to U = 71.3 m/s in BPM report + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + alphastar = 2.7*pi/180 + bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() + + # Now, need to get the data from the BPM report. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure54-a-LBL-VS.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_lbl_vs = bpm[:, 1] + SPL_lbl_vs = bpm[:, 2] + + for angle_of_attack_sign in [1, -1] + for use_Ualpha in [false, true] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_lbl_vs_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl; do_lblvs=true, use_Ualpha=use_Ualpha) + + SPL_lbl_vs_jl_interp = linear(freqs, SPL_lbl_vs_jl, f_lbl_vs.*1e3) + vmin, vmax = extrema(SPL_lbl_vs) + err = abs.(SPL_lbl_vs_jl_interp .- SPL_lbl_vs)./(vmax - vmin) + @test maximum(err) < 0.026 + end + end + end + + @testset "BPM Figure 59c" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 45.72e-2 # span in meters + chord = 10.16e-2 # chord in meters + U = 39.6 # freestream velocity in m/s + M = 0.116 # Mach number, corresponds to U = 39.6 m/s in BPM report + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + alphastar = 0.0*pi/180 + bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure59-c-LBL-VS.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_lbl_vs = bpm[:, 1] + SPL_lbl_vs = bpm[:, 2] + + for angle_of_attack_sign in [1, -1] + for use_Ualpha in [false, true] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_lbl_vs_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl; do_lblvs=true, use_Ualpha=use_Ualpha) + + # Now compare... + SPL_lbl_vs_jl_interp = linear(freqs, SPL_lbl_vs_jl, f_lbl_vs.*1e3) + vmin, vmax = extrema(SPL_lbl_vs) + err = abs.(SPL_lbl_vs_jl_interp .- SPL_lbl_vs)./(vmax - vmin) + @test maximum(err) < 0.11 + end + end + end + + @testset "BPM Figure 60c" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 45.72e-2 # span in meters + chord = 10.16e-2 # chord in meters + U = 39.6 # freestream velocity in m/s + M = 0.116 # Mach number, corresponds to U = 39.6 m/s in BPM report + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + alphastar = 3.3*pi/180 + bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure60-c-LBL-VS.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_lbl_vs = bpm[:, 1] + SPL_lbl_vs = bpm[:, 2] + + for angle_of_attack_sign in [1, -1] + for use_Ualpha in [false, true] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_lbl_vs_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl; do_lblvs=true, use_Ualpha=use_Ualpha) + + # Now compare... + SPL_lbl_vs_jl_interp = linear(freqs, SPL_lbl_vs_jl, f_lbl_vs.*1e3) + vmin, vmax = extrema(SPL_lbl_vs) + err = abs.(SPL_lbl_vs_jl_interp .- SPL_lbl_vs)./(vmax - vmin) + @test maximum(err) < 0.12 + end + end + end + + @testset "BPM Figure 60d" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 45.72e-2 # span in meters + chord = 10.16e-2 # chord in meters + U = 31.7 # freestream velocity in m/s + M = 0.093 # mach number, corresponds to u = 31.7 m/s in bpm report + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + alphastar = 3.3*pi/180 + bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure60-d-LBL-VS.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_lbl_vs = bpm[:, 1] + SPL_lbl_vs = bpm[:, 2] + + for angle_of_attack_sign in [1, -1] + for use_Ualpha in [false, true] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_lbl_vs_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl; do_lblvs=true, use_Ualpha=use_Ualpha) + + SPL_lbl_vs_jl_interp = linear(freqs, SPL_lbl_vs_jl, f_lbl_vs.*1e3) + vmin, vmax = extrema(SPL_lbl_vs) + err = abs.(SPL_lbl_vs_jl_interp .- SPL_lbl_vs)./(vmax - vmin) + @test maximum(err) < 0.026 + end + end + end + + @testset "BPM Figure 65d" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 45.72e-2 # span in meters + chord = 5.08e-2 # chord in meters + U = 31.7 # freestream velocity in m/s + M = 0.093 # mach number, corresponds to u = 31.7 m/s in bpm report + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + alphastar = 0.0*pi/180 + bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure65-d-LBL-VS.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_lbl_vs = bpm[:, 1] + SPL_lbl_vs = bpm[:, 2] + + for angle_of_attack_sign in [1, -1] + for use_Ualpha in [false, true] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_lbl_vs_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl; do_lblvs=true, use_Ualpha=use_Ualpha) + + SPL_lbl_vs_jl_interp = linear(freqs, SPL_lbl_vs_jl, f_lbl_vs.*1e3) + vmin, vmax = extrema(SPL_lbl_vs) + err = abs.(SPL_lbl_vs_jl_interp .- SPL_lbl_vs)./(vmax - vmin) + @test maximum(err) < 0.021 + end + end + end + + @testset "BPM Figure 66b" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 45.72e-2 # span in meters + chord = 5.08e-2 # chord in meters + U = 39.6 # freestream velocity in m/s + M = 0.116 # Mach number, corresponds to U = 39.6 m/s in BPM report + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + alphastar = 4.2*pi/180 + bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure66-b-LBL-VS.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_lbl_vs = bpm[:, 1] + SPL_lbl_vs = bpm[:, 2] + + for angle_of_attack_sign in [1, -1] + for use_Ualpha in [false, true] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_lbl_vs_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl; do_lblvs=true, use_Ualpha=use_Ualpha) + + SPL_lbl_vs_jl_interp = linear(freqs, SPL_lbl_vs_jl, f_lbl_vs.*1e3) + vmin, vmax = extrema(SPL_lbl_vs) + err = abs.(SPL_lbl_vs_jl_interp .- SPL_lbl_vs)./(vmax - vmin) + @test length(err) == 3 + @test err[1] < 0.089 + @test err[2] < 0.373 + @test err[3] < 0.746 + end + end + end + + @testset "BPM Figure 69a" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 45.72e-2 # span in meters + chord = 5.08e-2 # chord in meters + U = 71.3 # freestream velocity in m/s + M = 0.209 # Mach number, corresponds to U = 71.3 m/s in BPM report + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + alphastar = 15.4*pi/180 + bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() + + # Now, need to get the data from the BPM report. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure69-a-separation.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_alpha = bpm[:, 1] + SPL_alpha = bpm[:, 2] + + for angle_of_attack_sign in [1, -1] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl) + + # Now compare... + @test all(SPL_s_jl .≈ -100) + @test all(SPL_p_jl .≈ -100) + + SPL_alpha_jl_interp = linear(freqs, SPL_alpha_jl, f_alpha.*1e3) + vmin, vmax = extrema(SPL_alpha) + err = abs.(SPL_alpha_jl_interp .- SPL_alpha)./(vmax - vmin) + @test maximum(err) < 0.033 + end + end + + @testset "BPM Figure 91" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 30.48e-2 # span in meters + chord = 15.24e-2 # chord in meters + speedofsound = 340.46 + U = 71.3 # freestream velocity in m/s + # M = 0.209 # Mach number, corresponds to U = 71.3 m/s in BPM report + M = U/speedofsound + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + # alphatip = 0.71*10.8*pi/180 + alphastar = 10.8*pi/180 + bl = AcousticAnalogies.UntrippedN0012BoundaryLayer() + # blade_tip = AcousticAnalogies.RoundedTip{AcousticAnalogies.BPMTipAlphaCorrection}() + blade_tip = AcousticAnalogies.RoundedTip(AcousticAnalogies.BPMTipAlphaCorrection(), 0.0) + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure91-tip.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_tip = bpm[:, 1] + SPL_tip = bpm[:, 2] + + for angle_of_attack_sign in [1, -1] + for use_Ualpha in [false, true] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_tip_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl; do_tip_vortex=true, blade_tip=blade_tip, use_Ualpha=use_Ualpha) + + SPL_tip_jl_interp = linear(freqs, SPL_tip_jl, f_tip.*1e3) + vmin, vmax = extrema(SPL_tip) + err = abs.(SPL_tip_jl_interp .- SPL_tip)./(vmax - vmin) + @test maximum(err) < 0.047 + end + end + end + + @testset "BPM Figure 98b" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 45.72e-2 # span in meters + chord = 60.96e-2 # chord in meters + U = 69.5 # freestream velocity in m/s + M = U/340.46 + h = 1.1e-3 # trailing edge bluntness in meters + Psi = 14*pi/180 # bluntness angle in radians + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + alphastar = 0.0*pi/180 + bl = AcousticAnalogies.TrippedN0012BoundaryLayer() + + # Now, need to get the data from the BPM report. + # Figures 98 a-d only differ in trailing edge bluntness, so the other sources are all the same. + # And TBL-TE is the only significant source, other than bluntness. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure98-a-TBL-TE-suction.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_s = bpm[:, 1] + SPL_s = bpm[:, 2] + + # Suction and pressure are the same for zero angle of attack. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure98-a-TBL-TE-suction.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_p = bpm[:, 1] + SPL_p = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure98-b-bluntness.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_teb_vs = bpm[:, 1] + SPL_teb_vs = bpm[:, 2] + + for angle_of_attack_sign in [1, -1] + for use_Ualpha in [false, true] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_teb_vs_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl; do_tebvs=true, h=h, Psi=Psi, use_Ualpha=use_Ualpha) + + # Now compare... + SPL_s_jl_interp = linear(freqs, SPL_s_jl, f_s.*1e3) + vmin, vmax = extrema(SPL_s) + err = abs.(SPL_s_jl_interp .- SPL_s)./(vmax - vmin) + @test maximum(err) < 0.053 + + SPL_p_jl_interp = linear(freqs, SPL_p_jl, f_p.*1e3) + vmin, vmax = extrema(SPL_p) + err = abs.(SPL_p_jl_interp .- SPL_p)./(vmax - vmin) + @test maximum(err) < 0.053 + + SPL_teb_vs_jl_interp = linear(freqs, SPL_teb_vs_jl, f_teb_vs.*1e3) + vmin, vmax = extrema(SPL_teb_vs) + err = abs.(SPL_teb_vs_jl_interp .- SPL_teb_vs)./(vmax - vmin) + # Last two points are off. + # Not sure why. + @test maximum(err[1:end-2]) < 0.052 + @test maximum(err[1:end-2]) < 0.052 + @test maximum(err[1:end-1]) < 0.060 + @test maximum(err) < 0.171 + end + end + end + + @testset "BPM Figure 98c" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 45.72e-2 # span in meters + chord = 60.96e-2 # chord in meters + U = 69.5 # freestream velocity in m/s + M = U/340.46 + h = 1.9e-3 # trailing edge bluntness in meters + Psi = 14*pi/180 # bluntness angle in radians + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + M_c = 0.8*M + alphastar = 0.0*pi/180 + bl = AcousticAnalogies.TrippedN0012BoundaryLayer() + + # Now, need to get the data from the BPM report. + # Figures 98 a-d only differ in trailing edge bluntness, so the other sources are all the same. + # And TBL-TE is the only significant source, other than bluntness. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure98-a-TBL-TE-suction.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_s = bpm[:, 1] + SPL_s = bpm[:, 2] + + # Suction and pressure are the same for zero angle of attack. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure98-a-TBL-TE-suction.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_p = bpm[:, 1] + SPL_p = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure98-c-bluntness.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_teb_vs = bpm[:, 1] + SPL_teb_vs = bpm[:, 2] + + for angle_of_attack_sign in [1, -1] + for use_Ualpha in [false, true] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_teb_vs_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl; do_tebvs=true, h=h, Psi=Psi, use_Ualpha=use_Ualpha) + + # Now compare... + SPL_s_jl_interp = linear(freqs, SPL_s_jl, f_s.*1e3) + vmin, vmax = extrema(SPL_s) + err = abs.(SPL_s_jl_interp .- SPL_s)./(vmax - vmin) + @test maximum(err) < 0.053 + + SPL_p_jl_interp = linear(freqs, SPL_p_jl, f_p.*1e3) + vmin, vmax = extrema(SPL_p) + err = abs.(SPL_p_jl_interp .- SPL_p)./(vmax - vmin) + @test maximum(err) < 0.053 + + SPL_teb_vs_jl_interp = linear(freqs, SPL_teb_vs_jl, f_teb_vs.*1e3) + vmin, vmax = extrema(SPL_teb_vs) + err = abs.(SPL_teb_vs_jl_interp .- SPL_teb_vs)./(vmax - vmin) + # Last two points are off. + # Not sure why. + @test maximum(err[1:end-2]) < 0.040 + @test maximum(err[1:end-1]) < 0.189 + @test err[end] < 0.111 + end + end + end + + @testset "BPM Figure 98d" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 45.72e-2 # span in meters + chord = 60.96e-2 # chord in meters + U = 69.5 # freestream velocity in m/s + M = U/340.46 + h = 2.5e-3 # trailing edge bluntness in meters + Psi = 14*pi/180 # bluntness angle in radians + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + alphastar = 0.0*pi/180 + bl = AcousticAnalogies.TrippedN0012BoundaryLayer() + + # Now, need to get the data from the BPM report. + # Figures 98 a-d only differ in trailing edge bluntness, so the other sources are all the same. + # And TBL-TE is the only significant source, other than bluntness. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure98-a-TBL-TE-suction.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_s = bpm[:, 1] + SPL_s = bpm[:, 2] + + # Suction and pressure are the same for zero angle of attack. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure98-a-TBL-TE-suction.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_p = bpm[:, 1] + SPL_p = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure98-d-bluntness.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_teb_vs = bpm[:, 1] + SPL_teb_vs = bpm[:, 2] + + for angle_of_attack_sign in [1, -1] + for use_Ualpha in [false, true] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_teb_vs_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl; do_tebvs=true, h=h, Psi=Psi, use_Ualpha=use_Ualpha) + + # Now compare... + SPL_s_jl_interp = linear(freqs, SPL_s_jl, f_s.*1e3) + vmin, vmax = extrema(SPL_s) + err = abs.(SPL_s_jl_interp .- SPL_s)./(vmax - vmin) + @test maximum(err) < 0.053 + + SPL_p_jl_interp = linear(freqs, SPL_p_jl, f_p.*1e3) + vmin, vmax = extrema(SPL_p) + err = abs.(SPL_p_jl_interp .- SPL_p)./(vmax - vmin) + @test maximum(err) < 0.053 + + SPL_teb_vs_jl_interp = linear(freqs, SPL_teb_vs_jl, f_teb_vs.*1e3) + vmin, vmax = extrema(SPL_teb_vs) + err = abs.(SPL_teb_vs_jl_interp .- SPL_teb_vs)./(vmax - vmin) + # Last two points are off. + # Not sure why. + @test maximum(err[1:end-2]) < 0.044 + @test err[end-1] < 0.089 + @test err[end] < 0.089 + end + end + end + + @testset "BPM Figure 99b" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 45.72e-2 # span in meters + chord = 60.96e-2 # chord in meters + U = 38.6 # freestream velocity in m/s + M = U/340.46 + h = 1.1e-3 # trailing edge bluntness in meters + Psi = 14*pi/180 # bluntness angle in radians + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + alphastar = 0.0*pi/180 + bl = AcousticAnalogies.TrippedN0012BoundaryLayer() + + # Now, need to get the data from the BPM report. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure99-b-TBL-TE-suction.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_s = bpm[:, 1] + SPL_s = bpm[:, 2] + + # Suction and pressure are the same for zero angle of attack. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure99-b-TBL-TE-suction.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_p = bpm[:, 1] + SPL_p = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure99-b-bluntness.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_teb_vs = bpm[:, 1] + SPL_teb_vs = bpm[:, 2] + + for angle_of_attack_sign in [1, -1] + for use_Ualpha in [false, true] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_teb_vs_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl; do_tebvs=true, h=h, Psi=Psi, use_Ualpha=use_Ualpha) + + # Now compare... + SPL_s_jl_interp = linear(freqs, SPL_s_jl, f_s.*1e3) + vmin, vmax = extrema(SPL_s) + err = abs.(SPL_s_jl_interp .- SPL_s)./(vmax - vmin) + @test maximum(err) < 0.077 + + SPL_p_jl_interp = linear(freqs, SPL_p_jl, f_p.*1e3) + vmin, vmax = extrema(SPL_p) + err = abs.(SPL_p_jl_interp .- SPL_p)./(vmax - vmin) + @test maximum(err) < 0.077 + + SPL_teb_vs_jl_interp = linear(freqs, SPL_teb_vs_jl, f_teb_vs.*1e3) + vmin, vmax = extrema(SPL_teb_vs) + err = abs.(SPL_teb_vs_jl_interp .- SPL_teb_vs)./(vmax - vmin) + # Last two points are off. + # Not sure why. + @test maximum(err[1:end-2]) < 0.091 + @test err[ end-1] < 0.251 + @test err[ end ] < 0.400 + end + end + end + + @testset "BPM Figure 99c" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 45.72e-2 # span in meters + chord = 60.96e-2 # chord in meters + U = 38.6 # freestream velocity in m/s + M = U/340.46 + h = 1.9e-3 # trailing edge bluntness in meters + Psi = 14*pi/180 # bluntness angle in radians + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + alphastar = 0.0*pi/180 + bl = AcousticAnalogies.TrippedN0012BoundaryLayer() + + # Now, need to get the data from the BPM report. + # Figures 99 a-d only differ in trailing edge bluntness, so the other sources are all the same. + # And TBL-TE is the only significant source, other than bluntness. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure99-b-TBL-TE-suction.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_s = bpm[:, 1] + SPL_s = bpm[:, 2] + + # Suction and pressure are the same for zero angle of attack. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure99-b-TBL-TE-suction.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_p = bpm[:, 1] + SPL_p = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure99-c-bluntness.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_teb_vs = bpm[:, 1] + SPL_teb_vs = bpm[:, 2] + + for angle_of_attack_sign in [1, -1] + for use_Ualpha in [false, true] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_teb_vs_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl; do_tebvs=true, h=h, Psi=Psi, use_Ualpha=use_Ualpha) + + # Now compare... + SPL_s_jl_interp = linear(freqs, SPL_s_jl, f_s.*1e3) + vmin, vmax = extrema(SPL_s) + err = abs.(SPL_s_jl_interp .- SPL_s)./(vmax - vmin) + @test maximum(err) < 0.077 + + SPL_p_jl_interp = linear(freqs, SPL_p_jl, f_p.*1e3) + vmin, vmax = extrema(SPL_p) + err = abs.(SPL_p_jl_interp .- SPL_p)./(vmax - vmin) + @test maximum(err) < 0.077 + + SPL_teb_vs_jl_interp = linear(freqs, SPL_teb_vs_jl, f_teb_vs.*1e3) + vmin, vmax = extrema(SPL_teb_vs) + err = abs.(SPL_teb_vs_jl_interp .- SPL_teb_vs)./(vmax - vmin) + # Last two points are off. + # Not sure why. + @test maximum(err[1:end-2]) < 0.057 + @test err[ end-1] < 0.070 + @test err[ end ] < 0.256 + end + end + end + + @testset "BPM Figure 99d" begin + nu = 1.4529e-5 # kinematic viscosity, m^2/s + L = 45.72e-2 # span in meters + chord = 60.96e-2 # chord in meters + U = 38.6 # freestream velocity in m/s + M = U/340.46 + h = 2.5e-3 # trailing edge bluntness in meters + Psi = 14*pi/180 # bluntness angle in radians + r_e = 1.22 # radiation distance in meters + θ_e = 90*pi/180 + Φ_e = 90*pi/180 + alphastar = 0.0*pi/180 + bl = AcousticAnalogies.TrippedN0012BoundaryLayer() + + # Now, need to get the data from the BPM report. + # Figures 99 a-d only differ in trailing edge bluntness, so the other sources are all the same. + # And TBL-TE is the only significant source, other than bluntness. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure99-b-TBL-TE-suction.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_s = bpm[:, 1] + SPL_s = bpm[:, 2] + + # Suction and pressure are the same for zero angle of attack. + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure99-b-TBL-TE-suction.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_p = bpm[:, 1] + SPL_p = bpm[:, 2] + + fname = joinpath(@__DIR__, "bpm_data", "brooks_airfoil_self_noise_and_prediction_1989", "19890016302-figure99-d-bluntness.csv") + bpm = DelimitedFiles.readdlm(fname, ',') + f_teb_vs = bpm[:, 1] + SPL_teb_vs = bpm[:, 2] + + for angle_of_attack_sign in [1, -1] + for use_Ualpha in [false, true] + freqs, SPL_s_jl, SPL_p_jl, SPL_alpha_jl, SPL_teb_vs_jl = calculate_bpm_test(nu, L, chord, U, M, r_e, θ_e, Φ_e, angle_of_attack_sign*alphastar, bl; do_tebvs=true, h=h, Psi=Psi, use_Ualpha=use_Ualpha) + + # Now compare... + SPL_s_jl_interp = linear(freqs, SPL_s_jl, f_s.*1e3) + vmin, vmax = extrema(SPL_s) + err = abs.(SPL_s_jl_interp .- SPL_s)./(vmax - vmin) + @test maximum(err) < 0.077 + + SPL_p_jl_interp = linear(freqs, SPL_p_jl, f_p.*1e3) + vmin, vmax = extrema(SPL_p) + err = abs.(SPL_p_jl_interp .- SPL_p)./(vmax - vmin) + @test maximum(err) < 0.077 + + SPL_teb_vs_jl_interp = linear(freqs, SPL_teb_vs_jl, f_teb_vs.*1e3) + vmin, vmax = extrema(SPL_teb_vs) + err = abs.(SPL_teb_vs_jl_interp .- SPL_teb_vs)./(vmax - vmin) + # Last two points are off. + # Not sure why. + @test maximum(err[1:end-3]) < 0.047 + @test err[end-2] < 0.068 + @test err[end-1] < 0.213 + @test err[end] < 0.225 + end + end + end +end + +end # module diff --git a/test/ccblade_helper_tests.jl b/test/ccblade_helper_tests.jl deleted file mode 100644 index 669dcbcd..00000000 --- a/test/ccblade_helper_tests.jl +++ /dev/null @@ -1,94 +0,0 @@ -module CCBladeHelperTests - -using AcousticAnalogies -using CCBlade -using DelimitedFiles -using KinematicCoordinateTransformations -using StaticArrays -using Test - -include("gen_test_data/gen_ccblade_data/constants.jl") -using .CCBladeTestCaseConstants -ccbc = CCBladeTestCaseConstants - -@testset "CCBlade private utils tests" begin - - Δr = (ccbc.Rtip - ccbc.Rhub)/10 - r = (ccbc.Rhub+0.5*Δr):Δr:(ccbc.Rtip-0.5*Δr) - precone = 3*pi/180 - rotor = Rotor(ccbc.Rhub, ccbc.Rtip, ccbc.num_blades; precone=precone, turbine=false) - - dummy = similar(r) - sections = Section.(r, dummy, dummy, dummy) - - @test all(AcousticAnalogies.get_ccblade_dradii(rotor, sections) .≈ Δr) -end - -@testset "CCBlade CompactSourceElement test" begin - - omega = 2200*(2*pi/60) - # Read in the loading data. - data = readdlm("gen_test_data/gen_ccblade_data/ccblade_omega11.csv", ',') - fn = data[:, 1] - fc = data[:, 2] - - # Create the CCBlade objects. - rotor = Rotor(ccbc.Rhub, ccbc.Rtip, ccbc.num_blades; turbine=false) - sections = Section.(ccbc.radii, ccbc.chord, ccbc.theta, nothing) - ops = simple_op.(ccbc.v, omega, ccbc.radii, ccbc.rho; asound=ccbc.c0) - # Only care about getting the loading into the CCBlade Output structs. - dummies = fill(0.0, 13) - outs = Outputs.(fn, fc, dummies...) - - # Set the source time stuff. - num_blade_passes = 3 - steps_per_blade_pass = 8 - num_src_times = num_blade_passes*steps_per_blade_pass - bpp = 2*pi/omega/ccbc.num_blades - src_time_range = num_blade_passes*bpp - - # Finally get all the source elements. - aoc2 = fill(ccbc.area_over_chord_squared, length(sections)) - ses_helper = source_elements_ccblade(rotor, sections, ops, outs, aoc2, src_time_range, num_src_times) - - # Now need to get the source elements the "normal" way. First get the - # transformation objects. - rot_axis = @SVector [1.0, 0.0, 0.0] - blade_axis = @SVector [0.0, 1.0, 0.0] - y0_hub = @SVector [0.0, 0.0, 0.0] # m - v0_hub = ccbc.v.*rot_axis - t0 = 0.0 - rot_trans = SteadyRotXTransformation(t0, omega, 0.0) - const_vel_trans = ConstantVelocityTransformation(t0, y0_hub, v0_hub) - - # Need the source times. - dt = src_time_range/num_src_times - src_times = t0 .+ (0:num_src_times-1).*dt - - # This is just an array of the angular offsets of each blade. - θs = 2*pi/ccbc.num_blades.*(0:(ccbc.num_blades-1)) - - # Radial spacing. - dradii = get_dradii(ccbc.radii, ccbc.Rhub, ccbc.Rtip) - - # Reshape stuff for broadcasting. - radii = reshape(ccbc.radii, 1, :, 1) - dradii = reshape(dradii, 1, :, 1) - cs_area = reshape(ccbc.area_over_chord_squared.*ccbc.chord.^2, 1, :, 1) - fn = reshape(fn, 1, :, 1) - fc = reshape(fc, 1, :, 1) - src_times = reshape(src_times, :, 1, 1) # This isn't really necessary. - θs = reshape(θs, 1, 1, :) - - # Get all the transformations. - trans = compose.(src_times, Ref(const_vel_trans), Ref(rot_trans)) - - # Transform the source elements. - ses = CompactSourceElement.(ccbc.rho, ccbc.c0, radii, θs, dradii, cs_area, -fn, 0.0, fc, src_times) .|> trans - - for field in fieldnames(CompactSourceElement) - @test all(getproperty.(ses_helper, field) .≈ getproperty.(ses, field)) - end -end - -end diff --git a/test/compact_f1a_constructor_tests.jl b/test/compact_f1a_constructor_tests.jl new file mode 100644 index 00000000..9537a6f2 --- /dev/null +++ b/test/compact_f1a_constructor_tests.jl @@ -0,0 +1,182 @@ +module CompactF1AConstructorTests + +using AcousticAnalogies +using CCBlade +using FileIO: load +using KinematicCoordinateTransformations +using StaticArrays +using JLD2 +using Test + +include("gen_test_data/gen_ccblade_data/constants.jl") +using .CCBladeTestCaseConstants +ccbc = CCBladeTestCaseConstants + +@testset "CCBlade private utils tests" begin + + Δr = (ccbc.Rtip - ccbc.Rhub)/10 + r = (ccbc.Rhub+0.5*Δr):Δr:(ccbc.Rtip-0.5*Δr) + precone = 3*pi/180 + rotor = Rotor(ccbc.Rhub, ccbc.Rtip, ccbc.num_blades; precone=precone, turbine=false) + + dummy = similar(r) + sections = Section.(r, dummy, dummy, dummy) + + @test all(AcousticAnalogies.get_ccblade_dradii(rotor, sections) .≈ Δr) +end + +@testset "Constructor rotation tests" begin + @testset "CompactF1ASourceElement" begin + ρ0 = 1.1 + c0 = 1.2 + r = 2.0 + Δr = 0.1 + Λ = 0.2 + fn = 2.0 + fr = 3.0 + fc = 4.0 + τ = 0.1 + se_0theta = CompactF1ASourceElement(ρ0, c0, r, 0.0, Δr, Λ, fn, fr, fc, τ) + for θ in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + # Create a transformation that will undo the θ rotation. + trans = KinematicCoordinateTransformations.SteadyRotXTransformation(τ, 0.0, -θ) + # Create a source element with the theta rotation, then undo it. + se = CompactF1ASourceElement(ρ0, c0, r, θ, Δr, Λ, fn, fr, fc, τ) |> trans + # Check that we got the same thing: + for field in fieldnames(CompactF1ASourceElement) + @test getproperty(se, field) ≈ getproperty(se_0theta, field) + end + end + end + + @testset "CompactF1ASourceElement, CCBlade" begin + + # Create the CCBlade objects. + area_per_chord2 = 0.1 + τ = 0.1 + + ccblade_fname = joinpath(@__DIR__, "gen_test_data", "gen_ccblade_data", "ccblade_omega11-outputs.jld2") + outs_d = load(ccblade_fname) + section = CCBlade.Section(first(ccbc.radii), first(ccbc.chord), first(ccbc.theta)*pi/180, nothing) + Δr = ccbc.radii[2] - ccbc.radii[1] + op = CCBlade.OperatingPoint(ccbc.v, outs_d["omega"]*first(ccbc.radii), ccbc.rho, ccbc.pitch, ccbc.mu, ccbc.c0) + rotor0precone = CCBlade.Rotor(ccbc.Rhub, ccbc.Rtip, ccbc.num_blades) + out = CCBlade.Outputs(outs_d["Np"][1], outs_d["Tp"][1], outs_d["a"][1], outs_d["ap"][1], outs_d["u"][1], outs_d["v"][1], outs_d["phi"][1], outs_d["alpha"][1], outs_d["W"][1], outs_d["cl"][1], outs_d["cd"][1], outs_d["cn"][1], outs_d["ct"][1], outs_d["F"][1], outs_d["G"][1]) + + @test rotor0precone.precone ≈ 0.0 + Rhub = rotor0precone.Rhub + Rtip = rotor0precone.Rtip + num_blades = rotor0precone.B + turbine = rotor0precone.turbine + for positive_x_rotation in [true, false] + se_0theta0precone = CompactF1ASourceElement(rotor0precone, section, op, out, 0.0, Δr, area_per_chord2, τ, positive_x_rotation) + for precone in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + rotor = CCBlade.Rotor(Rhub, Rtip, num_blades; turbine=turbine, precone=precone) + # This is tricky: in my "normal" coordinate system, the blade is rotating around the x axis, moving axially in the positive x direction, and is initially aligned with the y axis. + # That means that the precone should be a rotation around the negative z axis. + # And so to undo it, we want a positive rotation around the positive z axis. + trans_precone = SteadyRotZTransformation(τ, 0.0, precone) + for θ in [5, 10, 65, 95, 260, 270, 290].*(pi/180) + trans_theta = SteadyRotXTransformation(τ, 0.0, -θ) + # Create a transformation that reverses the theta and precone rotations. + # The precone happens first, then theta. + # So to reverse it we need to do theta, then precone. + trans = KinematicCoordinateTransformations.compose(τ, trans_precone, trans_theta) + # Create a source element with the theta and precone rotations, then undo it. + se = CompactF1ASourceElement(rotor, section, op, out, θ, Δr, area_per_chord2, τ, positive_x_rotation) |> trans + # Check that we got the same thing: + for field in fieldnames(CompactF1ASourceElement) + @test getproperty(se, field) ≈ getproperty(se_0theta0precone, field) + end + end + end + end + + end +end + +@testset "CCBlade CompactF1ASourceElement complete test" begin + + for positive_x_rotation in [true, false] + # omega = 2200*(2*pi/60) + # Read in the loading data. + # data = readdlm("gen_test_data/gen_ccblade_data/ccblade_omega11.csv", ',') + # Np = data[:, 1] + # Tp = data[:, 2] + + # Read in the loading data. + fname = joinpath(@__DIR__, "gen_test_data", "gen_ccblade_data", "ccblade_omega11-outputs.jld2") + data_d = load(fname) + omega = data_d["omega"] + Np = data_d["Np"] + Tp = data_d["Tp"] + + # Create the CCBlade objects. + rotor = Rotor(ccbc.Rhub, ccbc.Rtip, ccbc.num_blades; turbine=false) + sections = Section.(ccbc.radii, ccbc.chord, ccbc.theta, nothing) + ops = simple_op.(ccbc.v, omega, ccbc.radii, ccbc.rho; asound=ccbc.c0) + # Only care about getting the loading into the CCBlade Output structs. + dummies = fill(0.0, 13) + outs = Outputs.(Np, Tp, dummies...) + + # Set the source time stuff. + num_blade_passes = 3 + steps_per_blade_pass = 8 + num_src_times = num_blade_passes*steps_per_blade_pass + bpp = 2*pi/omega/ccbc.num_blades + src_time_range = num_blade_passes*bpp + + # Finally get all the source elements. + aoc2 = fill(ccbc.area_over_chord_squared, length(sections)) + ses_helper = f1a_source_elements_ccblade(rotor, sections, ops, outs, aoc2, src_time_range, num_src_times, positive_x_rotation) + + # Now need to get the source elements the "normal" way. First get the + # transformation objects. + rot_axis = @SVector [1.0, 0.0, 0.0] + blade_axis = @SVector [0.0, 1.0, 0.0] + y0_hub = @SVector [0.0, 0.0, 0.0] # m + v0_hub = ccbc.v.*rot_axis + t0 = 0.0 + if positive_x_rotation + rot_trans = SteadyRotXTransformation(t0, omega, 0.0) + else + rot_trans = SteadyRotXTransformation(t0, -omega, 0.0) + end + const_vel_trans = ConstantVelocityTransformation(t0, y0_hub, v0_hub) + + # Need the source times. + dt = src_time_range/num_src_times + src_times = t0 .+ (0:num_src_times-1).*dt + + # This is just an array of the angular offsets of each blade. + θs = 2*pi/ccbc.num_blades.*(0:(ccbc.num_blades-1)) + + # Radial spacing. + dradii = get_dradii(ccbc.radii, ccbc.Rhub, ccbc.Rtip) + + # Reshape stuff for broadcasting. + radii = reshape(ccbc.radii, 1, :, 1) + dradii = reshape(dradii, 1, :, 1) + cs_area = reshape(ccbc.area_over_chord_squared.*ccbc.chord.^2, 1, :, 1) + Np = reshape(Np, 1, :, 1) + Tp = reshape(Tp, 1, :, 1) + src_times = reshape(src_times, :, 1, 1) # This isn't really necessary. + θs = reshape(θs, 1, 1, :) + + # Get all the transformations. + trans = compose.(src_times, Ref(const_vel_trans), Ref(rot_trans)) + + # Transform the source elements. + if positive_x_rotation + ses = CompactF1ASourceElement.(ccbc.rho, ccbc.c0, radii, θs, dradii, cs_area, -Np, 0.0, Tp, src_times) .|> trans + else + ses = CompactF1ASourceElement.(ccbc.rho, ccbc.c0, radii, θs, dradii, cs_area, -Np, 0.0, -Tp, src_times) .|> trans + end + + for field in fieldnames(CompactF1ASourceElement) + @test all(getproperty.(ses_helper, field) .≈ getproperty.(ses, field)) + end + end +end + +end diff --git a/test/doppler_tests.jl b/test/doppler_tests.jl new file mode 100644 index 00000000..98c719c3 --- /dev/null +++ b/test/doppler_tests.jl @@ -0,0 +1,184 @@ +module DopplerTests + +using AcousticAnalogies: AcousticAnalogies +using KinematicCoordinateTransformations: KinematicTransformation, SteadyRotXTransformation, SteadyRotYTransformation, SteadyRotZTransformation, ConstantVelocityTransformation, compose +using StaticArrays: SVector +using Test + +struct DummyElement{TDoppler,Ty0dot,Ty1dot,Ttime,TSoS} <: AcousticAnalogies.AbstractBroadbandSourceElement{AcousticAnalogies.BPMDirectivity,false, AcousticAnalogies.NoMachCorrection,TDoppler} + # Source position and its time derivatives. + y0dot::Ty0dot + y1dot::Ty1dot + # Source time. + τ::Ttime + # speed of sound + c0::TSoS +end + +function DummyElement{TDoppler}(y0dot, y1dot, τ, c0) where {TDoppler} + return DummyElement{TDoppler,typeof(y0dot),typeof(y1dot),typeof(τ),typeof(c0)}(y0dot, y1dot, τ, c0) +end + +function DummyElement{TDoppler}(se::DummyElement) where {TDoppler} + return DummyElement{TDoppler,typeof(se.y0dot),typeof(se.y1dot),typeof(se.τ),typeof(se.c0)}(se.y0dot, se.y1dot, se.τ, se.c0) +end + +""" + (trans::KinematicTransformation)(se::DummyElement) + +Transform the position and orientation of a source element according to the coordinate system transformation `trans`. +""" +function (trans::KinematicTransformation)(se::DummyElement{TDoppler,Ty0dot,Ty1dot,Ttime,TSoS}) where {TDoppler,Ty0dot,Ty1dot,Ttime,TSoS} + linear_only = false + y0dot, y1dot = trans(se.τ, se.y0dot, se.y1dot, linear_only) + + return DummyElement{TDoppler,Ty0dot,Ty1dot,Ttime,TSoS}(y0dot, y1dot, se.τ, se.c0) +end + +@testset "Doppler shift" begin + @testset "no motion" begin + @testset "stationary observer" begin + obs = AcousticAnalogies.StationaryAcousticObserver(SVector(1.2, 2.3, 3.4)) + se = DummyElement{true}(SVector(3.0, 4.3, 5.0), SVector(0.0, 0.0, 0.0), 10.0, 340.0) + @test AcousticAnalogies.doppler_factor(se, obs) ≈ 1.0 + + @test AcousticAnalogies.doppler_factor(DummyElement{false}(se), obs) ≈ 1.0 + end + + @testset "\"moving\" observer" begin + # Should get the same thing with a `ConstVelocityAcousticObserver` that's not moving. + obs = AcousticAnalogies.ConstVelocityAcousticObserver(8.0, SVector(1.2, 2.3, 3.4), SVector(0.0, 0.0, 0.0)) + se = DummyElement{true}(SVector(3.0, 4.3, 5.0), SVector(0.0, 0.0, 0.0), 10.0, 340.0) + @test AcousticAnalogies.doppler_factor(se, obs) ≈ 1.0 + @test AcousticAnalogies.doppler_factor(DummyElement{false}(se), obs) ≈ 1.0 + end + end + + @testset "moving source" begin + @testset "stationary observer" begin + for mach_vector in -0.9:0.1:0.9 + c0 = 343.0 + + # Observer time doesn't matter since the observer isn't moving. + t_obs = 6.5 + x_obs = SVector(1.2, 2.3, 3.4) + obs = AcousticAnalogies.StationaryAcousticObserver(x_obs) + + y0dot = SVector(1.2, 2.3, -3.4) + y1dot = SVector(0.0, 0.0, mach_vector*c0) + τ = 10.0 + se = DummyElement{true}(y0dot, y1dot, τ, c0) + + doppler_factor_expected = 1/(1 - mach_vector) + @test AcousticAnalogies.doppler_factor(se, obs) ≈ doppler_factor_expected + @test AcousticAnalogies.doppler_factor(DummyElement{false}(se), obs) ≈ 1.0 + + # Now, rotate and translate both the source and the observer. + # The Doppler shift factor should be the same, assuming we don't change the motion of the source and observer. + # Time parameter for the steady rotations doesn't matter because the rotation rate is zero. + trans1 = SteadyRotXTransformation(t_obs, 0.0, 3.0*pi/180) + trans2 = SteadyRotYTransformation(t_obs, 0.0, 4.0*pi/180) + trans3 = SteadyRotZTransformation(t_obs, 0.0, 5.0*pi/180) + x_trans = SVector(2.0, 3.0, 4.0) + v_trans = SVector(0.0, 0.0, 0.0) + # Time parameter for the constant velocity transformations doesn't matter because the velocity is zero. + trans4 = ConstantVelocityTransformation(t_obs, x_trans, v_trans) + + # Transform the source and observer. + trans = compose(t_obs, trans4, compose(t_obs, trans3, compose(t_obs, trans2, trans1))) + se_trans = trans(se) + obs_trans = AcousticAnalogies.StationaryAcousticObserver(trans(t_obs, obs(t_obs))) + + # Now we should still get the same Doppler factor. + @test AcousticAnalogies.doppler_factor(se_trans, obs_trans) ≈ doppler_factor_expected + @test AcousticAnalogies.doppler_factor(DummyElement{false}(se_trans), obs_trans) ≈ 1.0 + end + end + + @testset "\"moving\" observer" begin + for mach_vector in -0.9:0.1:0.9 + c0 = 343.0 + + # Observer time doesn't matter since the observer isn't moving. + t_obs = 6.5 + x_obs = SVector(1.2, 2.3, 3.4) + v_obs = SVector(0.0, 0.0, 0.0) + obs = AcousticAnalogies.ConstVelocityAcousticObserver(t_obs, x_obs, v_obs) + + y0dot = SVector(1.2, 2.3, -3.4) + y1dot = SVector(0.0, 0.0, mach_vector*c0) + τ = 10.0 + se = DummyElement{true}(y0dot, y1dot, τ, c0) + + doppler_factor_expected = 1/(1 - mach_vector) + @test AcousticAnalogies.doppler_factor(se, obs) ≈ doppler_factor_expected + @test AcousticAnalogies.doppler_factor(DummyElement{false}(se), obs) ≈ 1.0 + + # Now, rotate and translate both the source and the observer. + # The Doppler shift factor should be the same, assuming we don't change the motion of the source and observer. + # Time parameter for the steady rotations doesn't matter because the rotation rate is zero. + trans1 = SteadyRotXTransformation(t_obs, 0.0, 3.0*pi/180) + trans2 = SteadyRotYTransformation(t_obs, 0.0, 4.0*pi/180) + trans3 = SteadyRotZTransformation(t_obs, 0.0, 5.0*pi/180) + x_trans = SVector(2.0, 3.0, 4.0) + v_trans = SVector(0.0, 0.0, 0.0) + # Time parameter for the constant velocity transformations doesn't matter because the velocity is zero. + trans4 = ConstantVelocityTransformation(t_obs, x_trans, v_trans) + + # Transform the source and observer. + trans = compose(t_obs, trans4, compose(t_obs, trans3, compose(t_obs, trans2, trans1))) + se_trans = trans(se) + obs_trans = AcousticAnalogies.ConstVelocityAcousticObserver(t_obs, trans(t_obs, obs(t_obs), AcousticAnalogies.velocity(t_obs, obs))...) + + # Now we should still get the same Doppler factor. + @test AcousticAnalogies.doppler_factor(se_trans, obs_trans) ≈ doppler_factor_expected + @test AcousticAnalogies.doppler_factor(DummyElement{false}(se_trans), obs_trans) ≈ 1.0 + end + end + + @testset "actual moving observer" begin + for mach_vector_obs in -0.9:0.1:0.9 + for mach_vector_src in -0.9:0.1:0.9 + c0 = 343.0 + + t_obs = 10.0 + # Need to move the observer farther from the source for cases where they're moving towards each other, since the Doppler factor will change if they cross and move past each other. + x_obs = SVector(1.2, 2.3, 340.0) + v_obs = SVector(0.0, 0.0, mach_vector_obs*c0) + obs = AcousticAnalogies.ConstVelocityAcousticObserver(t_obs, x_obs, v_obs) + + y0dot = SVector(1.2, 2.3, -3.4) + y1dot = SVector(0.0, 0.0, mach_vector_src*c0) + τ = 10.0 + se = DummyElement{true}(y0dot, y1dot, τ, c0) + + doppler_factor_expected = (1 - mach_vector_obs)/(1 - mach_vector_src) + @test AcousticAnalogies.doppler_factor(se, obs) ≈ doppler_factor_expected + @test AcousticAnalogies.doppler_factor(DummyElement{false}(se), obs) ≈ 1.0 + + # Now, rotate and translate both the source and the observer. + # The Doppler shift factor should be the same, assuming we don't change the motion of the source and observer. + # Time parameter for the steady rotations doesn't matter because the rotation rate is zero. + trans1 = SteadyRotXTransformation(t_obs, 0.0, 3.0*pi/180) + trans2 = SteadyRotYTransformation(t_obs, 0.0, 4.0*pi/180) + trans3 = SteadyRotZTransformation(t_obs, 0.0, 5.0*pi/180) + x_trans = SVector(2.0, 3.0, 4.0) + v_trans = SVector(0.0, 0.0, 0.0) + # Time parameter for the constant velocity transformations doesn't matter because the velocity is zero. + trans4 = ConstantVelocityTransformation(t_obs, x_trans, v_trans) + + # Transform the source and observer. + trans = compose(t_obs, trans4, compose(t_obs, trans3, compose(t_obs, trans2, trans1))) + se_trans = trans(se) + obs_trans = AcousticAnalogies.ConstVelocityAcousticObserver(t_obs, trans(t_obs, obs(t_obs), AcousticAnalogies.velocity(t_obs, obs))...) + + # Now we should still get the same Doppler factor. + @test AcousticAnalogies.doppler_factor(se_trans, obs_trans) ≈ doppler_factor_expected + @test AcousticAnalogies.doppler_factor(DummyElement{false}(se_trans), obs_trans) ≈ 1.0 + end + end + end + end +end + +end # module diff --git a/test/f1a_tests.jl b/test/f1a_tests.jl index c7a67ddd..18d3c978 100644 --- a/test/f1a_tests.jl +++ b/test/f1a_tests.jl @@ -79,14 +79,14 @@ end f0dot(τ) = [-fn, -sin(omega*τ)*fc, cos(omega*τ)*fc] f1dot(τ) = [0, -omega*cos(omega*τ)*fc, -omega*sin(omega*τ)*fc] u(τ) = y0dot(τ)./radii - sef1 = CompactSourceElement(rho, c0, dradii, Λ, y0dot, y1dot, nothing, nothing, f0dot, nothing, 0.0, u) + sef1 = CompactF1ASourceElement(rho, c0, dradii, Λ, y0dot, y1dot, nothing, nothing, f0dot, nothing, 0.0, u) t = 0.0 dt = period*0.5^4 τ0, pmi0, pdiff0, pdinf0 = f1_integrand(sef1, obs, t) - sef1a = CompactSourceElement(rho, c0, dradii, Λ, y0dot(τ0), y1dot(τ0), y2dot(τ0), y3dot(τ0), f0dot(τ0), f1dot(τ0), τ0, u(τ0)) - apth = f1a(sef1a, obs) + sef1a = CompactF1ASourceElement(rho, c0, dradii, Λ, y0dot(τ0), y1dot(τ0), y2dot(τ0), y3dot(τ0), f0dot(τ0), f1dot(τ0), τ0, u(τ0)) + apth = noise(sef1a, obs) err_prev_pm = nothing err_prev_pd = nothing diff --git a/test/forwarddiff_test.jl b/test/forwarddiff_test.jl index 66fc699b..d421c6a6 100644 --- a/test/forwarddiff_test.jl +++ b/test/forwarddiff_test.jl @@ -76,7 +76,7 @@ function guided_example(x) fc = reshape(fc, 1, :, 1) src_times = reshape(src_times, :, 1, 1) # This isn't really necessary. - ses = CompactSourceElement.(rho, c0, radii, θs, dradii, cs_area, -fn, 0.0, fc, src_times) + ses = CompactF1ASourceElement.(rho, c0, radii, θs, dradii, cs_area, -fn, 0.0, fc, src_times) t0 = 0.0 # Time at which the angle between the source and target coordinate systems is equal to offest. offset = 0.0 # Angular offset between the source and target cooridante systems at t0. @@ -99,7 +99,7 @@ function guided_example(x) obs_time = adv_time.(ses, Ref(obs)) - apth = f1a.(ses, Ref(obs), obs_time) + apth = noise.(ses, Ref(obs), obs_time) bpp = period/num_blades # blade passing period obs_time_range = 2 * bpp diff --git a/test/gen_bpmjl_data/Project.toml b/test/gen_bpmjl_data/Project.toml new file mode 100644 index 00000000..b3e7f83f --- /dev/null +++ b/test/gen_bpmjl_data/Project.toml @@ -0,0 +1,7 @@ +[deps] +Accessors = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697" +AcousticMetrics = "046f749b-9c1e-43ca-86bc-6902340f753e" +BPM = "f91b385c-3ede-44c9-92c8-2a04f762ef2f" +CCBlade = "e1828068-15df-11e9-03e4-ef195ea46fa4" +FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" +JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819" diff --git a/test/gen_bpmjl_data/airfoils/README.md b/test/gen_bpmjl_data/airfoils/README.md new file mode 100644 index 00000000..1afca4f6 --- /dev/null +++ b/test/gen_bpmjl_data/airfoils/README.md @@ -0,0 +1 @@ +Airfoil data is from http://airfoiltools.com/polar/details?polar=xf-n0012-il-500000 diff --git a/test/gen_bpmjl_data/airfoils/xf-n0012-il-500000.dat b/test/gen_bpmjl_data/airfoils/xf-n0012-il-500000.dat new file mode 100644 index 00000000..9866b76b --- /dev/null +++ b/test/gen_bpmjl_data/airfoils/xf-n0012-il-500000.dat @@ -0,0 +1,147 @@ +From http://airfoiltools.com/polar/details?polar=xf-n0012-il-500000 +500000.0 +0.0 + -17.750 -1.0298 0.12468 0.12173 0.0079 1.0000 0.0199 + -17.500 -1.0693 0.11191 0.10877 0.0002 1.0000 0.0198 + -17.250 -1.0995 0.10168 0.09835 -0.0060 1.0000 0.0198 + -17.000 -1.1249 0.09280 0.08929 -0.0113 1.0000 0.0198 + -16.750 -1.1466 0.08496 0.08127 -0.0159 1.0000 0.0198 + -16.500 -1.1653 0.07799 0.07413 -0.0199 1.0000 0.0198 + -16.250 -1.1812 0.07170 0.06767 -0.0235 1.0000 0.0199 + -16.000 -1.1949 0.06606 0.06186 -0.0265 1.0000 0.0200 + -15.750 -1.2058 0.06100 0.05662 -0.0291 1.0000 0.0201 + -15.500 -1.2144 0.05648 0.05192 -0.0313 1.0000 0.0202 + -15.250 -1.2215 0.05237 0.04764 -0.0331 1.0000 0.0204 + -15.000 -1.2315 0.04811 0.04324 -0.0338 1.0000 0.0206 + -14.750 -1.2349 0.04484 0.03986 -0.0342 1.0000 0.0209 + -14.500 -1.2347 0.04212 0.03707 -0.0345 1.0000 0.0212 + -14.250 -1.2325 0.03975 0.03462 -0.0345 1.0000 0.0215 + -14.000 -1.2291 0.03762 0.03240 -0.0342 1.0000 0.0218 + -13.750 -1.2249 0.03570 0.03037 -0.0337 1.0000 0.0222 + -13.500 -1.2199 0.03394 0.02850 -0.0328 1.0000 0.0226 + -13.250 -1.2139 0.03236 0.02680 -0.0316 1.0000 0.0230 + -13.000 -1.2065 0.03098 0.02531 -0.0303 1.0000 0.0236 + -12.750 -1.1977 0.02979 0.02397 -0.0288 1.0000 0.0240 + -12.500 -1.1907 0.02837 0.02243 -0.0268 1.0000 0.0245 + -12.250 -1.1850 0.02684 0.02086 -0.0246 1.0000 0.0251 + -12.000 -1.1748 0.02586 0.01984 -0.0225 1.0000 0.0257 + -11.750 -1.1622 0.02501 0.01893 -0.0207 1.0000 0.0264 + -11.500 -1.1470 0.02416 0.01801 -0.0192 1.0000 0.0271 + -11.250 -1.1306 0.02336 0.01712 -0.0178 1.0000 0.0279 + -11.000 -1.1126 0.02267 0.01632 -0.0165 1.0000 0.0287 + -10.750 -1.0994 0.02143 0.01504 -0.0147 1.0000 0.0297 + -10.500 -1.0815 0.02069 0.01429 -0.0135 1.0000 0.0308 + -10.250 -1.0618 0.02009 0.01364 -0.0124 1.0000 0.0320 + -10.000 -1.0416 0.01951 0.01300 -0.0113 1.0000 0.0333 + -9.750 -1.0223 0.01882 0.01223 -0.0100 1.0000 0.0344 + -9.500 -1.0053 0.01794 0.01135 -0.0085 1.0000 0.0360 + -9.250 -0.9846 0.01743 0.01081 -0.0074 1.0000 0.0377 + -9.000 -0.9632 0.01700 0.01032 -0.0064 1.0000 0.0395 + -8.750 -0.9450 0.01628 0.00958 -0.0048 1.0000 0.0416 + -8.500 -0.9250 0.01577 0.00908 -0.0035 1.0000 0.0439 + -8.250 -0.9040 0.01537 0.00864 -0.0023 1.0000 0.0463 + -8.000 -0.8851 0.01479 0.00804 -0.0007 1.0000 0.0492 + -7.750 -0.8647 0.01437 0.00763 0.0006 1.0000 0.0526 + -7.500 -0.8439 0.01400 0.00722 0.0019 1.0000 0.0561 + -7.250 -0.8245 0.01350 0.00677 0.0034 1.0000 0.0609 + -7.000 -0.8036 0.01316 0.00640 0.0047 1.0000 0.0657 + -6.750 -0.7836 0.01275 0.00603 0.0061 1.0000 0.0723 + -6.500 -0.7633 0.01237 0.00568 0.0075 1.0000 0.0799 + -6.250 -0.7424 0.01204 0.00537 0.0087 1.0000 0.0888 + -6.000 -0.7216 0.01171 0.00509 0.0100 1.0000 0.1000 + -5.750 -0.7007 0.01136 0.00482 0.0112 1.0000 0.1141 + -5.500 -0.6797 0.01102 0.00458 0.0124 1.0000 0.1312 + -5.250 -0.6582 0.01072 0.00437 0.0134 1.0000 0.1513 + -5.000 -0.6274 0.01036 0.00414 0.0125 0.9985 0.1775 + -4.750 -0.5903 0.01000 0.00393 0.0102 0.9957 0.2096 + -4.500 -0.5529 0.00966 0.00374 0.0080 0.9931 0.2444 + -4.250 -0.5172 0.00932 0.00354 0.0061 0.9892 0.2791 + -4.000 -0.4798 0.00900 0.00338 0.0039 0.9858 0.3152 + -3.750 -0.4410 0.00869 0.00322 0.0014 0.9832 0.3524 + -3.500 -0.4066 0.00840 0.00307 -0.0001 0.9779 0.3872 + -3.250 -0.3690 0.00813 0.00293 -0.0022 0.9740 0.4226 + -3.000 -0.3306 0.00786 0.00279 -0.0044 0.9707 0.4575 + -2.750 -0.2994 0.00761 0.00267 -0.0050 0.9628 0.4893 + -2.500 -0.2655 0.00737 0.00254 -0.0062 0.9565 0.5214 + -2.250 -0.2374 0.00715 0.00243 -0.0060 0.9458 0.5510 + -2.000 -0.2089 0.00696 0.00233 -0.0059 0.9351 0.5802 + -1.750 -0.1812 0.00678 0.00223 -0.0055 0.9233 0.6091 + -1.500 -0.1552 0.00662 0.00215 -0.0048 0.9088 0.6370 + -1.250 -0.1293 0.00648 0.00209 -0.0040 0.8929 0.6642 + -1.000 -0.1034 0.00638 0.00203 -0.0032 0.8757 0.6915 + -0.750 -0.0777 0.00628 0.00198 -0.0024 0.8571 0.7177 + -0.500 -0.0517 0.00622 0.00195 -0.0016 0.8366 0.7435 + -0.250 -0.0259 0.00618 0.00193 -0.0008 0.8148 0.7683 + 0.000 0.0000 0.00618 0.00192 0.0000 0.7923 0.7923 + 0.250 0.0259 0.00618 0.00193 0.0008 0.7683 0.8148 + 0.500 0.0517 0.00622 0.00195 0.0016 0.7435 0.8367 + 0.750 0.0777 0.00628 0.00198 0.0024 0.7178 0.8571 + 1.000 0.1034 0.00638 0.00203 0.0032 0.6915 0.8757 + 1.250 0.1293 0.00648 0.00209 0.0040 0.6642 0.8929 + 1.500 0.1552 0.00662 0.00215 0.0048 0.6371 0.9088 + 1.750 0.1812 0.00678 0.00223 0.0055 0.6091 0.9233 + 2.000 0.2089 0.00696 0.00233 0.0059 0.5801 0.9351 + 2.250 0.2374 0.00716 0.00243 0.0060 0.5509 0.9458 + 2.500 0.2655 0.00737 0.00254 0.0062 0.5215 0.9566 + 2.750 0.2995 0.00761 0.00267 0.0050 0.4893 0.9628 + 3.000 0.3307 0.00786 0.00279 0.0044 0.4576 0.9707 + 3.250 0.3690 0.00813 0.00293 0.0022 0.4225 0.9740 + 3.500 0.4066 0.00840 0.00307 0.0001 0.3871 0.9779 + 3.750 0.4410 0.00869 0.00322 -0.0014 0.3524 0.9832 + 4.000 0.4798 0.00900 0.00338 -0.0039 0.3152 0.9858 + 4.250 0.5172 0.00932 0.00354 -0.0061 0.2791 0.9892 + 4.500 0.5530 0.00966 0.00374 -0.0080 0.2443 0.9931 + 4.750 0.5904 0.01000 0.00392 -0.0103 0.2096 0.9957 + 5.000 0.6275 0.01036 0.00414 -0.0125 0.1775 0.9985 + 5.250 0.6581 0.01072 0.00436 -0.0134 0.1513 1.0000 + 5.500 0.6796 0.01102 0.00457 -0.0123 0.1312 1.0000 + 5.750 0.7007 0.01136 0.00482 -0.0112 0.1141 1.0000 + 6.000 0.7215 0.01170 0.00509 -0.0100 0.1001 1.0000 + 6.250 0.7424 0.01204 0.00537 -0.0087 0.0889 1.0000 + 6.500 0.7632 0.01236 0.00568 -0.0074 0.0799 1.0000 + 6.750 0.7835 0.01275 0.00603 -0.0061 0.0724 1.0000 + 7.000 0.8036 0.01316 0.00640 -0.0047 0.0657 1.0000 + 7.250 0.8244 0.01350 0.00676 -0.0034 0.0608 1.0000 + 7.500 0.8439 0.01399 0.00721 -0.0019 0.0561 1.0000 + 7.750 0.8646 0.01437 0.00763 -0.0006 0.0526 1.0000 + 8.000 0.8851 0.01479 0.00804 0.0007 0.0492 1.0000 + 8.250 0.9040 0.01537 0.00863 0.0023 0.0463 1.0000 + 8.500 0.9250 0.01577 0.00908 0.0035 0.0439 1.0000 + 8.750 0.9450 0.01628 0.00958 0.0048 0.0416 1.0000 + 9.000 0.9632 0.01699 0.01032 0.0064 0.0395 1.0000 + 9.250 0.9847 0.01743 0.01081 0.0074 0.0377 1.0000 + 9.500 1.0054 0.01794 0.01135 0.0085 0.0360 1.0000 + 9.750 1.0224 0.01882 0.01223 0.0100 0.0344 1.0000 + 10.000 1.0417 0.01951 0.01299 0.0113 0.0333 1.0000 + 10.250 1.0620 0.02009 0.01364 0.0124 0.0320 1.0000 + 10.500 1.0817 0.02069 0.01428 0.0134 0.0308 1.0000 + 10.750 1.0995 0.02144 0.01504 0.0147 0.0297 1.0000 + 11.000 1.1128 0.02267 0.01631 0.0165 0.0287 1.0000 + 11.250 1.1309 0.02336 0.01711 0.0177 0.0279 1.0000 + 11.500 1.1474 0.02416 0.01801 0.0191 0.0271 1.0000 + 11.750 1.1626 0.02500 0.01893 0.0206 0.0263 1.0000 + 12.000 1.1753 0.02586 0.01984 0.0224 0.0257 1.0000 + 12.250 1.1855 0.02684 0.02086 0.0245 0.0251 1.0000 + 12.500 1.1912 0.02838 0.02244 0.0267 0.0245 1.0000 + 12.750 1.1984 0.02980 0.02398 0.0286 0.0240 1.0000 + 13.000 1.2072 0.03098 0.02530 0.0302 0.0235 1.0000 + 13.250 1.2147 0.03236 0.02681 0.0315 0.0230 1.0000 + 13.500 1.2208 0.03392 0.02849 0.0326 0.0226 1.0000 + 13.750 1.2259 0.03568 0.03036 0.0335 0.0222 1.0000 + 14.000 1.2302 0.03761 0.03239 0.0341 0.0218 1.0000 + 14.250 1.2337 0.03973 0.03459 0.0343 0.0215 1.0000 + 14.500 1.2360 0.04209 0.03703 0.0343 0.0212 1.0000 + 14.750 1.2363 0.04481 0.03983 0.0341 0.0209 1.0000 + 15.000 1.2327 0.04811 0.04324 0.0336 0.0206 1.0000 + 15.250 1.2219 0.05247 0.04774 0.0329 0.0203 1.0000 + 15.500 1.2159 0.05646 0.05191 0.0311 0.0202 1.0000 + 15.750 1.2073 0.06100 0.05662 0.0289 0.0201 1.0000 + 16.000 1.1964 0.06607 0.06187 0.0262 0.0200 1.0000 + 16.250 1.1828 0.07171 0.06768 0.0232 0.0199 1.0000 + 16.500 1.1669 0.07801 0.07415 0.0196 0.0198 1.0000 + 16.750 1.1482 0.08501 0.08133 0.0156 0.0198 1.0000 + 17.000 1.1265 0.09286 0.08936 0.0109 0.0197 1.0000 + 17.250 1.1011 0.10176 0.09843 0.0056 0.0197 1.0000 + 17.500 1.0705 0.11207 0.10894 -0.0006 0.0198 1.0000 + 17.750 1.0302 0.12505 0.12212 -0.0085 0.0199 1.0000 + 18.000 0.7725 0.21140 0.20887 -0.0516 0.0252 1.0000 diff --git a/test/gen_bpmjl_data/figure22b.jld2 b/test/gen_bpmjl_data/figure22b.jld2 new file mode 100644 index 00000000..5b55b107 Binary files /dev/null and b/test/gen_bpmjl_data/figure22b.jld2 differ diff --git a/test/gen_bpmjl_data/figure23c.jld2 b/test/gen_bpmjl_data/figure23c.jld2 new file mode 100644 index 00000000..26837a1c Binary files /dev/null and b/test/gen_bpmjl_data/figure23c.jld2 differ diff --git a/test/gen_bpmjl_data/figure24b.jld2 b/test/gen_bpmjl_data/figure24b.jld2 new file mode 100644 index 00000000..28d09a9c Binary files /dev/null and b/test/gen_bpmjl_data/figure24b.jld2 differ diff --git a/test/gen_bpmjl_data/itr_with_bpmjl.jl b/test/gen_bpmjl_data/itr_with_bpmjl.jl new file mode 100644 index 00000000..20cc1a03 --- /dev/null +++ b/test/gen_bpmjl_data/itr_with_bpmjl.jl @@ -0,0 +1,983 @@ +module ITRWithBPMJL + +using Accessors: Accessors +using AcousticMetrics: AcousticMetrics +using BPM: BPM +using CCBlade: CCBlade +# using DelimitedFiles: writedlm +using JLD2: JLD2 +using FileIO: save + +function get_airfoil(; af_fname, cr75, Re_exp) + (info, Re, Mach, alpha, cl, cd) = CCBlade.parsefile(af_fname, false) + + # Extend the angle of attack with the Viterna method. + (alpha, cl, cd) = CCBlade.viterna(alpha, cl, cd, cr75) + af = CCBlade.AlphaAF(alpha, cl, cd, info, Re, Mach) + + # Reynolds number correction. The 0.6 factor seems to match the NACA 0012 + # drag data from airfoiltools.com. + reynolds = CCBlade.SkinFriction(Re, Re_exp) + + # Mach number correction. + mach = CCBlade.PrandtlGlauert() + + # Rotational stall delay correction. Need some parameters from the CL curve. + m, alpha0 = CCBlade.linearliftcoeff(af, 1.0, 1.0) # dummy values for Re and Mach + # Create the Du Selig and Eggers correction. + rotation = CCBlade.DuSeligEggers(1.0, 1.0, 1.0, m, alpha0) + + # The usual hub and tip loss correction. + tip = CCBlade.PrandtlTipHub() + + return af, mach, reynolds, rotation, tip +end + +function from_cell_centers_to_interfaces(cc_vals::Vector) + N = length(cc_vals) + + b = cc_vals[:] + b[1] = 0.25*cc_vals[1] + 0.25*cc_vals[2] + + A = zeros(N, N) + for i in 1:N-1 + A[i, i] = 0.5 + A[i+1, i] = 0.5 + end + A[N, N] = 0.5 + + a = A\b + + @assert all(A*a .≈ b) + + interface_vals = zeros(N+1) + interface_vals[1] = 1.5*cc_vals[1] - 0.5*cc_vals[2] + interface_vals[2:end] .= a + + @assert all(0.5.*(interface_vals[1:end-1] .+ interface_vals[2:end]) .≈ cc_vals) + + return interface_vals +end + +function do_figure22b() + # Pettingill et al., "Acoustic And Performance Characteristics of an Ideally Twisted Rotor in Hover", 2021 + # Parameters from Table 1 + B = 4 # number of blades + Rtip = 0.1588 # meters + chord = 0.2*Rtip + # Standard day: + Tamb = 15 + 273.15 # 15°C in Kelvin + pamb = 101325.0 # Pa + R = 287.052874 # J/(kg*K) + rho = pamb/(R*Tamb) + asound = sqrt(1.4*R*Tamb) + + # CCBlade.jl defines pitch/collective as "the thing added to the twist to get the orientation of the chord line," but the paper appears to use "the angle of the chord line at the tip." + collective0 = 6.9*pi/180 + # The Figure 23 caption says Θ_tip = 7 deg, but I think that "actually" means 6.9°. + # And yes, collective is 0 here, which is a bit silly, I guess, but is consistent with the definition of twist down below. + collective = 6.9 .* (pi/180) .- collective0 + + mu = rho*1.4502e-5 + Vinf = 0.001*asound + + # Figure 22 caption says Ω_c = 5465 RPM. + rpm = 5465.0 + omega = rpm * (2*pi/60) + + # Get "cell-centered" radial locations. + num_radial = 50 + r_Rtip_ = range(0.2, 1.0; length=num_radial+1) + r_Rtip = 0.5 .* (r_Rtip_[2:end] .+ r_Rtip_[1:end-1]) + radii = r_Rtip .* Rtip + + Rhub = r_Rtip_[1]*Rtip + + # From Pettingill Equation (1), and value for Θ_tip in Table 1. + Θ_tip = 6.9 * pi/180 + twist = Θ_tip ./ (r_Rtip) + + # NACA 0012 airfoil stuff. + af_fname = joinpath(@__DIR__, "airfoils", "xf-n0012-il-500000.dat") + Re_exp = 0.6 + cr75 = chord / Rtip + af, mach_correction, reynolds_correction, rotation_correction, tip_correction = get_airfoil(; af_fname, cr75, Re_exp) + tip_correction = nothing + + precone = 0.0 + turbine = false + rotor = CCBlade.Rotor(Rhub, Rtip, B; precone=precone, turbine=turbine, mach=mach_correction, re=reynolds_correction, rotation=rotation_correction, tip=tip_correction) + + sections = CCBlade.Section.(radii, chord, twist, Ref(af)) + + ops = CCBlade.OperatingPoint.(Vinf, omega.*radii, rho, collective, mu, asound) + outs = CCBlade.solve.(Ref(rotor), sections, ops) + + # BPM.jl uses the M_c = 0.8*M assumption from the BPM report, so modify the W field of each CCBlade.Outputs struct to match that. + lens = Accessors.@optic _.W + outs_bpm_Mc = Accessors.set.(outs, Ref(lens), 0.8.*sqrt.(getproperty.(ops, :Vx).^2 .+ getproperty.(ops, :Vy).^2)) + @assert all(getproperty.(outs_bpm_Mc, :W) .≈ 0.8.*sqrt.(getproperty.(ops, :Vx).^2 .+ getproperty.(ops, :Vy).^2)) + + # Paper doesn't specify the microphone used for Figure 22, but earlier at the beginning of "C. Noise Characteristics and Trends" there is this: + # > For the purposes of this paper, presented acoustic spectra will correspond to an observer located −35° below the plane of the rotor (microphone 5). + # So I'll just assume that holds for Figure 22. + # The observer (microphone 5) is 35 deg behind/downstream of the rotor rotation plane. + r_obs = 2.27 # meters + theta_obs = -35*pi/180 + # So, the docstring for BPM.jl says that `V` argument is the wind velocity in the y direction. + # So I guess we should assume that the blades are rotating about the y axis. + # And if the freestream velocity is in the positive y axis, then, from the perspective of the fluid, the blades are translating in the negative y direction. + # And I want the observer to be downstream/behind the blades, so that would mean they would have a positive y position. + # So I want to rotate the observer around the positive x axis, so I'm going to switch the sign on `theta_obs`. + t0_obs = 0.0 + x0_obs = [0.0, r_obs*sin(-theta_obs), r_obs*cos(-theta_obs)] + + # Get the components of the observer position in a form that BPM.jl uses. + ox = x0_obs[1] + oy = x0_obs[2] + oz = x0_obs[3] + + # Radial locations. + rs = getproperty.(sections, :r) + + # BPM.jl docstring says we need the angle of attack in degrees. + # But it expects them at the interfaces, not cell centers. + alphas_deg = getproperty.(outs_bpm_Mc, :alpha) .* (180/pi) + rs_interface = from_cell_centers_to_interfaces(rs) + alphas_deg_interface = from_cell_centers_to_interfaces(alphas_deg) + + # Do the same thing for the chord. + # What other inputs do we need? + # So the distance from the pitch axis to the leading edge is used, apparently, to locate the trailing edge. + # Let's make sure that's true. + # Here's the relevant code + # + # # Calculate the trailing edge position relative to the hub + # xs = sin(beta)*d - cos(beta)*(c - c1) + # zs = cos(beta)*d + sin(beta)*(c - c1) + # + # `beta` is an azimuthal angle, and `d` is the radial distance of the blade element relative to the hub. + # So let's say that's zero. + # Then, I guess, `xs = (c - c1)` and `zs = r` + # So it looks like the twist is being ignored, I think. + # But, at any rate, if I set c1 = c, that effect is ignored. + chords = getproperty.(sections, :chord) + chords_interface = from_cell_centers_to_interfaces(chords) + c1s = chords_interface + + # In the text describing Figure 22, "For these predictions, the trip flag was set to “tripped”, due to the rough surface quality of the blade." + tripped_flags = true + + # In the Figure 22 caption, "for these predictions, bluntness thickness H was set to 0.8 mm and trailing edge angle Ψ was set to 16 degrees." + h = 0.8e-3 # meters + Psi = 16*pi/180 # radians + hs = fill(h, length(rs_interface)) + Psis = fill(Psi, length(rs_interface)) + Psis_deg = Psis .* 180/pi + + # Also need kinematic viscosity. + nu = mu/rho + + # Number of azimuthal stations per blade pass, I think. + num_betas = 20 + + # Save the inputs. + data = Dict( + "rho"=>rho, "asound"=>asound, "mu"=>mu, + "Vinf"=>Vinf, "omega"=>omega, + "B"=>B, + "Rhub"=>rotor.Rhub, + "Rtip"=>rotor.Rtip, + "radii"=>getproperty.(sections, :r), + "chord"=>getproperty.(sections, :chord), + "twist"=>getproperty.(sections, :theta), + "alpha"=>getproperty.(outs, :alpha), + "U"=>getproperty.(outs, :W), + "hs"=>hs[begin:end-1], + "Psis"=>Psis[begin:end-1], + "tripped_flags"=>fill(tripped_flags, length(sections)), + "num_src_times_blade_pass"=>num_betas) + # save("figure22b-inputs.jld2", data_inputs) + + # Now we can start doing the predictions. + oaspl_pressure, spl_pressure = BPM.sound_pressure_levels( + ox, oy, oz, Vinf, omega, + B, rs_interface, chords_interface, c1s, hs, + alphas_deg_interface, Psis_deg, nu, + asound; + turbulent_pressure=true, + turbulent_suction=false, + turbulent_separation=false, + blunt=false, + weighted=false, + trip=tripped_flags, + tip=false, + laminar=false, + round=false, + nbeta=num_betas, + smooth=false) + + oaspl_suction, spl_suction = BPM.sound_pressure_levels( + ox, oy, oz, Vinf, omega, + B, rs_interface, chords_interface, c1s, hs, + alphas_deg_interface, Psis_deg, nu, + asound; + turbulent_pressure=false, + turbulent_suction=true, + turbulent_separation=false, + blunt=false, + weighted=false, + trip=tripped_flags, + tip=false, + laminar=false, + round=false, + nbeta=num_betas, + smooth=false) + + oaspl_separation, spl_separation = BPM.sound_pressure_levels( + ox, oy, oz, Vinf, omega, + B, rs_interface, chords_interface, c1s, hs, + alphas_deg_interface, Psis_deg, nu, + asound; + turbulent_pressure=false, + turbulent_suction=false, + turbulent_separation=true, + blunt=false, + weighted=false, + trip=tripped_flags, + tip=false, + laminar=false, + round=false, + nbeta=num_betas, + smooth=false) + + oaspl_lblvs, spl_lblvs = BPM.sound_pressure_levels( + ox, oy, oz, Vinf, omega, + B, rs_interface, chords_interface, c1s, hs, + alphas_deg_interface, Psis_deg, nu, + asound; + turbulent_pressure=false, + turbulent_suction=false, + turbulent_separation=false, + blunt=false, + weighted=false, + trip=tripped_flags, + tip=false, + laminar=true, + round=false, + nbeta=num_betas, + smooth=false) + + oaspl_blunt, spl_blunt = BPM.sound_pressure_levels( + ox, oy, oz, Vinf, omega, + B, rs_interface, chords_interface, c1s, hs, + alphas_deg_interface, Psis_deg, nu, + asound; + turbulent_pressure=false, + turbulent_suction=false, + turbulent_separation=false, + blunt=true, + weighted=false, + trip=tripped_flags, + tip=false, + laminar=false, + round=false, + nbeta=num_betas, + smooth=false) + + oaspl_tip, spl_tip = BPM.sound_pressure_levels( + ox, oy, oz, Vinf, omega, B, rs_interface, chords_interface, c1s, hs, alphas_deg_interface, Psis_deg, nu, asound; + blunt=false, + weighted=false, + trip=tripped_flags, + tip=true, + laminar=false, + turbulent_pressure=false, + turbulent_suction=false, + turbulent_separation=false, + round=false, + nbeta=num_betas, + smooth=false) + + # header = "BPM.default_f,spl_pressure,spl_suction,spl_separation,spl_lblvs,spl_blunt,spl_tip\n" + # data = hcat(BPM.default_f, spl_pressure, spl_suction, spl_separation, spl_lblvs, spl_blunt, spl_tip) + + # fname = joinpath(@__DIR__, "figure22b.csv") + # open(fname, "w") do f + # write(f, header) + # writedlm(f, data, ',') + # end + + # Now I'd like to do the narrowband SPL like the Pettingill et al. paper does, instead of 1/3 octave SPL. + # So, to do that, I need to multiply the mean-squared pressure by Δf_nb/Δf_pbs, where `Δf_nb` is the 20 Hz narrowband and `Δf_pbs` is the bandwidth of each 1/3-octave proportional band. + # (Dividing the MSP by Δf_pbs aka the 1/3 octave spacing is like getting a power-spectral density, then multiplying by the narrowband spacing Δf_nb gives us the MSP associated with the narrowband.) + # I think the paper describes that, right? + # Right, here's something: + # + # > The current prediction method is limited to one-third octave bands, but it is compared to the narrowband experiment with Δf = 20 Hz. + # > This is done by dividing the energy from the one-third octave bands by the number of bands in Δf = 20 Hz. + # + # So, `Δf_pbs/Δf_nb` would represent the number of `Δf_nb`-width bands that could fit in a proportional band of bin width `Δf_pbs`. + # And then I'm dividing by that. + # So that seems like the right thing. + # First, I'll confirm that the frequencies BPM.jl are using are the ApproximateThirdOctaveCenterBands. + # This will give me those center bands: + cbands_approx3rdcenter = AcousticMetrics.ApproximateThirdOctaveCenterBands(first(BPM.default_f), last(BPM.default_f)) + @assert maximum(abs.(BPM.default_f .- cbands_approx3rdcenter)) < 1e-10 + + # So then I need to get the spacing associated with the proportional bands. + # So get the lower and upper "edges" of the bands. + freqs_l = AcousticMetrics.lower_bands(cbands_approx3rdcenter) + freqs_u = AcousticMetrics.upper_bands(cbands_approx3rdcenter) + # And then the spacing for each band. + df_pbs = freqs_u .- freqs_l + # Also need the experimental narrowband spacing, which is 20 Hz. + df_nb = 20.0 + # So, if spl = 10*log10(msp/pref^2), and I want to multiply the msp by df_nb/df_pbs, then + # + # spl_nb = 10*log10((msp*df_nb/df_pbs)/pref^2) = 10*(log10(msp/pref^2) + log10(df_nb/df_pbs)) + # spl_nb = 10*log10(msp/pref^2) + 10*log10(df_nb/df_pbs) + # spl_nb = spl + 10*log10(df_nb/df_pbs) + # + # That's easy. + spl_nb_pressure = @. spl_pressure + 10*log10(df_nb/df_pbs) + spl_nb_suction = @. spl_suction + 10*log10(df_nb/df_pbs) + spl_nb_separation = @. spl_separation + 10*log10(df_nb/df_pbs) + spl_nb_lblvs = @. spl_lblvs + 10*log10(df_nb/df_pbs) + spl_nb_blunt = @. spl_blunt + 10*log10(df_nb/df_pbs) + spl_nb_tip = @. spl_tip + 10*log10(df_nb/df_pbs) + + data["freqs"] = BPM.default_f + data["spl_nb_pressure"] = spl_nb_pressure + data["spl_nb_suction"] = spl_nb_suction + data["spl_nb_separation"] = spl_nb_separation + data["spl_nb_lblvs"] = spl_nb_lblvs + data["spl_nb_blunt"] = spl_nb_blunt + data["spl_nb_tip"] = spl_nb_tip + save(joinpath(@__DIR__, "figure22b.jld2"), data) + + return nothing +end + +function do_figure23c() + # Pettingill et al., "Acoustic And Performance Characteristics of an Ideally Twisted Rotor in Hover", 2021 + # Parameters from Table 1 + B = 4 # number of blades + Rtip = 0.1588 # meters + chord = 0.2*Rtip + # Standard day: + Tamb = 15 + 273.15 # 15°C in Kelvin + pamb = 101325.0 # Pa + R = 287.052874 # J/(kg*K) + rho = pamb/(R*Tamb) + asound = sqrt(1.4*R*Tamb) + + # CCBlade.jl defines pitch/collective as "the thing added to the twist to get the orientation of the chord line," but the paper appears to use "the angle of the chord line at the tip." + collective0 = 6.9*pi/180 + # The Figure 23 caption says Θ_tip = 7 deg, but I think that "actually" means 6.9°. + # And yes, collective is 0 here, which is a bit silly, I guess, but is consistent with the definition of twist down below. + collective = 6.9 .* (pi/180) .- collective0 + + mu = rho*1.4502e-5 + Vinf = 0.001*asound + + # Figure 23 caption says Ω_c = 5510 RPM. + rpm = 5510.0 + omega = rpm * (2*pi/60) + + # Get "cell-centered" radial locations. + num_radial = 50 + r_Rtip_ = range(0.2, 1.0; length=num_radial+1) + r_Rtip = 0.5 .* (r_Rtip_[2:end] .+ r_Rtip_[1:end-1]) + radii = r_Rtip .* Rtip + + Rhub = r_Rtip_[1]*Rtip + + # From Pettingill Equation (1), and value for Θ_tip in Table 1. + Θ_tip = 6.9 * pi/180 + twist = Θ_tip ./ (r_Rtip) + + # NACA 0012 airfoil stuff. + af_fname = joinpath(@__DIR__, "airfoils", "xf-n0012-il-500000.dat") + Re_exp = 0.6 + cr75 = chord / Rtip + af, mach_correction, reynolds_correction, rotation_correction, tip_correction = get_airfoil(; af_fname, cr75, Re_exp) + tip_correction = nothing + + precone = 0.0 + turbine = false + rotor = CCBlade.Rotor(Rhub, Rtip, B; precone=precone, turbine=turbine, mach=mach_correction, re=reynolds_correction, rotation=rotation_correction, tip=tip_correction) + + sections = CCBlade.Section.(radii, chord, twist, Ref(af)) + + ops = CCBlade.OperatingPoint.(Vinf, omega.*radii, rho, collective, mu, asound) + outs = CCBlade.solve.(Ref(rotor), sections, ops) + + # BPM.jl uses the M_c = 0.8*M assumption from the BPM report, so modify the W field of each CCBlade.Outputs struct to match that. + lens = Accessors.@optic _.W + outs_bpm_Mc = Accessors.set.(outs, Ref(lens), 0.8.*sqrt.(getproperty.(ops, :Vx).^2 .+ getproperty.(ops, :Vy).^2)) + @assert all(getproperty.(outs_bpm_Mc, :W) .≈ 0.8.*sqrt.(getproperty.(ops, :Vx).^2 .+ getproperty.(ops, :Vy).^2)) + + # Paper doesn't specify the microphone used for Figure 23, but earlier at the beginning of "C. Noise Characteristics and Trends" there is this: + # > For the purposes of this paper, presented acoustic spectra will correspond to an observer located −35° below the plane of the rotor (microphone 5). + # So I'll just assume that holds for Figure 23. + # The observer (microphone 5) is 35 deg behind/downstream of the rotor rotation plane. + r_obs = 2.27 # meters + theta_obs = -35*pi/180 + # So, the docstring for BPM.jl says that `V` argument is the wind velocity in the y direction. + # So I guess we should assume that the blades are rotating about the y axis. + # And if the freestream velocity is in the positive y axis, then, from the perspective of the fluid, the blades are translating in the negative y direction. + # And I want the observer to be downstream/behind the blades, so that would mean they would have a positive y position. + # So I want to rotate the observer around the positive x axis, so I'm going to switch the sign on `theta_obs`. + t0_obs = 0.0 + x0_obs = [0.0, r_obs*sin(-theta_obs), r_obs*cos(-theta_obs)] + + # Get the components of the observer position in a form that BPM.jl uses. + ox = x0_obs[1] + oy = x0_obs[2] + oz = x0_obs[3] + + # Radial locations. + rs = getproperty.(sections, :r) + + # BPM.jl docstring says we need the angle of attack in degrees. + # But it expects them at the interfaces, not cell centers. + rs_interface = from_cell_centers_to_interfaces(rs) + alphas_deg = getproperty.(outs_bpm_Mc, :alpha) .* (180/pi) + alphas_deg_interface = from_cell_centers_to_interfaces(alphas_deg) + + # Do the same thing for the chord. + # What other inputs do we need? + # So the distance from the pitch axis to the leading edge is used, apparently, to locate the trailing edge. + # Let's make sure that's true. + # Here's the relevant code + # + # # Calculate the trailing edge position relative to the hub + # xs = sin(beta)*d - cos(beta)*(c - c1) + # zs = cos(beta)*d + sin(beta)*(c - c1) + # + # `beta` is an azimuthal angle, and `d` is the radial distance of the blade element relative to the hub. + # So let's say that's zero. + # Then, I guess, `xs = (c - c1)` and `zs = r` + # So it looks like the twist is being ignored, I think. + # But, at any rate, if I set c1 = c, that effect is ignored. + chords = getproperty.(sections, :chord) + chords_interface = from_cell_centers_to_interfaces(chords) + c1s = chords_interface + + # So, for the boundary layer, we want to use untripped for the 95% of the blade from the hub to almost tip, and then tripped for the last 5% of the blade at the tip. + # So what are those section indices? + num_untripped = Int(round(0.95*num_radial)) + num_tripped = num_radial - num_untripped + _tripped_flags = vcat(fill(false, num_untripped), fill(true, num_tripped)) + @assert length(_tripped_flags) == num_radial + # This is working with num_radial, the number of cell-centers, not interfaces. + # I think this is the right thing to do though, because it looks like the last value of the `trip` argument is not used by BPM.jl. + # But I'll add an extra `true` just to be consistent. + tripped_flags = vcat(_tripped_flags, _tripped_flags[end:end]) + + # Now, the other trick: need to only include LBLVS noise for elements where the Reynolds number is < 160000. + # So, we need the Reynolds number for each section. + Re_c = rho * getproperty(outs_bpm_Mc, :W) .* getproperty.(sections, :chord) / mu + # So now we just need to decide which radial stations have the low or high Re_c values. + low_Re_c = 160000 + _lblvs_flags = Re_c .< low_Re_c + # Again, this is working with num_radial-length arrays, which are dealing with cell-centered quantities. + # Again, the last value is ignored, but I'll add a value to be consistent. + lblvs_flags = vcat(_lblvs_flags, _lblvs_flags[end:end]) + + # In the Figure 23 caption, "for these predictions, bluntness thickness H was set to 0.5 mm and trailing edge angle Ψ was set to 14 degrees." + h = 0.5e-3 # meters + Psi = 14*pi/180 # radians + hs = fill(h, length(rs_interface)) + Psis = fill(Psi, length(rs_interface)) + Psis_deg = Psis .* 180/pi + + # Also need kinematic viscosity. + nu = mu/rho + + # Number of azimuthal stations per blade pass, I think. + num_betas = 20 + + # Save the inputs. + data = Dict( + "rho"=>rho, "asound"=>asound, "mu"=>mu, + "Vinf"=>Vinf, "omega"=>omega, + "B"=>B, + "Rhub"=>rotor.Rhub, + "Rtip"=>rotor.Rtip, + "radii"=>getproperty.(sections, :r), + "chord"=>getproperty.(sections, :chord), + "twist"=>getproperty.(sections, :theta), + "alpha"=>getproperty.(outs, :alpha), + "U"=>getproperty.(outs, :W), + "hs"=>hs[begin:end-1], + "Psis"=>Psis[begin:end-1], + "tripped_flags"=>tripped_flags[begin:end-1], + "lblvs_flags"=>lblvs_flags[begin:end-1], + "num_src_times_blade_pass"=>num_betas) + + # Now we can start doing the predictions. + oaspl_pressure, spl_pressure = BPM.sound_pressure_levels( + ox, oy, oz, Vinf, omega, + B, rs_interface, chords_interface, c1s, hs, + alphas_deg_interface, Psis_deg, nu, + asound; + turbulent_pressure=true, + turbulent_suction=false, + turbulent_separation=false, + blunt=false, + weighted=false, + trip=tripped_flags, + tip=false, + laminar=false, + round=false, + nbeta=num_betas, + smooth=false) + + oaspl_suction, spl_suction = BPM.sound_pressure_levels( + ox, oy, oz, Vinf, omega, + B, rs_interface, chords_interface, c1s, hs, + alphas_deg_interface, Psis_deg, nu, + asound; + turbulent_pressure=false, + turbulent_suction=true, + turbulent_separation=false, + blunt=false, + weighted=false, + trip=tripped_flags, + tip=false, + laminar=false, + round=false, + nbeta=num_betas, + smooth=false) + + oaspl_separation, spl_separation = BPM.sound_pressure_levels( + ox, oy, oz, Vinf, omega, + B, rs_interface, chords_interface, c1s, hs, + alphas_deg_interface, Psis_deg, nu, + asound; + turbulent_pressure=false, + turbulent_suction=false, + turbulent_separation=true, + blunt=false, + weighted=false, + trip=tripped_flags, + tip=false, + laminar=false, + round=false, + nbeta=num_betas, + smooth=false) + + oaspl_lblvs, spl_lblvs = BPM.sound_pressure_levels( + ox, oy, oz, Vinf, omega, + B, rs_interface, chords_interface, c1s, hs, + alphas_deg_interface, Psis_deg, nu, + asound; + turbulent_pressure=false, + turbulent_suction=false, + turbulent_separation=false, + blunt=false, + weighted=false, + trip=tripped_flags, + tip=false, + laminar=lblvs_flags, + round=false, + nbeta=num_betas, + smooth=false) + + oaspl_blunt, spl_blunt = BPM.sound_pressure_levels( + ox, oy, oz, Vinf, omega, + B, rs_interface, chords_interface, c1s, hs, + alphas_deg_interface, Psis_deg, nu, + asound; + turbulent_pressure=false, + turbulent_suction=false, + turbulent_separation=false, + blunt=true, + weighted=false, + trip=tripped_flags, + tip=false, + laminar=false, + round=false, + nbeta=num_betas, + smooth=false) + + oaspl_tip, spl_tip = BPM.sound_pressure_levels( + ox, oy, oz, Vinf, omega, B, rs_interface, chords_interface, c1s, hs, alphas_deg_interface, Psis_deg, nu, asound; + blunt=false, + weighted=false, + trip=tripped_flags, + tip=true, + laminar=false, + turbulent_pressure=false, + turbulent_suction=false, + turbulent_separation=false, + round=false, + nbeta=num_betas, + smooth=false) + + # Now I'd like to do the narrowband SPL like the Pettingill et al. paper does, instead of 1/3 octave SPL. + # So, to do that, I need to multiply the mean-squared pressure by Δf_nb/Δf_pbs, where `Δf_nb` is the 20 Hz narrowband and `Δf_pbs` is the bandwidth of each 1/3-octave proportional band. + # (Dividing the MSP by Δf_pbs aka the 1/3 octave spacing is like getting a power-spectral density, then multiplying by the narrowband spacing Δf_nb gives us the MSP associated with the narrowband.) + # I think the paper describes that, right? + # Right, here's something: + # + # > The current prediction method is limited to one-third octave bands, but it is compared to the narrowband experiment with Δf = 20 Hz. + # > This is done by dividing the energy from the one-third octave bands by the number of bands in Δf = 20 Hz. + # + # So, `Δf_pbs/Δf_nb` would represent the number of `Δf_nb`-width bands that could fit in a proportional band of bin width `Δf_pbs`. + # And then I'm dividing by that. + # So that seems like the right thing. + # First, I'll confirm that the frequencies BPM.jl are using are the ApproximateThirdOctaveCenterBands. + # This will give me those center bands: + cbands_approx3rdcenter = AcousticMetrics.ApproximateThirdOctaveCenterBands(first(BPM.default_f), last(BPM.default_f)) + @assert maximum(abs.(BPM.default_f .- cbands_approx3rdcenter)) < 1e-10 + + # So then I need to get the spacing associated with the proportional bands. + # So get the lower and upper "edges" of the bands. + freqs_l = AcousticMetrics.lower_bands(cbands_approx3rdcenter) + freqs_u = AcousticMetrics.upper_bands(cbands_approx3rdcenter) + # And then the spacing for each band. + df_pbs = freqs_u .- freqs_l + # Also need the experimental narrowband spacing, which is 20 Hz. + df_nb = 20.0 + # So, if spl = 10*log10(msp/pref^2), and I want to multiply the msp by df_nb/df_pbs, then + # + # spl_nb = 10*log10((msp*df_nb/df_pbs)/pref^2) = 10*(log10(msp/pref^2) + log10(df_nb/df_pbs)) + # spl_nb = 10*log10(msp/pref^2) + 10*log10(df_nb/df_pbs) + # spl_nb = spl + 10*log10(df_nb/df_pbs) + # + # That's easy. + spl_nb_pressure = @. spl_pressure + 10*log10(df_nb/df_pbs) + spl_nb_suction = @. spl_suction + 10*log10(df_nb/df_pbs) + spl_nb_separation = @. spl_separation + 10*log10(df_nb/df_pbs) + spl_nb_lblvs = @. spl_lblvs + 10*log10(df_nb/df_pbs) + spl_nb_blunt = @. spl_blunt + 10*log10(df_nb/df_pbs) + spl_nb_tip = @. spl_tip + 10*log10(df_nb/df_pbs) + + data["freqs"] = BPM.default_f + data["spl_nb_pressure"] = spl_nb_pressure + data["spl_nb_suction"] = spl_nb_suction + data["spl_nb_separation"] = spl_nb_separation + data["spl_nb_lblvs"] = spl_nb_lblvs + data["spl_nb_blunt"] = spl_nb_blunt + data["spl_nb_tip"] = spl_nb_tip + save(joinpath(@__DIR__, "figure23c.jld2"), data) + + return nothing +end + +function do_figure24b() + # Pettingill et al., "Acoustic And Performance Characteristics of an Ideally Twisted Rotor in Hover", 2021 + # Parameters from Table 1 + B = 4 # number of blades + Rtip = 0.1588 # meters + chord = 0.2*Rtip + # From the first paragraph on page 3, the rotor was designed to produce 11.12 N of thrust. + # Using that and the value of the design thrust coefficient in Table 1 to get the density and speed of sound. + # omega_target = 5500.0 * (2*pi/60) + # thrust_target = 11.12 # Newtons + # CT_target = 0.0137 + # Mtip_target = 0.27 + # asound = omega_target*Rtip/Mtip_target + # rho = thrust_target/(CT_target * (pi*Rtip^2) * (omega_target*Rtip)^2) + # Standard day: + Tamb = 15 + 273.15 # 15°C in Kelvin + pamb = 101325.0 # Pa + R = 287.052874 # J/(kg*K) + rho = pamb/(R*Tamb) + asound = sqrt(1.4*R*Tamb) + + # CCBlade.jl defines pitch/collective as "the thing added to the twist to get the orientation of the chord line," but the paper appears to use "the angle of the chord line at the tip." + collective0 = 6.9*pi/180 + # The Figure 24 caption says Θ_tip = 7 deg, but I think that "actually" means 6.9°. + # And yes, collective is 0 here, which is a bit silly, I guess, but is consistent with the definition of twist down below. + collective = 6.9 .* (pi/180) .- collective0 + + mu = rho*1.4502e-5 + Vinf = 0.001*asound + + # Figure 24 caption says Ω_c = 2938 RPM. + rpm = 2938.0 + omega = rpm * (2*pi/60) + + # Get "cell-centered" radial locations. + num_radial = 50 + r_Rtip_ = range(0.2, 1.0; length=num_radial+1) + r_Rtip = 0.5 .* (r_Rtip_[2:end] .+ r_Rtip_[1:end-1]) + radii = r_Rtip .* Rtip + + Rhub = r_Rtip_[1]*Rtip + + # From Pettingill Equation (1), and value for Θ_tip in Table 1. + Θ_tip = 6.9 * pi/180 + twist = Θ_tip ./ (r_Rtip) + + # NACA 0012 airfoil stuff. + af_fname = joinpath(@__DIR__, "airfoils", "xf-n0012-il-500000.dat") + Re_exp = 0.6 + cr75 = chord / Rtip + af, mach_correction, reynolds_correction, rotation_correction, tip_correction = get_airfoil(; af_fname, cr75, Re_exp) + tip_correction = nothing + + precone = 0.0 + turbine = false + rotor = CCBlade.Rotor(Rhub, Rtip, B; precone=precone, turbine=turbine, mach=mach_correction, re=reynolds_correction, rotation=rotation_correction, tip=tip_correction) + + sections = CCBlade.Section.(radii, chord, twist, Ref(af)) + + ops = CCBlade.OperatingPoint.(Vinf, omega.*radii, rho, collective, mu, asound) + outs = CCBlade.solve.(Ref(rotor), sections, ops) + + # BPM.jl uses the M_c = 0.8*M assumption from the BPM report, so modify the W field of each CCBlade.Outputs struct to match that. + lens = Accessors.@optic _.W + outs_bpm_Mc = Accessors.set.(outs, Ref(lens), 0.8.*sqrt.(getproperty.(ops, :Vx).^2 .+ getproperty.(ops, :Vy).^2)) + @assert all(getproperty.(outs_bpm_Mc, :W) .≈ 0.8.*sqrt.(getproperty.(ops, :Vx).^2 .+ getproperty.(ops, :Vy).^2)) + + # Paper doesn't specify the microphone used for Figure 24, but earlier at the beginning of "C. Noise Characteristics and Trends" there is this: + # > For the purposes of this paper, presented acoustic spectra will correspond to an observer located −35° below the plane of the rotor (microphone 5). + # So I'll just assume that holds for Figure 24. + # The observer (microphone 5) is 35 deg behind/downstream of the rotor rotation plane. + r_obs = 2.27 # meters + theta_obs = -35*pi/180 + # So, the docstring for BPM.jl says that `V` argument is the wind velocity in the y direction. + # So I guess we should assume that the blades are rotating about the y axis. + # And if the freestream velocity is in the positive y axis, then, from the perspective of the fluid, the blades are translating in the negative y direction. + # And I want the observer to be downstream/behind the blades, so that would mean they would have a positive y position. + # So I want to rotate the observer around the positive x axis, so I'm going to switch the sign on `theta_obs`. + t0_obs = 0.0 + x0_obs = [0.0, r_obs*sin(-theta_obs), r_obs*cos(-theta_obs)] + + # Get the components of the observer position in a form that BPM.jl uses. + ox = x0_obs[1] + oy = x0_obs[2] + oz = x0_obs[3] + + # Radial locations. + rs = getproperty.(sections, :r) + + # BPM.jl docstring says we need the angle of attack in degrees. + # But it expects them at the interfaces, not cell centers. + alphas_deg = getproperty.(outs_bpm_Mc, :alpha) .* (180/pi) + rs_interface = from_cell_centers_to_interfaces(rs) + alphas_deg_interface = from_cell_centers_to_interfaces(alphas_deg) + + # Do the same thing for the chord. + # What other inputs do we need? + # So the distance from the pitch axis to the leading edge is used, apparently, to locate the trailing edge. + # Let's make sure that's true. + # Here's the relevant code + # + # # Calculate the trailing edge position relative to the hub + # xs = sin(beta)*d - cos(beta)*(c - c1) + # zs = cos(beta)*d + sin(beta)*(c - c1) + # + # `beta` is an azimuthal angle, and `d` is the radial distance of the blade element relative to the hub. + # So let's say that's zero. + # Then, I guess, `xs = (c - c1)` and `zs = r` + # So it looks like the twist is being ignored, I think. + # But, at any rate, if I set c1 = c, that effect is ignored. + chords = getproperty.(sections, :chord) + chords_interface = from_cell_centers_to_interfaces(chords) + c1s = chords_interface + + # So, for the boundary layer, we want to use untripped for the 95% of the blade from the hub to almost tip, and then tripped for the last 5% of the blade at the tip. + # So what are those section indices? + num_untripped = Int(round(0.95*num_radial)) + num_tripped = num_radial - num_untripped + _tripped_flags = vcat(fill(false, num_untripped), fill(true, num_tripped)) + @assert length(_tripped_flags) == num_radial + # This is working with num_radial, the number of cell-centers, not interfaces. + # I think this is the right thing to do though, because it looks like the last value of the `trip` argument is not used by BPM.jl. + # But I'll add an extra entry at the end, just to be consistent. + tripped_flags = vcat(_tripped_flags, _tripped_flags[end:end]) + + # In the Figure 24 caption, "for these predictions, bluntness thickness H was set to 0.5 mm and trailing edge angle Ψ was set to 14 degrees." + h = 0.5e-3 # meters + Psi = 14*pi/180 # radians + hs = fill(h, length(rs_interface)) + Psis_deg = fill(Psi*180/pi, length(rs_interface)) + + # Also need kinematic viscosity. + nu = mu/rho + + # Number of azimuthal stations per blade pass, I think. + num_betas = 20 + + # Save the inputs in a dict that we'll write out later. + data = Dict( + "rho"=>rho, "asound"=>asound, "mu"=>mu, + "Vinf"=>Vinf, "omega"=>omega, + "B"=>B, + "Rhub"=>rotor.Rhub, + "Rtip"=>rotor.Rtip, + "radii"=>getproperty.(sections, :r), + "chord"=>getproperty.(sections, :chord), + "twist"=>getproperty.(sections, :theta), + "alpha"=>getproperty.(outs, :alpha), + "U"=>getproperty.(outs, :W), + "hs"=>hs[begin:end-1], + "Psis"=>fill(Psi, length(sections)), + "tripped_flags"=>tripped_flags[begin:end-1], + "num_src_times_blade_pass"=>num_betas) + # save(joinpath(@__DIR__, "figure24b-inputs.jld2"), data_inputs) + + # Now we can start doing the predictions. + oaspl_pressure, spl_pressure = BPM.sound_pressure_levels( + ox, oy, oz, Vinf, omega, + B, rs_interface, chords_interface, c1s, hs, + alphas_deg_interface, Psis_deg, nu, + asound; + turbulent_pressure=true, + turbulent_suction=false, + turbulent_separation=false, + blunt=false, + weighted=false, + trip=tripped_flags, + tip=false, + laminar=false, + round=false, + nbeta=num_betas, + smooth=false) + + oaspl_suction, spl_suction = BPM.sound_pressure_levels( + ox, oy, oz, Vinf, omega, + B, rs_interface, chords_interface, c1s, hs, + alphas_deg_interface, Psis_deg, nu, + asound; + turbulent_pressure=false, + turbulent_suction=true, + turbulent_separation=false, + blunt=false, + weighted=false, + trip=tripped_flags, + tip=false, + laminar=false, + round=false, + nbeta=num_betas, + smooth=false) + + oaspl_separation, spl_separation = BPM.sound_pressure_levels( + ox, oy, oz, Vinf, omega, + B, rs_interface, chords_interface, c1s, hs, + alphas_deg_interface, Psis_deg, nu, + asound; + turbulent_pressure=false, + turbulent_suction=false, + turbulent_separation=true, + blunt=false, + weighted=false, + trip=tripped_flags, + tip=false, + laminar=false, + round=false, + nbeta=num_betas, + smooth=false) + + oaspl_lblvs, spl_lblvs = BPM.sound_pressure_levels( + ox, oy, oz, Vinf, omega, + B, rs_interface, chords_interface, c1s, hs, + alphas_deg_interface, Psis_deg, nu, + asound; + turbulent_pressure=false, + turbulent_suction=false, + turbulent_separation=false, + blunt=false, + weighted=false, + trip=tripped_flags, + tip=false, + laminar=true, + round=false, + nbeta=num_betas, + smooth=false) + + oaspl_blunt, spl_blunt = BPM.sound_pressure_levels( + ox, oy, oz, Vinf, omega, + B, rs_interface, chords_interface, c1s, hs, + alphas_deg_interface, Psis_deg, nu, + asound; + turbulent_pressure=false, + turbulent_suction=false, + turbulent_separation=false, + blunt=true, + weighted=false, + trip=tripped_flags, + tip=false, + laminar=false, + round=false, + nbeta=num_betas, + smooth=false) + + oaspl_tip, spl_tip = BPM.sound_pressure_levels( + ox, oy, oz, Vinf, omega, B, rs_interface, chords_interface, c1s, hs, alphas_deg_interface, Psis_deg, nu, asound; + blunt=false, + weighted=false, + trip=tripped_flags, + tip=true, + laminar=false, + turbulent_pressure=false, + turbulent_suction=false, + turbulent_separation=false, + round=false, + nbeta=num_betas, + smooth=false) + + # Now I'd like to do the narrowband SPL like the Pettingill et al. paper does, instead of 1/3 octave SPL. + # So, to do that, I need to multiply the mean-squared pressure by Δf_nb/Δf_pbs, where `Δf_nb` is the 20 Hz narrowband and `Δf_pbs` is the bandwidth of each 1/3-octave proportional band. + # (Dividing the MSP by Δf_pbs aka the 1/3 octave spacing is like getting a power-spectral density, then multiplying by the narrowband spacing Δf_nb gives us the MSP associated with the narrowband.) + # I think the paper describes that, right? + # Right, here's something: + # + # > The current prediction method is limited to one-third octave bands, but it is compared to the narrowband experiment with Δf = 20 Hz. + # > This is done by dividing the energy from the one-third octave bands by the number of bands in Δf = 20 Hz. + # + # So, `Δf_pbs/Δf_nb` would represent the number of `Δf_nb`-width bands that could fit in a proportional band of bin width `Δf_pbs`. + # And then I'm dividing by that. + # So that seems like the right thing. + # First, I'll confirm that the frequencies BPM.jl are using are the ApproximateThirdOctaveCenterBands. + # This will give me those center bands: + cbands_approx3rdcenter = AcousticMetrics.ApproximateThirdOctaveCenterBands(first(BPM.default_f), last(BPM.default_f)) + @assert maximum(abs.(BPM.default_f .- cbands_approx3rdcenter)) < 1e-10 + + # So then I need to get the spacing associated with the proportional bands. + # So get the lower and upper "edges" of the bands. + freqs_l = AcousticMetrics.lower_bands(cbands_approx3rdcenter) + freqs_u = AcousticMetrics.upper_bands(cbands_approx3rdcenter) + # And then the spacing for each band. + df_pbs = freqs_u .- freqs_l + # Also need the experimental narrowband spacing, which is 20 Hz. + df_nb = 20.0 + # So, if spl = 10*log10(msp/pref^2), and I want to multiply the msp by df_nb/df_pbs, then + # + # spl_nb = 10*log10((msp*df_nb/df_pbs)/pref^2) = 10*(log10(msp/pref^2) + log10(df_nb/df_pbs)) + # spl_nb = 10*log10(msp/pref^2) + 10*log10(df_nb/df_pbs) + # spl_nb = spl + 10*log10(df_nb/df_pbs) + # + # That's easy. + spl_nb_pressure = @. spl_pressure + 10*log10(df_nb/df_pbs) + spl_nb_suction = @. spl_suction + 10*log10(df_nb/df_pbs) + spl_nb_separation = @. spl_separation + 10*log10(df_nb/df_pbs) + spl_nb_lblvs = @. spl_lblvs + 10*log10(df_nb/df_pbs) + spl_nb_blunt = @. spl_blunt + 10*log10(df_nb/df_pbs) + spl_nb_tip = @. spl_tip + 10*log10(df_nb/df_pbs) + + data["freqs"] = BPM.default_f + data["spl_nb_pressure"] = spl_nb_pressure + data["spl_nb_suction"] = spl_nb_suction + data["spl_nb_separation"] = spl_nb_separation + data["spl_nb_lblvs"] = spl_nb_lblvs + data["spl_nb_blunt"] = spl_nb_blunt + data["spl_nb_tip"] = spl_nb_tip + save(joinpath(@__DIR__, "figure24b.jld2"), data) + + return nothing +end + +function doit() + do_figure22b() + do_figure23c() + do_figure24b() +end + +end # module diff --git a/test/gen_test_data/gen_ccblade_data/GenCCBladeData.jl b/test/gen_test_data/gen_ccblade_data/GenCCBladeData.jl index b8c0ede7..16ca718c 100644 --- a/test/gen_test_data/gen_ccblade_data/GenCCBladeData.jl +++ b/test/gen_test_data/gen_ccblade_data/GenCCBladeData.jl @@ -1,6 +1,8 @@ module GenCCBladeData -import CCBlade, DelimitedFiles +using CCBlade: CCBlade +using FileIO: save +using JLD2: JLD2 using Printf: @sprintf include("constants.jl") @@ -21,24 +23,25 @@ function omega_sweep() DCL_STALL=0.1, MCRIT=0.8, CDMIN=0.13e-1, CLDMIN=0.5, DCDCL2=0.4e-2, REREF=0.2e6, REXP=-0.4) airfoil_interp(a, r, m) = af_xrotor(a, r, m, xrotor_config) - theta_rad = theta .* pi/180.0 + theta_rad = CCBladeTestCaseConstants.theta .* pi/180.0 - rotor = CCBlade.Rotor(Rhub, Rtip, num_blades) - sections = CCBlade.Section.(radii, chord, theta_rad, airfoil_interp) + rotor = CCBlade.Rotor(CCBladeTestCaseConstants.Rhub, CCBladeTestCaseConstants.Rtip, CCBladeTestCaseConstants.num_blades) + sections = CCBlade.Section.(CCBladeTestCaseConstants.radii, CCBladeTestCaseConstants.chord, theta_rad, airfoil_interp) rpm = 200.0:200.0:2200.0 # rev/min for i in eachindex(rpm) omega = rpm[i]*(2*pi/60.0) - ops = CCBlade.OperatingPoint.(v, omega.*radii, rho, pitch, mu, c0) + ops = CCBlade.OperatingPoint.(CCBladeTestCaseConstants.v, omega.*CCBladeTestCaseConstants.radii, CCBladeTestCaseConstants.rho, CCBladeTestCaseConstants.pitch, CCBladeTestCaseConstants.mu, CCBladeTestCaseConstants.c0) outs = CCBlade.solve.(Ref(rotor), sections, ops) - # Get the normal and circumferential loading from the CCBlade output. - fn = getproperty.(outs, :Np) # N/m - fc = getproperty.(outs, :Tp) # N/m + outs_d = Dict{String,Any}(string(f)=>getproperty.(outs, f) for f in fieldnames(eltype(outs))) + outs_d["omega"] = omega + save("ccblade_omega$(@sprintf "%02d" i)-outputs.jld2", outs_d) - data = hcat(fn, fc) - DelimitedFiles.writedlm("ccblade_omega$(@sprintf "%02d" i).csv", data, ',') + # data = DelimitedFiles.readdlm("ccblade_omega$(@sprintf "%02d" i).csv", ',') + # @show maximum(abs.(getproperty.(outs, :Np) .- data[:, 1])) + # @show maximum(abs.(getproperty.(outs, :Tp) .- data[:, 2])) end return nothing diff --git a/test/gen_test_data/gen_ccblade_data/Project.toml b/test/gen_test_data/gen_ccblade_data/Project.toml index ef3611f1..4e3d352a 100644 --- a/test/gen_test_data/gen_ccblade_data/Project.toml +++ b/test/gen_test_data/gen_ccblade_data/Project.toml @@ -1,2 +1,4 @@ [deps] CCBlade = "e1828068-15df-11e9-03e4-ef195ea46fa4" +FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" +JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819" diff --git a/test/gen_test_data/gen_ccblade_data/ccblade_omega01-outputs.jld2 b/test/gen_test_data/gen_ccblade_data/ccblade_omega01-outputs.jld2 new file mode 100644 index 00000000..375eb123 Binary files /dev/null and b/test/gen_test_data/gen_ccblade_data/ccblade_omega01-outputs.jld2 differ diff --git a/test/gen_test_data/gen_ccblade_data/ccblade_omega01.csv b/test/gen_test_data/gen_ccblade_data/ccblade_omega01.csv deleted file mode 100644 index 8acb923a..00000000 --- a/test/gen_test_data/gen_ccblade_data/ccblade_omega01.csv +++ /dev/null @@ -1,30 +0,0 @@ --1.4356148551649774,-1.1892665533272921 --2.4033835404694757,-2.035227010210563 --2.714224004941967,-1.690391363173225 --2.90053695932714,-1.522321977754197 --3.0725006780721773,-1.4717592764402014 --3.287413875239289,-1.4680017708823037 --3.5460548833673458,-1.476051826364756 --3.8350056028300523,-1.4818698498206253 --4.139837472259518,-1.4799789398935497 --4.444924440073268,-1.4677992534137092 --4.7302406132587524,-1.4423318535253125 --4.971906950196616,-1.4006237487465638 --5.149640086605236,-1.3419398338647721 --5.2570214597678335,-1.2694882589791543 --5.301565051930928,-1.1889817991965437 --5.2994110280763,-1.1064894554659686 --5.263657204306303,-1.0258871101236533 --5.201597378937523,-0.9489122151478151 --5.114191437595163,-0.8756103752852625 --4.996336325079433,-0.8048640026200113 --4.838361176030778,-0.7348308254480691 --4.62840684760792,-0.6635572659315122 --4.354609206819768,-0.5892497882056179 --4.007851941330612,-0.51077981080502 --3.5831141668261215,-0.42768400567837145 --3.080886295443626,-0.34046207052012273 --2.5088939840160127,-0.25075174583407456 --1.8831189920553497,-0.16161104218427425 --1.236388506612615,-0.07882953588675484 --0.6696509540756329,-0.01537496560942175 diff --git a/test/gen_test_data/gen_ccblade_data/ccblade_omega02-outputs.jld2 b/test/gen_test_data/gen_ccblade_data/ccblade_omega02-outputs.jld2 new file mode 100644 index 00000000..284c355a Binary files /dev/null and b/test/gen_test_data/gen_ccblade_data/ccblade_omega02-outputs.jld2 differ diff --git a/test/gen_test_data/gen_ccblade_data/ccblade_omega02.csv b/test/gen_test_data/gen_ccblade_data/ccblade_omega02.csv deleted file mode 100644 index 928170af..00000000 --- a/test/gen_test_data/gen_ccblade_data/ccblade_omega02.csv +++ /dev/null @@ -1,30 +0,0 @@ --0.8081627859024333,-0.4879159791591857 --1.7692216394334002,-1.0566199161358347 --2.47779198634459,-1.1903646101928886 --2.450218745830217,-0.8821626123648489 --1.8231052125059064,-0.4120956788427575 --0.8165009789530026,0.0694382739756377 -0.42131055253541094,0.5129117061920175 -1.7915298903381849,0.905092299640566 -3.209480494542257,1.2415723522699604 -4.623510700199433,1.5267053509875492 -5.98872754536636,1.7645860003069869 -7.267005133575843,1.9590802784039494 -8.437288116211292,2.1157529975577347 -9.474850234953504,2.237804273252361 -10.36698933079454,2.3292481785658854 -11.091949364294413,2.391378828857214 -11.637867635972011,2.4261447142937245 -11.993135229835021,2.434578322616922 -12.140707148639725,2.4159888379755223 -12.066688114577815,2.3694415583707222 -11.760401612644594,2.293679143160627 -11.217932062701902,2.187723151858948 -10.44532053629812,2.0513087580919764 -9.460321591822538,1.8852346565237015 -8.292586837400245,1.6913997814951967 -6.979989174095764,1.47231018330384 -5.564618143679254,1.2306360959715537 -4.093301445929345,0.9691260724745733 -2.6333502836199787,0.6933253812293767 -1.3826079810497929,0.43780213369674076 diff --git a/test/gen_test_data/gen_ccblade_data/ccblade_omega03-outputs.jld2 b/test/gen_test_data/gen_ccblade_data/ccblade_omega03-outputs.jld2 new file mode 100644 index 00000000..8c4ae099 Binary files /dev/null and b/test/gen_test_data/gen_ccblade_data/ccblade_omega03-outputs.jld2 differ diff --git a/test/gen_test_data/gen_ccblade_data/ccblade_omega03.csv b/test/gen_test_data/gen_ccblade_data/ccblade_omega03.csv deleted file mode 100644 index f2932c2d..00000000 --- a/test/gen_test_data/gen_ccblade_data/ccblade_omega03.csv +++ /dev/null @@ -1,30 +0,0 @@ -0.4062878172353916,0.6251509857828307 -1.5978989964604244,1.3540472035922286 -3.8913502391854315,2.2905860611711315 -6.945985729008861,3.1534038061456005 -10.479003902316219,3.8960418563191657 -14.34894782994682,4.537416204342948 -18.402036991663472,5.082389239846945 -22.506250052316915,5.53839925491329 -26.534691759671894,5.90995288490889 -30.41717825906992,6.209808478726682 -34.08573573367564,6.446046111831672 -37.47756463384888,6.6244788781528925 -40.559521232410646,6.753328055020695 -43.28343098321236,6.836006156600791 -45.619656130594755,6.877191483178978 -47.51164511214904,6.876253014262575 -48.913888122692434,6.833357865873524 -49.77218720011957,6.7466932990738835 -50.008361824561,6.610481951643511 -49.54263209784511,6.418293965028741 -48.29672214148976,6.162877558176648 -46.209431060555204,5.8379841439449045 -43.2517359206161,5.439596728895308 -39.439799251492275,4.9672663589018144 -34.83947523739131,4.424285187734197 -29.56017587995048,3.81674934816248 -23.747647978489834,3.1528561804441075 -17.58814648042165,2.442958514061069 -11.378229417662023,1.7076794539297087 -5.991833729822369,1.0459768699010352 diff --git a/test/gen_test_data/gen_ccblade_data/ccblade_omega04-outputs.jld2 b/test/gen_test_data/gen_ccblade_data/ccblade_omega04-outputs.jld2 new file mode 100644 index 00000000..3e61dd9d Binary files /dev/null and b/test/gen_test_data/gen_ccblade_data/ccblade_omega04-outputs.jld2 differ diff --git a/test/gen_test_data/gen_ccblade_data/ccblade_omega04.csv b/test/gen_test_data/gen_ccblade_data/ccblade_omega04.csv deleted file mode 100644 index 91897bef..00000000 --- a/test/gen_test_data/gen_ccblade_data/ccblade_omega04.csv +++ /dev/null @@ -1,30 +0,0 @@ -2.2365741156263845,2.18294132276027 -6.877041676137847,4.669659741633142 -13.97331389675828,6.903373660822529 -21.6610632624273,8.359060398529284 -29.59539968225063,9.400317995715618 -37.794676084014924,10.22934595201654 -46.077454125343436,10.896604139582324 -54.267026971018225,11.430655501585763 -62.185105613817925,11.845472524093445 -69.74273239461903,12.163837329708747 -76.84513013369599,12.398362407304605 -83.39907454057138,12.556945430221512 -89.35764780351631,12.65111026145649 -94.6416220204346,12.684345294574925 -99.19807680530114,12.662175195168297 -102.92021941928408,12.581367707790111 -105.7111847284934,12.439845939599982 -107.44945492150208,12.232228432863373 -107.95887688597793,11.946222163730726 -107.05032522066317,11.568403482062449 -104.52984073398608,11.083876303471936 -100.23312775908603,10.47966689200192 -94.06102106777949,9.747011488052964 -86.01188965656647,8.883934924220467 -76.19546078437365,7.895705290776532 -64.82449233992364,6.793197380493197 -52.20389409005738,5.591970561924484 -38.74037411116123,4.312488050355793 -25.09607145400904,2.995383729685258 -13.212900926321305,1.8242658966324687 diff --git a/test/gen_test_data/gen_ccblade_data/ccblade_omega05-outputs.jld2 b/test/gen_test_data/gen_ccblade_data/ccblade_omega05-outputs.jld2 new file mode 100644 index 00000000..501b6cf3 Binary files /dev/null and b/test/gen_test_data/gen_ccblade_data/ccblade_omega05-outputs.jld2 differ diff --git a/test/gen_test_data/gen_ccblade_data/ccblade_omega05.csv b/test/gen_test_data/gen_ccblade_data/ccblade_omega05.csv deleted file mode 100644 index 3e8ea30f..00000000 --- a/test/gen_test_data/gen_ccblade_data/ccblade_omega05.csv +++ /dev/null @@ -1,30 +0,0 @@ -4.695712744160382,4.198338773776219 -14.105786458558223,8.945366931031646 -27.79462386593288,12.769134611318332 -41.717993441401234,14.915356152579516 -55.56027951646474,16.304418920412004 -69.55799522891743,17.349862485786222 -83.49038907029453,18.155363279979625 -97.13232303769854,18.77634536774553 -110.24736426226144,19.238366549374575 -122.72836216286414,19.576316920354127 -134.44982611504383,19.8078926097469 -145.28140533083274,19.94298986865557 -155.1594217201861,19.996763579773532 -163.9640982806851,19.972250986947998 -171.61086192113098,19.875588597554113 -177.92470159992604,19.699787120528878 -182.73709695476424,19.439569351235054 -185.83153461349386,19.084761825522428 -186.89328393896844,18.6146006548202 -185.57560370591514,18.006702065146953 -181.51468801235868,17.2364964895808 -174.38995455900914,16.282598603866333 -163.98927816991826,15.130446060028094 -150.27001352022137,13.776394938166659 -133.38895630855072,12.228579426372413 -113.69290678625356,10.504287981852338 -91.70447014556396,8.628850214951168 -68.13915971366598,6.636085090138808 -44.17452224930383,4.592778422617947 -23.246243554006213,2.790743956253222 diff --git a/test/gen_test_data/gen_ccblade_data/ccblade_omega06-outputs.jld2 b/test/gen_test_data/gen_ccblade_data/ccblade_omega06-outputs.jld2 new file mode 100644 index 00000000..3ac4e25f Binary files /dev/null and b/test/gen_test_data/gen_ccblade_data/ccblade_omega06-outputs.jld2 differ diff --git a/test/gen_test_data/gen_ccblade_data/ccblade_omega06.csv b/test/gen_test_data/gen_ccblade_data/ccblade_omega06.csv deleted file mode 100644 index 1fd5b563..00000000 --- a/test/gen_test_data/gen_ccblade_data/ccblade_omega06.csv +++ /dev/null @@ -1,30 +0,0 @@ -7.790083157191316,6.677279307500257 -23.302592372949945,14.204482059964265 -45.377840063288275,19.935959636993214 -67.15088117860891,22.888888357223205 -88.42492742751725,24.681838872582965 -109.71151163690413,25.975769859178715 -130.74579972621063,26.939147076026742 -151.2539013983942,27.66076983563699 -170.9362600826506,28.180073212940254 -189.66928819869855,28.546139859356497 -207.29329749576377,28.782183754524336 -223.63371511671428,28.899814824993964 -238.60614236770184,28.91792986222974 -252.03873681900134,28.83829348125378 -263.8041484634278,28.66710417182947 -273.637094113485,28.392034495974293 -281.27206307715375,28.003179865344173 -286.3635670848133,27.483800282544166 -288.4097925101639,26.802030709763866 -286.84873283684294,25.92382999410158 -281.08205903991603,24.81218906779605 -270.56846926836295,23.434966677397714 -254.9294970251297,21.770286483445293 -234.0495644292605,19.81249692788044 -208.13088561872092,17.573628122296 -177.6848449841105,15.07945690173419 -143.51575437881908,12.368236114734877 -106.74783980086505,9.491452502131095 -69.24475535733974,6.549926978621265 -36.414669064650596,3.9718307722253385 diff --git a/test/gen_test_data/gen_ccblade_data/ccblade_omega07-outputs.jld2 b/test/gen_test_data/gen_ccblade_data/ccblade_omega07-outputs.jld2 new file mode 100644 index 00000000..f38314b2 Binary files /dev/null and b/test/gen_test_data/gen_ccblade_data/ccblade_omega07-outputs.jld2 differ diff --git a/test/gen_test_data/gen_ccblade_data/ccblade_omega07.csv b/test/gen_test_data/gen_ccblade_data/ccblade_omega07.csv deleted file mode 100644 index 2be37f69..00000000 --- a/test/gen_test_data/gen_ccblade_data/ccblade_omega07.csv +++ /dev/null @@ -1,30 +0,0 @@ -11.523224603748753,9.622847210337504 -34.477148033989984,20.458289670155835 -66.73774668831341,28.426497086839532 -97.98829390306733,32.31136373480983 -128.23949205832352,34.56995082553851 -158.33738037978765,36.150411863683345 -187.9734757038718,37.298818556910426 -216.82813967892113,38.14404278824167 -244.53618209090493,38.741685736147055 -270.96141213977774,39.157069162107874 -295.9078228069052,39.41924669916611 -319.149997316757,39.54107427335061 -340.5786489565897,39.545113321968756 -359.95675178543377,39.43074004148009 -377.1002936742519,39.20333998127648 -391.62679210053375,38.84317621911263 -403.14164353647476,38.33372022665292 -411.1271067625122,37.64917520104268 -414.83338517350376,36.74300587687395 -413.4101670570284,35.56571441951477 -405.9423130185103,34.06387457543358 -391.5845022443514,32.191025049174655 -369.72096442678975,29.91543336862272 -340.11694678896134,27.2284118925134 -303.0103601100828,24.146761344899193 -259.1070391234548,20.707194402524518 -209.5651012971376,16.965003242838968 -156.03497128479887,12.995229335052125 -101.2691387291243,8.94329707012189 -53.207655451375146,5.408935551689907 diff --git a/test/gen_test_data/gen_ccblade_data/ccblade_omega08-outputs.jld2 b/test/gen_test_data/gen_ccblade_data/ccblade_omega08-outputs.jld2 new file mode 100644 index 00000000..b87afde6 Binary files /dev/null and b/test/gen_test_data/gen_ccblade_data/ccblade_omega08-outputs.jld2 differ diff --git a/test/gen_test_data/gen_ccblade_data/ccblade_omega08.csv b/test/gen_test_data/gen_ccblade_data/ccblade_omega08.csv deleted file mode 100644 index 68eaef8b..00000000 --- a/test/gen_test_data/gen_ccblade_data/ccblade_omega08.csv +++ /dev/null @@ -1,30 +0,0 @@ -15.897318919171543,13.036819145368296 -47.635422116807966,27.71317308980833 -91.8862661843894,38.25403217833602 -134.25746845063415,43.20275176807124 -175.05690269261575,45.99512935092161 -215.52898982226392,47.908257920990636 -255.32727624494677,49.279179839427016 -294.093637232352,50.28365684292668 -331.39846954859166,50.995766891174554 -367.1003720045839,51.499153127009535 -400.96785513313046,51.82900057604185 -432.7201218159274,51.99883588403286 -462.2202305993945,52.03469583519743 -489.1525413948306,51.93219046882265 -513.2605903243614,51.69469517940693 -534.0127975436181,51.29241596281952 -550.8452758956379,50.699473109144016 -563.0123222927978,49.877526341431164 -569.4373647727299,48.760411579166444 -568.8851203506586,47.277637853293356 -560.0130251025791,45.35335954600304 -541.5568751942911,42.92104365244562 -512.5620953539424,39.93453693885331 -472.6024510814552,36.379483724639734 -421.92551567795965,32.27755796703787 -361.4571022485447,27.67898581722471 -292.7915036389308,22.66144140799136 -218.24913615459198,17.331798286607462 -141.72404028631422,11.89497664268284 -74.37299177664342,7.168778293352193 diff --git a/test/gen_test_data/gen_ccblade_data/ccblade_omega09-outputs.jld2 b/test/gen_test_data/gen_ccblade_data/ccblade_omega09-outputs.jld2 new file mode 100644 index 00000000..e9d37bf7 Binary files /dev/null and b/test/gen_test_data/gen_ccblade_data/ccblade_omega09-outputs.jld2 differ diff --git a/test/gen_test_data/gen_ccblade_data/ccblade_omega09.csv b/test/gen_test_data/gen_ccblade_data/ccblade_omega09.csv deleted file mode 100644 index d625ac61..00000000 --- a/test/gen_test_data/gen_ccblade_data/ccblade_omega09.csv +++ /dev/null @@ -1,30 +0,0 @@ -20.913832602014793,16.920318658562007 -62.78166555747269,35.97332639714413 -120.83448197533615,49.428104980698095 -175.9866211178062,55.57893794026472 -228.9354379380376,58.98084718908416 -281.3933099009674,61.2828888324899 -332.98764192622446,62.92684469279654 -383.3348906983963,64.1424027241161 -431.94791504250026,65.02458883081594 -478.69340494324507,65.67766992162446 -523.3108884073284,66.14342549699305 -565.4647179212063,66.43557447774836 -604.9921798914909,66.58354512450524 -641.488393553667,66.57771561215637 -674.6095313793375,66.41806885428879 -703.6397047063278,66.0615407037923 -727.7974276531905,65.46931961230113 -746.0380609529624,64.5856957459517 -756.8547645308932,63.317860962199845 -758.49511103516,61.56600248397873 -749.0330888327105,59.222369869767135 -726.6171392277746,56.19056692935537 -689.7974361641361,52.40140158651094 -637.8336701390824,47.82860725322723 -570.9213756370386,42.49651629122281 -490.21588542376946,36.4707070465552 -397.8398326540626,29.85794856193851 -296.9665300868296,22.808935914683147 -192.9653588356733,15.610331861903123 -101.09907699711354,9.363778868441113 diff --git a/test/gen_test_data/gen_ccblade_data/ccblade_omega10-outputs.jld2 b/test/gen_test_data/gen_ccblade_data/ccblade_omega10-outputs.jld2 new file mode 100644 index 00000000..433bb2be Binary files /dev/null and b/test/gen_test_data/gen_ccblade_data/ccblade_omega10-outputs.jld2 differ diff --git a/test/gen_test_data/gen_ccblade_data/ccblade_omega10.csv b/test/gen_test_data/gen_ccblade_data/ccblade_omega10.csv deleted file mode 100644 index 2688223a..00000000 --- a/test/gen_test_data/gen_ccblade_data/ccblade_omega10.csv +++ /dev/null @@ -1,30 +0,0 @@ -26.573824121609768,21.274122011752425 -79.9192918860314,45.241915341761555 -153.59355226551614,61.95678022746453 -223.2061471909869,69.45471015983934 -289.9402262763528,73.55082097524024 -356.0527555418802,76.31020115429922 -421.1644802787604,78.29362068362332 -484.88750509189,79.79216291834884 -546.6925048718949,80.9247003584436 -606.4771120341865,81.81899122997311 -663.9685228310613,82.52444688743715 -718.7871787929266,83.05504873557044 -770.7574228295007,83.44415748789865 -819.3841354003197,83.67588413088328 -864.2291821504015,83.74577035810148 -904.3600391117399,83.59408539629209 -938.7253821994404,83.16484775283627 -965.895455691519,82.37864047639822 -983.7982962173398,81.10616174562696 -989.9802804016997,79.2055460781565 -981.7028710050221,76.52158319153712 -956.2650375835127,72.91050378711373 -911.4614832892426,68.26295805413253 -846.0115305702118,62.52606044005395 -759.9127457524788,55.72165031287891 -654.5050727690351,47.9536126763203 -532.5302365006334,39.35518980072539 -398.25864334818607,30.097992862365306 -259.01196901398475,20.553982904797852 -135.4074918582125,12.216259973569786 diff --git a/test/gen_test_data/gen_ccblade_data/ccblade_omega11-outputs.jld2 b/test/gen_test_data/gen_ccblade_data/ccblade_omega11-outputs.jld2 new file mode 100644 index 00000000..fb22c924 Binary files /dev/null and b/test/gen_test_data/gen_ccblade_data/ccblade_omega11-outputs.jld2 differ diff --git a/test/gen_test_data/gen_ccblade_data/ccblade_omega11.csv b/test/gen_test_data/gen_ccblade_data/ccblade_omega11.csv deleted file mode 100644 index aaa67983..00000000 --- a/test/gen_test_data/gen_ccblade_data/ccblade_omega11.csv +++ /dev/null @@ -1,30 +0,0 @@ -32.87810395677037,26.09881302938423 -99.05130471878633,55.5216259955307 -190.1751697055377,75.84767780212506 -275.9492967565419,84.84509232798283 -358.14423433748146,89.73045068624886 -439.64679797145624,93.02999477395113 -520.1002808148281,95.4384273852926 -599.1445046901513,97.31647535460424 -676.2358818769462,98.81063179767507 -751.3409657831587,100.07617771995163 -824.2087672338118,101.17251941705561 -894.4465814696498,102.11543878532882 -961.9015451678036,102.94453631586998 -1026.0112737521583,103.63835661864168 -1086.2610633094212,104.18877957193807 -1141.4900032393818,104.51732850056433 -1190.3376703335655,104.54735678589765 -1230.8999662260915,104.1688287897138 -1260.375390697363,103.20319203286938 -1275.354422403355,101.46246817378582 -1271.8827617273287,99.11692436681635 -1245.9059108698596,96.49009546562475 -1193.9967137923225,93.45834266417528 -1113.9397490286995,89.49783586366624 -1005.273267675585,83.87176811707455 -869.4101036003673,75.83190739325453 -709.8100230053759,64.88004605331857 -532.1946243370355,50.98243352318318 -346.53986082379265,34.85525518071079 -180.66763939805125,19.358679206883078 diff --git a/test/itr_figure22b_barc.jl b/test/itr_figure22b_barc.jl new file mode 100644 index 00000000..2dc263f5 --- /dev/null +++ b/test/itr_figure22b_barc.jl @@ -0,0 +1,234 @@ +using AcousticAnalogies +using AcousticMetrics: AcousticMetrics +using DelimitedFiles: readdlm +using KinematicCoordinateTransformations: compose, SteadyRotXTransformation, ConstantVelocityTransformation +using FileIO: load +using FLOWMath: akima +using StaticArrays: @SVector +using Test + +data = load(joinpath(@__DIR__, "gen_bpmjl_data", "figure22b.jld2")) +rho = data["rho"] +asound = data["asound"] +mu = data["mu"] +Vinf = data["Vinf"] +omega = data["omega"] +B = data["B"] +Rhub = data["Rhub"] +Rtip = data["Rtip"] +radii = data["radii"] +chord = data["chord"] +twist = data["twist"] +alpha = data["alpha"] +U = data["U"] +hs = data["hs"] +num_src_times_blade_pass = data["num_src_times_blade_pass"] +Psis = data["Psis"] + +nu = mu/rho +num_radial = length(radii) +dradii = AcousticAnalogies.get_dradii(radii, Rhub, Rtip) + +# Get the source time, which will be one blade pass worth of time, each blade pass with `num_src_times_blade_pass` steps per blade pass. +bpp = 1/(B/(2*pi)*omega) # 1/(B blade_passes/rev * 1 rev / (2*pi rad) * omega rad/s) +num_blade_pass = 1 +period_src = num_blade_pass*bpp +num_src_times = num_src_times_blade_pass * num_blade_pass +t0 = 0.0 +dt = period_src/num_src_times +src_times = t0 .+ (0:num_src_times-1).*dt + +# Now let's define the coordinate system. +# I'm going to do my usual thing, which is to have the freestream velocity pointed in the negative x direction, and thus the blades will be translating in the positive x direction. +# And the blades will be rotating about the positive x axis at a rate of `omega`. +rot_trans = SteadyRotXTransformation(t0, omega, 0.0) + +# The hub/rotation axis of the blades will start at the origin at time `t0`, and translate in the positive x direction at a speed of `Vinf`. +y0_hub = @SVector [0.0, 0.0, 0.0] # m +v0_hub = @SVector [Vinf, 0.0, 0.0] # m/s +const_vel_trans = ConstantVelocityTransformation(t0, y0_hub, v0_hub) + +# Now I can put the two transformations together: +trans = compose.(src_times, Ref(const_vel_trans), Ref(rot_trans)) + +# Azimuthal offset for each blade. +θs = (0:(B-1)) .* (2*pi/B) + +# Paper doesn't specify the microphone used for Figure 22, but earlier at the beginning of "C. Noise Characteristics and Trends" there is this: +# > For the purposes of this paper, presented acoustic spectra will correspond to an observer located −35° below the plane of the rotor (microphone 5). +# So I'll just assume that holds for Figure 22. +# For the coordinate system, I'm doing my usual thing, which is to have the freestream velocity pointed in the negative x direction, and thus the blades will be translating in the positive x direction. +# The observer (microphone 5) is 35 deg behind/downstream of the rotor rotation plane, so this should be good. +# But it will of course be moving with the same freestream in the positive x direction. +r_obs = 2.27 # meters +theta_obs = -35*pi/180 +# The observer is moving in the positive x direction at Vinf, at the origin at time t0. +t0_obs = 0.0 +x0_obs = @SVector [r_obs*sin(theta_obs), r_obs*cos(theta_obs), 0.0] +v_obs = @SVector [Vinf, 0.0, 0.0] +obs = AcousticAnalogies.ConstVelocityAcousticObserver(t0_obs, x0_obs, v_obs) + +# In the text describing Figure 22, "For these predictions, the trip flag was set to “tripped”, due to the rough surface quality of the blade." +bl = AcousticAnalogies.TrippedN0012BoundaryLayer() +# In the Figure 22 caption, "for these predictions, bluntness thickness H was set to 0.8 mm and trailing edge angle Ψ was set to 16 degrees." +h = 0.8e-3 # meters +Psi = 16*pi/180 # radians + +# I don't see any discussion for what type of tip was used for the tip vortex noise. +# The flat tip seems to match the PAS+ROTONET+BARC predictions well. +blade_tip = AcousticAnalogies.FlatTip() + +# Reshape the inputs to the source element constructors so that everything will line up with (num_times, num_radial, num_blades). +θs_rs = reshape(θs, 1, 1, :) +radii_rs = reshape(radii, 1, :, 1) +dradii_rs = reshape(dradii, 1, :, 1) +chord_rs = reshape(chord, 1, :, 1) +twist_rs = reshape(twist, 1, :, 1) +hs_rs = reshape(hs, 1, :, 1) +Psis_rs = reshape(Psis, 1, :, 1) +Us_rs = reshape(U, 1, :, 1) +alphas_rs = reshape(alpha, 1, :, 1) +# bls_rs = reshape(bls, 1, :, 1) + +# Separate things into tip and no-tip. +radii_rs_no_tip = @view radii_rs[:, begin:end-1, :] +dradii_rs_no_tip = @view dradii_rs[:, begin:end-1, :] +chord_rs_no_tip = @view chord_rs[:, begin:end-1, :] +twist_rs_no_tip = @view twist_rs[:, begin:end-1, :] +hs_rs_no_tip = @view hs_rs[:, begin:end-1, :] +Psis_rs_no_tip = @view Psis_rs[:, begin:end-1, :] +Us_rs_no_tip = @view Us_rs[:, begin:end-1, :] +alphas_rs_no_tip = @view alphas_rs[:, begin:end-1, :] +# bls_rs_no_tip = @view bls_rs[:, begin:end-1, :] + +radii_rs_with_tip = @view radii_rs[:, end:end, :] +dradii_rs_with_tip = @view dradii_rs[:, end:end, :] +chord_rs_with_tip = @view chord_rs[:, end:end, :] +twist_rs_with_tip = @view twist_rs[:, end:end, :] +hs_rs_with_tip = @view hs_rs[:, end:end, :] +Psis_rs_with_tip = @view Psis_rs[:, end:end, :] +Us_rs_with_tip = @view Us_rs[:, end:end, :] +alphas_rs_with_tip = @view alphas_rs[:, end:end, :] +# bls_rs_with_tip = @view bls_rs[:, end:end, :] + +positive_x_rotation = true +ses_no_tip = CombinedNoTipBroadbandSourceElement.(asound, nu, radii_rs_no_tip, θs_rs, dradii_rs_no_tip, chord_rs_no_tip, twist_rs_no_tip, hs_rs_no_tip, Psis_rs_no_tip, Us_rs_no_tip, alphas_rs_no_tip, src_times, dt, Ref(bl), positive_x_rotation) .|> trans + +ses_with_tip = CombinedWithTipBroadbandSourceElement.(asound, nu, radii_rs_with_tip, θs_rs, dradii_rs_with_tip, chord_rs_with_tip, twist_rs_with_tip, hs_rs_with_tip, Psis_rs_with_tip, Us_rs_with_tip, alphas_rs_with_tip, src_times, dt, Ref(bl), Ref(blade_tip), positive_x_rotation) .|> trans + +# It's more convinient to cat all the sources together. +ses = cat(ses_no_tip, ses_with_tip; dims=2) + +# The predictions in Figure 22b appear to be on 1/3 octave, ranging from about 200 Hz to 60,000 Hz. +# But let's expand the range of source frequencies to account for Doppler shifting. +freqs_src = AcousticMetrics.ExactProportionalBands{3, :center}(10.0, 200000.0) +freqs_obs = AcousticMetrics.ExactProportionalBands{3, :center}(200.0, 60000.0) + +# Now we can do a noise prediction. +bpm_outs = AcousticAnalogies.noise.(ses, Ref(obs), Ref(freqs_src)) + +# This seperates out the noise prediction for each source-observer combination into the different sources. +pbs_tblte_ps = AcousticAnalogies.pbs_pressure.(bpm_outs) +pbs_tblte_ss = AcousticAnalogies.pbs_suction.(bpm_outs) +pbs_tblte_alphas = AcousticAnalogies.pbs_alpha.(bpm_outs) +pbs_lblvss = AcousticAnalogies.pbs_lblvs.(bpm_outs) +pbs_tebs = AcousticAnalogies.pbs_teb.(bpm_outs) +pbs_tips = AcousticAnalogies.pbs_tip.(bpm_outs[:, end:end, :]) + +# Now, need to combine each broadband noise prediction. +# The time axis the axis over which the time varies for each source. +time_axis = 1 +pbs_pressure = AcousticMetrics.combine(pbs_tblte_ps, freqs_obs, time_axis) +pbs_suction = AcousticMetrics.combine(pbs_tblte_ss, freqs_obs, time_axis) +pbs_alpha = AcousticMetrics.combine(pbs_tblte_alphas, freqs_obs, time_axis) +pbs_lblvs = AcousticMetrics.combine(pbs_lblvss, freqs_obs, time_axis) +pbs_teb = AcousticMetrics.combine(pbs_tebs, freqs_obs, time_axis) +pbs_tip = AcousticMetrics.combine(pbs_tips, freqs_obs, time_axis) + +# Now I need to account for the fact that Figure 22b is actually comparing to narrowband experimental data with a frequency spacing of 20 Hz. +# So, to do that, I need to multiply the mean-squared pressure by Δf_nb/Δf_pbs, where `Δf_nb` is the 20 Hz narrowband and `Δf_pbs` is the bandwidth of each 1/3-octave proportional band. +# I think the paper describes that, right? +# Right, here's something: +# +# > The current prediction method is limited to one-third octave bands, but it is compared to the narrowband experiment with Δf = 20 Hz. +# > This is done by dividing the energy from the one-third octave bands by the number of bands in Δf = 20 Hz. +# +# So, `Δf_pbs/Δf_nb` would represent the number of `Δf_nb`-width bands that could fit in a proportional band of bin width `Δf_pbs`. +# And then I'm dividing by that. +# So that seems like the right thing. +# So, first thing is to get the proportional band spacing. +freqs_l = AcousticMetrics.lower_bands(freqs_obs) +freqs_u = AcousticMetrics.upper_bands(freqs_obs) +df_pbs = freqs_u .- freqs_l + +# Also need the experimental narrowband spacing. +df_nb = 20.0 +# Now multiply each by that. +nb_pressure = pbs_pressure .* df_nb ./ df_pbs +nb_suction = pbs_suction .* df_nb ./ df_pbs +nb_alpha = pbs_alpha .* df_nb ./ df_pbs +nb_lblvs = pbs_lblvs .* df_nb ./ df_pbs +nb_teb = pbs_teb .* df_nb ./ df_pbs +nb_tip = pbs_tip .* df_nb ./ df_pbs + +# Now I want the SPL, which should just be this: +pref = 20e-6 +spl_pressure = 10 .* log10.(nb_pressure./(pref^2)) +spl_suction = 10 .* log10.(nb_suction./(pref^2)) +spl_alpha = 10 .* log10.(nb_alpha./(pref^2)) +spl_lblvs = 10 .* log10.(nb_lblvs./(pref^2)) +spl_teb = 10 .* log10.(nb_teb./(pref^2)) +spl_tip = 10 .* log10.(nb_tip./(pref^2)) + +# Now I should be able to compare to the BARC data. +# Need to read it in first. +data_pressure_barc = readdlm(joinpath(@__DIR__, "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure22b-TBL-TE-pressure-2.csv"), ',') +freq_pressure_barc = data_pressure_barc[:, 1] +spl_pressure_barc = data_pressure_barc[:, 2] + +data_suction_barc = readdlm(joinpath(@__DIR__, "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure22b-TBL-TE-suction-2.csv"), ',') +freq_suction_barc = data_suction_barc[:, 1] +spl_suction_barc = data_suction_barc[:, 2] + +data_separation_barc = readdlm(joinpath(@__DIR__, "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure22b-separation-2.csv"), ',') +freq_separation_barc = data_separation_barc[:, 1] +spl_separation_barc = data_separation_barc[:, 2] + +data_lblvs_barc = readdlm(joinpath(@__DIR__, "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure22b-LBLVS.csv"), ',') +freq_lblvs_barc = data_lblvs_barc[:, 1] +spl_lblvs_barc = data_lblvs_barc[:, 2] + +data_teb_barc = readdlm(joinpath(@__DIR__, "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure22b-BVS.csv"), ',') +freq_teb_barc = data_teb_barc[:, 1] +spl_teb_barc = data_teb_barc[:, 2] + +data_tip_barc = readdlm(joinpath(@__DIR__, "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure22b-tip_vortex_shedding.csv"), ',') +freq_tip_barc = data_tip_barc[:, 1] +spl_tip_barc = data_tip_barc[:, 2] + +# Interpolate the AcousticAnalogies.jl data onto the frequencies from the BARC CSV file. +spl_pressure_interp = akima(freqs_obs, spl_pressure, freq_pressure_barc) +spl_suction_interp = akima(freqs_obs, spl_suction, freq_suction_barc) +spl_separation_interp = akima(freqs_obs, spl_alpha, freq_separation_barc) +spl_lblvs_interp = akima(freqs_obs, spl_lblvs, freq_lblvs_barc) +spl_teb_interp = akima(freqs_obs, spl_teb, freq_teb_barc) +spl_tip_interp = akima(freqs_obs, spl_tip, freq_tip_barc) + +# Now compare. +@test maximum(abs.(spl_pressure_interp .- spl_pressure_barc)) < 0.543 + +# Lower frequencies don't line up as well as higher. +# Not sure why. +@test abs(spl_suction_interp[1] - spl_suction_barc[1]) < 3.59 +@test abs(spl_suction_interp[2] - spl_suction_barc[2]) < 2.71 +@test abs(spl_suction_interp[3] - spl_suction_barc[3]) < 1.24 +@test maximum(abs.(spl_suction_interp[4:end] .- spl_suction_barc[4:end])) < 0.462 + +# Lower frequencies don't line up as well as higher. +# Not sure why. +@test all(abs.(spl_separation_interp[1:12] .- spl_separation_barc[1:12]) .< [8.54, 7.63, 7.48, 6.82, 6.51, 6.60, 5.99, 4.87, 4.21, 2.58, 1.29, 0.299]) +@test maximum(abs.(spl_separation_interp[13:end] .- spl_separation_barc[13:end])) < 0.466 + +@test all(abs.(spl_teb_interp .- spl_teb_barc) .< [0.134, 0.349, 0.424, 0.133, 0.187, 0.603, 0.244, 2.60]) +@test all(abs.(spl_tip_interp .- spl_tip_barc) .< [0.0641, 0.0426, 0.170, 0.0923, 0.116, 0.231, 0.228, 0.160, 0.121]) + diff --git a/test/itr_figure22b_bpmjl.jl b/test/itr_figure22b_bpmjl.jl new file mode 100644 index 00000000..0b199fb2 --- /dev/null +++ b/test/itr_figure22b_bpmjl.jl @@ -0,0 +1,292 @@ +using AcousticAnalogies +using AcousticMetrics: AcousticMetrics +using KinematicCoordinateTransformations: compose, SteadyRotXTransformation, SteadyRotYTransformation, SteadyRotZTransformation, ConstantVelocityTransformation +using FileIO: load +using FLOWMath: Akima +using StaticArrays +using Test + +# tip vortex noise correction data based on "Airfoil Tip Vortex Formation Noise" +# Copied from BPM.jl (would like to add BPM.jl as a dependency if it's registered in General some day). +const bm_tip_alpha_aspect_data = [2.0,2.67,4.0,6.0,12.0,24.0] +const bm_tip_alpha_aratio_data = [0.54,0.62,0.71,0.79,0.89,0.95] +const bm_tip_alpha_aspect_ratio_correction = Akima(bm_tip_alpha_aspect_data, bm_tip_alpha_aratio_data) + +function bm_tip_vortex_alpha_correction_nonsmooth(aspect_ratio) + # compute tip lift curve slope + if aspect_ratio < 2.0 + aratio = 0.5*one(aspect_ratio) + elseif 2.0 <= aspect_ratio <= 24.0 + aratio = bm_tip_alpha_aspect_ratio_correction(aspect_ratio) + elseif aspect_ratio > 24.0 + aratio = 1.0*one(aspect_ratio) + end + + return aratio +end + +struct BMTipAlphaCorrection{TCorrection} <: AbstractTipAlphaCorrection + correction::TCorrection + + function BMTipAlphaCorrection(aspect_ratio) + # correction = BPM._tip_vortex_alpha_correction_nonsmooth(aspect_ratio) + correction = bm_tip_vortex_alpha_correction_nonsmooth(aspect_ratio) + return new{typeof(correction)}(correction) + end +end + +function AcousticAnalogies.tip_vortex_alpha_correction(blade_tip::AbstractBladeTip{<:BMTipAlphaCorrection}, alphatip) + a0l = AcousticAnalogies.alpha_zerolift(blade_tip) + correction_factor = AcousticAnalogies.tip_alpha_correction(blade_tip).correction + return correction_factor * (alphatip - a0l) + a0l +end + +data = load(joinpath(@__DIR__, "gen_bpmjl_data", "figure22b.jld2")) +rho = data["rho"] +asound = data["asound"] +mu = data["mu"] +Vinf = data["Vinf"] +omega = data["omega"] +B = data["B"] +Rhub = data["Rhub"] +Rtip = data["Rtip"] +radii = data["radii"] +chord = data["chord"] +twist = data["twist"] +alpha = data["alpha"] +U = data["U"] +hs = data["hs"] +Psis = data["Psis"] +num_src_times_blade_pass = data["num_src_times_blade_pass"] +tripped_flags = data["tripped_flags"] + +num_radial = length(radii) + +nu = mu/rho +dradii = AcousticAnalogies.get_dradii(radii, Rhub, Rtip) + +# Get some transform stuff. +bpp = 1/(B/(2*pi)*omega) # 1/(B blade_passes/rev * 1 rev / (2*pi rad) * omega rad/s) +num_blade_pass = 1 +period_src = num_blade_pass*bpp +num_src_times = num_src_times_blade_pass * num_blade_pass +t0 = 0.0 +dt = period_src/num_src_times +src_times = t0 .+ (0:num_src_times-1).*dt + +# I don't see any discussion for what type of tip was used for the tip vortex noise. +# FlatTip with no CCBlade.jl tip correction or BPM-style tip correction seems to match the BARC predictions well. +# blade_tip = AcousticAnalogies.FlatTip(AcousticAnalogies.NoTipAlphaCorrection()) +# BPM.jl uses a different tip alpha correction which appears to require the blade aspect ratio, defined as the blade radius divided by the average chord. +cbar = sum(chord .* dradii) / (Rtip - Rhub) +aspect_ratio = Rtip/cbar +alpha0lift = 0.0 +blade_tip = AcousticAnalogies.FlatTip(BMTipAlphaCorrection(aspect_ratio), alpha0lift) + +# Getting the coordinate system consistent with BPM.jl is a bit tricky. +# Here's a bit of code from BPM.jl: +# +# # Calculate the trailing edge position relative to the hub +# xs = sin(beta)*d - cos(beta)*(c - c1) +# zs = cos(beta)*d + sin(beta)*(c - c1) +# +# OK, so that shows me that the blade is initially aligned with the z axis, rotating to the positive x direction. +# And I know the blades are rotating about the positive y axis. +# So that's the answer for the BPM.jl coordinate system: +# +# * freestream in the positive y axis direction. +# * first blade initially aligned with the positive z axis, rotating about the positive y axis. +# +# Now, what do I need to do with AcousticAnalogies to make that happen? +# I want the blades to be translating in the negative y direction, rotating about the positive y axis. +# I usually start with the blades rotating about either the positive or negative x axis, moving in the direction of the positive x axis. +# I think the answer is, +# +# * start out with the blades rotating about the negative x axis, moving in the direction of the positive x axis +# * rotate 90° about the negative z axis. +# After this, the blades will be moving in the negative y direction, rotating about the positive y axis, which is good. +# But I want the first blade to be aligned with the positive z axis, and stopping here would mean it's aligned with the positive x axis. +# * rotate 90° about the negative y axis. +# This will put the first blade in line with the positive z axis. + +# So, let's do what we said we need to do. +# Start with a rotation about the negative x axis. +positive_x_rotation = false +rot_trans = SteadyRotXTransformation(t0, omega*ifelse(positive_x_rotation, 1, -1), 0) + +# Then translate along the positive x axis. +y0_hub = @SVector [0.0, 0.0, 0.0] # m +v0_hub = @SVector [Vinf, 0.0, 0.0] +const_vel_trans = ConstantVelocityTransformation(t0, y0_hub, v0_hub) + +# Then a 90° rotation about the negative z axis. +trans_z90deg = SteadyRotZTransformation(0.0, 0.0, -0.5*pi) + +# Then a 90° rotation about the negative y axis. +trans_y90deg = SteadyRotYTransformation(0.0, 0.0, -0.5*pi) + +# Put them all together: +trans = compose.(src_times, Ref(trans_y90deg), + compose.(src_times, Ref(trans_z90deg), + compose.(src_times, Ref(const_vel_trans), Ref(rot_trans)))) + +# Use the M_c = 0.8*M that BPM.jl and the BPM report use. +U = @. 0.8*sqrt(Vinf^2 + (omega*radii)^2) + +# Azimuthal offset for each blade. +θs = (0:(B-1)) .* (2*pi/B) .* ifelse(positive_x_rotation, 1, -1) + +bls = [ifelse(tf, + AcousticAnalogies.TrippedN0012BoundaryLayer(), + AcousticAnalogies.UntrippedN0012BoundaryLayer()) for tf in tripped_flags] + +# Need to do the LBLVS with the untripped boundary layer to match what BPM.jl is doing. +# bls_lblvs = fill(AcousticAnalogies.UntrippedN0012BoundaryLayer(), num_radial) +bl_lblvs = AcousticAnalogies.UntrippedN0012BoundaryLayer() + +r_obs = 2.27 # meters +theta_obs = -35*pi/180 +# So, the docstring for BPM.jl says that `V` argument is the wind velocity in the y direction. +# So I guess we should assume that the blades are rotating about the y axis. +# And if the freestream velocity is in the positive y axis, then, from the perspective of the fluid, the blades are translating in the negative y direction. +# And I want the observer to be downstream/behind the blades, so that would mean they would have a positive y position. +# So I want to rotate the observer around the positive x axis, so I'm going to switch the sign on `theta_obs`. +t0_obs = 0.0 +x0_obs = [0.0, r_obs*sin(-theta_obs), r_obs*cos(-theta_obs)] +# The observer is moving in the same direction as the blades, which is the negative y axis. +v_obs = @SVector [0.0, -Vinf, 0.0] +obs = AcousticAnalogies.ConstVelocityAcousticObserver(t0_obs, x0_obs, v_obs) + +# Reshape the inputs to the source element constructors so that everything will line up with (num_times, num_radial, num_blades). +θs_rs = reshape(θs, 1, 1, :) +radii_rs = reshape(radii, 1, :, 1) +dradii_rs = reshape(dradii, 1, :, 1) +chord_rs = reshape(chord, 1, :, 1) +twist_rs = reshape(twist, 1, :, 1) +hs_rs = reshape(hs, 1, :, 1) +Psis_rs = reshape(Psis, 1, :, 1) +Us_rs = reshape(U, 1, :, 1) +alphas_rs = reshape(alpha, 1, :, 1) +bls_rs = reshape(bls, 1, :, 1) +# bls_untripped_rs = reshape(bls_lblvs, 1, :, 1) + +# Separate things into tip and no-tip. +radii_rs_no_tip = @view radii_rs[:, begin:end-1, :] +dradii_rs_no_tip = @view dradii_rs[:, begin:end-1, :] +chord_rs_no_tip = @view chord_rs[:, begin:end-1, :] +twist_rs_no_tip = @view twist_rs[:, begin:end-1, :] +hs_rs_no_tip = @view hs_rs[:, begin:end-1, :] +Psis_rs_no_tip = @view Psis_rs[:, begin:end-1, :] +Us_rs_no_tip = @view Us_rs[:, begin:end-1, :] +alphas_rs_no_tip = @view alphas_rs[:, begin:end-1, :] +bls_rs_no_tip = @view bls_rs[:, begin:end-1, :] + +radii_rs_with_tip = @view radii_rs[:, end:end, :] +dradii_rs_with_tip = @view dradii_rs[:, end:end, :] +chord_rs_with_tip = @view chord_rs[:, end:end, :] +twist_rs_with_tip = @view twist_rs[:, end:end, :] +hs_rs_with_tip = @view hs_rs[:, end:end, :] +Psis_rs_with_tip = @view Psis_rs[:, end:end, :] +Us_rs_with_tip = @view Us_rs[:, end:end, :] +alphas_rs_with_tip = @view alphas_rs[:, end:end, :] +bls_rs_with_tip = @view bls_rs[:, end:end, :] + +direct = AcousticAnalogies.BPMDirectivity +use_UInduction = false +use_Doppler = false +mach_correction = AcousticAnalogies.NoMachCorrection +ses_no_tip = CombinedNoTipBroadbandSourceElement{direct,use_UInduction,mach_correction,use_Doppler}.(asound, nu, radii_rs_no_tip, θs_rs, dradii_rs_no_tip, chord_rs_no_tip, twist_rs_no_tip, hs_rs_no_tip, Psis_rs_no_tip, Us_rs_no_tip, alphas_rs_no_tip, src_times, dt, bls_rs_no_tip, positive_x_rotation) .|> trans + +ses_with_tip = CombinedWithTipBroadbandSourceElement{direct,use_UInduction,mach_correction,use_Doppler}.(asound, nu, radii_rs_with_tip, θs_rs, dradii_rs_with_tip, chord_rs_with_tip, twist_rs_with_tip, hs_rs_with_tip, Psis_rs_with_tip, Us_rs_with_tip, alphas_rs_with_tip, src_times, dt, bls_rs_with_tip, Ref(blade_tip), positive_x_rotation) .|> trans + +# Need to do the LBLVS with the untripped boundary layer to match what BPM.jl is doing. +lblvs_ses_untripped = AcousticAnalogies.LBLVSSourceElement{direct,use_UInduction,use_Doppler}.(asound, nu, radii_rs, θs_rs, dradii_rs, chord_rs, twist_rs, Us_rs, alphas_rs, src_times, dt, Ref(bl_lblvs), positive_x_rotation) .|> trans + +# # Write out the source elements. +# pvd_no_tip = AcousticAnalogies.to_paraview_collection(joinpath(@__DIR__, "figure22b-no_tip"), ses_no_tip) +# pvd_with_tip = AcousticAnalogies.to_paraview_collection(joinpath(@__DIR__, "figure22b-with_tip"), ses_with_tip) +# pvd_all = AcousticAnalogies.to_paraview_collection(joinpath(@__DIR__, "figure22b-all"), (ses_no_tip, ses_with_tip); observers=(obs,)) + +# Put the source elements together: +ses = cat(ses_no_tip, ses_with_tip; dims=2) + +# Define the frequencies we'd like to evaluate. +# BPM.jl uses the approximate 1/3rd-octave bands. +freqs_obs = AcousticMetrics.ApproximateThirdOctaveCenterBands(100.0, 40000.0) +freqs_src = freqs_obs + +# Now do the noise prediction. +bpm_outs = AcousticAnalogies.noise.(ses, Ref(obs), Ref(freqs_src)) +pbs_lblvss_untripped = AcousticAnalogies.noise.(lblvs_ses_untripped, Ref(obs), Ref(freqs_src)) + +# Separate out each source. +pbs_tblte_ps = AcousticAnalogies.pbs_pressure.(bpm_outs) +pbs_tblte_ss = AcousticAnalogies.pbs_suction.(bpm_outs) +pbs_tblte_alphas = AcousticAnalogies.pbs_alpha.(bpm_outs) +pbs_tebs = AcousticAnalogies.pbs_teb.(bpm_outs) +pbs_tips = AcousticAnalogies.pbs_tip.(bpm_outs[:, end:end, :]) + +# Combine each noise prediction. +time_axis = 1 +pbs_pressure = AcousticMetrics.combine(pbs_tblte_ps, freqs_obs, time_axis) +pbs_suction = AcousticMetrics.combine(pbs_tblte_ss, freqs_obs, time_axis) +pbs_alpha = AcousticMetrics.combine(pbs_tblte_alphas, freqs_obs, time_axis) +pbs_teb = AcousticMetrics.combine(pbs_tebs, freqs_obs, time_axis) +pbs_tip = AcousticMetrics.combine(pbs_tips, freqs_obs, time_axis) +pbs_lblvs_untripped = AcousticMetrics.combine(pbs_lblvss_untripped, freqs_obs, time_axis) + +# Now I need to account for the fact that Figure 22b is actually comparing to narrowband experimental data with a frequency spacing of 20 Hz. +# So, to do that, I need to multiply the mean-squared pressure by Δf_nb/Δf_pbs, where `Δf_nb` is the 20 Hz narrowband and `Δf_pbs` is the bandwidth of each 1/3-octave proportional band. +# (Dividing the MSP by Δf_pbs aka the 1/3 octave spacing is like getting a power-spectral density, then multiplying by the narrowband spacing Δf_nb gives us the MSP associated with the narrowband.) +# I think the paper describes that, right? +# Right, here's something: +# +# > The current prediction method is limited to one-third octave bands, but it is compared to the narrowband experiment with Δf = 20 Hz. +# > This is done by dividing the energy from the one-third octave bands by the number of bands in Δf = 20 Hz. +# +# So, `Δf_pbs/Δf_nb` would represent the number of `Δf_nb`-width bands that could fit in a proportional band of bin width `Δf_pbs`. +# And then I'm dividing by that. +# So that seems like the right thing. +# So, first thing is to get the proportional band spacing. +freqs_l = AcousticMetrics.lower_bands(freqs_obs) +freqs_u = AcousticMetrics.upper_bands(freqs_obs) +df_pbs = freqs_u .- freqs_l +# Also need the experimental narrowband spacing. +df_nb = 20.0 +# Now multiply each by that. +nb_pressure = pbs_pressure .* df_nb ./ df_pbs +nb_suction = pbs_suction .* df_nb ./ df_pbs +nb_alpha = pbs_alpha .* df_nb ./ df_pbs +nb_teb = pbs_teb .* df_nb ./ df_pbs +nb_tip = pbs_tip .* df_nb ./ df_pbs +nb_lblvs_untripped = pbs_lblvs_untripped .* df_nb ./ df_pbs + +# Now I want the SPL, which should just be this: +pref = 20e-6 +spl_pressure = 10 .* log10.(nb_pressure./(pref^2)) +spl_suction = 10 .* log10.(nb_suction./(pref^2)) +spl_alpha = 10 .* log10.(nb_alpha./(pref^2)) +spl_teb = 10 .* log10.(nb_teb./(pref^2)) +spl_tip = 10 .* log10.(nb_tip./(pref^2)) +spl_lblvs_untripped = 10 .* log10.(nb_lblvs_untripped./(pref^2)) + +# Read in the BPM.jl data. +freq_bpmjl = data["freqs"] +spl_pressure_bpmjl = data["spl_nb_pressure"] +spl_suction_bpmjl = data["spl_nb_suction"] +spl_separation_bpmjl = data["spl_nb_separation"] +spl_lblvs_bpmjl = data["spl_nb_lblvs"] +spl_blunt_bpmjl = data["spl_nb_blunt"] +spl_tip_bpmjl = data["spl_nb_tip"] + +# The frequencies in the CSV file should match the observer frequencies we're using. +@test all(freqs_obs .≈ freq_bpmjl) + +# Only look at the SPLs that are actually significant, i.e. greater than 10 dB. +@test maximum(abs.(spl_pressure[spl_pressure_bpmjl .> 10] .- spl_pressure_bpmjl[spl_pressure_bpmjl .> 10])) < 0.77 +@test maximum(abs.(spl_suction[spl_suction_bpmjl .> 10] .- spl_suction_bpmjl[spl_suction_bpmjl .> 10])) < 0.78 +@test maximum(abs.(spl_alpha[spl_separation_bpmjl .> 10] .- spl_separation_bpmjl[spl_separation_bpmjl .> 10])) < 0.78 +@test maximum(abs.(spl_lblvs_untripped[spl_lblvs_bpmjl .> 10] .- spl_lblvs_bpmjl[spl_lblvs_bpmjl .> 10])) < 0.81 +@test maximum(abs.(spl_teb[spl_blunt_bpmjl .> 10] .- spl_blunt_bpmjl[spl_blunt_bpmjl .> 10])) < 0.81 +@test maximum(abs.(spl_tip[spl_tip_bpmjl .> 10] .- spl_tip_bpmjl[spl_tip_bpmjl .> 10])) < 1.25 + diff --git a/test/itr_figure23c_barc.jl b/test/itr_figure23c_barc.jl new file mode 100644 index 00000000..7860d8df --- /dev/null +++ b/test/itr_figure23c_barc.jl @@ -0,0 +1,261 @@ +using AcousticAnalogies +using AcousticMetrics: AcousticMetrics +using DelimitedFiles: readdlm +using KinematicCoordinateTransformations: compose, SteadyRotXTransformation, ConstantVelocityTransformation +using FileIO: load +using FLOWMath: akima +using StaticArrays: @SVector +using Test + +data = load(joinpath(@__DIR__, "gen_bpmjl_data", "figure23c.jld2")) +rho = data["rho"] +asound = data["asound"] +mu = data["mu"] +Vinf = data["Vinf"] +omega = data["omega"] +B = data["B"] +Rhub = data["Rhub"] +Rtip = data["Rtip"] +radii = data["radii"] +chord = data["chord"] +twist = data["twist"] +alpha = data["alpha"] +U = data["U"] +hs = data["hs"] +num_src_times_blade_pass = data["num_src_times_blade_pass"] +Psis = data["Psis"] + +nu = mu/rho +num_radial = length(radii) +dradii = AcousticAnalogies.get_dradii(radii, Rhub, Rtip) + +# Get the source time, which will be one blade pass worth of time, each blade pass with `num_src_times_blade_pass` steps per blade pass. +bpp = 1/(B/(2*pi)*omega) # 1/(B blade_passes/rev * 1 rev / (2*pi rad) * omega rad/s) +num_blade_pass = 1 +period_src = num_blade_pass*bpp +num_src_times = num_src_times_blade_pass * num_blade_pass +t0 = 0.0 +dt = period_src/num_src_times +src_times = t0 .+ (0:num_src_times-1).*dt + +# Now let's define the coordinate system. +# I'm going to do my usual thing, which is to have the freestream velocity pointed in the negative x direction, and thus the blades will be translating in the positive x direction. +# And the blades will be rotating about the positive x axis at a rate of `omega`. +rot_trans = SteadyRotXTransformation(t0, omega, 0.0) + +# The hub/rotation axis of the blades will start at the origin at time `t0`, and translate in the positive x direction at a speed of `Vinf`. +y0_hub = @SVector [0.0, 0.0, 0.0] # m +v0_hub = @SVector [Vinf, 0.0, 0.0] # m/s +const_vel_trans = ConstantVelocityTransformation(t0, y0_hub, v0_hub) + +# Now I can put the two transformations together: +trans = compose.(src_times, Ref(const_vel_trans), Ref(rot_trans)) + +# Azimuthal offset for each blade. +θs = (0:(B-1)) .* (2*pi/B) + +# Paper doesn't specify the microphone used for Figure 23, but earlier at the beginning of "C. Noise Characteristics and Trends" there is this: +# > For the purposes of this paper, presented acoustic spectra will correspond to an observer located −35° below the plane of the rotor (microphone 5). +# So I'll just assume that holds for Figure 23. +# For the coordinate system, I'm doing my usual thing, which is to have the freestream velocity pointed in the negative x direction, and thus the blades will be translating in the positive x direction. +# The observer (microphone 5) is 35 deg behind/downstream of the rotor rotation plane, so this should be good. +# But it will of course be moving with the same freestream in the positive x direction. +r_obs = 2.27 # meters +theta_obs = -35*pi/180 +# The observer is moving in the positive x direction at Vinf, at the origin at time t0. +t0_obs = 0.0 +x0_obs = @SVector [r_obs*sin(theta_obs), r_obs*cos(theta_obs), 0.0] +v_obs = @SVector [Vinf, 0.0, 0.0] +obs = AcousticAnalogies.ConstVelocityAcousticObserver(t0_obs, x0_obs, v_obs) + +# So, for the boundary layer, we want to use untripped for the 95% of the blade from the hub to almost tip, and then tripped for the last 5% of the blade at the tip. +num_untripped = Int(round(0.95*num_radial)) +num_tripped = num_radial - num_untripped +bls_untripped = fill(AcousticAnalogies.UntrippedN0012BoundaryLayer(), num_untripped) +bls_tripped = fill(AcousticAnalogies.TrippedN0012BoundaryLayer(), num_tripped) +bls = vcat(bls_untripped, bls_tripped) + +# Now, the other trick: need to only include LBLVS noise for elements where the Reynolds number is < 160000. +# So, we need the Reynolds number for each section. +Re_c = @. U * chord / nu +# So now we want to extract the radial stations that meet that < 160000 condition. +low_Re_c = 160000 +mask_low_Re_c = Re_c .< low_Re_c + +# And we're also going to use the untripped boundary layer for the LBLVS source. +bl_lblvs = AcousticAnalogies.UntrippedN0012BoundaryLayer() + +# In the Figure 23 caption, "for these predictions, bluntness thickness H was set to 0.5 mm and trailing edge angle Ψ was set to 14 degrees." +h = 0.5e-3 # meters +Psi = 14*pi/180 # radians + +# I don't see any discussion for what type of tip was used for the tip vortex noise. +# The flat tip seems to match the PAS+ROTONET+BARC predictions well. +blade_tip = AcousticAnalogies.FlatTip() + +# Reshape the inputs to the source element constructors so that everything will line up with (num_times, num_radial, num_blades). +θs_rs = reshape(θs, 1, 1, :) +radii_rs = reshape(radii, 1, :, 1) +dradii_rs = reshape(dradii, 1, :, 1) +chord_rs = reshape(chord, 1, :, 1) +twist_rs = reshape(twist, 1, :, 1) +hs_rs = reshape(hs, 1, :, 1) +Psis_rs = reshape(Psis, 1, :, 1) +Us_rs = reshape(U, 1, :, 1) +alphas_rs = reshape(alpha, 1, :, 1) +bls_rs = reshape(bls, 1, :, 1) + +# Separate things into tip and no-tip. +radii_rs_no_tip = @view radii_rs[:, begin:end-1, :] +dradii_rs_no_tip = @view dradii_rs[:, begin:end-1, :] +chord_rs_no_tip = @view chord_rs[:, begin:end-1, :] +twist_rs_no_tip = @view twist_rs[:, begin:end-1, :] +hs_rs_no_tip = @view hs_rs[:, begin:end-1, :] +Psis_rs_no_tip = @view Psis_rs[:, begin:end-1, :] +Us_rs_no_tip = @view Us_rs[:, begin:end-1, :] +alphas_rs_no_tip = @view alphas_rs[:, begin:end-1, :] +bls_rs_no_tip = @view bls_rs[:, begin:end-1, :] + +radii_rs_with_tip = @view radii_rs[:, end:end, :] +dradii_rs_with_tip = @view dradii_rs[:, end:end, :] +chord_rs_with_tip = @view chord_rs[:, end:end, :] +twist_rs_with_tip = @view twist_rs[:, end:end, :] +hs_rs_with_tip = @view hs_rs[:, end:end, :] +Psis_rs_with_tip = @view Psis_rs[:, end:end, :] +Us_rs_with_tip = @view Us_rs[:, end:end, :] +alphas_rs_with_tip = @view alphas_rs[:, end:end, :] +bls_rs_with_tip = @view bls_rs[:, end:end, :] + +positive_x_rotation = true +ses_no_tip = CombinedNoTipBroadbandSourceElement.(asound, nu, radii_rs_no_tip, θs_rs, dradii_rs_no_tip, chord_rs_no_tip, twist_rs_no_tip, hs_rs_no_tip, Psis_rs_no_tip, Us_rs_no_tip, alphas_rs_no_tip, src_times, dt, bls_rs_no_tip, positive_x_rotation) .|> trans +ses_with_tip = CombinedWithTipBroadbandSourceElement.(asound, nu, radii_rs_with_tip, θs_rs, dradii_rs_with_tip, chord_rs_with_tip, twist_rs_with_tip, hs_rs_with_tip, Psis_rs_with_tip, Us_rs_with_tip, alphas_rs_with_tip, src_times, dt, bls_rs_with_tip, Ref(blade_tip), positive_x_rotation) .|> trans + +# It's more convinient to cat all the sources together. +ses = cat(ses_no_tip, ses_with_tip; dims=2) + +# Need to do the LBLVS stuff separately. +# Grab the parts of the inputs that correspond to the low Reynolds number stations. +radii_lblvs = @view radii[mask_low_Re_c] +dradii_lblvs = @view dradii[mask_low_Re_c] +chord_lblvs = @view chord[mask_low_Re_c] +twist_lblvs = @view twist[mask_low_Re_c] +hs_lblvs = @view hs[mask_low_Re_c] +Psis_lblvs = @view Psis[mask_low_Re_c] +Us_lblvs = @view U[mask_low_Re_c] +alphas_lblvs = @view alpha[mask_low_Re_c] + +# And do the reshaping. +radii_lblvs_rs = reshape(radii_lblvs, 1, :, 1) +dradii_lblvs_rs = reshape(dradii_lblvs, 1, :, 1) +chord_lblvs_rs = reshape(chord_lblvs, 1, :, 1) +twist_lblvs_rs = reshape(twist_lblvs, 1, :, 1) +hs_lblvs_rs = reshape(hs_lblvs, 1, :, 1) +Psis_lblvs_rs = reshape(Psis_lblvs, 1, :, 1) +Us_lblvs_rs = reshape(Us_lblvs, 1, :, 1) +alphas_lblvs_rs = reshape(alphas_lblvs, 1, :, 1) + +# Now we can create the source elements. +ses_lblvs = LBLVSSourceElement.(asound, nu, radii_lblvs_rs, θs_rs, dradii_lblvs_rs, chord_lblvs_rs, twist_lblvs_rs, Us_lblvs_rs, alphas_lblvs_rs, src_times, dt, Ref(bl_lblvs), positive_x_rotation) .|> trans + +# The predictions in Figure 23c appear to be on 1/3 octave, ranging from about 200 Hz to 60,000 Hz. +# But let's expand the range of source frequencies to account for Doppler shifting. +freqs_src = AcousticMetrics.ExactProportionalBands{3, :center}(10.0, 200000.0) +freqs_obs = AcousticMetrics.ExactProportionalBands{3, :center}(200.0, 60000.0) + +# Now we can do a noise prediction. +bpm_outs = AcousticAnalogies.noise.(ses, Ref(obs), Ref(freqs_src)) +pbs_lblvss = AcousticAnalogies.noise.(ses_lblvs, Ref(obs), Ref(freqs_src)) + +# This seperates out the noise prediction for each source-observer combination into the different sources. +pbs_tblte_ps = AcousticAnalogies.pbs_pressure.(bpm_outs) +pbs_tblte_ss = AcousticAnalogies.pbs_suction.(bpm_outs) +pbs_tblte_alphas = AcousticAnalogies.pbs_alpha.(bpm_outs) +pbs_tebs = AcousticAnalogies.pbs_teb.(bpm_outs) +pbs_tips = AcousticAnalogies.pbs_tip.(bpm_outs[:, end:end, :]) + +# Now, need to combine each broadband noise prediction. +# The time axis the axis over which the time varies for each source. +time_axis = 1 +pbs_pressure = AcousticMetrics.combine(pbs_tblte_ps, freqs_obs, time_axis) +pbs_suction = AcousticMetrics.combine(pbs_tblte_ss, freqs_obs, time_axis) +pbs_alpha = AcousticMetrics.combine(pbs_tblte_alphas, freqs_obs, time_axis) +pbs_teb = AcousticMetrics.combine(pbs_tebs, freqs_obs, time_axis) +pbs_tip = AcousticMetrics.combine(pbs_tips, freqs_obs, time_axis) +pbs_lblvs = AcousticMetrics.combine(pbs_lblvss, freqs_obs, time_axis) + +# Now I need to account for the fact that Figure 23c is actually comparing to narrowband experimental data with a frequency spacing of 20 Hz. +# So, to do that, I need to multiply the mean-squared pressure by Δf_nb/Δf_pbs, where `Δf_nb` is the 20 Hz narrowband and `Δf_pbs` is the bandwidth of each 1/3-octave proportional band. +# I think the paper describes that, right? +# Right, here's something: +# +# > The current prediction method is limited to one-third octave bands, but it is compared to the narrowband experiment with Δf = 20 Hz. +# > This is done by dividing the energy from the one-third octave bands by the number of bands in Δf = 20 Hz. +# +# So, `Δf_pbs/Δf_nb` would represent the number of `Δf_nb`-width bands that could fit in a proportional band of bin width `Δf_pbs`. +# And then I'm dividing by that. +# So that seems like the right thing. +# So, first thing is to get the proportional band spacing. +freqs_l = AcousticMetrics.lower_bands(freqs_obs) +freqs_u = AcousticMetrics.upper_bands(freqs_obs) +df_pbs = freqs_u .- freqs_l + +# Also need the experimental narrowband spacing. +df_nb = 20.0 +# Now multiply each by that. +nb_pressure = pbs_pressure .* df_nb ./ df_pbs +nb_suction = pbs_suction .* df_nb ./ df_pbs +nb_alpha = pbs_alpha .* df_nb ./ df_pbs +nb_lblvs = pbs_lblvs .* df_nb ./ df_pbs +nb_teb = pbs_teb .* df_nb ./ df_pbs +nb_tip = pbs_tip .* df_nb ./ df_pbs + +# Now I want the SPL, which should just be this: +pref = 20e-6 +spl_pressure = 10 .* log10.(nb_pressure./(pref^2)) +spl_suction = 10 .* log10.(nb_suction./(pref^2)) +spl_alpha = 10 .* log10.(nb_alpha./(pref^2)) +spl_lblvs = 10 .* log10.(nb_lblvs./(pref^2)) +spl_teb = 10 .* log10.(nb_teb./(pref^2)) +spl_tip = 10 .* log10.(nb_tip./(pref^2)) + +# Now I should be able to compare to the BARC data. +# Need to read it in first. +data_pressure_barc = readdlm(joinpath(@__DIR__, "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure23c-TBL-TE-pressure.csv"), ',') +freq_pressure_barc = data_pressure_barc[:, 1] +spl_pressure_barc = data_pressure_barc[:, 2] + +data_suction_barc = readdlm(joinpath(@__DIR__, "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure23c-TBL-TE-suction.csv"), ',') +freq_suction_barc = data_suction_barc[:, 1] +spl_suction_barc = data_suction_barc[:, 2] + +data_separation_barc = readdlm(joinpath(@__DIR__, "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure23c-separation.csv"), ',') +freq_separation_barc = data_separation_barc[:, 1] +spl_separation_barc = data_separation_barc[:, 2] + +data_lblvs_barc = readdlm(joinpath(@__DIR__, "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure23c-LBLVS.csv"), ',') +freq_lblvs_barc = data_lblvs_barc[:, 1] +spl_lblvs_barc = data_lblvs_barc[:, 2] + +data_teb_barc = readdlm(joinpath(@__DIR__, "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure23c-BVS.csv"), ',') +freq_teb_barc = data_teb_barc[:, 1] +spl_teb_barc = data_teb_barc[:, 2] + +data_tip_barc = readdlm(joinpath(@__DIR__, "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure23c-tip_vortex_shedding.csv"), ',') +freq_tip_barc = data_tip_barc[:, 1] +spl_tip_barc = data_tip_barc[:, 2] + +# Interpolate the AcousticAnalogies.jl data onto the frequencies from the BARC CSV file. +spl_pressure_interp = akima(freqs_obs, spl_pressure, freq_pressure_barc) +spl_suction_interp = akima(freqs_obs, spl_suction, freq_suction_barc) +spl_separation_interp = akima(freqs_obs, spl_alpha, freq_separation_barc) +spl_lblvs_interp = akima(freqs_obs, spl_lblvs, freq_lblvs_barc) +spl_teb_interp = akima(freqs_obs, spl_teb, freq_teb_barc) +spl_tip_interp = akima(freqs_obs, spl_tip, freq_tip_barc) + +# Now compare. +@test all(abs.(spl_pressure_interp .- spl_pressure_barc) .< [1.918, 1.880, 1.484, 1.65, 1.496, 1.170, 1.043, 0.729, 0.406, 0.406, 1.49, 1.142, 1.131]) +@test all(abs.(spl_suction_interp .- spl_suction_barc) .< [2.193, 2.066, 1.984, 1.961, 1.686, 1.423, 1.255, 1.060, 0.339, 0.101, 0.149, 0.749, 1.363, 1.220, 1.547, 1.979]) +@test all(abs.(spl_separation_interp .- spl_separation_barc) .< [17.002, 14.84, 12.09, 10.20, 9.42, 8.371, 7.763, 7.504, 7.099, 6.124, 5.307, 2.843, 2.326, 2.560, 2.583, 2.088, 1.448, 0.628, 0.112, 0.873, 1.971]) +@test all(abs.(spl_lblvs_interp .- spl_lblvs_barc) .< [3.369, 3.795, 3.758, 3.797, 3.765, 3.749, 3.545, 3.927, 3.922, 3.652, 3.571]) +@test all(abs.(spl_teb_interp .- spl_teb_barc) .< [0.274, 0.135, 0.211, 0.127, 0.0584, 2.200, 2.981]) +@test all(abs.(spl_tip_interp .- spl_tip_barc) .< [0.590, 0.659, 0.625, 0.460, 0.240, 0.467, 0.434, 0.0235, 0.0468]) diff --git a/test/itr_figure23c_bpmjl.jl b/test/itr_figure23c_bpmjl.jl new file mode 100644 index 00000000..4eac5cb2 --- /dev/null +++ b/test/itr_figure23c_bpmjl.jl @@ -0,0 +1,312 @@ +using AcousticAnalogies +using AcousticMetrics: AcousticMetrics +using KinematicCoordinateTransformations: compose, SteadyRotXTransformation, SteadyRotYTransformation, SteadyRotZTransformation, ConstantVelocityTransformation +using FileIO: load +using FLOWMath: Akima +using StaticArrays: @SVector +using Test + +# tip vortex noise correction data based on "Airfoil Tip Vortex Formation Noise" +# Copied from BPM.jl (would like to add BPM.jl as a dependency if it's registered in General some day). +const bm_tip_alpha_aspect_data = [2.0,2.67,4.0,6.0,12.0,24.0] +const bm_tip_alpha_aratio_data = [0.54,0.62,0.71,0.79,0.89,0.95] +const bm_tip_alpha_aspect_ratio_correction = Akima(bm_tip_alpha_aspect_data, bm_tip_alpha_aratio_data) + +function bm_tip_vortex_alpha_correction_nonsmooth(aspect_ratio) + # compute tip lift curve slope + if aspect_ratio < 2.0 + aratio = 0.5*one(aspect_ratio) + elseif 2.0 <= aspect_ratio <= 24.0 + aratio = bm_tip_alpha_aspect_ratio_correction(aspect_ratio) + elseif aspect_ratio > 24.0 + aratio = 1.0*one(aspect_ratio) + end + + return aratio +end + +struct BMTipAlphaCorrection{TCorrection} <: AbstractTipAlphaCorrection + correction::TCorrection + + function BMTipAlphaCorrection(aspect_ratio) + # correction = BPM._tip_vortex_alpha_correction_nonsmooth(aspect_ratio) + correction = bm_tip_vortex_alpha_correction_nonsmooth(aspect_ratio) + return new{typeof(correction)}(correction) + end +end + +function AcousticAnalogies.tip_vortex_alpha_correction(blade_tip::AbstractBladeTip{<:BMTipAlphaCorrection}, alphatip) + a0l = AcousticAnalogies.alpha_zerolift(blade_tip) + correction_factor = AcousticAnalogies.tip_alpha_correction(blade_tip).correction + return correction_factor * (alphatip - a0l) + a0l +end + + +data = load(joinpath(@__DIR__, "gen_bpmjl_data", "figure23c.jld2")) +rho = data["rho"] +asound = data["asound"] +mu = data["mu"] +Vinf = data["Vinf"] +omega = data["omega"] +B = data["B"] +Rhub = data["Rhub"] +Rtip = data["Rtip"] +radii = data["radii"] +chord = data["chord"] +twist = data["twist"] +alpha = data["alpha"] +U = data["U"] +hs = data["hs"] +Psis = data["Psis"] +num_src_times_blade_pass = data["num_src_times_blade_pass"] +tripped_flags = data["tripped_flags"] +lblvs_flags = data["lblvs_flags"] + +num_radial = length(radii) + +nu = mu/rho +dradii = AcousticAnalogies.get_dradii(radii, Rhub, Rtip) + +# Get some transform stuff. +bpp = 1/(B/(2*pi)*omega) # 1/(B blade_passes/rev * 1 rev / (2*pi rad) * omega rad/s) +num_blade_pass = 1 +period_src = num_blade_pass*bpp +num_src_times = num_src_times_blade_pass * num_blade_pass +t0 = 0.0 +dt = period_src/num_src_times +src_times = t0 .+ (0:num_src_times-1).*dt + +# I don't see any discussion for what type of tip was used for the tip vortex noise. +# FlatTip with no CCBlade.jl tip correction or BPM-style tip correction seems to match the BARC predictions well. +# blade_tip = AcousticAnalogies.FlatTip(AcousticAnalogies.NoTipAlphaCorrection()) +# BPM.jl uses a different tip alpha correction which appears to require the blade aspect ratio, defined as the blade radius divided by the average chord. +cbar = sum(chord .* dradii) / (Rtip - Rhub) +aspect_ratio = Rtip/cbar +alpha0lift = 0.0 +blade_tip = AcousticAnalogies.FlatTip(BMTipAlphaCorrection(aspect_ratio), alpha0lift) + +# Getting the coordinate system consistent with BPM.jl is a bit tricky. +# Here's a bit of code from BPM.jl: +# +# # Calculate the trailing edge position relative to the hub +# xs = sin(beta)*d - cos(beta)*(c - c1) +# zs = cos(beta)*d + sin(beta)*(c - c1) +# +# OK, so that shows me that the blade is initially aligned with the z axis, rotating to the positive x direction. +# And I know the blades are rotating about the positive y axis. +# So that's the answer for the BPM.jl coordinate system: +# +# * freestream in the positive y axis direction. +# * first blade initially aligned with the positive z axis, rotating about the positive y axis. +# +# Now, what do I need to do with AcousticAnalogies to make that happen? +# I want the blades to be translating in the negative y direction, rotating about the positive y axis. +# I usually start with the blades rotating about either the positive or negative x axis, moving in the direction of the positive x axis. +# I think the answer is, +# +# * start out with the blades rotating about the negative x axis, moving in the direction of the positive x axis +# * rotate 90° about the negative z axis. +# After this, the blades will be moving in the negative y direction, rotating about the positive y axis, which is good. +# But I want the first blade to be aligned with the positive z axis, and stopping here would mean it's aligned with the positive x axis. +# * rotate 90° about the negative y axis. +# This will put the first blade in line with the positive z axis. + +# So, let's do what we said we need to do. +# Start with a rotation about the negative x axis. +positive_x_rotation = false +rot_trans = SteadyRotXTransformation(t0, omega*ifelse(positive_x_rotation, 1, -1), 0) + +# Then translate along the positive x axis. +y0_hub = @SVector [0.0, 0.0, 0.0] # m +v0_hub = @SVector [Vinf, 0.0, 0.0] +const_vel_trans = ConstantVelocityTransformation(t0, y0_hub, v0_hub) + +# Then a 90° rotation about the negative z axis. +trans_z90deg = SteadyRotZTransformation(0.0, 0.0, -0.5*pi) + +# Then a 90° rotation about the negative y axis. +trans_y90deg = SteadyRotYTransformation(0.0, 0.0, -0.5*pi) + +# Put them all together: +trans = compose.(src_times, Ref(trans_y90deg), + compose.(src_times, Ref(trans_z90deg), + compose.(src_times, Ref(const_vel_trans), Ref(rot_trans)))) + +# Use the M_c = 0.8*M that BPM.jl and the BPM report use. +U = @. 0.8*sqrt(Vinf^2 + (omega*radii)^2) + +# Azimuthal offset for each blade. +θs = (0:(B-1)) .* (2*pi/B) .* ifelse(positive_x_rotation, 1, -1) + +bls = [ifelse(tf, + AcousticAnalogies.TrippedN0012BoundaryLayer(), + AcousticAnalogies.UntrippedN0012BoundaryLayer()) for tf in tripped_flags] + +# Need to do the LBLVS with the untripped boundary layer to match what BPM.jl is doing. +# bls_lblvs = fill(AcousticAnalogies.UntrippedN0012BoundaryLayer(), num_radial) +bl_lblvs = AcousticAnalogies.UntrippedN0012BoundaryLayer() + +r_obs = 2.27 # meters +theta_obs = -35*pi/180 +# So, the docstring for BPM.jl says that `V` argument is the wind velocity in the y direction. +# So I guess we should assume that the blades are rotating about the y axis. +# And if the freestream velocity is in the positive y axis, then, from the perspective of the fluid, the blades are translating in the negative y direction. +# And I want the observer to be downstream/behind the blades, so that would mean they would have a positive y position. +# So I want to rotate the observer around the positive x axis, so I'm going to switch the sign on `theta_obs`. +t0_obs = 0.0 +x0_obs = [0.0, r_obs*sin(-theta_obs), r_obs*cos(-theta_obs)] +# The observer is moving in the same direction as the blades, which is the negative y axis. +v_obs = @SVector [0.0, -Vinf, 0.0] +obs = AcousticAnalogies.ConstVelocityAcousticObserver(t0_obs, x0_obs, v_obs) + +# Reshape the inputs to the source element constructors so that everything will line up with (num_times, num_radial, num_blades). +θs_rs = reshape(θs, 1, 1, :) +radii_rs = reshape(radii, 1, :, 1) +dradii_rs = reshape(dradii, 1, :, 1) +chord_rs = reshape(chord, 1, :, 1) +twist_rs = reshape(twist, 1, :, 1) +hs_rs = reshape(hs, 1, :, 1) +Psis_rs = reshape(Psis, 1, :, 1) +Us_rs = reshape(U, 1, :, 1) +alphas_rs = reshape(alpha, 1, :, 1) +bls_rs = reshape(bls, 1, :, 1) +# bls_untripped_rs = reshape(bls_lblvs, 1, :, 1) + +# Separate things into tip and no-tip. +radii_rs_no_tip = @view radii_rs[:, begin:end-1, :] +dradii_rs_no_tip = @view dradii_rs[:, begin:end-1, :] +chord_rs_no_tip = @view chord_rs[:, begin:end-1, :] +twist_rs_no_tip = @view twist_rs[:, begin:end-1, :] +hs_rs_no_tip = @view hs_rs[:, begin:end-1, :] +Psis_rs_no_tip = @view Psis_rs[:, begin:end-1, :] +Us_rs_no_tip = @view Us_rs[:, begin:end-1, :] +alphas_rs_no_tip = @view alphas_rs[:, begin:end-1, :] +bls_rs_no_tip = @view bls_rs[:, begin:end-1, :] + +radii_rs_with_tip = @view radii_rs[:, end:end, :] +dradii_rs_with_tip = @view dradii_rs[:, end:end, :] +chord_rs_with_tip = @view chord_rs[:, end:end, :] +twist_rs_with_tip = @view twist_rs[:, end:end, :] +hs_rs_with_tip = @view hs_rs[:, end:end, :] +Psis_rs_with_tip = @view Psis_rs[:, end:end, :] +Us_rs_with_tip = @view Us_rs[:, end:end, :] +alphas_rs_with_tip = @view alphas_rs[:, end:end, :] +bls_rs_with_tip = @view bls_rs[:, end:end, :] + +direct = AcousticAnalogies.BPMDirectivity +use_UInduction = false +use_Doppler = false +mach_correction = AcousticAnalogies.NoMachCorrection +ses_no_tip = CombinedNoTipBroadbandSourceElement{direct,use_UInduction,mach_correction,use_Doppler}.(asound, nu, radii_rs_no_tip, θs_rs, dradii_rs_no_tip, chord_rs_no_tip, twist_rs_no_tip, hs_rs_no_tip, Psis_rs_no_tip, Us_rs_no_tip, alphas_rs_no_tip, src_times, dt, bls_rs_no_tip, positive_x_rotation) .|> trans + +ses_with_tip = CombinedWithTipBroadbandSourceElement{direct,use_UInduction,mach_correction,use_Doppler}.(asound, nu, radii_rs_with_tip, θs_rs, dradii_rs_with_tip, chord_rs_with_tip, twist_rs_with_tip, hs_rs_with_tip, Psis_rs_with_tip, Us_rs_with_tip, alphas_rs_with_tip, src_times, dt, bls_rs_with_tip, Ref(blade_tip), positive_x_rotation) .|> trans + +# Need to do the LBLVS with the untripped boundary layer to match what BPM.jl is doing, and only where `lblvs_flags` is true. +# So extract the radial locations where that's true. +radii_lblvs = @view radii[lblvs_flags] +dradii_lblvs = @view dradii[lblvs_flags] +chord_lblvs = @view chord[lblvs_flags] +twist_lblvs = @view twist[lblvs_flags] +Us_lblvs = @view U[lblvs_flags] +alphas_lblvs = @view alpha[lblvs_flags] +# bls_lblvs = @view bls_lblvs[lblvs_flags] + +# Now do the usual reshaping. +radii_lblvs_rs = reshape(radii_lblvs, 1, :, 1) +dradii_lblvs_rs = reshape(dradii_lblvs, 1, :, 1) +chord_lblvs_rs = reshape(chord_lblvs, 1, :, 1) +twist_lblvs_rs = reshape(twist_lblvs, 1, :, 1) +Us_lblvs_rs = reshape(Us_lblvs, 1, :, 1) +alphas_lblvs_rs = reshape(alphas_lblvs, 1, :, 1) +# bls_lblvs_rs = reshape(bls_lblvs, 1, :, 1) + +# Now we can construct the lblvs source elements. +lblvs_ses = AcousticAnalogies.LBLVSSourceElement{direct,use_UInduction,use_Doppler}.(asound, nu, radii_lblvs_rs, θs_rs, dradii_lblvs_rs, chord_lblvs_rs, twist_lblvs_rs, Us_lblvs_rs, alphas_lblvs_rs, src_times, dt, Ref(bl_lblvs), positive_x_rotation) .|> trans + +# Write out the source elements. +# pvd_no_tip = AcousticAnalogies.to_paraview_collection(joinpath(@__DIR__, "figure23c-no_tip"), ses_no_tip) +# pvd_with_tip = AcousticAnalogies.to_paraview_collection(joinpath(@__DIR__, "figure23c-with_tip"), ses_with_tip) +# pvd_all = AcousticAnalogies.to_paraview_collection(joinpath(@__DIR__, "figure23c-all"), (ses_no_tip, ses_with_tip, lblvs_ses); observers=(obs,)) + +# Put the source elements together: +ses = cat(ses_no_tip, ses_with_tip; dims=2) + +# Define the frequencies we'd like to evaluate. +# BPM.jl uses the approximate 1/3rd-octave bands. +freqs_obs = AcousticMetrics.ApproximateThirdOctaveCenterBands(100.0, 40000.0) +freqs_src = freqs_obs + +# Now do the noise prediction. +bpm_outs = AcousticAnalogies.noise.(ses, Ref(obs), Ref(freqs_src)) +pbs_lblvss = AcousticAnalogies.noise.(lblvs_ses, Ref(obs), Ref(freqs_src)) + +# Separate out each source. +pbs_tblte_ps = AcousticAnalogies.pbs_pressure.(bpm_outs) +pbs_tblte_ss = AcousticAnalogies.pbs_suction.(bpm_outs) +pbs_tblte_alphas = AcousticAnalogies.pbs_alpha.(bpm_outs) +pbs_tebs = AcousticAnalogies.pbs_teb.(bpm_outs) +pbs_tips = AcousticAnalogies.pbs_tip.(bpm_outs[:, end:end, :]) + +# Combine each noise prediction. +time_axis = 1 +pbs_pressure = AcousticMetrics.combine(pbs_tblte_ps, freqs_obs, time_axis) +pbs_suction = AcousticMetrics.combine(pbs_tblte_ss, freqs_obs, time_axis) +pbs_alpha = AcousticMetrics.combine(pbs_tblte_alphas, freqs_obs, time_axis) +pbs_teb = AcousticMetrics.combine(pbs_tebs, freqs_obs, time_axis) +pbs_tip = AcousticMetrics.combine(pbs_tips, freqs_obs, time_axis) +pbs_lblvs = AcousticMetrics.combine(pbs_lblvss, freqs_obs, time_axis) + +# Now I need to account for the fact that Figure 23c is actually comparing to narrowband experimental data with a frequency spacing of 20 Hz. +# So, to do that, I need to multiply the mean-squared pressure by Δf_nb/Δf_pbs, where `Δf_nb` is the 20 Hz narrowband and `Δf_pbs` is the bandwidth of each 1/3-octave proportional band. +# (Dividing the MSP by Δf_pbs aka the 1/3 octave spacing is like getting a power-spectral density, then multiplying by the narrowband spacing Δf_nb gives us the MSP associated with the narrowband.) +# I think the paper describes that, right? +# Right, here's something: +# +# > The current prediction method is limited to one-third octave bands, but it is compared to the narrowband experiment with Δf = 20 Hz. +# > This is done by dividing the energy from the one-third octave bands by the number of bands in Δf = 20 Hz. +# +# So, `Δf_pbs/Δf_nb` would represent the number of `Δf_nb`-width bands that could fit in a proportional band of bin width `Δf_pbs`. +# And then I'm dividing by that. +# So that seems like the right thing. +# So, first thing is to get the proportional band spacing. +freqs_l = AcousticMetrics.lower_bands(freqs_obs) +freqs_u = AcousticMetrics.upper_bands(freqs_obs) +df_pbs = freqs_u .- freqs_l +# Also need the experimental narrowband spacing. +df_nb = 20.0 +# Now multiply each by that. +nb_pressure = pbs_pressure .* df_nb ./ df_pbs +nb_suction = pbs_suction .* df_nb ./ df_pbs +nb_alpha = pbs_alpha .* df_nb ./ df_pbs +nb_teb = pbs_teb .* df_nb ./ df_pbs +nb_tip = pbs_tip .* df_nb ./ df_pbs +nb_lblvs = pbs_lblvs .* df_nb ./ df_pbs + +# Now I want the SPL, which should just be this: +pref = 20e-6 +spl_pressure = 10 .* log10.(nb_pressure./(pref^2)) +spl_suction = 10 .* log10.(nb_suction./(pref^2)) +spl_alpha = 10 .* log10.(nb_alpha./(pref^2)) +spl_teb = 10 .* log10.(nb_teb./(pref^2)) +spl_tip = 10 .* log10.(nb_tip./(pref^2)) +spl_lblvs = 10 .* log10.(nb_lblvs./(pref^2)) + +# Read in the BPM.jl data. +freq_bpmjl = data["freqs"] +spl_pressure_bpmjl = data["spl_nb_pressure"] +spl_suction_bpmjl = data["spl_nb_suction"] +spl_separation_bpmjl = data["spl_nb_separation"] +spl_lblvs_bpmjl = data["spl_nb_lblvs"] +spl_blunt_bpmjl = data["spl_nb_blunt"] +spl_tip_bpmjl = data["spl_nb_tip"] + +# The frequencies in the CSV file should match the observer frequencies we're using. +@test all(freqs_obs .≈ freq_bpmjl) + +# Only look at the SPLs that are actually significant, i.e. greater than 10 dB. +@test maximum(abs.(spl_pressure[spl_pressure_bpmjl .> 10] .- spl_pressure_bpmjl[spl_pressure_bpmjl .> 10])) < 0.826 +@test maximum(abs.(spl_suction[spl_suction_bpmjl .> 10] .- spl_suction_bpmjl[spl_suction_bpmjl .> 10])) < 0.774 +@test maximum(abs.(spl_alpha[spl_separation_bpmjl .> 10] .- spl_separation_bpmjl[spl_separation_bpmjl .> 10])) < 0.771 +@test maximum(abs.(spl_teb[spl_blunt_bpmjl .> 10] .- spl_blunt_bpmjl[spl_blunt_bpmjl .> 10])) < 0.792 +@test maximum(abs.(spl_tip[spl_tip_bpmjl .> 10] .- spl_tip_bpmjl[spl_tip_bpmjl .> 10])) < 1.26 +@test maximum(abs.(spl_lblvs[spl_lblvs_bpmjl .> 10] .- spl_lblvs_bpmjl[spl_lblvs_bpmjl .> 10])) < 0.811 diff --git a/test/itr_figure24b_barc.jl b/test/itr_figure24b_barc.jl new file mode 100644 index 00000000..73a3bd1e --- /dev/null +++ b/test/itr_figure24b_barc.jl @@ -0,0 +1,233 @@ +using AcousticAnalogies +using AcousticMetrics: AcousticMetrics +using DelimitedFiles: readdlm +using KinematicCoordinateTransformations: compose, SteadyRotXTransformation, ConstantVelocityTransformation +using FileIO: load +using FLOWMath: akima +using StaticArrays: @SVector +using Test + +data = load(joinpath(@__DIR__, "gen_bpmjl_data", "figure24b.jld2")) +rho = data["rho"] +asound = data["asound"] +mu = data["mu"] +Vinf = data["Vinf"] +omega = data["omega"] +B = data["B"] +Rhub = data["Rhub"] +Rtip = data["Rtip"] +radii = data["radii"] +chord = data["chord"] +twist = data["twist"] +alpha = data["alpha"] +U = data["U"] +hs = data["hs"] +num_src_times_blade_pass = data["num_src_times_blade_pass"] +Psis = data["Psis"] + +nu = mu/rho +num_radial = length(radii) +dradii = AcousticAnalogies.get_dradii(radii, Rhub, Rtip) + +# Get the source time, which will be one blade pass worth of time, each blade pass with `num_src_times_blade_pass` steps per blade pass. +bpp = 1/(B/(2*pi)*omega) # 1/(B blade_passes/rev * 1 rev / (2*pi rad) * omega rad/s) +num_blade_pass = 1 +period_src = num_blade_pass*bpp +num_src_times = num_src_times_blade_pass * num_blade_pass +t0 = 0.0 +dt = period_src/num_src_times +src_times = t0 .+ (0:num_src_times-1).*dt + +# Now let's define the coordinate system. +# I'm going to do my usual thing, which is to have the freestream velocity pointed in the negative x direction, and thus the blades will be translating in the positive x direction. +# And the blades will be rotating about the positive x axis at a rate of `omega`. +rot_trans = SteadyRotXTransformation(t0, omega, 0.0) + +# The hub/rotation axis of the blades will start at the origin at time `t0`, and translate in the positive x direction at a speed of `Vinf`. +y0_hub = @SVector [0.0, 0.0, 0.0] # m +v0_hub = @SVector [Vinf, 0.0, 0.0] # m/s +const_vel_trans = ConstantVelocityTransformation(t0, y0_hub, v0_hub) + +# Now I can put the two transformations together: +trans = compose.(src_times, Ref(const_vel_trans), Ref(rot_trans)) + +# Azimuthal offset for each blade. +θs = (0:(B-1)) .* (2*pi/B) + +# Paper doesn't specify the microphone used for Figure 24, but earlier at the beginning of "C. Noise Characteristics and Trends" there is this: +# > For the purposes of this paper, presented acoustic spectra will correspond to an observer located −35° below the plane of the rotor (microphone 5). +# So I'll just assume that holds for Figure 23. +# For the coordinate system, I'm doing my usual thing, which is to have the freestream velocity pointed in the negative x direction, and thus the blades will be translating in the positive x direction. +# The observer (microphone 5) is 35 deg behind/downstream of the rotor rotation plane, so this should be good. +# But it will of course be moving with the same freestream in the positive x direction. +r_obs = 2.27 # meters +theta_obs = -35*pi/180 +# The observer is moving in the positive x direction at Vinf, at the origin at time t0. +t0_obs = 0.0 +x0_obs = @SVector [r_obs*sin(theta_obs), r_obs*cos(theta_obs), 0.0] +v_obs = @SVector [Vinf, 0.0, 0.0] +obs = AcousticAnalogies.ConstVelocityAcousticObserver(t0_obs, x0_obs, v_obs) + +# So, for the boundary layer, we want to use untripped for the 95% of the blade from the hub to almost tip, and then tripped for the last 5% of the blade at the tip. +num_untripped = Int(round(0.95*num_radial)) +num_tripped = num_radial - num_untripped +bls_untripped = fill(AcousticAnalogies.UntrippedN0012BoundaryLayer(), num_untripped) +bls_tripped = fill(AcousticAnalogies.TrippedN0012BoundaryLayer(), num_tripped) +bls = vcat(bls_untripped, bls_tripped) + +# And we're also going to use the untripped boundary layer for the LBLVS source. +bl_lblvs = AcousticAnalogies.UntrippedN0012BoundaryLayer() + +# In the Figure 24 caption, "for these predictions, bluntness thickness H was set to 0.5 mm and trailing edge angle Ψ was set to 14 degrees." +h = 0.5e-3 # meters +Psi = 14*pi/180 # radians + +# I don't see any discussion for what type of tip was used for the tip vortex noise. +# The flat tip seems to match the PAS+ROTONET+BARC predictions well. +blade_tip = AcousticAnalogies.FlatTip() + +# Reshape the inputs to the source element constructors so that everything will line up with (num_times, num_radial, num_blades). +θs_rs = reshape(θs, 1, 1, :) +radii_rs = reshape(radii, 1, :, 1) +dradii_rs = reshape(dradii, 1, :, 1) +chord_rs = reshape(chord, 1, :, 1) +twist_rs = reshape(twist, 1, :, 1) +hs_rs = reshape(hs, 1, :, 1) +Psis_rs = reshape(Psis, 1, :, 1) +Us_rs = reshape(U, 1, :, 1) +alphas_rs = reshape(alpha, 1, :, 1) +bls_rs = reshape(bls, 1, :, 1) + +# Separate things into tip and no-tip. +radii_rs_no_tip = @view radii_rs[:, begin:end-1, :] +dradii_rs_no_tip = @view dradii_rs[:, begin:end-1, :] +chord_rs_no_tip = @view chord_rs[:, begin:end-1, :] +twist_rs_no_tip = @view twist_rs[:, begin:end-1, :] +hs_rs_no_tip = @view hs_rs[:, begin:end-1, :] +Psis_rs_no_tip = @view Psis_rs[:, begin:end-1, :] +Us_rs_no_tip = @view Us_rs[:, begin:end-1, :] +alphas_rs_no_tip = @view alphas_rs[:, begin:end-1, :] +bls_rs_no_tip = @view bls_rs[:, begin:end-1, :] + +radii_rs_with_tip = @view radii_rs[:, end:end, :] +dradii_rs_with_tip = @view dradii_rs[:, end:end, :] +chord_rs_with_tip = @view chord_rs[:, end:end, :] +twist_rs_with_tip = @view twist_rs[:, end:end, :] +hs_rs_with_tip = @view hs_rs[:, end:end, :] +Psis_rs_with_tip = @view Psis_rs[:, end:end, :] +Us_rs_with_tip = @view Us_rs[:, end:end, :] +alphas_rs_with_tip = @view alphas_rs[:, end:end, :] +bls_rs_with_tip = @view bls_rs[:, end:end, :] + +positive_x_rotation = true +ses_no_tip = CombinedNoTipBroadbandSourceElement.(asound, nu, radii_rs_no_tip, θs_rs, dradii_rs_no_tip, chord_rs_no_tip, twist_rs_no_tip, hs_rs_no_tip, Psis_rs_no_tip, Us_rs_no_tip, alphas_rs_no_tip, src_times, dt, bls_rs_no_tip, positive_x_rotation) .|> trans +ses_with_tip = CombinedWithTipBroadbandSourceElement.(asound, nu, radii_rs_with_tip, θs_rs, dradii_rs_with_tip, chord_rs_with_tip, twist_rs_with_tip, hs_rs_with_tip, Psis_rs_with_tip, Us_rs_with_tip, alphas_rs_with_tip, src_times, dt, bls_rs_with_tip, Ref(blade_tip), positive_x_rotation) .|> trans + +# It's more convinient to cat all the sources together. +ses = cat(ses_no_tip, ses_with_tip; dims=2) + +# The LBLVS uses a different boundary layer, and all radial stations. +ses_lblvs = LBLVSSourceElement.(asound, nu, radii_rs, θs_rs, dradii_rs, chord_rs, twist_rs, Us_rs, alphas_rs, src_times, dt, Ref(bl_lblvs), positive_x_rotation) .|> trans + +# The predictions in Figure 24b appear to be on 1/3 octave, ranging from about 200 Hz to 60,000 Hz. +# But let's expand the range of source frequencies to account for Doppler shifting. +freqs_src = AcousticMetrics.ExactProportionalBands{3, :center}(10.0, 200000.0) +freqs_obs = AcousticMetrics.ExactProportionalBands{3, :center}(200.0, 60000.0) + +# Now we can do a noise prediction. +bpm_outs = AcousticAnalogies.noise.(ses, Ref(obs), Ref(freqs_src)) +pbs_lblvss = AcousticAnalogies.noise.(ses_lblvs, Ref(obs), Ref(freqs_src)) + +# This seperates out the noise prediction for each source-observer combination into the different sources. +pbs_tblte_ps = AcousticAnalogies.pbs_pressure.(bpm_outs) +pbs_tblte_ss = AcousticAnalogies.pbs_suction.(bpm_outs) +pbs_tblte_alphas = AcousticAnalogies.pbs_alpha.(bpm_outs) +pbs_tebs = AcousticAnalogies.pbs_teb.(bpm_outs) +pbs_tips = AcousticAnalogies.pbs_tip.(bpm_outs[:, end:end, :]) + +# Now, need to combine each broadband noise prediction. +# The time axis the axis over which the time varies for each source. +time_axis = 1 +pbs_pressure = AcousticMetrics.combine(pbs_tblte_ps, freqs_obs, time_axis) +pbs_suction = AcousticMetrics.combine(pbs_tblte_ss, freqs_obs, time_axis) +pbs_alpha = AcousticMetrics.combine(pbs_tblte_alphas, freqs_obs, time_axis) +pbs_teb = AcousticMetrics.combine(pbs_tebs, freqs_obs, time_axis) +pbs_tip = AcousticMetrics.combine(pbs_tips, freqs_obs, time_axis) +pbs_lblvs = AcousticMetrics.combine(pbs_lblvss, freqs_obs, time_axis) + +# Now I need to account for the fact that Figure 24b is actually comparing to narrowband experimental data with a frequency spacing of 20 Hz. +# So, to do that, I need to multiply the mean-squared pressure by Δf_nb/Δf_pbs, where `Δf_nb` is the 20 Hz narrowband and `Δf_pbs` is the bandwidth of each 1/3-octave proportional band. +# I think the paper describes that, right? +# Right, here's something: +# +# > The current prediction method is limited to one-third octave bands, but it is compared to the narrowband experiment with Δf = 20 Hz. +# > This is done by dividing the energy from the one-third octave bands by the number of bands in Δf = 20 Hz. +# +# So, `Δf_pbs/Δf_nb` would represent the number of `Δf_nb`-width bands that could fit in a proportional band of bin width `Δf_pbs`. +# And then I'm dividing by that. +# So that seems like the right thing. +# So, first thing is to get the proportional band spacing. +freqs_l = AcousticMetrics.lower_bands(freqs_obs) +freqs_u = AcousticMetrics.upper_bands(freqs_obs) +df_pbs = freqs_u .- freqs_l + +# Also need the experimental narrowband spacing. +df_nb = 20.0 +# Now multiply each by that. +nb_pressure = pbs_pressure .* df_nb ./ df_pbs +nb_suction = pbs_suction .* df_nb ./ df_pbs +nb_alpha = pbs_alpha .* df_nb ./ df_pbs +nb_lblvs = pbs_lblvs .* df_nb ./ df_pbs +nb_teb = pbs_teb .* df_nb ./ df_pbs +nb_tip = pbs_tip .* df_nb ./ df_pbs + +# Now I want the SPL, which should just be this: +pref = 20e-6 +spl_pressure = 10 .* log10.(nb_pressure./(pref^2)) +spl_suction = 10 .* log10.(nb_suction./(pref^2)) +spl_alpha = 10 .* log10.(nb_alpha./(pref^2)) +spl_lblvs = 10 .* log10.(nb_lblvs./(pref^2)) +spl_teb = 10 .* log10.(nb_teb./(pref^2)) +spl_tip = 10 .* log10.(nb_tip./(pref^2)) + +# Now I should be able to compare to the BARC data. +# Need to read it in first. +data_pressure_barc = readdlm(joinpath(@__DIR__, "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure24b-TBL-TE-pressure.csv"), ',') +freq_pressure_barc = data_pressure_barc[:, 1] +spl_pressure_barc = data_pressure_barc[:, 2] + +data_suction_barc = readdlm(joinpath(@__DIR__, "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure24b-TBL-TE-suction.csv"), ',') +freq_suction_barc = data_suction_barc[:, 1] +spl_suction_barc = data_suction_barc[:, 2] + +data_separation_barc = readdlm(joinpath(@__DIR__, "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure24b-separation.csv"), ',') +freq_separation_barc = data_separation_barc[:, 1] +spl_separation_barc = data_separation_barc[:, 2] + +data_lblvs_barc = readdlm(joinpath(@__DIR__, "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure24b-LBLVS.csv"), ',') +freq_lblvs_barc = data_lblvs_barc[:, 1] +spl_lblvs_barc = data_lblvs_barc[:, 2] + +data_teb_barc = readdlm(joinpath(@__DIR__, "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure24b-BVS.csv"), ',') +freq_teb_barc = data_teb_barc[:, 1] +spl_teb_barc = data_teb_barc[:, 2] + +data_tip_barc = readdlm(joinpath(@__DIR__, "bpm_data", "pettingill_acoustic_performance_characteristics_of_ideally_twisted_rotor_in_hover_2021", "figure24b-tip_vortex_shedding.csv"), ',') +freq_tip_barc = data_tip_barc[:, 1] +spl_tip_barc = data_tip_barc[:, 2] + +# Interpolate the AcousticAnalogies.jl data onto the frequencies from the BARC CSV file. +spl_pressure_interp = akima(freqs_obs, spl_pressure, freq_pressure_barc) +spl_suction_interp = akima(freqs_obs, spl_suction, freq_suction_barc) +spl_separation_interp = akima(freqs_obs, spl_alpha, freq_separation_barc) +spl_lblvs_interp = akima(freqs_obs, spl_lblvs, freq_lblvs_barc) +spl_teb_interp = akima(freqs_obs, spl_teb, freq_teb_barc) +spl_tip_interp = akima(freqs_obs, spl_tip, freq_tip_barc) + +# Now compare. +@test all(abs.(spl_pressure_interp .- spl_pressure_barc) .< [2.839, 2.365, 1.971, 1.892, 1.368, 0.801, 0.567, 0.145, 0.571, 0.746, 0.925, 0.760]) +@test all(abs.(spl_suction_interp .- spl_suction_barc) .< [0.291, 0.527, 0.447, 0.854, 0.818, 0.503, 0.247, 0.229, 0.105, 0.469, 0.563, 0.702, 0.947, 1.224]) +@test all(abs.(spl_separation_interp .- spl_separation_barc) .< [12.876, 10.398, 8.513, 7.067, 6.679, 5.426, 4.791, 4.325, 3.330, 1.307, 1.565, 1.437, 0.881, 0.384, 0.0727, 0.643, 1.357, 1.596, 1.886]) +@test all(abs.(spl_lblvs_interp .- spl_lblvs_barc) .< [28.442, 24.625, 20.380, 16.315, 12.763, 8.731, 5.498, 2.812, 0.964, 0.390, 0.628, 0.743, 0.903, 0.0362, 0.0262, 1.801, 3.430, 5.011, 4.375, 3.376]) +@test all(abs.(spl_teb_interp .- spl_teb_barc) .< [0.134, 0.306, 0.459, 0.106, 0.139, 0.809]) +@test all(abs.(spl_tip_interp .- spl_tip_barc) .< [0.862, 0.839, 0.843, 0.545, 0.429, 0.616, 0.382, 0.135]) diff --git a/test/itr_figure24b_bpmjl.jl b/test/itr_figure24b_bpmjl.jl new file mode 100644 index 00000000..234f52e9 --- /dev/null +++ b/test/itr_figure24b_bpmjl.jl @@ -0,0 +1,290 @@ +using AcousticAnalogies +using AcousticMetrics: AcousticMetrics +using KinematicCoordinateTransformations: compose, SteadyRotXTransformation, SteadyRotYTransformation, SteadyRotZTransformation, ConstantVelocityTransformation +using FileIO: load +using FLOWMath: Akima +using StaticArrays: @SVector +using Test + +# tip vortex noise correction data based on "Airfoil Tip Vortex Formation Noise" +# Copied from BPM.jl (would like to add BPM.jl as a dependency if it's registered in General some day). +const bm_tip_alpha_aspect_data = [2.0,2.67,4.0,6.0,12.0,24.0] +const bm_tip_alpha_aratio_data = [0.54,0.62,0.71,0.79,0.89,0.95] +const bm_tip_alpha_aspect_ratio_correction = Akima(bm_tip_alpha_aspect_data, bm_tip_alpha_aratio_data) + +function bm_tip_vortex_alpha_correction_nonsmooth(aspect_ratio) + # compute tip lift curve slope + if aspect_ratio < 2.0 + aratio = 0.5*one(aspect_ratio) + elseif 2.0 <= aspect_ratio <= 24.0 + aratio = bm_tip_alpha_aspect_ratio_correction(aspect_ratio) + elseif aspect_ratio > 24.0 + aratio = 1.0*one(aspect_ratio) + end + + return aratio +end + +struct BMTipAlphaCorrection{TCorrection} <: AbstractTipAlphaCorrection + correction::TCorrection + + function BMTipAlphaCorrection(aspect_ratio) + # correction = BPM._tip_vortex_alpha_correction_nonsmooth(aspect_ratio) + correction = bm_tip_vortex_alpha_correction_nonsmooth(aspect_ratio) + return new{typeof(correction)}(correction) + end +end + +function AcousticAnalogies.tip_vortex_alpha_correction(blade_tip::AbstractBladeTip{<:BMTipAlphaCorrection}, alphatip) + a0l = AcousticAnalogies.alpha_zerolift(blade_tip) + correction_factor = AcousticAnalogies.tip_alpha_correction(blade_tip).correction + return correction_factor * (alphatip - a0l) + a0l +end + +data = load(joinpath(@__DIR__, "gen_bpmjl_data", "figure24b.jld2")) +rho = data["rho"] +asound = data["asound"] +mu = data["mu"] +Vinf = data["Vinf"] +omega = data["omega"] +B = data["B"] +Rhub = data["Rhub"] +Rtip = data["Rtip"] +radii = data["radii"] +chord = data["chord"] +twist = data["twist"] +alpha = data["alpha"] +U = data["U"] +hs = data["hs"] +Psis = data["Psis"] +num_src_times_blade_pass = data["num_src_times_blade_pass"] +tripped_flags = data["tripped_flags"] + +num_radial = length(radii) + +nu = mu/rho +dradii = AcousticAnalogies.get_dradii(radii, Rhub, Rtip) + +# Get some transform stuff. +bpp = 1/(B/(2*pi)*omega) # 1/(B blade_passes/rev * 1 rev / (2*pi rad) * omega rad/s) +num_blade_pass = 1 +period_src = num_blade_pass*bpp +num_src_times = num_src_times_blade_pass * num_blade_pass +t0 = 0.0 +dt = period_src/num_src_times +src_times = t0 .+ (0:num_src_times-1).*dt + +# I don't see any discussion for what type of tip was used for the tip vortex noise. +# FlatTip with no CCBlade.jl tip correction or BPM-style tip correction seems to match the BARC predictions well. +# blade_tip = AcousticAnalogies.FlatTip(AcousticAnalogies.NoTipAlphaCorrection()) +# BPM.jl uses a different tip alpha correction which appears to require the blade aspect ratio, defined as the blade radius divided by the average chord. +cbar = sum(chord .* dradii) / (Rtip - Rhub) +aspect_ratio = Rtip/cbar +alpha0lift = 0.0 +blade_tip = AcousticAnalogies.FlatTip(BMTipAlphaCorrection(aspect_ratio), alpha0lift) + +# Getting the coordinate system consistent with BPM.jl is a bit tricky. +# Here's a bit of code from BPM.jl: +# +# # Calculate the trailing edge position relative to the hub +# xs = sin(beta)*d - cos(beta)*(c - c1) +# zs = cos(beta)*d + sin(beta)*(c - c1) +# +# OK, so that shows me that the blade is initially aligned with the z axis, rotating to the positive x direction. +# And I know the blades are rotating about the positive y axis. +# So that's the answer for the BPM.jl coordinate system: +# +# * freestream in the positive y axis direction. +# * first blade initially aligned with the positive z axis, rotating about the positive y axis. +# +# Now, what do I need to do with AcousticAnalogies to make that happen? +# I want the blades to be translating in the negative y direction, rotating about the positive y axis. +# I usually start with the blades rotating about either the positive or negative x axis, moving in the direction of the positive x axis. +# I think the answer is, +# +# * start out with the blades rotating about the negative x axis, moving in the direction of the positive x axis +# * rotate 90° about the negative z axis. +# After this, the blades will be moving in the negative y direction, rotating about the positive y axis, which is good. +# But I want the first blade to be aligned with the positive z axis, and stopping here would mean it's aligned with the positive x axis. +# * rotate 90° about the negative y axis. +# This will put the first blade in line with the positive z axis. + +# So, let's do what we said we need to do. +# Start with a rotation about the negative x axis. +positive_x_rotation = false +rot_trans = SteadyRotXTransformation(t0, omega*ifelse(positive_x_rotation, 1, -1), 0) + +# Then translate along the positive x axis. +y0_hub = @SVector [0.0, 0.0, 0.0] # m +v0_hub = @SVector [Vinf, 0.0, 0.0] +const_vel_trans = ConstantVelocityTransformation(t0, y0_hub, v0_hub) + +# Then a 90° rotation about the negative z axis. +trans_z90deg = SteadyRotZTransformation(0.0, 0.0, -0.5*pi) + +# Then a 90° rotation about the negative y axis. +trans_y90deg = SteadyRotYTransformation(0.0, 0.0, -0.5*pi) + +# Put them all together: +trans = compose.(src_times, Ref(trans_y90deg), + compose.(src_times, Ref(trans_z90deg), + compose.(src_times, Ref(const_vel_trans), Ref(rot_trans)))) + +# Use the M_c = 0.8*M that BPM.jl and the BPM report use. +U = @. 0.8*sqrt(Vinf^2 + (omega*radii)^2) + +# Azimuthal offset for each blade. +θs = (0:(B-1)) .* (2*pi/B) .* ifelse(positive_x_rotation, 1, -1) + +bls = [ifelse(tf, + AcousticAnalogies.TrippedN0012BoundaryLayer(), + AcousticAnalogies.UntrippedN0012BoundaryLayer()) for tf in tripped_flags] + +# Need to do the LBLVS with the untripped boundary layer to match what BPM.jl is doing. +bl_lblvs = AcousticAnalogies.UntrippedN0012BoundaryLayer() + +r_obs = 2.27 # meters +theta_obs = -35*pi/180 +# So, the docstring for BPM.jl says that `V` argument is the wind velocity in the y direction. +# So I guess we should assume that the blades are rotating about the y axis. +# And if the freestream velocity is in the positive y axis, then, from the perspective of the fluid, the blades are translating in the negative y direction. +# And I want the observer to be downstream/behind the blades, so that would mean they would have a positive y position. +# So I want to rotate the observer around the positive x axis, so I'm going to switch the sign on `theta_obs`. +t0_obs = 0.0 +x0_obs = [0.0, r_obs*sin(-theta_obs), r_obs*cos(-theta_obs)] +# The observer is moving in the same direction as the blades, which is the negative y axis. +v_obs = @SVector [0.0, -Vinf, 0.0] +obs = AcousticAnalogies.ConstVelocityAcousticObserver(t0_obs, x0_obs, v_obs) + +# Reshape the inputs to the source element constructors so that everything will line up with (num_times, num_radial, num_blades). +θs_rs = reshape(θs, 1, 1, :) +radii_rs = reshape(radii, 1, :, 1) +dradii_rs = reshape(dradii, 1, :, 1) +chord_rs = reshape(chord, 1, :, 1) +twist_rs = reshape(twist, 1, :, 1) +hs_rs = reshape(hs, 1, :, 1) +Psis_rs = reshape(Psis, 1, :, 1) +Us_rs = reshape(U, 1, :, 1) +alphas_rs = reshape(alpha, 1, :, 1) +bls_rs = reshape(bls, 1, :, 1) +# bls_untripped_rs = reshape(bls_lblvs, 1, :, 1) + +# Separate things into tip and no-tip. +radii_rs_no_tip = @view radii_rs[:, begin:end-1, :] +dradii_rs_no_tip = @view dradii_rs[:, begin:end-1, :] +chord_rs_no_tip = @view chord_rs[:, begin:end-1, :] +twist_rs_no_tip = @view twist_rs[:, begin:end-1, :] +hs_rs_no_tip = @view hs_rs[:, begin:end-1, :] +Psis_rs_no_tip = @view Psis_rs[:, begin:end-1, :] +Us_rs_no_tip = @view Us_rs[:, begin:end-1, :] +alphas_rs_no_tip = @view alphas_rs[:, begin:end-1, :] +bls_rs_no_tip = @view bls_rs[:, begin:end-1, :] + +radii_rs_with_tip = @view radii_rs[:, end:end, :] +dradii_rs_with_tip = @view dradii_rs[:, end:end, :] +chord_rs_with_tip = @view chord_rs[:, end:end, :] +twist_rs_with_tip = @view twist_rs[:, end:end, :] +hs_rs_with_tip = @view hs_rs[:, end:end, :] +Psis_rs_with_tip = @view Psis_rs[:, end:end, :] +Us_rs_with_tip = @view Us_rs[:, end:end, :] +alphas_rs_with_tip = @view alphas_rs[:, end:end, :] +bls_rs_with_tip = @view bls_rs[:, end:end, :] + +direct = AcousticAnalogies.BPMDirectivity +use_UInduction = false +use_Doppler = false +mach_correction = AcousticAnalogies.NoMachCorrection +ses_no_tip = CombinedNoTipBroadbandSourceElement{direct,use_UInduction,mach_correction,use_Doppler}.(asound, nu, radii_rs_no_tip, θs_rs, dradii_rs_no_tip, chord_rs_no_tip, twist_rs_no_tip, hs_rs_no_tip, Psis_rs_no_tip, Us_rs_no_tip, alphas_rs_no_tip, src_times, dt, bls_rs_no_tip, positive_x_rotation) .|> trans + +ses_with_tip = CombinedWithTipBroadbandSourceElement{direct,use_UInduction,mach_correction,use_Doppler}.(asound, nu, radii_rs_with_tip, θs_rs, dradii_rs_with_tip, chord_rs_with_tip, twist_rs_with_tip, hs_rs_with_tip, Psis_rs_with_tip, Us_rs_with_tip, alphas_rs_with_tip, src_times, dt, bls_rs_with_tip, Ref(blade_tip), positive_x_rotation) .|> trans + +# Now we can construct the lblvs source elements. +lblvs_ses = AcousticAnalogies.LBLVSSourceElement{direct,use_UInduction,use_Doppler}.(asound, nu, radii_rs, θs_rs, dradii_rs, chord_rs, twist_rs, Us_rs, alphas_rs, src_times, dt, Ref(bl_lblvs), positive_x_rotation) .|> trans + +# Write out the source elements. +# pvd_no_tip = AcousticAnalogies.to_paraview_collection(joinpath(@__DIR__, "figure24b-no_tip"), ses_no_tip) +# pvd_with_tip = AcousticAnalogies.to_paraview_collection(joinpath(@__DIR__, "figure24b-with_tip"), ses_with_tip) +# pvd_all = AcousticAnalogies.to_paraview_collection(joinpath(@__DIR__, "figure24b-all"), (ses_no_tip, ses_with_tip, lblvs_ses); observers=(obs,)) + +# Put the source elements together: +ses = cat(ses_no_tip, ses_with_tip; dims=2) + +# Define the frequencies we'd like to evaluate. +# BPM.jl uses the approximate 1/3rd-octave bands. +freqs_obs = AcousticMetrics.ApproximateThirdOctaveCenterBands(100.0, 40000.0) +freqs_src = freqs_obs + +# Now do the noise prediction. +bpm_outs = AcousticAnalogies.noise.(ses, Ref(obs), Ref(freqs_src)) +pbs_lblvss = AcousticAnalogies.noise.(lblvs_ses, Ref(obs), Ref(freqs_src)) + +# Separate out each source. +pbs_tblte_ps = AcousticAnalogies.pbs_pressure.(bpm_outs) +pbs_tblte_ss = AcousticAnalogies.pbs_suction.(bpm_outs) +pbs_tblte_alphas = AcousticAnalogies.pbs_alpha.(bpm_outs) +pbs_tebs = AcousticAnalogies.pbs_teb.(bpm_outs) +pbs_tips = AcousticAnalogies.pbs_tip.(bpm_outs[:, end:end, :]) + +# Combine each noise prediction. +time_axis = 1 +pbs_pressure = AcousticMetrics.combine(pbs_tblte_ps, freqs_obs, time_axis) +pbs_suction = AcousticMetrics.combine(pbs_tblte_ss, freqs_obs, time_axis) +pbs_alpha = AcousticMetrics.combine(pbs_tblte_alphas, freqs_obs, time_axis) +pbs_teb = AcousticMetrics.combine(pbs_tebs, freqs_obs, time_axis) +pbs_tip = AcousticMetrics.combine(pbs_tips, freqs_obs, time_axis) +pbs_lblvs = AcousticMetrics.combine(pbs_lblvss, freqs_obs, time_axis) + +# Now I need to account for the fact that Figure 23c is actually comparing to narrowband experimental data with a frequency spacing of 20 Hz. +# So, to do that, I need to multiply the mean-squared pressure by Δf_nb/Δf_pbs, where `Δf_nb` is the 20 Hz narrowband and `Δf_pbs` is the bandwidth of each 1/3-octave proportional band. +# (Dividing the MSP by Δf_pbs aka the 1/3 octave spacing is like getting a power-spectral density, then multiplying by the narrowband spacing Δf_nb gives us the MSP associated with the narrowband.) +# I think the paper describes that, right? +# Right, here's something: +# +# > The current prediction method is limited to one-third octave bands, but it is compared to the narrowband experiment with Δf = 20 Hz. +# > This is done by dividing the energy from the one-third octave bands by the number of bands in Δf = 20 Hz. +# +# So, `Δf_pbs/Δf_nb` would represent the number of `Δf_nb`-width bands that could fit in a proportional band of bin width `Δf_pbs`. +# And then I'm dividing by that. +# So that seems like the right thing. +# So, first thing is to get the proportional band spacing. +freqs_l = AcousticMetrics.lower_bands(freqs_obs) +freqs_u = AcousticMetrics.upper_bands(freqs_obs) +df_pbs = freqs_u .- freqs_l +# Also need the experimental narrowband spacing. +df_nb = 20.0 +# Now multiply each by that. +nb_pressure = pbs_pressure .* df_nb ./ df_pbs +nb_suction = pbs_suction .* df_nb ./ df_pbs +nb_alpha = pbs_alpha .* df_nb ./ df_pbs +nb_teb = pbs_teb .* df_nb ./ df_pbs +nb_tip = pbs_tip .* df_nb ./ df_pbs +nb_lblvs = pbs_lblvs .* df_nb ./ df_pbs + +# Now I want the SPL, which should just be this: +pref = 20e-6 +spl_pressure = 10 .* log10.(nb_pressure./(pref^2)) +spl_suction = 10 .* log10.(nb_suction./(pref^2)) +spl_alpha = 10 .* log10.(nb_alpha./(pref^2)) +spl_teb = 10 .* log10.(nb_teb./(pref^2)) +spl_tip = 10 .* log10.(nb_tip./(pref^2)) +spl_lblvs = 10 .* log10.(nb_lblvs./(pref^2)) + +# Read in the BPM.jl data. +freq_bpmjl = data["freqs"] +spl_pressure_bpmjl = data["spl_nb_pressure"] +spl_suction_bpmjl = data["spl_nb_suction"] +spl_separation_bpmjl = data["spl_nb_separation"] +spl_lblvs_bpmjl = data["spl_nb_lblvs"] +spl_blunt_bpmjl = data["spl_nb_blunt"] +spl_tip_bpmjl = data["spl_nb_tip"] + +# The frequencies in the CSV file should match the observer frequencies we're using. +@test all(freqs_obs .≈ freq_bpmjl) + +# Only look at the SPLs that are actually significant, i.e. greater than 0 dB. +@test maximum(abs.(spl_pressure[spl_pressure_bpmjl .> 0] .- spl_pressure_bpmjl[spl_pressure_bpmjl .> 0])) < 0.496 +@test maximum(abs.(spl_suction[spl_suction_bpmjl .> 0] .- spl_suction_bpmjl[spl_suction_bpmjl .> 0])) < 0.476 +@test maximum(abs.(spl_alpha[spl_separation_bpmjl .> 0] .- spl_separation_bpmjl[spl_separation_bpmjl .> 0])) < 0.479 +@test maximum(abs.(spl_teb[spl_blunt_bpmjl .> 0] .- spl_blunt_bpmjl[spl_blunt_bpmjl .> 0])) < 0.489 +@test maximum(abs.(spl_tip[spl_tip_bpmjl .> 0] .- spl_tip_bpmjl[spl_tip_bpmjl .> 0])) < 0.874 +@test maximum(abs.(spl_lblvs[spl_lblvs_bpmjl .> 0] .- spl_lblvs_bpmjl[spl_lblvs_bpmjl .> 0])) < 0.499 diff --git a/test/runtests.jl b/test/runtests.jl index 27737ff9..adea76f7 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -3,11 +3,15 @@ module AcousticAnalogiesTests include("adv_time_tests.jl") include("combine_tests.jl") include("f1a_tests.jl") -include("ccblade_helper_tests.jl") +include("compact_f1a_constructor_tests.jl") include("anopp2_comparison.jl") include("forwarddiff_test.jl") +include("doppler_tests.jl") +include("boundary_layer_tests.jl") +include("bpm_shape_function_tests.jl") +include("broadband_source_element_tests.jl") include("writevtk_tests.jl") include("openfast_helper_tests.jl") -# include("iea3p4.jl") +include("bpm_itr_tests.jl") end # module diff --git a/test/writevtk/cf1a_mb_with_observers-00000001.vtm b/test/writevtk/cf1a_mb_with_observers-00000001.vtm new file mode 100755 index 00000000..8644bf54 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000001.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000002.vtm b/test/writevtk/cf1a_mb_with_observers-00000002.vtm new file mode 100755 index 00000000..fe917eff --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000002.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000003.vtm b/test/writevtk/cf1a_mb_with_observers-00000003.vtm new file mode 100755 index 00000000..10829502 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000003.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000004.vtm b/test/writevtk/cf1a_mb_with_observers-00000004.vtm new file mode 100755 index 00000000..c61738db --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000004.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000005.vtm b/test/writevtk/cf1a_mb_with_observers-00000005.vtm new file mode 100755 index 00000000..96bf3fda --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000005.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000006.vtm b/test/writevtk/cf1a_mb_with_observers-00000006.vtm new file mode 100755 index 00000000..a0a00ac8 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000006.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000007.vtm b/test/writevtk/cf1a_mb_with_observers-00000007.vtm new file mode 100755 index 00000000..f7badc45 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000007.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000008.vtm b/test/writevtk/cf1a_mb_with_observers-00000008.vtm new file mode 100755 index 00000000..12335f6f --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000008.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000009.vtm b/test/writevtk/cf1a_mb_with_observers-00000009.vtm new file mode 100755 index 00000000..ce92a14a --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000009.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000010.vtm b/test/writevtk/cf1a_mb_with_observers-00000010.vtm new file mode 100755 index 00000000..ffa344d1 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000010.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000011.vtm b/test/writevtk/cf1a_mb_with_observers-00000011.vtm new file mode 100755 index 00000000..f8962bfb --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000011.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000012.vtm b/test/writevtk/cf1a_mb_with_observers-00000012.vtm new file mode 100755 index 00000000..1a351912 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000012.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000013.vtm b/test/writevtk/cf1a_mb_with_observers-00000013.vtm new file mode 100755 index 00000000..0dc4ed0a --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000013.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000014.vtm b/test/writevtk/cf1a_mb_with_observers-00000014.vtm new file mode 100755 index 00000000..eb29547e --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000014.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000015.vtm b/test/writevtk/cf1a_mb_with_observers-00000015.vtm new file mode 100755 index 00000000..b9fb75ea --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000015.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000016.vtm b/test/writevtk/cf1a_mb_with_observers-00000016.vtm new file mode 100755 index 00000000..74dc7a34 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000016.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000017.vtm b/test/writevtk/cf1a_mb_with_observers-00000017.vtm new file mode 100755 index 00000000..2543c7a7 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000017.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000018.vtm b/test/writevtk/cf1a_mb_with_observers-00000018.vtm new file mode 100755 index 00000000..e46dbfc5 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000018.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000019.vtm b/test/writevtk/cf1a_mb_with_observers-00000019.vtm new file mode 100755 index 00000000..3a3ae09d --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000019.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000020.vtm b/test/writevtk/cf1a_mb_with_observers-00000020.vtm new file mode 100755 index 00000000..7a37b341 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000020.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000021.vtm b/test/writevtk/cf1a_mb_with_observers-00000021.vtm new file mode 100755 index 00000000..937758d1 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000021.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000022.vtm b/test/writevtk/cf1a_mb_with_observers-00000022.vtm new file mode 100755 index 00000000..fde9ee85 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000022.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000023.vtm b/test/writevtk/cf1a_mb_with_observers-00000023.vtm new file mode 100755 index 00000000..5c96d458 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000023.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000024.vtm b/test/writevtk/cf1a_mb_with_observers-00000024.vtm new file mode 100755 index 00000000..fa228894 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000024.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000025.vtm b/test/writevtk/cf1a_mb_with_observers-00000025.vtm new file mode 100755 index 00000000..3ecc06ad --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000025.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000026.vtm b/test/writevtk/cf1a_mb_with_observers-00000026.vtm new file mode 100755 index 00000000..a204c771 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000026.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000027.vtm b/test/writevtk/cf1a_mb_with_observers-00000027.vtm new file mode 100755 index 00000000..5e8bc6d2 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000027.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000028.vtm b/test/writevtk/cf1a_mb_with_observers-00000028.vtm new file mode 100755 index 00000000..b91961b1 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000028.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000029.vtm b/test/writevtk/cf1a_mb_with_observers-00000029.vtm new file mode 100755 index 00000000..f3135966 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000029.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000030.vtm b/test/writevtk/cf1a_mb_with_observers-00000030.vtm new file mode 100755 index 00000000..50fcaaf2 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000030.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000031.vtm b/test/writevtk/cf1a_mb_with_observers-00000031.vtm new file mode 100755 index 00000000..6781773e --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000031.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000032.vtm b/test/writevtk/cf1a_mb_with_observers-00000032.vtm new file mode 100755 index 00000000..aad15a02 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000032.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000033.vtm b/test/writevtk/cf1a_mb_with_observers-00000033.vtm new file mode 100755 index 00000000..7e761f87 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000033.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000034.vtm b/test/writevtk/cf1a_mb_with_observers-00000034.vtm new file mode 100755 index 00000000..ee77b09b --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000034.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000035.vtm b/test/writevtk/cf1a_mb_with_observers-00000035.vtm new file mode 100755 index 00000000..a61152e6 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000035.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000036.vtm b/test/writevtk/cf1a_mb_with_observers-00000036.vtm new file mode 100755 index 00000000..b6724499 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000036.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000037.vtm b/test/writevtk/cf1a_mb_with_observers-00000037.vtm new file mode 100755 index 00000000..b919d168 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000037.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000038.vtm b/test/writevtk/cf1a_mb_with_observers-00000038.vtm new file mode 100755 index 00000000..e9a63246 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000038.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000039.vtm b/test/writevtk/cf1a_mb_with_observers-00000039.vtm new file mode 100755 index 00000000..8da72d8f --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000039.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000040.vtm b/test/writevtk/cf1a_mb_with_observers-00000040.vtm new file mode 100755 index 00000000..b83bbc6c --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000040.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000041.vtm b/test/writevtk/cf1a_mb_with_observers-00000041.vtm new file mode 100755 index 00000000..aac3f738 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000041.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000042.vtm b/test/writevtk/cf1a_mb_with_observers-00000042.vtm new file mode 100755 index 00000000..62b566f9 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000042.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000043.vtm b/test/writevtk/cf1a_mb_with_observers-00000043.vtm new file mode 100755 index 00000000..a5faea33 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000043.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000044.vtm b/test/writevtk/cf1a_mb_with_observers-00000044.vtm new file mode 100755 index 00000000..72d6bb9e --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000044.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000045.vtm b/test/writevtk/cf1a_mb_with_observers-00000045.vtm new file mode 100755 index 00000000..b8f57366 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000045.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000046.vtm b/test/writevtk/cf1a_mb_with_observers-00000046.vtm new file mode 100755 index 00000000..715d9d5e --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000046.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000047.vtm b/test/writevtk/cf1a_mb_with_observers-00000047.vtm new file mode 100755 index 00000000..b53a3df5 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000047.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000048.vtm b/test/writevtk/cf1a_mb_with_observers-00000048.vtm new file mode 100755 index 00000000..58776900 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000048.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000049.vtm b/test/writevtk/cf1a_mb_with_observers-00000049.vtm new file mode 100755 index 00000000..f5602dd8 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000049.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000050.vtm b/test/writevtk/cf1a_mb_with_observers-00000050.vtm new file mode 100755 index 00000000..5778542e --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000050.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000051.vtm b/test/writevtk/cf1a_mb_with_observers-00000051.vtm new file mode 100755 index 00000000..21113068 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000051.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000052.vtm b/test/writevtk/cf1a_mb_with_observers-00000052.vtm new file mode 100755 index 00000000..681e1f6a --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000052.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000053.vtm b/test/writevtk/cf1a_mb_with_observers-00000053.vtm new file mode 100755 index 00000000..b8ba5fb1 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000053.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000054.vtm b/test/writevtk/cf1a_mb_with_observers-00000054.vtm new file mode 100755 index 00000000..98ce4231 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000054.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000055.vtm b/test/writevtk/cf1a_mb_with_observers-00000055.vtm new file mode 100755 index 00000000..f4b92e97 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000055.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000056.vtm b/test/writevtk/cf1a_mb_with_observers-00000056.vtm new file mode 100755 index 00000000..5ae65a6d --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000056.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000057.vtm b/test/writevtk/cf1a_mb_with_observers-00000057.vtm new file mode 100755 index 00000000..9ab96a34 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000057.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000058.vtm b/test/writevtk/cf1a_mb_with_observers-00000058.vtm new file mode 100755 index 00000000..4a670559 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000058.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000059.vtm b/test/writevtk/cf1a_mb_with_observers-00000059.vtm new file mode 100755 index 00000000..fa11fd70 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000059.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000060.vtm b/test/writevtk/cf1a_mb_with_observers-00000060.vtm new file mode 100755 index 00000000..1ca1fbbb --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000060.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000061.vtm b/test/writevtk/cf1a_mb_with_observers-00000061.vtm new file mode 100755 index 00000000..d35cf81d --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000061.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000062.vtm b/test/writevtk/cf1a_mb_with_observers-00000062.vtm new file mode 100755 index 00000000..2425a0c0 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000062.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000063.vtm b/test/writevtk/cf1a_mb_with_observers-00000063.vtm new file mode 100755 index 00000000..9160e1ad --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000063.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-00000064.vtm b/test/writevtk/cf1a_mb_with_observers-00000064.vtm new file mode 100755 index 00000000..09c69914 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers-00000064.vtm @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000001.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000001.vtp new file mode 100644 index 00000000..1f52dd6d Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000001.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000002.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000002.vtp new file mode 100644 index 00000000..1eac8045 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000002.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000003.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000003.vtp new file mode 100644 index 00000000..ce277c96 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000003.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000004.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000004.vtp new file mode 100644 index 00000000..3aa16eae Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000004.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000005.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000005.vtp new file mode 100644 index 00000000..2530890c Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000005.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000006.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000006.vtp new file mode 100644 index 00000000..89958e5b Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000006.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000007.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000007.vtp new file mode 100644 index 00000000..4f259f3f Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000007.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000008.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000008.vtp new file mode 100644 index 00000000..a2cf5af5 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000008.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000009.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000009.vtp new file mode 100644 index 00000000..a6c22f19 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000009.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000010.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000010.vtp new file mode 100644 index 00000000..d087924a Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000010.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000011.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000011.vtp new file mode 100644 index 00000000..6539fdc0 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000011.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000012.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000012.vtp new file mode 100644 index 00000000..84152a2b Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000012.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000013.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000013.vtp new file mode 100644 index 00000000..bc332189 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000013.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000014.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000014.vtp new file mode 100644 index 00000000..050b7833 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000014.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000015.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000015.vtp new file mode 100644 index 00000000..390bc406 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000015.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000016.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000016.vtp new file mode 100644 index 00000000..c6e31536 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000016.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000017.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000017.vtp new file mode 100644 index 00000000..b40b3979 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000017.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000018.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000018.vtp new file mode 100644 index 00000000..c659bdd3 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000018.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000019.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000019.vtp new file mode 100644 index 00000000..50a69691 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000019.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000020.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000020.vtp new file mode 100644 index 00000000..68225f50 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000020.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000021.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000021.vtp new file mode 100644 index 00000000..9e38bbdc Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000021.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000022.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000022.vtp new file mode 100644 index 00000000..0124cff0 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000022.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000023.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000023.vtp new file mode 100644 index 00000000..87d9b0bb Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000023.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000024.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000024.vtp new file mode 100644 index 00000000..c5bd4d46 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000024.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000025.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000025.vtp new file mode 100644 index 00000000..016db759 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000025.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000026.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000026.vtp new file mode 100644 index 00000000..9568a617 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000026.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000027.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000027.vtp new file mode 100644 index 00000000..ca158ba4 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000027.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000028.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000028.vtp new file mode 100644 index 00000000..8cea531f Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000028.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000029.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000029.vtp new file mode 100644 index 00000000..228a1921 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000029.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000030.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000030.vtp new file mode 100644 index 00000000..4ab4ef5c Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000030.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000031.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000031.vtp new file mode 100644 index 00000000..1f0b2182 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000031.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000032.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000032.vtp new file mode 100644 index 00000000..30858c1e Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000032.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000033.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000033.vtp new file mode 100644 index 00000000..16d2316e Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000033.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000034.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000034.vtp new file mode 100644 index 00000000..4495400d Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000034.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000035.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000035.vtp new file mode 100644 index 00000000..4d9679f8 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000035.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000036.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000036.vtp new file mode 100644 index 00000000..3b7e2ef0 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000036.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000037.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000037.vtp new file mode 100644 index 00000000..094f9e2c Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000037.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000038.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000038.vtp new file mode 100644 index 00000000..5fe9dcfc Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000038.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000039.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000039.vtp new file mode 100644 index 00000000..522dba0b Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000039.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000040.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000040.vtp new file mode 100644 index 00000000..58a6c870 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000040.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000041.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000041.vtp new file mode 100644 index 00000000..2d7688ce Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000041.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000042.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000042.vtp new file mode 100644 index 00000000..d615d6a2 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000042.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000043.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000043.vtp new file mode 100644 index 00000000..e1269b05 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000043.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000044.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000044.vtp new file mode 100644 index 00000000..c60c7545 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000044.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000045.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000045.vtp new file mode 100644 index 00000000..402e1d64 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000045.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000046.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000046.vtp new file mode 100644 index 00000000..6a2cb4c2 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000046.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000047.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000047.vtp new file mode 100644 index 00000000..836c5122 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000047.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000048.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000048.vtp new file mode 100644 index 00000000..6f432299 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000048.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000049.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000049.vtp new file mode 100644 index 00000000..932969cc Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000049.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000050.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000050.vtp new file mode 100644 index 00000000..1e310052 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000050.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000051.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000051.vtp new file mode 100644 index 00000000..53247057 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000051.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000052.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000052.vtp new file mode 100644 index 00000000..b90f461b Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000052.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000053.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000053.vtp new file mode 100644 index 00000000..46c97f1b Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000053.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000054.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000054.vtp new file mode 100644 index 00000000..1b115d03 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000054.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000055.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000055.vtp new file mode 100644 index 00000000..3cc5cd8f Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000055.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000056.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000056.vtp new file mode 100644 index 00000000..63198664 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000056.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000057.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000057.vtp new file mode 100644 index 00000000..7c7b0736 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000057.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000058.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000058.vtp new file mode 100644 index 00000000..e178acc5 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000058.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000059.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000059.vtp new file mode 100644 index 00000000..1bae7bcd Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000059.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000060.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000060.vtp new file mode 100644 index 00000000..ccc8faca Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000060.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000061.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000061.vtp new file mode 100644 index 00000000..c8cb83e4 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000061.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000062.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000062.vtp new file mode 100644 index 00000000..0b229a3c Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000062.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000063.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000063.vtp new file mode 100644 index 00000000..ed8c2ec4 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000063.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block1-00000064.vtp b/test/writevtk/cf1a_mb_with_observers-block1-00000064.vtp new file mode 100644 index 00000000..fd314a45 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block1-00000064.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000001.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000001.vtp new file mode 100644 index 00000000..15298be8 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000001.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000002.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000002.vtp new file mode 100644 index 00000000..888acbdb Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000002.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000003.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000003.vtp new file mode 100644 index 00000000..119b67ae Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000003.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000004.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000004.vtp new file mode 100644 index 00000000..8cbcee60 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000004.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000005.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000005.vtp new file mode 100644 index 00000000..4bcd3651 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000005.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000006.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000006.vtp new file mode 100644 index 00000000..03df0b82 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000006.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000007.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000007.vtp new file mode 100644 index 00000000..fdd46764 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000007.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000008.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000008.vtp new file mode 100644 index 00000000..06f0044b Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000008.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000009.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000009.vtp new file mode 100644 index 00000000..785a2a99 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000009.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000010.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000010.vtp new file mode 100644 index 00000000..dd1fcfb4 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000010.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000011.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000011.vtp new file mode 100644 index 00000000..050f05a5 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000011.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000012.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000012.vtp new file mode 100644 index 00000000..f329306c Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000012.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000013.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000013.vtp new file mode 100644 index 00000000..54ff0349 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000013.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000014.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000014.vtp new file mode 100644 index 00000000..e60aea84 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000014.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000015.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000015.vtp new file mode 100644 index 00000000..5523bd5f Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000015.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000016.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000016.vtp new file mode 100644 index 00000000..e19b01b7 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000016.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000017.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000017.vtp new file mode 100644 index 00000000..db0ffdc9 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000017.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000018.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000018.vtp new file mode 100644 index 00000000..f7b074b1 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000018.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000019.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000019.vtp new file mode 100644 index 00000000..3854e499 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000019.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000020.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000020.vtp new file mode 100644 index 00000000..31cbbc42 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000020.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000021.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000021.vtp new file mode 100644 index 00000000..2dcc4315 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000021.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000022.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000022.vtp new file mode 100644 index 00000000..b6afa5c3 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000022.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000023.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000023.vtp new file mode 100644 index 00000000..3b3076cf Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000023.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000024.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000024.vtp new file mode 100644 index 00000000..a355d9c9 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000024.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000025.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000025.vtp new file mode 100644 index 00000000..1a7d59cc Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000025.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000026.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000026.vtp new file mode 100644 index 00000000..ab350a94 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000026.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000027.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000027.vtp new file mode 100644 index 00000000..bd08f0fb Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000027.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000028.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000028.vtp new file mode 100644 index 00000000..579dfd04 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000028.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000029.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000029.vtp new file mode 100644 index 00000000..4eab0b4e Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000029.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000030.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000030.vtp new file mode 100644 index 00000000..919a8c1f Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000030.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000031.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000031.vtp new file mode 100644 index 00000000..500b91fe Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000031.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000032.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000032.vtp new file mode 100644 index 00000000..7045cb20 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000032.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000033.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000033.vtp new file mode 100644 index 00000000..ee8bc8bb Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000033.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000034.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000034.vtp new file mode 100644 index 00000000..9d7c55bc Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000034.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000035.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000035.vtp new file mode 100644 index 00000000..b32e97dd Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000035.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000036.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000036.vtp new file mode 100644 index 00000000..c903152c Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000036.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000037.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000037.vtp new file mode 100644 index 00000000..8d01879f Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000037.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000038.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000038.vtp new file mode 100644 index 00000000..8a51fed3 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000038.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000039.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000039.vtp new file mode 100644 index 00000000..d1167ac1 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000039.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000040.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000040.vtp new file mode 100644 index 00000000..e511f462 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000040.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000041.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000041.vtp new file mode 100644 index 00000000..f4c95bd6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000041.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000042.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000042.vtp new file mode 100644 index 00000000..3f9b2656 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000042.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000043.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000043.vtp new file mode 100644 index 00000000..d017d528 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000043.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000044.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000044.vtp new file mode 100644 index 00000000..6737983b Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000044.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000045.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000045.vtp new file mode 100644 index 00000000..c85417da Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000045.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000046.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000046.vtp new file mode 100644 index 00000000..2ef4b57d Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000046.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000047.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000047.vtp new file mode 100644 index 00000000..13031659 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000047.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000048.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000048.vtp new file mode 100644 index 00000000..f569a0d4 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000048.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000049.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000049.vtp new file mode 100644 index 00000000..093dd09e Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000049.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000050.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000050.vtp new file mode 100644 index 00000000..70e92dab Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000050.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000051.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000051.vtp new file mode 100644 index 00000000..fb04e6db Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000051.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000052.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000052.vtp new file mode 100644 index 00000000..2f27d90a Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000052.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000053.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000053.vtp new file mode 100644 index 00000000..12eb9eb6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000053.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000054.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000054.vtp new file mode 100644 index 00000000..92d2c5ae Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000054.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000055.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000055.vtp new file mode 100644 index 00000000..0ffe2bda Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000055.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000056.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000056.vtp new file mode 100644 index 00000000..eb2cb6ca Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000056.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000057.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000057.vtp new file mode 100644 index 00000000..20bedef5 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000057.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000058.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000058.vtp new file mode 100644 index 00000000..23244892 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000058.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000059.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000059.vtp new file mode 100644 index 00000000..8e15f9c9 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000059.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000060.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000060.vtp new file mode 100644 index 00000000..980b4206 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000060.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000061.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000061.vtp new file mode 100644 index 00000000..75012617 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000061.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000062.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000062.vtp new file mode 100644 index 00000000..b690c49d Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000062.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000063.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000063.vtp new file mode 100644 index 00000000..10faea9c Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000063.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-block2-00000064.vtp b/test/writevtk/cf1a_mb_with_observers-block2-00000064.vtp new file mode 100644 index 00000000..e628fc4b Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-block2-00000064.vtp differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000001.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000001.vtu new file mode 100644 index 00000000..e83120f4 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000001.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000002.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000002.vtu new file mode 100644 index 00000000..e41b83ad Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000002.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000003.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000003.vtu new file mode 100644 index 00000000..413080f3 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000003.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000004.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000004.vtu new file mode 100644 index 00000000..12732e78 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000004.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000005.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000005.vtu new file mode 100644 index 00000000..9cffa5ca Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000005.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000006.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000006.vtu new file mode 100644 index 00000000..7d2b8ecf Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000006.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000007.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000007.vtu new file mode 100644 index 00000000..b15d823e Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000007.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000008.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000008.vtu new file mode 100644 index 00000000..49511de4 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000008.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000009.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000009.vtu new file mode 100644 index 00000000..bb549826 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000009.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000010.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000010.vtu new file mode 100644 index 00000000..3793b11e Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000010.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000011.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000011.vtu new file mode 100644 index 00000000..94d0569a Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000011.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000012.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000012.vtu new file mode 100644 index 00000000..711f6831 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000012.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000013.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000013.vtu new file mode 100644 index 00000000..77f0514e Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000013.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000014.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000014.vtu new file mode 100644 index 00000000..7427b39c Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000014.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000015.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000015.vtu new file mode 100644 index 00000000..e8d82112 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000015.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000016.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000016.vtu new file mode 100644 index 00000000..4a633ebc Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000016.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000017.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000017.vtu new file mode 100644 index 00000000..e4ad5dff Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000017.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000018.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000018.vtu new file mode 100644 index 00000000..4e9c199a Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000018.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000019.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000019.vtu new file mode 100644 index 00000000..b00178cb Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000019.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000020.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000020.vtu new file mode 100644 index 00000000..9ba33416 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000020.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000021.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000021.vtu new file mode 100644 index 00000000..2201df5c Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000021.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000022.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000022.vtu new file mode 100644 index 00000000..0f2415af Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000022.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000023.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000023.vtu new file mode 100644 index 00000000..eb332277 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000023.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000024.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000024.vtu new file mode 100644 index 00000000..8b0454dc Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000024.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000025.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000025.vtu new file mode 100644 index 00000000..c4c0da29 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000025.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000026.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000026.vtu new file mode 100644 index 00000000..1877ba7b Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000026.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000027.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000027.vtu new file mode 100644 index 00000000..29bc7f70 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000027.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000028.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000028.vtu new file mode 100644 index 00000000..360780cf Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000028.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000029.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000029.vtu new file mode 100644 index 00000000..06b220d9 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000029.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000030.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000030.vtu new file mode 100644 index 00000000..00bb4831 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000030.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000031.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000031.vtu new file mode 100644 index 00000000..b1d64615 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000031.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000032.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000032.vtu new file mode 100644 index 00000000..6976b660 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000032.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000033.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000033.vtu new file mode 100644 index 00000000..8f1a0d96 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000033.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000034.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000034.vtu new file mode 100644 index 00000000..69498206 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000034.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000035.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000035.vtu new file mode 100644 index 00000000..da4a1449 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000035.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000036.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000036.vtu new file mode 100644 index 00000000..ce665493 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000036.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000037.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000037.vtu new file mode 100644 index 00000000..dee6fd94 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000037.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000038.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000038.vtu new file mode 100644 index 00000000..16bf99d9 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000038.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000039.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000039.vtu new file mode 100644 index 00000000..ae06646a Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000039.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000040.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000040.vtu new file mode 100644 index 00000000..7f7e5126 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000040.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000041.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000041.vtu new file mode 100644 index 00000000..75f85039 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000041.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000042.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000042.vtu new file mode 100644 index 00000000..b574397a Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000042.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000043.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000043.vtu new file mode 100644 index 00000000..c17c9963 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000043.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000044.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000044.vtu new file mode 100644 index 00000000..a165f4dc Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000044.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000045.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000045.vtu new file mode 100644 index 00000000..ad72dc53 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000045.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000046.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000046.vtu new file mode 100644 index 00000000..5e73a483 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000046.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000047.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000047.vtu new file mode 100644 index 00000000..8ca8c93f Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000047.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000048.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000048.vtu new file mode 100644 index 00000000..50c0e46c Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000048.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000049.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000049.vtu new file mode 100644 index 00000000..9d328364 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000049.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000050.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000050.vtu new file mode 100644 index 00000000..3203da4f Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000050.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000051.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000051.vtu new file mode 100644 index 00000000..fbf0499f Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000051.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000052.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000052.vtu new file mode 100644 index 00000000..2008c79e Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000052.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000053.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000053.vtu new file mode 100644 index 00000000..cbb6510a Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000053.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000054.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000054.vtu new file mode 100644 index 00000000..365570f3 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000054.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000055.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000055.vtu new file mode 100644 index 00000000..2734e26c Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000055.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000056.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000056.vtu new file mode 100644 index 00000000..f3b90ff5 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000056.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000057.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000057.vtu new file mode 100644 index 00000000..7fe3074b Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000057.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000058.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000058.vtu new file mode 100644 index 00000000..c47edfe0 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000058.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000059.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000059.vtu new file mode 100644 index 00000000..548971f3 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000059.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000060.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000060.vtu new file mode 100644 index 00000000..442cc301 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000060.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000061.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000061.vtu new file mode 100644 index 00000000..190d5f08 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000061.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000062.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000062.vtu new file mode 100644 index 00000000..aac59816 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000062.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000063.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000063.vtu new file mode 100644 index 00000000..51f0d9a5 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000063.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer1-00000064.vtu b/test/writevtk/cf1a_mb_with_observers-observer1-00000064.vtu new file mode 100644 index 00000000..3162b720 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer1-00000064.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000001.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000001.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000001.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000002.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000002.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000002.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000003.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000003.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000003.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000004.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000004.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000004.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000005.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000005.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000005.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000006.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000006.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000006.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000007.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000007.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000007.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000008.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000008.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000008.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000009.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000009.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000009.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000010.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000010.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000010.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000011.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000011.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000011.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000012.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000012.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000012.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000013.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000013.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000013.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000014.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000014.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000014.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000015.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000015.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000015.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000016.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000016.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000016.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000017.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000017.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000017.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000018.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000018.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000018.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000019.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000019.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000019.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000020.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000020.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000020.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000021.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000021.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000021.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000022.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000022.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000022.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000023.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000023.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000023.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000024.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000024.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000024.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000025.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000025.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000025.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000026.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000026.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000026.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000027.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000027.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000027.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000028.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000028.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000028.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000029.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000029.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000029.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000030.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000030.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000030.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000031.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000031.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000031.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000032.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000032.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000032.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000033.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000033.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000033.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000034.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000034.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000034.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000035.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000035.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000035.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000036.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000036.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000036.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000037.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000037.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000037.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000038.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000038.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000038.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000039.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000039.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000039.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000040.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000040.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000040.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000041.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000041.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000041.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000042.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000042.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000042.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000043.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000043.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000043.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000044.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000044.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000044.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000045.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000045.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000045.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000046.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000046.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000046.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000047.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000047.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000047.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000048.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000048.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000048.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000049.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000049.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000049.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000050.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000050.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000050.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000051.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000051.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000051.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000052.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000052.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000052.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000053.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000053.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000053.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000054.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000054.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000054.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000055.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000055.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000055.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000056.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000056.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000056.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000057.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000057.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000057.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000058.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000058.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000058.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000059.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000059.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000059.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000060.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000060.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000060.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000061.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000061.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000061.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000062.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000062.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000062.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000063.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000063.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000063.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers-observer2-00000064.vtu b/test/writevtk/cf1a_mb_with_observers-observer2-00000064.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_mb_with_observers-observer2-00000064.vtu differ diff --git a/test/writevtk/cf1a_mb_with_observers.pvd b/test/writevtk/cf1a_mb_with_observers.pvd new file mode 100755 index 00000000..c2f7f9b8 --- /dev/null +++ b/test/writevtk/cf1a_mb_with_observers.pvd @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000001.vtm b/test/writevtk/cf1a_with_observers-00000001.vtm new file mode 100755 index 00000000..24da1d1d --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000001.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000002.vtm b/test/writevtk/cf1a_with_observers-00000002.vtm new file mode 100755 index 00000000..9c32c143 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000002.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000003.vtm b/test/writevtk/cf1a_with_observers-00000003.vtm new file mode 100755 index 00000000..4d4fc897 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000003.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000004.vtm b/test/writevtk/cf1a_with_observers-00000004.vtm new file mode 100755 index 00000000..e2106f23 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000004.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000005.vtm b/test/writevtk/cf1a_with_observers-00000005.vtm new file mode 100755 index 00000000..31f4ae66 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000005.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000006.vtm b/test/writevtk/cf1a_with_observers-00000006.vtm new file mode 100755 index 00000000..a293dbd9 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000006.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000007.vtm b/test/writevtk/cf1a_with_observers-00000007.vtm new file mode 100755 index 00000000..ead1eb61 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000007.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000008.vtm b/test/writevtk/cf1a_with_observers-00000008.vtm new file mode 100755 index 00000000..c6ee0328 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000008.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000009.vtm b/test/writevtk/cf1a_with_observers-00000009.vtm new file mode 100755 index 00000000..32aa89ef --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000009.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000010.vtm b/test/writevtk/cf1a_with_observers-00000010.vtm new file mode 100755 index 00000000..7bcb3b84 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000010.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000011.vtm b/test/writevtk/cf1a_with_observers-00000011.vtm new file mode 100755 index 00000000..5b12dc58 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000011.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000012.vtm b/test/writevtk/cf1a_with_observers-00000012.vtm new file mode 100755 index 00000000..2e8318ce --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000012.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000013.vtm b/test/writevtk/cf1a_with_observers-00000013.vtm new file mode 100755 index 00000000..13cec646 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000013.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000014.vtm b/test/writevtk/cf1a_with_observers-00000014.vtm new file mode 100755 index 00000000..1b852017 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000014.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000015.vtm b/test/writevtk/cf1a_with_observers-00000015.vtm new file mode 100755 index 00000000..fdd577fb --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000015.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000016.vtm b/test/writevtk/cf1a_with_observers-00000016.vtm new file mode 100755 index 00000000..2fa57c76 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000016.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000017.vtm b/test/writevtk/cf1a_with_observers-00000017.vtm new file mode 100755 index 00000000..5019301f --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000017.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000018.vtm b/test/writevtk/cf1a_with_observers-00000018.vtm new file mode 100755 index 00000000..090c845d --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000018.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000019.vtm b/test/writevtk/cf1a_with_observers-00000019.vtm new file mode 100755 index 00000000..c2aba527 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000019.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000020.vtm b/test/writevtk/cf1a_with_observers-00000020.vtm new file mode 100755 index 00000000..04a5b637 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000020.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000021.vtm b/test/writevtk/cf1a_with_observers-00000021.vtm new file mode 100755 index 00000000..0edb2c2b --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000021.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000022.vtm b/test/writevtk/cf1a_with_observers-00000022.vtm new file mode 100755 index 00000000..7c16e5f7 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000022.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000023.vtm b/test/writevtk/cf1a_with_observers-00000023.vtm new file mode 100755 index 00000000..4ae2d260 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000023.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000024.vtm b/test/writevtk/cf1a_with_observers-00000024.vtm new file mode 100755 index 00000000..2847599b --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000024.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000025.vtm b/test/writevtk/cf1a_with_observers-00000025.vtm new file mode 100755 index 00000000..6fc8f549 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000025.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000026.vtm b/test/writevtk/cf1a_with_observers-00000026.vtm new file mode 100755 index 00000000..9aa70865 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000026.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000027.vtm b/test/writevtk/cf1a_with_observers-00000027.vtm new file mode 100755 index 00000000..89621987 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000027.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000028.vtm b/test/writevtk/cf1a_with_observers-00000028.vtm new file mode 100755 index 00000000..f19ebe09 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000028.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000029.vtm b/test/writevtk/cf1a_with_observers-00000029.vtm new file mode 100755 index 00000000..56c8baca --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000029.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000030.vtm b/test/writevtk/cf1a_with_observers-00000030.vtm new file mode 100755 index 00000000..5b205c8c --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000030.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000031.vtm b/test/writevtk/cf1a_with_observers-00000031.vtm new file mode 100755 index 00000000..34f807e0 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000031.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000032.vtm b/test/writevtk/cf1a_with_observers-00000032.vtm new file mode 100755 index 00000000..560b2aab --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000032.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000033.vtm b/test/writevtk/cf1a_with_observers-00000033.vtm new file mode 100755 index 00000000..fbba9867 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000033.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000034.vtm b/test/writevtk/cf1a_with_observers-00000034.vtm new file mode 100755 index 00000000..b327fdc1 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000034.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000035.vtm b/test/writevtk/cf1a_with_observers-00000035.vtm new file mode 100755 index 00000000..612f63e8 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000035.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000036.vtm b/test/writevtk/cf1a_with_observers-00000036.vtm new file mode 100755 index 00000000..b5247898 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000036.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000037.vtm b/test/writevtk/cf1a_with_observers-00000037.vtm new file mode 100755 index 00000000..7681f721 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000037.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000038.vtm b/test/writevtk/cf1a_with_observers-00000038.vtm new file mode 100755 index 00000000..2a330258 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000038.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000039.vtm b/test/writevtk/cf1a_with_observers-00000039.vtm new file mode 100755 index 00000000..cdab9791 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000039.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000040.vtm b/test/writevtk/cf1a_with_observers-00000040.vtm new file mode 100755 index 00000000..b6e068ed --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000040.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000041.vtm b/test/writevtk/cf1a_with_observers-00000041.vtm new file mode 100755 index 00000000..9b07df78 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000041.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000042.vtm b/test/writevtk/cf1a_with_observers-00000042.vtm new file mode 100755 index 00000000..e8f6a0d1 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000042.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000043.vtm b/test/writevtk/cf1a_with_observers-00000043.vtm new file mode 100755 index 00000000..cb18b94f --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000043.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000044.vtm b/test/writevtk/cf1a_with_observers-00000044.vtm new file mode 100755 index 00000000..a90512d2 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000044.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000045.vtm b/test/writevtk/cf1a_with_observers-00000045.vtm new file mode 100755 index 00000000..04ca8ac9 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000045.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000046.vtm b/test/writevtk/cf1a_with_observers-00000046.vtm new file mode 100755 index 00000000..74f3063c --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000046.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000047.vtm b/test/writevtk/cf1a_with_observers-00000047.vtm new file mode 100755 index 00000000..3015afb3 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000047.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000048.vtm b/test/writevtk/cf1a_with_observers-00000048.vtm new file mode 100755 index 00000000..d6b67c55 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000048.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000049.vtm b/test/writevtk/cf1a_with_observers-00000049.vtm new file mode 100755 index 00000000..4b8da497 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000049.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000050.vtm b/test/writevtk/cf1a_with_observers-00000050.vtm new file mode 100755 index 00000000..bb359961 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000050.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000051.vtm b/test/writevtk/cf1a_with_observers-00000051.vtm new file mode 100755 index 00000000..816c80c2 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000051.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000052.vtm b/test/writevtk/cf1a_with_observers-00000052.vtm new file mode 100755 index 00000000..d4844582 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000052.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000053.vtm b/test/writevtk/cf1a_with_observers-00000053.vtm new file mode 100755 index 00000000..2ba0a108 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000053.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000054.vtm b/test/writevtk/cf1a_with_observers-00000054.vtm new file mode 100755 index 00000000..f759feb6 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000054.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000055.vtm b/test/writevtk/cf1a_with_observers-00000055.vtm new file mode 100755 index 00000000..d2e22dc2 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000055.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000056.vtm b/test/writevtk/cf1a_with_observers-00000056.vtm new file mode 100755 index 00000000..aefcd2d0 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000056.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000057.vtm b/test/writevtk/cf1a_with_observers-00000057.vtm new file mode 100755 index 00000000..4d63e00d --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000057.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000058.vtm b/test/writevtk/cf1a_with_observers-00000058.vtm new file mode 100755 index 00000000..e61050f2 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000058.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000059.vtm b/test/writevtk/cf1a_with_observers-00000059.vtm new file mode 100755 index 00000000..65915a39 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000059.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000060.vtm b/test/writevtk/cf1a_with_observers-00000060.vtm new file mode 100755 index 00000000..a3faf5c9 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000060.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000061.vtm b/test/writevtk/cf1a_with_observers-00000061.vtm new file mode 100755 index 00000000..32428db5 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000061.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000062.vtm b/test/writevtk/cf1a_with_observers-00000062.vtm new file mode 100755 index 00000000..c46895b6 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000062.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000063.vtm b/test/writevtk/cf1a_with_observers-00000063.vtm new file mode 100755 index 00000000..40d3e745 --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000063.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-00000064.vtm b/test/writevtk/cf1a_with_observers-00000064.vtm new file mode 100755 index 00000000..0404b03c --- /dev/null +++ b/test/writevtk/cf1a_with_observers-00000064.vtm @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/writevtk/cf1a_with_observers-block1-00000001.vtp b/test/writevtk/cf1a_with_observers-block1-00000001.vtp new file mode 100644 index 00000000..f5287cbd Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000001.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000002.vtp b/test/writevtk/cf1a_with_observers-block1-00000002.vtp new file mode 100644 index 00000000..d4f3d4c6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000002.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000003.vtp b/test/writevtk/cf1a_with_observers-block1-00000003.vtp new file mode 100644 index 00000000..4a3926b5 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000003.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000004.vtp b/test/writevtk/cf1a_with_observers-block1-00000004.vtp new file mode 100644 index 00000000..36363474 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000004.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000005.vtp b/test/writevtk/cf1a_with_observers-block1-00000005.vtp new file mode 100644 index 00000000..eb851843 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000005.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000006.vtp b/test/writevtk/cf1a_with_observers-block1-00000006.vtp new file mode 100644 index 00000000..6826097a Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000006.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000007.vtp b/test/writevtk/cf1a_with_observers-block1-00000007.vtp new file mode 100644 index 00000000..fe5b11d5 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000007.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000008.vtp b/test/writevtk/cf1a_with_observers-block1-00000008.vtp new file mode 100644 index 00000000..77d989b4 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000008.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000009.vtp b/test/writevtk/cf1a_with_observers-block1-00000009.vtp new file mode 100644 index 00000000..493d6902 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000009.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000010.vtp b/test/writevtk/cf1a_with_observers-block1-00000010.vtp new file mode 100644 index 00000000..10fd64f5 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000010.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000011.vtp b/test/writevtk/cf1a_with_observers-block1-00000011.vtp new file mode 100644 index 00000000..0a9d0d91 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000011.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000012.vtp b/test/writevtk/cf1a_with_observers-block1-00000012.vtp new file mode 100644 index 00000000..e8718c1d Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000012.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000013.vtp b/test/writevtk/cf1a_with_observers-block1-00000013.vtp new file mode 100644 index 00000000..a4ab9883 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000013.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000014.vtp b/test/writevtk/cf1a_with_observers-block1-00000014.vtp new file mode 100644 index 00000000..5df3fa2e Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000014.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000015.vtp b/test/writevtk/cf1a_with_observers-block1-00000015.vtp new file mode 100644 index 00000000..c24cc08a Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000015.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000016.vtp b/test/writevtk/cf1a_with_observers-block1-00000016.vtp new file mode 100644 index 00000000..764f6662 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000016.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000017.vtp b/test/writevtk/cf1a_with_observers-block1-00000017.vtp new file mode 100644 index 00000000..4e2ae6aa Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000017.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000018.vtp b/test/writevtk/cf1a_with_observers-block1-00000018.vtp new file mode 100644 index 00000000..eab87d85 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000018.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000019.vtp b/test/writevtk/cf1a_with_observers-block1-00000019.vtp new file mode 100644 index 00000000..b493167b Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000019.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000020.vtp b/test/writevtk/cf1a_with_observers-block1-00000020.vtp new file mode 100644 index 00000000..b8a9302b Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000020.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000021.vtp b/test/writevtk/cf1a_with_observers-block1-00000021.vtp new file mode 100644 index 00000000..ccf4c6f4 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000021.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000022.vtp b/test/writevtk/cf1a_with_observers-block1-00000022.vtp new file mode 100644 index 00000000..ca34660a Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000022.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000023.vtp b/test/writevtk/cf1a_with_observers-block1-00000023.vtp new file mode 100644 index 00000000..87f42f50 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000023.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000024.vtp b/test/writevtk/cf1a_with_observers-block1-00000024.vtp new file mode 100644 index 00000000..f8b704c2 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000024.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000025.vtp b/test/writevtk/cf1a_with_observers-block1-00000025.vtp new file mode 100644 index 00000000..4832c290 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000025.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000026.vtp b/test/writevtk/cf1a_with_observers-block1-00000026.vtp new file mode 100644 index 00000000..c9a7d7c2 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000026.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000027.vtp b/test/writevtk/cf1a_with_observers-block1-00000027.vtp new file mode 100644 index 00000000..a545dc54 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000027.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000028.vtp b/test/writevtk/cf1a_with_observers-block1-00000028.vtp new file mode 100644 index 00000000..d1adede2 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000028.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000029.vtp b/test/writevtk/cf1a_with_observers-block1-00000029.vtp new file mode 100644 index 00000000..6dcf9d9f Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000029.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000030.vtp b/test/writevtk/cf1a_with_observers-block1-00000030.vtp new file mode 100644 index 00000000..c8c7b79e Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000030.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000031.vtp b/test/writevtk/cf1a_with_observers-block1-00000031.vtp new file mode 100644 index 00000000..d7eb795c Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000031.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000032.vtp b/test/writevtk/cf1a_with_observers-block1-00000032.vtp new file mode 100644 index 00000000..e5b3dc2c Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000032.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000033.vtp b/test/writevtk/cf1a_with_observers-block1-00000033.vtp new file mode 100644 index 00000000..d688505f Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000033.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000034.vtp b/test/writevtk/cf1a_with_observers-block1-00000034.vtp new file mode 100644 index 00000000..b0bde10f Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000034.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000035.vtp b/test/writevtk/cf1a_with_observers-block1-00000035.vtp new file mode 100644 index 00000000..01c4c7ca Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000035.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000036.vtp b/test/writevtk/cf1a_with_observers-block1-00000036.vtp new file mode 100644 index 00000000..86e0660f Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000036.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000037.vtp b/test/writevtk/cf1a_with_observers-block1-00000037.vtp new file mode 100644 index 00000000..2b50ea23 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000037.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000038.vtp b/test/writevtk/cf1a_with_observers-block1-00000038.vtp new file mode 100644 index 00000000..4c7e0cb4 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000038.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000039.vtp b/test/writevtk/cf1a_with_observers-block1-00000039.vtp new file mode 100644 index 00000000..2841ddf8 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000039.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000040.vtp b/test/writevtk/cf1a_with_observers-block1-00000040.vtp new file mode 100644 index 00000000..c08e2540 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000040.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000041.vtp b/test/writevtk/cf1a_with_observers-block1-00000041.vtp new file mode 100644 index 00000000..57000438 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000041.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000042.vtp b/test/writevtk/cf1a_with_observers-block1-00000042.vtp new file mode 100644 index 00000000..545613f3 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000042.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000043.vtp b/test/writevtk/cf1a_with_observers-block1-00000043.vtp new file mode 100644 index 00000000..06e755be Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000043.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000044.vtp b/test/writevtk/cf1a_with_observers-block1-00000044.vtp new file mode 100644 index 00000000..244f19ea Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000044.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000045.vtp b/test/writevtk/cf1a_with_observers-block1-00000045.vtp new file mode 100644 index 00000000..7711ae0b Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000045.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000046.vtp b/test/writevtk/cf1a_with_observers-block1-00000046.vtp new file mode 100644 index 00000000..809a30a3 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000046.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000047.vtp b/test/writevtk/cf1a_with_observers-block1-00000047.vtp new file mode 100644 index 00000000..ccc0a464 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000047.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000048.vtp b/test/writevtk/cf1a_with_observers-block1-00000048.vtp new file mode 100644 index 00000000..c0434b2e Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000048.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000049.vtp b/test/writevtk/cf1a_with_observers-block1-00000049.vtp new file mode 100644 index 00000000..142ec2e2 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000049.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000050.vtp b/test/writevtk/cf1a_with_observers-block1-00000050.vtp new file mode 100644 index 00000000..8a5b9a34 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000050.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000051.vtp b/test/writevtk/cf1a_with_observers-block1-00000051.vtp new file mode 100644 index 00000000..e3a92568 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000051.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000052.vtp b/test/writevtk/cf1a_with_observers-block1-00000052.vtp new file mode 100644 index 00000000..f7537020 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000052.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000053.vtp b/test/writevtk/cf1a_with_observers-block1-00000053.vtp new file mode 100644 index 00000000..5433661a Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000053.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000054.vtp b/test/writevtk/cf1a_with_observers-block1-00000054.vtp new file mode 100644 index 00000000..f28c5656 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000054.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000055.vtp b/test/writevtk/cf1a_with_observers-block1-00000055.vtp new file mode 100644 index 00000000..ad9d8524 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000055.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000056.vtp b/test/writevtk/cf1a_with_observers-block1-00000056.vtp new file mode 100644 index 00000000..3bd50219 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000056.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000057.vtp b/test/writevtk/cf1a_with_observers-block1-00000057.vtp new file mode 100644 index 00000000..1d3dea3d Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000057.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000058.vtp b/test/writevtk/cf1a_with_observers-block1-00000058.vtp new file mode 100644 index 00000000..573cb4e1 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000058.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000059.vtp b/test/writevtk/cf1a_with_observers-block1-00000059.vtp new file mode 100644 index 00000000..4e229cf7 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000059.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000060.vtp b/test/writevtk/cf1a_with_observers-block1-00000060.vtp new file mode 100644 index 00000000..2c35eafe Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000060.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000061.vtp b/test/writevtk/cf1a_with_observers-block1-00000061.vtp new file mode 100644 index 00000000..46f664c7 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000061.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000062.vtp b/test/writevtk/cf1a_with_observers-block1-00000062.vtp new file mode 100644 index 00000000..96bf5e4b Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000062.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000063.vtp b/test/writevtk/cf1a_with_observers-block1-00000063.vtp new file mode 100644 index 00000000..0fc4a312 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000063.vtp differ diff --git a/test/writevtk/cf1a_with_observers-block1-00000064.vtp b/test/writevtk/cf1a_with_observers-block1-00000064.vtp new file mode 100644 index 00000000..5de26b9a Binary files /dev/null and b/test/writevtk/cf1a_with_observers-block1-00000064.vtp differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000001.vtu b/test/writevtk/cf1a_with_observers-observer1-00000001.vtu new file mode 100644 index 00000000..e83120f4 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000001.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000002.vtu b/test/writevtk/cf1a_with_observers-observer1-00000002.vtu new file mode 100644 index 00000000..e41b83ad Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000002.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000003.vtu b/test/writevtk/cf1a_with_observers-observer1-00000003.vtu new file mode 100644 index 00000000..413080f3 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000003.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000004.vtu b/test/writevtk/cf1a_with_observers-observer1-00000004.vtu new file mode 100644 index 00000000..12732e78 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000004.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000005.vtu b/test/writevtk/cf1a_with_observers-observer1-00000005.vtu new file mode 100644 index 00000000..9cffa5ca Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000005.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000006.vtu b/test/writevtk/cf1a_with_observers-observer1-00000006.vtu new file mode 100644 index 00000000..7d2b8ecf Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000006.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000007.vtu b/test/writevtk/cf1a_with_observers-observer1-00000007.vtu new file mode 100644 index 00000000..b15d823e Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000007.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000008.vtu b/test/writevtk/cf1a_with_observers-observer1-00000008.vtu new file mode 100644 index 00000000..49511de4 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000008.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000009.vtu b/test/writevtk/cf1a_with_observers-observer1-00000009.vtu new file mode 100644 index 00000000..bb549826 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000009.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000010.vtu b/test/writevtk/cf1a_with_observers-observer1-00000010.vtu new file mode 100644 index 00000000..3793b11e Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000010.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000011.vtu b/test/writevtk/cf1a_with_observers-observer1-00000011.vtu new file mode 100644 index 00000000..94d0569a Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000011.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000012.vtu b/test/writevtk/cf1a_with_observers-observer1-00000012.vtu new file mode 100644 index 00000000..711f6831 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000012.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000013.vtu b/test/writevtk/cf1a_with_observers-observer1-00000013.vtu new file mode 100644 index 00000000..77f0514e Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000013.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000014.vtu b/test/writevtk/cf1a_with_observers-observer1-00000014.vtu new file mode 100644 index 00000000..7427b39c Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000014.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000015.vtu b/test/writevtk/cf1a_with_observers-observer1-00000015.vtu new file mode 100644 index 00000000..e8d82112 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000015.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000016.vtu b/test/writevtk/cf1a_with_observers-observer1-00000016.vtu new file mode 100644 index 00000000..4a633ebc Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000016.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000017.vtu b/test/writevtk/cf1a_with_observers-observer1-00000017.vtu new file mode 100644 index 00000000..e4ad5dff Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000017.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000018.vtu b/test/writevtk/cf1a_with_observers-observer1-00000018.vtu new file mode 100644 index 00000000..4e9c199a Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000018.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000019.vtu b/test/writevtk/cf1a_with_observers-observer1-00000019.vtu new file mode 100644 index 00000000..b00178cb Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000019.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000020.vtu b/test/writevtk/cf1a_with_observers-observer1-00000020.vtu new file mode 100644 index 00000000..9ba33416 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000020.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000021.vtu b/test/writevtk/cf1a_with_observers-observer1-00000021.vtu new file mode 100644 index 00000000..2201df5c Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000021.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000022.vtu b/test/writevtk/cf1a_with_observers-observer1-00000022.vtu new file mode 100644 index 00000000..0f2415af Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000022.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000023.vtu b/test/writevtk/cf1a_with_observers-observer1-00000023.vtu new file mode 100644 index 00000000..eb332277 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000023.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000024.vtu b/test/writevtk/cf1a_with_observers-observer1-00000024.vtu new file mode 100644 index 00000000..8b0454dc Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000024.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000025.vtu b/test/writevtk/cf1a_with_observers-observer1-00000025.vtu new file mode 100644 index 00000000..c4c0da29 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000025.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000026.vtu b/test/writevtk/cf1a_with_observers-observer1-00000026.vtu new file mode 100644 index 00000000..1877ba7b Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000026.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000027.vtu b/test/writevtk/cf1a_with_observers-observer1-00000027.vtu new file mode 100644 index 00000000..29bc7f70 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000027.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000028.vtu b/test/writevtk/cf1a_with_observers-observer1-00000028.vtu new file mode 100644 index 00000000..360780cf Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000028.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000029.vtu b/test/writevtk/cf1a_with_observers-observer1-00000029.vtu new file mode 100644 index 00000000..06b220d9 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000029.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000030.vtu b/test/writevtk/cf1a_with_observers-observer1-00000030.vtu new file mode 100644 index 00000000..00bb4831 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000030.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000031.vtu b/test/writevtk/cf1a_with_observers-observer1-00000031.vtu new file mode 100644 index 00000000..b1d64615 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000031.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000032.vtu b/test/writevtk/cf1a_with_observers-observer1-00000032.vtu new file mode 100644 index 00000000..6976b660 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000032.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000033.vtu b/test/writevtk/cf1a_with_observers-observer1-00000033.vtu new file mode 100644 index 00000000..8f1a0d96 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000033.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000034.vtu b/test/writevtk/cf1a_with_observers-observer1-00000034.vtu new file mode 100644 index 00000000..69498206 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000034.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000035.vtu b/test/writevtk/cf1a_with_observers-observer1-00000035.vtu new file mode 100644 index 00000000..da4a1449 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000035.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000036.vtu b/test/writevtk/cf1a_with_observers-observer1-00000036.vtu new file mode 100644 index 00000000..ce665493 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000036.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000037.vtu b/test/writevtk/cf1a_with_observers-observer1-00000037.vtu new file mode 100644 index 00000000..dee6fd94 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000037.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000038.vtu b/test/writevtk/cf1a_with_observers-observer1-00000038.vtu new file mode 100644 index 00000000..16bf99d9 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000038.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000039.vtu b/test/writevtk/cf1a_with_observers-observer1-00000039.vtu new file mode 100644 index 00000000..ae06646a Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000039.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000040.vtu b/test/writevtk/cf1a_with_observers-observer1-00000040.vtu new file mode 100644 index 00000000..7f7e5126 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000040.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000041.vtu b/test/writevtk/cf1a_with_observers-observer1-00000041.vtu new file mode 100644 index 00000000..75f85039 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000041.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000042.vtu b/test/writevtk/cf1a_with_observers-observer1-00000042.vtu new file mode 100644 index 00000000..b574397a Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000042.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000043.vtu b/test/writevtk/cf1a_with_observers-observer1-00000043.vtu new file mode 100644 index 00000000..c17c9963 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000043.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000044.vtu b/test/writevtk/cf1a_with_observers-observer1-00000044.vtu new file mode 100644 index 00000000..a165f4dc Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000044.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000045.vtu b/test/writevtk/cf1a_with_observers-observer1-00000045.vtu new file mode 100644 index 00000000..ad72dc53 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000045.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000046.vtu b/test/writevtk/cf1a_with_observers-observer1-00000046.vtu new file mode 100644 index 00000000..5e73a483 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000046.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000047.vtu b/test/writevtk/cf1a_with_observers-observer1-00000047.vtu new file mode 100644 index 00000000..8ca8c93f Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000047.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000048.vtu b/test/writevtk/cf1a_with_observers-observer1-00000048.vtu new file mode 100644 index 00000000..50c0e46c Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000048.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000049.vtu b/test/writevtk/cf1a_with_observers-observer1-00000049.vtu new file mode 100644 index 00000000..9d328364 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000049.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000050.vtu b/test/writevtk/cf1a_with_observers-observer1-00000050.vtu new file mode 100644 index 00000000..3203da4f Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000050.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000051.vtu b/test/writevtk/cf1a_with_observers-observer1-00000051.vtu new file mode 100644 index 00000000..fbf0499f Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000051.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000052.vtu b/test/writevtk/cf1a_with_observers-observer1-00000052.vtu new file mode 100644 index 00000000..2008c79e Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000052.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000053.vtu b/test/writevtk/cf1a_with_observers-observer1-00000053.vtu new file mode 100644 index 00000000..cbb6510a Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000053.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000054.vtu b/test/writevtk/cf1a_with_observers-observer1-00000054.vtu new file mode 100644 index 00000000..365570f3 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000054.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000055.vtu b/test/writevtk/cf1a_with_observers-observer1-00000055.vtu new file mode 100644 index 00000000..2734e26c Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000055.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000056.vtu b/test/writevtk/cf1a_with_observers-observer1-00000056.vtu new file mode 100644 index 00000000..f3b90ff5 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000056.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000057.vtu b/test/writevtk/cf1a_with_observers-observer1-00000057.vtu new file mode 100644 index 00000000..7fe3074b Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000057.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000058.vtu b/test/writevtk/cf1a_with_observers-observer1-00000058.vtu new file mode 100644 index 00000000..c47edfe0 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000058.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000059.vtu b/test/writevtk/cf1a_with_observers-observer1-00000059.vtu new file mode 100644 index 00000000..548971f3 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000059.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000060.vtu b/test/writevtk/cf1a_with_observers-observer1-00000060.vtu new file mode 100644 index 00000000..442cc301 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000060.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000061.vtu b/test/writevtk/cf1a_with_observers-observer1-00000061.vtu new file mode 100644 index 00000000..190d5f08 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000061.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000062.vtu b/test/writevtk/cf1a_with_observers-observer1-00000062.vtu new file mode 100644 index 00000000..aac59816 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000062.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000063.vtu b/test/writevtk/cf1a_with_observers-observer1-00000063.vtu new file mode 100644 index 00000000..51f0d9a5 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000063.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer1-00000064.vtu b/test/writevtk/cf1a_with_observers-observer1-00000064.vtu new file mode 100644 index 00000000..3162b720 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer1-00000064.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000001.vtu b/test/writevtk/cf1a_with_observers-observer2-00000001.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000001.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000002.vtu b/test/writevtk/cf1a_with_observers-observer2-00000002.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000002.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000003.vtu b/test/writevtk/cf1a_with_observers-observer2-00000003.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000003.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000004.vtu b/test/writevtk/cf1a_with_observers-observer2-00000004.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000004.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000005.vtu b/test/writevtk/cf1a_with_observers-observer2-00000005.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000005.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000006.vtu b/test/writevtk/cf1a_with_observers-observer2-00000006.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000006.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000007.vtu b/test/writevtk/cf1a_with_observers-observer2-00000007.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000007.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000008.vtu b/test/writevtk/cf1a_with_observers-observer2-00000008.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000008.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000009.vtu b/test/writevtk/cf1a_with_observers-observer2-00000009.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000009.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000010.vtu b/test/writevtk/cf1a_with_observers-observer2-00000010.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000010.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000011.vtu b/test/writevtk/cf1a_with_observers-observer2-00000011.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000011.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000012.vtu b/test/writevtk/cf1a_with_observers-observer2-00000012.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000012.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000013.vtu b/test/writevtk/cf1a_with_observers-observer2-00000013.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000013.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000014.vtu b/test/writevtk/cf1a_with_observers-observer2-00000014.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000014.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000015.vtu b/test/writevtk/cf1a_with_observers-observer2-00000015.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000015.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000016.vtu b/test/writevtk/cf1a_with_observers-observer2-00000016.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000016.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000017.vtu b/test/writevtk/cf1a_with_observers-observer2-00000017.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000017.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000018.vtu b/test/writevtk/cf1a_with_observers-observer2-00000018.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000018.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000019.vtu b/test/writevtk/cf1a_with_observers-observer2-00000019.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000019.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000020.vtu b/test/writevtk/cf1a_with_observers-observer2-00000020.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000020.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000021.vtu b/test/writevtk/cf1a_with_observers-observer2-00000021.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000021.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000022.vtu b/test/writevtk/cf1a_with_observers-observer2-00000022.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000022.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000023.vtu b/test/writevtk/cf1a_with_observers-observer2-00000023.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000023.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000024.vtu b/test/writevtk/cf1a_with_observers-observer2-00000024.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000024.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000025.vtu b/test/writevtk/cf1a_with_observers-observer2-00000025.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000025.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000026.vtu b/test/writevtk/cf1a_with_observers-observer2-00000026.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000026.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000027.vtu b/test/writevtk/cf1a_with_observers-observer2-00000027.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000027.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000028.vtu b/test/writevtk/cf1a_with_observers-observer2-00000028.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000028.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000029.vtu b/test/writevtk/cf1a_with_observers-observer2-00000029.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000029.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000030.vtu b/test/writevtk/cf1a_with_observers-observer2-00000030.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000030.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000031.vtu b/test/writevtk/cf1a_with_observers-observer2-00000031.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000031.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000032.vtu b/test/writevtk/cf1a_with_observers-observer2-00000032.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000032.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000033.vtu b/test/writevtk/cf1a_with_observers-observer2-00000033.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000033.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000034.vtu b/test/writevtk/cf1a_with_observers-observer2-00000034.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000034.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000035.vtu b/test/writevtk/cf1a_with_observers-observer2-00000035.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000035.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000036.vtu b/test/writevtk/cf1a_with_observers-observer2-00000036.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000036.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000037.vtu b/test/writevtk/cf1a_with_observers-observer2-00000037.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000037.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000038.vtu b/test/writevtk/cf1a_with_observers-observer2-00000038.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000038.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000039.vtu b/test/writevtk/cf1a_with_observers-observer2-00000039.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000039.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000040.vtu b/test/writevtk/cf1a_with_observers-observer2-00000040.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000040.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000041.vtu b/test/writevtk/cf1a_with_observers-observer2-00000041.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000041.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000042.vtu b/test/writevtk/cf1a_with_observers-observer2-00000042.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000042.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000043.vtu b/test/writevtk/cf1a_with_observers-observer2-00000043.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000043.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000044.vtu b/test/writevtk/cf1a_with_observers-observer2-00000044.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000044.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000045.vtu b/test/writevtk/cf1a_with_observers-observer2-00000045.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000045.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000046.vtu b/test/writevtk/cf1a_with_observers-observer2-00000046.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000046.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000047.vtu b/test/writevtk/cf1a_with_observers-observer2-00000047.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000047.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000048.vtu b/test/writevtk/cf1a_with_observers-observer2-00000048.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000048.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000049.vtu b/test/writevtk/cf1a_with_observers-observer2-00000049.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000049.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000050.vtu b/test/writevtk/cf1a_with_observers-observer2-00000050.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000050.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000051.vtu b/test/writevtk/cf1a_with_observers-observer2-00000051.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000051.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000052.vtu b/test/writevtk/cf1a_with_observers-observer2-00000052.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000052.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000053.vtu b/test/writevtk/cf1a_with_observers-observer2-00000053.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000053.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000054.vtu b/test/writevtk/cf1a_with_observers-observer2-00000054.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000054.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000055.vtu b/test/writevtk/cf1a_with_observers-observer2-00000055.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000055.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000056.vtu b/test/writevtk/cf1a_with_observers-observer2-00000056.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000056.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000057.vtu b/test/writevtk/cf1a_with_observers-observer2-00000057.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000057.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000058.vtu b/test/writevtk/cf1a_with_observers-observer2-00000058.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000058.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000059.vtu b/test/writevtk/cf1a_with_observers-observer2-00000059.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000059.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000060.vtu b/test/writevtk/cf1a_with_observers-observer2-00000060.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000060.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000061.vtu b/test/writevtk/cf1a_with_observers-observer2-00000061.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000061.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000062.vtu b/test/writevtk/cf1a_with_observers-observer2-00000062.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000062.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000063.vtu b/test/writevtk/cf1a_with_observers-observer2-00000063.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000063.vtu differ diff --git a/test/writevtk/cf1a_with_observers-observer2-00000064.vtu b/test/writevtk/cf1a_with_observers-observer2-00000064.vtu new file mode 100644 index 00000000..962e65b6 Binary files /dev/null and b/test/writevtk/cf1a_with_observers-observer2-00000064.vtu differ diff --git a/test/writevtk/cf1a_with_observers.pvd b/test/writevtk/cf1a_with_observers.pvd new file mode 100755 index 00000000..1ed2b7ff --- /dev/null +++ b/test/writevtk/cf1a_with_observers.pvd @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/writevtk_tests.jl b/test/writevtk_tests.jl index 499bfa4f..7f100c91 100644 --- a/test/writevtk_tests.jl +++ b/test/writevtk_tests.jl @@ -4,8 +4,13 @@ using AcousticAnalogies using Formatting: format using JLD2: JLD2 using SHA: sha1 +using StaticArrays: @SVector using Test +function to_cf1a(se) + return CompactF1ASourceElement(se.ρ0, se.c0, se.Δr, se.Λ, se.y0dot, se.y1dot, se.y2dot, se.y3dot, se.f0dot, se.f1dot, se.τ, se.u) +end + @testset "WriteVTK tests" begin @testset "Compact F1A source elements" begin @@ -13,7 +18,8 @@ using Test ses = nothing JLD2.jldopen(fname, "r") do file - ses = file["ses"] + # Renaming CompactSourceElement to CompactF1ASourceElement breaks reconstructing the source elements from the jld2file. + ses = to_cf1a.(file["ses"]) end name = "cf1a" @@ -26,10 +32,108 @@ using Test @test sha_str == sha_str_check end - fname = "$(name).pvd" - sha_str = bytes2hex(open(sha1, fname)) - sha_str_check = bytes2hex(open(sha1, joinpath("writevtk", fname))) - @test sha_str == sha_str_check + if !Sys.iswindows() + fname = "$(name).pvd" + sha_str = bytes2hex(open(sha1, fname)) + sha_str_check = bytes2hex(open(sha1, joinpath(@__DIR__, "writevtk", fname))) + @test sha_str == sha_str_check + end + + end + + @testset "Compact F1A source elements, with observers" begin + fname = joinpath(@__DIR__, "writevtk", "cf1a.jld2") + + ses = nothing + JLD2.jldopen(fname, "r") do file + # Renaming CompactSourceElement to CompactF1ASourceElement breaks reconstructing the source elements from the jld2file. + ses = to_cf1a.(file["ses"]) + end + + obs1 = AcousticAnalogies.ConstVelocityAcousticObserver(0.0, @SVector([0, 2.0, 0]), @SVector([5.0, 0.0, 0.0])) + obs2 = AcousticAnalogies.StationaryAcousticObserver(@SVector [0, 2.5, 0]) + obs = [obs1, obs2] + + name = "cf1a_with_observers" + pvd = AcousticAnalogies.to_paraview_collection(name, (ses,); observers=obs) + + for i in 1:size(ses, 1) + fname = format("{}-block1-{:08d}.vtp", name, i) + sha_str = bytes2hex(open(sha1, fname)) + sha_str_check = bytes2hex(open(sha1, joinpath(@__DIR__, "writevtk", fname))) + @test sha_str == sha_str_check + + # The source element files for this test case with observers should be the same as the case without the observers. + name2 = "cf1a" + fname2 = format("{}{:08d}.vtp", name2, i) + sha_str_check = bytes2hex(open(sha1, joinpath(@__DIR__, "writevtk", fname))) + @test sha_str == sha_str_check + + for j in 1:length(obs) + fname = format("{}-observer$(j)-{:08d}.vtu", name, i) + sha_str = bytes2hex(open(sha1, fname)) + sha_str_check = bytes2hex(open(sha1, joinpath(@__DIR__, "writevtk", fname))) + # @test sha_str == sha_str_check + end + + end + + if !Sys.iswindows() + fname = "$(name).pvd" + sha_str = bytes2hex(open(sha1, fname)) + sha_str_check = bytes2hex(open(sha1, joinpath(@__DIR__, "writevtk", fname))) + @test sha_str == sha_str_check + end + + end + + @testset "Compact F1A source elements, multiblock, with observers" begin + fname = joinpath(@__DIR__, "writevtk", "cf1a.jld2") + + ses = nothing + JLD2.jldopen(fname, "r") do file + # Renaming CompactSourceElement to CompactF1ASourceElement breaks reconstructing the source elements from the jld2file. + ses = to_cf1a.(file["ses"]) + end + + # Split the array into "blocks." + ses_mb = tuple([ses[:, :, b] for b in 1:size(ses, 3)]...) + + obs1 = AcousticAnalogies.ConstVelocityAcousticObserver(0.0, @SVector([0, 2.0, 0]), @SVector([5.0, 0.0, 0.0])) + obs2 = AcousticAnalogies.StationaryAcousticObserver(@SVector [0, 2.5, 0]) + obs = [obs1, obs2] + + name = "cf1a_mb_with_observers" + pvd = AcousticAnalogies.to_paraview_collection(name, ses_mb; observers=obs) + + for i in 1:size(ses, 1) + for b in 1:length(ses_mb) + fname = format("{}-block$(b)-{:08d}.vtp", name, i) + sha_str = bytes2hex(open(sha1, fname)) + sha_str_check = bytes2hex(open(sha1, joinpath(@__DIR__, "writevtk", fname))) + @test sha_str == sha_str_check + end + + for j in 1:length(obs) + fname = format("{}-observer$(j)-{:08d}.vtu", name, i) + sha_str = bytes2hex(open(sha1, fname)) + sha_str_check = bytes2hex(open(sha1, joinpath(@__DIR__, "writevtk", fname))) + # @test sha_str == sha_str_check + + # The observers for this case should be identical to the observers from the single-block case. + fname2 = format("cf1a_with_observers-observer$(j)-{:08d}.vtu", i) + sha_str_check = bytes2hex(open(sha1, joinpath(@__DIR__, "writevtk", fname2))) + # @test sha_str == sha_str_check + end + + end + + if !Sys.iswindows() + fname = "$(name).pvd" + sha_str = bytes2hex(open(sha1, fname)) + sha_str_check = bytes2hex(open(sha1, joinpath(@__DIR__, "writevtk", fname))) + @test sha_str == sha_str_check + end end