def get_CD_CL(self, filepath, bodypath): """Load the forces from file and return the force coefficients.""" t, fx, fy = petibmpy.read_forces(filepath) # Non-dimensionalize time by the period. t_nodim = self.f * t # Reverse sign of force in x-direction when the body moving # in the positive x-direction. U0, _ = self.translational_velocity(t) fx *= -U0 / numpy.abs(U0) # Normalize the forces by the maximum quasi-steady force on the wing. D, L = [], [] x0 = petibmpy.read_body(bodypath, skiprows=1, usecols=0) y0 = numpy.zeros_like(x0) for ti in t: alpha = self.orientation_angle(ti) x, y = petibmpy.rotate2d(x0, y0, center=(0.0, 0.0), angle=alpha, mode='rad') Di, Li = self.quasi_steady_forces(ti, x, y, 0.0, 0.0, rho=1.0) D.append(numpy.max(Di)) L.append(numpy.max(Li)) D, L = numpy.array(D), numpy.array(L) cd, cl = fx / numpy.max(D), fy / numpy.max(L) return {'CD': (t_nodim, cd), 'CL': (t_nodim, cl)}
def load_force_coefficients(filepath, config): """Load forces from file and return force coefficients.""" # Load forces from file. t, fx, fy, fz = petibmpy.read_forces(filepath) fx *= -1.0 # drag to thrust # Convert forces to force coefficients. rho, U_inf, A_plan = (getattr(config, name) for name in ('rho', 'U_inf', 'A_plan')) coeff = 1 / (0.5 * rho * U_inf**2 * A_plan) # Non-dimensionalize time values by period. t /= config.T ct, cl, cz = petibmpy.get_force_coefficients(fx, fy, fz, coeff=coeff) return Solution(t=t, ct=ct, cl=cl, cz=cz)
def test_read_forces(self): """Test function `read_forces`.""" # Tests for files containing forces for single and multiple bodies. for n, name in enumerate(['single', 'multiple']): dim = [2, 3] # test 2D and 3D for d in dim: filepaths = [] for i in range(2): # test read from single and multiple files filepath = self.datadir / f'forces{d}d-{name}-{i * 5}.txt' filepaths.append(filepath) res = petibmpy.read_forces(*filepaths) self.assertTrue(len(res) == d * (n + 1) + 1) num = res[0].size self.assertTrue(all(r.size == num for r in res))
def test_get_time_averaged_values(self): """Test function `get_time_averaged_values`.""" dim = 3 # Load forces from file. filepath1 = self.datadir / f'forces{dim}d-single-0.txt' filepath2 = self.datadir / f'forces{dim}d-single-5.txt' t, fx, fy, fz = petibmpy.read_forces(filepath1, filepath2) # Compute time-averaged value in one direction. fx1, = petibmpy.get_time_averaged_values(t, fx) self.assertAlmostEqual(fx1, numpy.mean(fx), places=7) # Compute time-averaged value for each direction. fx1, fy1, fz1 = petibmpy.get_time_averaged_values(t, fx, fy, fz) self.assertAlmostEqual(fx1, numpy.mean(fx), places=7) self.assertAlmostEqual(fy1, numpy.mean(fy), places=7) self.assertAlmostEqual(fz1, numpy.mean(fz), places=7) # Compute averaged values providing larger time interval. time_limits = (-1.0, 100.0) fx1, fy1, fz1 = petibmpy.get_time_averaged_values(t, fx, fy, fz, limits=time_limits) self.assertAlmostEqual(fx1, numpy.mean(fx), places=7) self.assertAlmostEqual(fy1, numpy.mean(fy), places=7) self.assertAlmostEqual(fz1, numpy.mean(fz), places=7) # Compute averaged values providing restricted time interval. time_limits = (5.0, 6.0) fx1, fy1, fz1 = petibmpy.get_time_averaged_values(t, fx, fy, fz, limits=time_limits) self.assertAlmostEqual(fx1, 0.55) self.assertAlmostEqual(fy1, 1.55) self.assertAlmostEqual(fz1, 2.55) # Check if runtime error is raised when wrong time limits are set. time_limits = (5.5, 5.5) # 5.5 is not a saved time value with self.assertRaises(RuntimeError): fx1, = petibmpy.get_time_averaged_values(t, fx, limits=time_limits)
def test_get_force_coefficients(self): """Test function `get_force_coefficients`.""" dim = 3 # Load forces from file. filepath = self.datadir / f'forces{dim}d-single-0.txt' _, fx, fy, fz = petibmpy.read_forces(filepath) # Convert one direction with unit coefficient. cd, = petibmpy.get_force_coefficients(fx) self.assertTrue(numpy.allclose(cd, fx)) # Convert two directions with unit coefficient. cd, cl = petibmpy.get_force_coefficients(fx, fy) self.assertTrue(numpy.allclose(cd, fx)) self.assertTrue(numpy.allclose(cl, fy)) # Convert three directions with unit coefficient. cd, cl, cz = petibmpy.get_force_coefficients(fx, fy, fz) self.assertTrue(numpy.allclose(cd, fx)) self.assertTrue(numpy.allclose(cl, fy)) self.assertTrue(numpy.allclose(cz, fz)) # Convert three directions with random coefficient. coeff = random.uniform(0.1, 5.0) cd, cl, cz = petibmpy.get_force_coefficients(fx, fy, fz, coeff=coeff) self.assertTrue(numpy.allclose(cd / coeff, fx)) self.assertTrue(numpy.allclose(cl / coeff, fy)) self.assertTrue(numpy.allclose(cz / coeff, fz))
"""Generate a figure of the force coefficients over time. Save the figure in the sub-folder `figures` of the simulation directory. """ import pathlib from matplotlib import pyplot import petibmpy simudir = pathlib.Path(__file__).absolute().parents[1] filepath = simudir / 'output' / 'forces-0.txt' t, fx, fy, fz = petibmpy.read_forces(filepath) rho, u_inf = 1.0, 1.0 # density and freestream speed dyn_pressure = 0.5 * rho * u_inf**2 # dynamic pressure c = 1.0 # chord length Lz = 3.2 * c # spanwise length coeff = 1 / (dyn_pressure * c * Lz) # scaling factor for force coefficients cd, cl, cz = petibmpy.get_force_coefficients(fx, fy, fz, coeff=coeff) pyplot.rc('font', family='serif', size=16) fig, ax = pyplot.subplots(figsize=(8.0, 4.0)) ax.set_xlabel('Non-dimensional time') ax.set_ylabel('Force coefficients') ax.grid() ax.plot(t, cd, label='$C_D$') ax.plot(t, cl, label='$C_L$') ax.plot(t, cz, label='$C_z$') ax.legend() ax.set_xlim(t[0], t[-1])
v1 = (p1 - p2) / numpy.linalg.norm(p1 - p2) v2 = (p3 - p1) / numpy.linalg.norm(p3 - p1) v3 = numpy.cross(v1, v2) return v3 / numpy.linalg.norm(v3) # Set simulation directory and data directory. simudir = pathlib.Path(__file__).absolute().parents[1] datadir = simudir / 'output' # Create the wing kinematics. wing = rodney.WingKinematics(Re=200.0, St=0.6, psi=110.0, nt_period=2000) # Compute the cycle-averaged thrust. filepath = datadir / 'forces-0.txt' t, fx, _, _ = petibmpy.read_forces(filepath) thrust = -fx # switch from drag to thrust time_limits = (4 * wing.T, 5 * wing.T) # interval to consider for average thrust_avg, = petibmpy.get_time_averaged_values(t, thrust, limits=time_limits) # Compute the cycle-averaged thrust coefficient. rho, U_inf, A_plan = (getattr(wing, name) for name in ('rho', 'U_inf', 'A_plan')) scale = 1 / (0.5 * rho * U_inf**2 * A_plan) ct, = petibmpy.get_force_coefficients(thrust, coeff=scale) ct_avg, = petibmpy.get_time_averaged_values(t, ct, limits=time_limits) # Load original boundary coordinates from file. filepath = simudir / 'wing.body' wing.load_body(filepath, skiprows=1)
from matplotlib import pyplot import numpy import pathlib import petibmpy # Set directories and parameters. simudir = pathlib.Path(__file__).absolute().parents[1] rootdir = simudir.parents[2] datadir = rootdir / 'data' show_figure = True # display the Matplotlib figure save_figure = True # save the Matplotlib figure as PNG # Load drag force from file and compute drag coefficient. filepath = simudir / 'output' / 'forces-0.txt' t, fx, _ = petibmpy.read_forces(filepath) cd = 2 * fx # Load drag coefficient from Koumoutsakos & Leonard (1995). filename = 'koumoutsakos_leonard_1995_cylinder_dragCoefficientRe3000.dat' filepath = datadir / filename t2, cd2 = petibmpy.read_forces(filepath) t2 *= 0.5 # Plot the history of the drag coefficient. pyplot.rc('font', family='serif', size=14) fig, ax = pyplot.subplots(figsize=(6.0, 4.0)) ax.set_xlabel('Non-dimensional time') ax.set_ylabel('Drag coefficient') ax.plot(t, cd, label='PetIBM') ax.plot(t2,