π¬
Solver Purpose & Physical Scope
Model adiabatic compressible duct flow with friction: exit Mach (M2), choking length (Lmax), static and total pressure losses, and temperature variations.
π Discipline: Cfd
β‘ Precision: IEEE-754 64-bit Real(`real(8)`)
π₯ Total Downloads: 195 times
π Source File:
compressible_fanno_flow_duct.f90
π calcul/CFD /
compressible_fanno_flow_duct.f90
program compressible_fanno_flow_duct
implicit none
integer :: iostat_val, iter
double precision :: M1_mach, D_duct_mm, L_duct_m, f_fanning, P01_bar, T01_K, gamma_ratio
double precision :: D_m, f4LD_1, Lmax1_m, f4LD_2, M2_mach, M_low, M_high, M_mid, f4LD_mid
double precision :: T_Tstar_1, T_Tstar_2, P_Pstar_1, P_Pstar_2, P0_P0star_1, P0_P0star_2
double precision :: P1_bar, P2_bar, P02_bar, T1_K, T2_K
logical :: is_choked
! Read inputs
read(*,*,iostat=iostat_val) M1_mach ! Inlet Mach Number (e.g. 0.35)
read(*,*,iostat=iostat_val) D_duct_mm ! Duct Diameter [mm] (e.g. 100.0)
read(*,*,iostat=iostat_val) L_duct_m ! Duct Length [m] (e.g. 25.0)
read(*,*,iostat=iostat_val) f_fanning ! Fanning Friction Factor (e.g. 0.005)
read(*,*,iostat=iostat_val) P01_bar ! Total Pressure [bar] (e.g. 6.0)
read(*,*,iostat=iostat_val) T01_K ! Total Temperature [K] (e.g. 300.0)
read(*,*,iostat=iostat_val) gamma_ratio ! Specific Heat Ratio (e.g. 1.40)
if (iostat_val /= 0) then
write(*,*) 'ERROR: Invalid input data for Fanno flow calculation.'
stop
end if
if (M1_mach <= 0.01d0 .or. D_duct_mm <= 0.0d0 .or. L_duct_m <= 0.0d0 .or. f_fanning <= 0.0d0) then
write(*,*) 'ERROR: Mach, diameter, length, and friction factor must be positive.'
stop
end if
D_m = D_duct_mm * 1.0d-3
! Inlet Fanno Parameter (4fL*/D)1
f4LD_1 = (1.0d0 - (M1_mach**2)) / (gamma_ratio * (M1_mach**2)) + &
((gamma_ratio + 1.0d0) / (2.0d0 * gamma_ratio)) * &
log(((gamma_ratio + 1.0d0) * (M1_mach**2)) / (2.0d0 + (gamma_ratio - 1.0d0) * (M1_mach**2)))
Lmax1_m = f4LD_1 * D_m / (4.0d0 * f_fanning)
if (L_duct_m >= Lmax1_m) then
is_choked = .true.
M2_mach = 1.0d0
f4LD_2 = 0.0d0
else
is_choked = .false.
f4LD_2 = f4LD_1 - (4.0d0 * f_fanning * L_duct_m) / D_m
! Solve for M2 via Bisection
if (M1_mach < 1.0d0) then
M_low = M1_mach
M_high = 0.9999d0
else
M_low = 1.0001d0
M_high = M1_mach
end if
do iter = 1, 100
M_mid = 0.5d0 * (M_low + M_high)
f4LD_mid = (1.0d0 - (M_mid**2)) / (gamma_ratio * (M_mid**2)) + &
((gamma_ratio + 1.0d0) / (2.0d0 * gamma_ratio)) * &
log(((gamma_ratio + 1.0d0) * (M_mid**2)) / (2.0d0 + (gamma_ratio - 1.0d0) * (M_mid**2)))
if (M1_mach < 1.0d0) then
if (f4LD_mid > f4LD_2) then
M_low = M_mid
else
M_high = M_mid
end if
else
if (f4LD_mid < f4LD_2) then
M_low = M_mid
else
M_high = M_mid
end if
end if
end do
M2_mach = M_mid
end if
! Sonic Reference Ratios
T_Tstar_1 = (gamma_ratio + 1.0d0) / (2.0d0 + (gamma_ratio - 1.0d0) * (M1_mach**2))
T_Tstar_2 = (gamma_ratio + 1.0d0) / (2.0d0 + (gamma_ratio - 1.0d0) * (M2_mach**2))
P_Pstar_1 = (1.0d0 / M1_mach) * sqrt(T_Tstar_1)
P_Pstar_2 = (1.0d0 / M2_mach) * sqrt(T_Tstar_2)
P0_P0star_1 = (1.0d0 / M1_mach) * ((2.0d0 + (gamma_ratio - 1.0d0) * (M1_mach**2)) / &
(gamma_ratio + 1.0d0))**((gamma_ratio + 1.0d0) / (2.0d0 * (gamma_ratio - 1.0d0)))
P0_P0star_2 = (1.0d0 / M2_mach) * ((2.0d0 + (gamma_ratio - 1.0d0) * (M2_mach**2)) / &
(gamma_ratio + 1.0d0))**((gamma_ratio + 1.0d0) / (2.0d0 * (gamma_ratio - 1.0d0)))
P1_bar = P01_bar * (1.0d0 + 0.5d0 * (gamma_ratio - 1.0d0) * (M1_mach**2))**(-gamma_ratio / (gamma_ratio - 1.0d0))
P2_bar = P1_bar * (P_Pstar_2 / P_Pstar_1)
P02_bar = P01_bar * (P0_P0star_2 / P0_P0star_1)
T1_K = T01_K / (1.0d0 + 0.5d0 * (gamma_ratio - 1.0d0) * (M1_mach**2))
T2_K = T1_K * (T_Tstar_2 / T_Tstar_1)
! Output Results
write(*,'(A)') '============================================================'
write(*,'(A)') ' THERMOFLUIDCALC β COMPRESSIBLE FANNO FLOW ENGINE'
write(*,'(A)') '============================================================'
write(*,'(A,F10.2,A,F10.2,A)') 'Duct Diam / Length (f) = ', D_duct_mm, ' mm / ', L_duct_m, ' m (f = ', f_fanning, ')'
write(*,'(A,F10.2,A,F10.2,A)') 'Inlet Mach / Stagnation P0= ', M1_mach, ' / ', P01_bar, ' bar'
write(*,'(A)') '------------------------------------------------------------'
write(*,'(A,F10.4)') 'EXIT MACH NUMBER (M2) = ', M2_mach
write(*,'(A,F10.2,A)') 'Sonic Choking Length Lmax = ', Lmax1_m, ' meters'
if (is_choked) then
write(*,'(A)') 'Flow Status = CHOKED (Sonic Throat M2 = 1.0)'
else
write(*,'(A)') 'Flow Status = UNCHOKED (Friction limited)'
end if
write(*,'(A,F10.3,A,F10.3,A)') 'Static Pressure P1 -> P2 = ', P1_bar, ' bar -> ', P2_bar, ' bar'
write(*,'(A,F10.3,A,F10.3,A)') 'Total Pressure P01 -> P02 = ', P01_bar, ' bar -> ', P02_bar, ' bar'
write(*,'(A,F10.1,A,F10.1,A)') 'Static Temp T1 -> T2 = ', T1_K, ' K -> ', T2_K, ' K'
write(*,'(A)') '============================================================'
end program compressible_fanno_flow_duct
π» How to Compile & Run Locally
1. Compilation (GNU Fortran / Intel oneAPI):
gfortran -O3 compressible_fanno_flow_duct.f90 -o compressible_fanno_flow_duct
2. Execution with input.txt redirection:
compressible_fanno_flow_duct < input.txt
π Sample input.txt File Structure
Sample Data:
0.25 80.0 30.0 0.005 7.0 295.0 1.40
Parameter Description:
Inlet Mach Number\nDuct Diameter [mm]\nDuct Length [m]\nFanning Friction Factor f\nInlet Total Pressure [bar]\nInlet Total Temp [K]\nSpecific Heat Ratio gamma