💻 Fortran Source Code Library
We currently offer 172 open-source, production-grade Fortran codes for offline testing. Run calculations locally on your own machine, view code structure, read technical explanations, and download compilation packages including sample input files.
Rayleigh Flow Calculator
Core Numerical Engine in Fortran 90 • 31 total downloads
! =========================================================================
! Source File: rayleigh_flow.f90
! =========================================================================
! ============================================================================
! ThermoFluidCalc — Rayleigh Flow Solver
! Reference: Shapiro, Dynamics and Thermodynamics of Compressible Fluid Flow
! ============================================================================
program rayleigh_flow
implicit none
! Input variables
double precision :: M1 ! Inlet Mach number
double precision :: gamma ! Specific heat ratio (default 1.4)
double precision :: T01 ! Inlet Stagnation Temp [K] (0 = skip)
double precision :: P01 ! Inlet Stagnation Pressure [kPa] (0 = skip)
double precision :: q ! Heat added per unit mass [kJ/kg] (0 = skip)
! Constants
double precision, parameter :: R_air = 287.05d0 ! Gas constant [J/kg-K]
! Intermediate and output variables
double precision :: Cp, Cp_kJ
double precision :: T0star, q_max, q_Joules
double precision :: M2 ! Exit Mach number
double precision :: T2_T1, T02_T01, P2_P1, P02_P01, rho2_rho1
double precision :: T1, P1, rho1, V1, T2, P2, rho2, V2
double precision :: P02, T02 ! exit stagnation properties
double precision :: T_Tstar1, T0_T0star1, P_Pstar1, P0_P0star1, V_Vstar1, rho_rhostar1
double precision :: T_Tstar2, T0_T0star2, P_Pstar2, P0_P0star2, V_Vstar2, rho_rhostar2
double precision :: delta_s_over_R
double precision :: phi_target
double precision :: M1_orig
double precision :: P01_eff
integer :: status ! 1=Subsonic unchoked, 2=Supersonic unchoked, 3=Thermally choked
! Read input from stdin
read(*,*) M1
read(*,*) gamma
read(*,*) T01
read(*,*) P01
read(*,*) q
! Set defaults and bounds
if (gamma <= 1.0d0) gamma = 1.4d0
if (M1 <= 0.0d0) M1 = 0.5d0
if (q < 0.0d0) q = 0.0d0
! If heat is added, we must have reference stagnation temperature and pressure
! If the user did not provide them, we default them
if (T01 <= 0.0d0) T01 = 300.0d0
if (P01 <= 0.0d0) P01 = 101.325d0
M1_orig = M1
Cp = gamma * R_air / (gamma - 1.0d0) ! J/kg-K
Cp_kJ = Cp / 1000.0d0 ! kJ/kg-K
T0star = T01 / rayleigh_t0_ratio(M1, gamma)
q_max = Cp_kJ * (T0star - T01)
! Initialize shock effects for supersonic choking
P01_eff = P01
! ── DETERMINE FLOW STATUS AND SOLVE EXIT MACH ────────────
if (q <= q_max) then
! FLOW IS UNCHOKED
if (M1 < 1.0d0) then
status = 1 ! Subsonic unchoked
else
status = 2 ! Supersonic unchoked
end if
T02 = T01 + q / Cp_kJ
phi_target = T02 / T0star
if (M1 < 1.0d0) then
M2 = solve_mach_from_t0_ratio(phi_target, gamma, .true., M1)
else
M2 = solve_mach_from_t0_ratio(phi_target, gamma, .false., M1)
end if
else
! FLOW IS THERMALLY CHOKED
status = 3
M2 = 1.0d0
T02 = T01 + q / Cp_kJ ! Exit stagnation temperature
! The new inlet flow must become subsonic and adapt to a lower Mach number.
! This holds true for both subsonic and supersonic initial states.
phi_target = T01 / T02
M1 = solve_mach_from_t0_ratio(phi_target, gamma, .true., 0.5d0)
! Stagnation temperature at inlet remains constant
! Stagnation pressure at inlet remains constant if subsonic, or suffers shock loss if supersonic
if (M1_orig > 1.0d0) then
P01_eff = P01 * shock_p0_ratio(M1_orig, gamma)
else
P01_eff = P01
end if
! Re-calculate choking conditions for the new Rayleigh line
T0star = T01 / rayleigh_t0_ratio(M1, gamma)
q_max = Cp_kJ * (T0star - T01)
end if
! ── COMPUTE RAYLEIGH RATIOS AT INLET AND EXIT ────────────
T_Tstar1 = ((gamma + 1.0d0) * M1 / (1.0d0 + gamma * M1**2))**2
T0_T0star1 = rayleigh_t0_ratio(M1, gamma)
P_Pstar1 = (gamma + 1.0d0) / (1.0d0 + gamma * M1**2)
P0_P0star1 = P_Pstar1 * ((2.0d0 + (gamma - 1.0d0) * M1**2) / (gamma + 1.0d0))**(gamma / (gamma - 1.0d0))
V_Vstar1 = (gamma + 1.0d0) * M1**2 / (1.0d0 + gamma * M1**2)
rho_rhostar1 = 1.0d0 / V_Vstar1
T_Tstar2 = ((gamma + 1.0d0) * M2 / (1.0d0 + gamma * M2**2))**2
T0_T0star2 = rayleigh_t0_ratio(M2, gamma)
P_Pstar2 = (gamma + 1.0d0) / (1.0d0 + gamma * M2**2)
P0_P0star2 = P_Pstar2 * ((2.0d0 + (gamma - 1.0d0) * M2**2) / (gamma + 1.0d0))**(gamma / (gamma - 1.0d0))
V_Vstar2 = (gamma + 1.0d0) * M2**2 / (1.0d0 + gamma * M2**2)
rho_rhostar2 = 1.0d0 / V_Vstar2
! Property changes across duct
T2_T1 = T_Tstar2 / T_Tstar1
T02_T01 = T0_T0star2 / T0_T0star1
P2_P1 = P_Pstar2 / P_Pstar1
P02_P01 = (P01_eff / P01) * (P0_P0star2 / P0_P0star1)
rho2_rho1 = rho_rhostar2 / rho_rhostar1
delta_s_over_R = (gamma / (gamma - 1.0d0)) * log(T2_T1) - log(P2_P1)
! ── COMPUTE ACTUAL PHYSICAL PROPERTIES ───────────────────
T1 = T01 / (1.0d0 + (gamma - 1.0d0) / 2.0d0 * M1**2)
V1 = M1 * sqrt(gamma * R_air * T1)
P1 = P01_eff / (1.0d0 + (gamma - 1.0d0) / 2.0d0 * M1**2)**(gamma / (gamma - 1.0d0))
rho1 = P1 / (R_air * T1 / 1000.0d0)
T2 = T1 * T2_T1
V2 = M2 * sqrt(gamma * R_air * T2)
P2 = P1 * P2_P1
rho2 = P2 / (R_air * T2 / 1000.0d0)
P02 = P01_eff * (P0_P0star2 / P0_P0star1)
! ── OUTPUT RESULTS IN KEY-VALUE FORMAT ───────────────────
write(*, '(A, I2)') "Status Code = ", status
select case (status)
case (1)
write(*, '(A)') "Status = Subsonic Flow"
case (2)
write(*, '(A)') "Status = Supersonic Flow"
case (3)
if (M1_orig < 1.0d0) then
write(*, '(A)') "Status = Thermally Choked Subsonic Flow"
else
write(*, '(A)') "Status = Thermally Choked Supersonic Flow (Shocked)"
end if
end select
write(*, '(A, F14.6)') "Inlet Mach (M1) = ", M1
write(*, '(A, F14.6)') "Exit Mach (M2) = ", M2
write(*, '(A, F14.6)') "Original Inlet Mach = ", M1_orig
write(*, '(A, F14.6)') "Heat Added (q) = ", q
write(*, '(A, F14.6)') "Max Heat Added (q_max) = ", q_max
write(*, '(A, F14.6)') "Specific Heat Ratio (gamma) = ", gamma
write(*, '(A, F14.6)') "Inlet T/Tstar = ", T_Tstar1
write(*, '(A, F14.6)') "Inlet T0/T0star = ", T0_T0star1
write(*, '(A, F14.6)') "Inlet P/Pstar = ", P_Pstar1
write(*, '(A, F14.6)') "Inlet P0/P0star = ", P0_P0star1
write(*, '(A, F14.6)') "Inlet V/Vstar = ", V_Vstar1
write(*, '(A, F14.6)') "Inlet rho/rhostar = ", rho_rhostar1
write(*, '(A, F14.6)') "Exit T/Tstar = ", T_Tstar2
write(*, '(A, F14.6)') "Exit T0/T0star = ", T0_T0star2
write(*, '(A, F14.6)') "Exit P/Pstar = ", P_Pstar2
write(*, '(A, F14.6)') "Exit P0/P0star = ", P0_P0star2
write(*, '(A, F14.6)') "Exit V/Vstar = ", V_Vstar2
write(*, '(A, F14.6)') "Exit rho/rhostar = ", rho_rhostar2
write(*, '(A, F14.6)') "Temperature Ratio (T2/T1) = ", T2_T1
write(*, '(A, F14.6)') "Stagnation Temp Ratio (T02/T01) = ", T02_T01
write(*, '(A, F14.6)') "Pressure Ratio (P2/P1) = ", P2_P1
write(*, '(A, F14.6)') "Stagnation Pressure Ratio (P02/P01) = ", P02_P01
write(*, '(A, F14.6)') "Density Ratio (rho2/rho1) = ", rho2_rho1
write(*, '(A, F14.6)') "Entropy Change (delta_s/R) = ", delta_s_over_R
write(*, '(A, F14.4)') "Inlet Temperature (T1) = ", T1
write(*, '(A, F14.4)') "Exit Temperature (T2) = ", T2
write(*, '(A, F14.2)') "Inlet Velocity (V1) = ", V1
write(*, '(A, F14.2)') "Exit Velocity (V2) = ", V2
write(*, '(A, F14.4)') "Inlet Pressure (P1) = ", P1
write(*, '(A, F14.4)') "Exit Pressure (P2) = ", P2
write(*, '(A, F14.4)') "Inlet Stagnation Temp (T01) = ", T01
write(*, '(A, F14.4)') "Exit Stagnation Temp (T02) = T02"
write(*, '(A, F14.4)') "Inlet Stagnation Pres (P01) = ", P01
write(*, '(A, F14.4)') "Exit Stagnation Pres (P02) = ", P02
write(*, '(A, F14.6)') "Inlet Density (rho1) = ", rho1
write(*, '(A, F14.6)') "Exit Density (rho2) = ", rho2
contains
! Stagnation temperature ratio function T0/T0*
double precision function rayleigh_t0_ratio(M, g)
double precision, intent(in) :: M, g
rayleigh_t0_ratio = (2.0d0 * (g + 1.0d0) * M**2 * (1.0d0 + (g - 1.0d0) / 2.0d0 * M**2)) / (1.0d0 + g * M**2)**2
end function rayleigh_t0_ratio
! Stagnation pressure ratio across a normal shock P02/P01
double precision function shock_p0_ratio(M, g)
double precision, intent(in) :: M, g
double precision :: t1, t2
t1 = (g + 1.0d0) / (2.0d0 * g * M**2 - (g - 1.0d0))
t2 = ((g + 1.0d0) * M**2) / (2.0d0 + (g - 1.0d0) * M**2)
shock_p0_ratio = t1**(1.0d0 / (g - 1.0d0)) * t2**(g / (g - 1.0d0))
end function shock_p0_ratio
! Solve Mach number from Stagnation Temperature Ratio using Newton-Raphson
double precision function solve_mach_from_t0_ratio(target_phi, g, is_sub, init_guess)
double precision, intent(in) :: target_phi, g, init_guess
logical, intent(in) :: is_sub
double precision :: M, M_next, f_val, df_val
double precision :: num, den, dnum, dden
integer :: iter
M = init_guess
if (is_sub .and. M >= 1.0d0) M = 0.5d0
if (.not. is_sub .and. M <= 1.0d0) M = 2.0d0
! Safeguard target_phi
if (target_phi >= 0.99999d0) then
solve_mach_from_t0_ratio = 1.0d0
return
end if
do iter = 1, 100
! We solve N(M) - target_phi * D(M) = 0
! N(M) = 2(g+1)M^2 + (g^2 - 1)M^4
! D(M) = (1 + g M^2)^2
num = 2.0d0 * (g + 1.0d0) * M**2 + (g**2 - 1.0d0) * M**4
den = (1.0d0 + g * M**2)**2
f_val = num - target_phi * den
! Derivatives:
! N'(M) = 4(g+1)M + 4(g^2 - 1)M^3
! D'(M) = 4 g M (1 + g M^2)
dnum = 4.0d0 * (g + 1.0d0) * M + 4.0d0 * (g**2 - 1.0d0) * M**3
dden = 4.0d0 * g * M * (1.0d0 + g * M**2)
df_val = dnum - target_phi * dden
if (abs(df_val) < 1.0d-12) exit
M_next = M - f_val / df_val
! Keep guess in bounds
if (is_sub) then
if (M_next <= 0.0d0) M_next = M / 2.0d0
if (M_next >= 1.0d0) M_next = (M + 1.0d0) / 2.0d0
else
if (M_next <= 1.0d0) M_next = (M + 1.0d0) / 2.0d0
end if
if (abs(M_next - M) < 1.0d-8) then
M = M_next
exit
end if
M = M_next
end do
solve_mach_from_t0_ratio = M
end function solve_mach_from_t0_ratio
end program rayleigh_flow
Solver Description
Solves 1D compressible flow with heat addition or extraction (Rayleigh Flow) for both subsonic and supersonic regimes. Computes Rayleigh line ratios (T/T*, T0/T0*, P/P*, P0/P0*, V/V*), maximum heat addition before choking, and entropy changes. Resolves exit Mach numbers for arbitrary heat inputs, determines thermal choking limits, and computes adjusted subsonic inlet states and shock losses for choked ducts.
Key Numerical Methods & Architecture
- Input Redirection: Reads parameters sequentially from standard input (`stdin`) using Fortran sequential read (`read(*,*)`), ensuring modular integration.
- Modular Design: Formulated using pure mathematical routines, separation of equations from output formatting, and precise numerical solvers (e.g. bisection, Newton-Raphson).
- Standard Compliant: Written in clean, standards-compliant Fortran 90 to ensure cross-compiler compatibility.
🛠️ Local Compilation
To test this code on your machine, compile the source code file(s) using a standard Fortran compiler (e.g., `gfortran`).
Compilation Command:
Execution Command:
Execute the program by feeding the sample input file into the program using stdin redirection:
📥 Downloads & Local Files
Preview of the required input file (input.txt):
0.5
! Specific heat ratio gamma
1.4
! Inlet stagnation temp T0 [K]
300.0
! Inlet stagnation pressure P0 [kPa]
101.325
! Heat added q [kJ/kg]
50.0