|
| 1 | +#!/usr/bin/env python3 |
| 2 | +"""Immersed-boundary force on a thin plate, against a published measurement (issue 1849). |
| 3 | +
|
| 4 | +A 2D flat plate pitching about its leading edge, 0 -> 45 degrees on an Eldredge smoothed ramp (a = 21), |
| 5 | +K = pi/8 (case C1), Re_c = 300, Ma 0.2. The plate is 2.5 percent of the chord thick, matching the experiment. |
| 6 | +
|
| 7 | + Jantzen, Taira, Granlund & Ol, Phys. Fluids 26, 053606 (2014), Fig. 10, 2D panel, curve C1. |
| 8 | +
|
| 9 | +`NCELL` sets how many cells lie across the plate thickness; the physical problem does not change with it, so |
| 10 | +the sweep isolates the immersed-boundary resolution requirement from any change of geometry. See README.md |
| 11 | +for what the sweep shows and why it matters. |
| 12 | +
|
| 13 | + NCELL=2 python3 case.py dx = 0.0125 c |
| 14 | + NCELL=4 python3 case.py dx = 0.00625 c (default) |
| 15 | + NCELL=8 python3 case.py dx = 0.003125 c |
| 16 | + NCELL=16 python3 case.py dx = 0.0015625 c |
| 17 | +""" |
| 18 | + |
| 19 | +import json |
| 20 | +import math |
| 21 | +import os |
| 22 | + |
| 23 | +U, rho, Ma, gamma, Re = 1.0, 1.0, 0.2, 1.4, 300.0 |
| 24 | +P = rho * U**2 / (gamma * Ma**2) |
| 25 | +cs = math.sqrt(gamma * P / rho) |
| 26 | +K = math.pi / 8 |
| 27 | +Omega = 2 * K * U # rad per c/U; pitch time = 45 deg / Omega = 1 c/U |
| 28 | +th_max = math.radians(45.0) |
| 29 | +t_p = th_max / Omega |
| 30 | +a_smooth = 21.0 |
| 31 | +THICK = 0.025 |
| 32 | +t0 = 2.0 # settle at 0 deg before the ramp |
| 33 | +t_end = t0 + t_p + 4.0 |
| 34 | +x0, x1, y0, y1 = -2.0, 5.0, -2.5, 2.5 |
| 35 | + |
| 36 | +# L4 added after the first three failed to converge: refining 2 -> 4 -> 8 cells across the thickness moved |
| 37 | +# the peak lift 6.41 -> 4.68 -> 4.46 against a reference of 7.00, i.e. away from it and then stalling. |
| 38 | +# Two under-resolved answers landing near each other is not convergence. If a few cells across a thin |
| 39 | +# body is simply too few for the immersed boundary, 16 should move back toward the reference; if the |
| 40 | +# finite thickness is genuinely the difference, it should stay near 4.5. |
| 41 | +LEVELS = {"L1": 0.0125, "L2": 0.00625, "L3": 0.003125, "L4": 0.0015625} |
| 42 | + |
| 43 | + |
| 44 | +NCELL = int(os.environ.get("NCELL", 4)) |
| 45 | +dx = THICK / NCELL |
| 46 | +m, n = int((x1 - x0) / dx) - 1, int((y1 - y0) / dx) - 1 |
| 47 | +dt = 0.4 * dx / (U + cs) |
| 48 | +nt = int(t_end / dt) |
| 49 | + |
| 50 | +case = { |
| 51 | + "run_time_info": "T", |
| 52 | + "parallel_io": "T", |
| 53 | + "prim_vars_wrt": "T", |
| 54 | + "ib_state_wrt": "T", |
| 55 | + "format": "silo", |
| 56 | + "precision": "double", |
| 57 | + "x_domain%beg": x0, |
| 58 | + "x_domain%end": x1, |
| 59 | + "y_domain%beg": y0, |
| 60 | + "y_domain%end": y1, |
| 61 | + "m": m, |
| 62 | + "n": n, |
| 63 | + "p": 0, |
| 64 | + "cyl_coord": "F", |
| 65 | + "dt": dt, |
| 66 | + "t_step_start": 0, |
| 67 | + "t_step_stop": nt, |
| 68 | + "t_step_save": max(1, nt // 40), |
| 69 | + "num_patches": 1, |
| 70 | + "num_fluids": 1, |
| 71 | + "model_eqns": "5eq", |
| 72 | + "alt_soundspeed": "F", |
| 73 | + "mpp_lim": "F", |
| 74 | + "mixture_err": "T", |
| 75 | + "time_stepper": "rk3", |
| 76 | + "weno_order": 5, |
| 77 | + "weno_eps": 1.0e-10, |
| 78 | + "weno_Re_flux": "T", |
| 79 | + "weno_avg": "T", |
| 80 | + "avg_state": "arithmetic", |
| 81 | + "mapped_weno": "T", |
| 82 | + "null_weights": "F", |
| 83 | + "mp_weno": "F", |
| 84 | + "riemann_solver": "hllc", |
| 85 | + "low_Mach": 2, |
| 86 | + "wave_speeds": "direct", |
| 87 | + "viscous": "T", |
| 88 | + "fd_order": 4, |
| 89 | + "patch_icpp(1)%geometry": 3, |
| 90 | + "patch_icpp(1)%x_centroid": 0.5 * (x0 + x1), |
| 91 | + "patch_icpp(1)%y_centroid": 0.5 * (y0 + y1), |
| 92 | + "patch_icpp(1)%length_x": x1 - x0, |
| 93 | + "patch_icpp(1)%length_y": y1 - y0, |
| 94 | + "patch_icpp(1)%vel(1)": U, |
| 95 | + "patch_icpp(1)%vel(2)": 0.0, |
| 96 | + "patch_icpp(1)%pres": P, |
| 97 | + "patch_icpp(1)%alpha_rho(1)": rho, |
| 98 | + "patch_icpp(1)%alpha(1)": 1.0, |
| 99 | + "fluid_pp(1)%gamma": 1.0 / (gamma - 1.0), |
| 100 | + "fluid_pp(1)%eos": "ideal_gas", |
| 101 | + "fluid_pp(1)%Re(1)": Re, |
| 102 | + "bc_x%beg": -7, |
| 103 | + "bc_x%grcbc_in": "T", |
| 104 | + "bc_x%vel_in(1)": U, |
| 105 | + "bc_x%vel_in(2)": 0.0, |
| 106 | + "bc_x%pres_in": P, |
| 107 | + "bc_x%alpha_rho_in(1)": rho, |
| 108 | + "bc_x%alpha_in(1)": 1.0, |
| 109 | + "bc_x%end": -8, |
| 110 | + "bc_x%grcbc_out": "T", |
| 111 | + "bc_x%pres_out": P, |
| 112 | + "bc_y%beg": -9, |
| 113 | + "bc_y%end": -9, |
| 114 | + "ib": "T", |
| 115 | + "num_ibs": 1, |
| 116 | + "patch_ib(1)%geometry": 3, |
| 117 | + "patch_ib(1)%x_centroid": 0.5, |
| 118 | + "patch_ib(1)%y_centroid": 0.0, |
| 119 | + "patch_ib(1)%length_x": 1.0, |
| 120 | + "patch_ib(1)%length_y": THICK, |
| 121 | + "patch_ib(1)%slip": "F", |
| 122 | + "patch_ib(1)%moving_ibm": 1, |
| 123 | + "patch_ib(1)%angles(3)": 0.0, |
| 124 | + "patch_ib(1)%angular_vel(3)": 0.0, |
| 125 | + "omega_wrt(3)": "T", |
| 126 | +} |
| 127 | +tau = f"(t - {t0})" |
| 128 | +th = f"(0.5*{th_max}*(1.0 + (log(cosh({a_smooth}*{tau})) - log(cosh({a_smooth}*({tau} - {t_p}))))/{a_smooth * t_p}))" |
| 129 | +thd = f"(0.5*{Omega}*(tanh({a_smooth}*{tau}) - tanh({a_smooth}*({tau} - {t_p}))))" |
| 130 | +case["patch_ib(1)%angular_vel(3)"] = thd |
| 131 | +case["patch_ib(1)%vel(1)"] = f"-0.5*{thd}*sin({th})" |
| 132 | +case["patch_ib(1)%vel(2)"] = f"0.5*{thd}*cos({th})" |
| 133 | + |
| 134 | +if __name__ == "__main__": |
| 135 | + if os.environ.get("SUMMARY"): |
| 136 | + print(f"{NCELL} cells across the {THICK:g} c thickness: dx = {dx:g} c, " f"{m + 1} x {n + 1} = {(m + 1) * (n + 1) / 1e6:.2f} M cells, {nt} steps of dt = {dt:.2e}") |
| 137 | + else: |
| 138 | + print(json.dumps(case, indent=4)) |
0 commit comments