Calculate Dimensional Forces#
Two snippets will demonstrate how to obtain dimensional forces in the following scenarios:
total forces on the wall boundaries
forces excluding selected boundaries
Total Forces on the Wall Boundaries#
import flow360 as fl
import pandas as pd
case = fl.Case.from_cloud(case_id="your-case-id")
# the data structure holding the force coefficients, averaged over the last 10% of pseudo steps
forces_total = case.results.total_forces.get_averages(0.1)
# gather all reference values
density = case.params.operating_condition.thermal_state.density
reference_velocity = case.params.reference_velocity
reference_area = case.params.reference_geometry.area
reference_length = case.params.reference_geometry.moment_length
# Calculate dynamic pressure
dynamic_pressure = 0.5 * density * reference_velocity**2
# Calculate forces from force coefficients (F = Cf * q * A)
force_scale = dynamic_pressure * reference_area
# Calculate moments from moment coefficients (M = Cm * q * A * L)
moment_scale = force_scale * reference_length
# Create a new series with actual forces and moments
forces_actual = {}
# Convert force coefficients to forces (N)
force_coeffs = ['CL', 'CD', 'CFx', 'CFy', 'CFz',
'CLPressure', 'CDPressure', 'CFxPressure', 'CFyPressure', 'CFzPressure',
'CLSkinFriction', 'CDSkinFriction', 'CFxSkinFriction', 'CFySkinFriction', 'CFzSkinFriction']
for coeff in force_coeffs:
forces_actual[coeff.lstrip("C")] = (forces_total[coeff] * force_scale).to(fl.u.N)
# Convert moment coefficients to moments (N·m)
moment_x_coeffs = ['CMx', 'CMxPressure', 'CMxSkinFriction']
moment_y_coeffs = ['CMy', 'CMyPressure', 'CMySkinFriction']
moment_z_coeffs = ['CMz', 'CMzPressure', 'CMzSkinFriction']
for coeff in moment_x_coeffs:
forces_actual[coeff.lstrip("C")] = (forces_total[coeff] * moment_scale[0]).to(fl.u.N * fl.u.m)
for coeff in moment_y_coeffs:
forces_actual[coeff.lstrip("C")] = (forces_total[coeff] * moment_scale[1]).to(fl.u.N * fl.u.m)
for coeff in moment_z_coeffs:
forces_actual[coeff.lstrip("C")] = (forces_total[coeff] * moment_scale[2]).to(fl.u.N * fl.u.m)
# Rename the series to indicate these are actual forces/moments
forces_actual = pd.Series(forces_actual)
# Print the results
print("\n" + "="*60)
print("FORCE COEFFICIENTS:")
print("="*60)
print(forces_total)
print("\n" + "="*60)
print("ACTUAL FORCES (N) AND MOMENTS (N·m):")
print("="*60)
print(forces_actual)
Forces Excluding Selected Boundaries#
import flow360 as fl
import pandas as pd
case = fl.Case.from_cloud(case_id="your-case-id")
# the data structure holding the force coefficients
forces_by_surface = case.results.surface_forces
# exclude the wind tunnel elements
forces_by_surface.filter(exclude="*tunnel*")
# perform averaging
forces_total = forces_by_surface.get_averages(0.1)
# gather all reference values
density = case.params.operating_condition.thermal_state.density
reference_velocity = case.params.reference_velocity
reference_area = case.params.reference_geometry.area
reference_length = case.params.reference_geometry.moment_length
# Calculate dynamic pressure
dynamic_pressure = 0.5 * density * reference_velocity**2
# Calculate forces from force coefficients (F = Cf * q * A)
force_scale = dynamic_pressure * reference_area
# Calculate moments from moment coefficients (M = Cm * q * A * L)
moment_scale = force_scale * reference_length
# Create a new series with actual forces and moments
forces_actual = {}
# Convert force coefficients to forces (N)
force_coeffs = ['totalCL', 'totalCD', 'totalCFx', 'totalCFy', 'totalCFz',
'totalCLPressure', 'totalCDPressure', 'totalCFxPressure', 'totalCFyPressure', 'totalCFzPressure',
'totalCLSkinFriction', 'totalCDSkinFriction', 'totalCFxSkinFriction', 'totalCFySkinFriction', 'totalCFzSkinFriction']
for coeff in force_coeffs:
forces_actual[coeff.lstrip("C")] = (forces_total[coeff] * force_scale).to(fl.u.N)
# Convert moment coefficients to moments (N·m)
moment_x_coeffs = ['totalCMx', 'totalCMxPressure', 'totalCMxSkinFriction']
moment_y_coeffs = ['totalCMy', 'totalCMyPressure', 'totalCMySkinFriction']
moment_z_coeffs = ['totalCMz', 'totalCMzPressure', 'totalCMzSkinFriction']
for coeff in moment_x_coeffs:
forces_actual[coeff.lstrip("C")] = (forces_total[coeff] * moment_scale[0]).to(fl.u.N * fl.u.m)
for coeff in moment_y_coeffs:
forces_actual[coeff.lstrip("C")] = (forces_total[coeff] * moment_scale[1]).to(fl.u.N * fl.u.m)
for coeff in moment_z_coeffs:
forces_actual[coeff.lstrip("C")] = (forces_total[coeff] * moment_scale[2]).to(fl.u.N * fl.u.m)
# Rename the series to indicate these are actual forces/moments
forces_actual = pd.Series(forces_actual)
# Print the results
print("\n" + "="*60)
print("FORCE COEFFICIENTS - WIND TUNNEL EXCLUDED:")
print("="*60)
print(forces_total[forces_total.index.str.startswith("total")])
print("\n" + "="*60)
print("ACTUAL FORCES (N) AND MOMENTS (N·m) - WIND TUNNEL EXCLUDED:")
print("="*60)
print(forces_actual)
Note
The filter() method also supports an include argument for selecting only specific boundaries
(e.g., forces_by_surface.filter(include="*wing*")). Both include and exclude accept
wildcard patterns.