Path: blob/main/examples/p4est_2d_dgsem/elixir_euler_subsonic_cylinder.jl
2055 views
using OrdinaryDiffEqLowStorageRK1using Trixi23###############################################################################4# semidiscretization of the compressible Euler equations56equations = CompressibleEulerEquations2D(1.4)78@inline function initial_condition_mach038_flow(x, t,9equations::CompressibleEulerEquations2D)10# set the freestream flow parameters11rho_freestream = 1.412v1 = 0.3813v2 = 0.014p_freestream = 1.01516prim = SVector(rho_freestream, v1, v2, p_freestream)17return prim2cons(prim, equations)18end1920initial_condition = initial_condition_mach038_flow2122volume_flux = flux_ranocha_turbo # FluxRotated(flux_chandrashekar) can also be used23# Up to version 0.13.0, `max_abs_speed_naive` was used as the default wave speed estimate of24# `const flux_lax_friedrichs = FluxLaxFriedrichs(), i.e., `FluxLaxFriedrichs(max_abs_speed = max_abs_speed_naive)`.25# In the `StepsizeCallback`, though, the less diffusive `max_abs_speeds` is employed which is consistent with `max_abs_speed`.26# Thus, we exchanged in PR#2458 the default wave speed used in the LLF flux to `max_abs_speed`.27# To ensure that every example still runs we specify explicitly `FluxLaxFriedrichs(max_abs_speed_naive)`.28# We remark, however, that the now default `max_abs_speed` is in general recommended due to compliance with the29# `StepsizeCallback` (CFL-Condition) and less diffusion.30surface_flux = FluxLaxFriedrichs(max_abs_speed_naive)3132polydeg = 333solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux,34volume_integral = VolumeIntegralFluxDifferencing(volume_flux))3536function mapping2cylinder(xi, eta)37xi_, eta_ = 0.5 * (xi + 1), 0.5 * (eta + 1.0) # Map from [-1,1] to [0,1] for simplicity3839R2 = 50.0 # Bigger circle40R1 = 0.5 # Smaller circle4142# Ensure an isotropic mesh by using elements with smaller radial length near the inner circle4344r = R1 * exp(xi_ * log(R2 / R1))45theta = 2.0 * pi * eta_4647x = r * cos(theta)48y = r * sin(theta)49return (x, y)50end5152cells_per_dimension = (64, 64)53# xi = -1 maps to the inner circle and xi = +1 maps to the outer circle and we can specify boundary54# conditions there. However, the image of eta = -1, +1 coincides at the line y = 0. There is no55# physical boundary there so we specify `periodicity = true` there and the solver treats the56# element across eta = -1, +1 as neighbours which is what we want57mesh = P4estMesh(cells_per_dimension, mapping = mapping2cylinder, polydeg = polydeg,58periodicity = (false, true))5960# The boundary condition on the outer cylinder is constant but subsonic, so we cannot compute the61# boundary flux from the external information alone. Thus, we use the numerical flux to distinguish62# between inflow and outflow characteristics63@inline function boundary_condition_subsonic_constant(u_inner,64normal_direction::AbstractVector, x,65t,66surface_flux_function,67equations::CompressibleEulerEquations2D)68u_boundary = initial_condition_mach038_flow(x, t, equations)6970return surface_flux_function(u_inner, u_boundary, normal_direction, equations)71end7273boundary_conditions = Dict(:x_neg => boundary_condition_slip_wall,74:x_pos => boundary_condition_subsonic_constant)7576semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver,77boundary_conditions = boundary_conditions)7879###############################################################################80# ODE solvers8182# Run for a long time to reach a steady state83tspan = (0.0, 100.0)84ode = semidiscretize(semi, tspan)8586# Callbacks8788summary_callback = SummaryCallback()8990analysis_interval = 20009192aoa = 0.093rho_inf = 1.494u_inf = 0.3895l_inf = 1.0 # Diameter of circle9697force_boundary_symbol = (:x_neg,)98drag_coefficient = AnalysisSurfaceIntegral(force_boundary_symbol,99DragCoefficientPressure2D(aoa, rho_inf, u_inf,100l_inf))101102lift_coefficient = AnalysisSurfaceIntegral(force_boundary_symbol,103LiftCoefficientPressure2D(aoa, rho_inf, u_inf,104l_inf))105106analysis_callback = AnalysisCallback(semi, interval = analysis_interval,107output_directory = "out",108save_analysis = true,109analysis_integrals = (drag_coefficient,110lift_coefficient))111112alive_callback = AliveCallback(analysis_interval = analysis_interval)113114save_solution = SaveSolutionCallback(interval = 500,115save_initial_solution = true,116save_final_solution = true,117solution_variables = cons2prim)118119stepsize_callback = StepsizeCallback(cfl = 2.0)120121callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution,122stepsize_callback)123124###############################################################################125# run the simulation126sol = solve(ode,127CarpenterKennedy2N54(williamson_condition = false;128thread = Trixi.True());129dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback130ode_default_options()..., callback = callbacks);131132133