💻 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.

Regenerative Rankine Cycle

Core Numerical Engine in Fortran 90 • 29 total downloads

rankine_regenerative.f90
! =========================================================================
! Source File: rankine_regenerative.f90
! =========================================================================

program rankine_regenerative
    implicit none
    integer :: fwh_type, n_extractions, i, iostat_val
    double precision :: P_boiler, T_boiler, P_cond, P_ext1, P_ext2
    double precision :: eta_turbine, eta_pump
    double precision :: h1, s1, h2a, h2s, h3a, h3s, h4, h5, h6a, h6s
    double precision :: h_f_cond, h_fg_cond, s_f_cond, s_fg_cond, T_sat_cond
    double precision :: h_f_ext1, h_fg_ext1, s_f_ext1, s_fg_ext1, T_sat_ext1
    double precision :: h_f_ext2, h_fg_ext2, s_f_ext2, s_fg_ext2, T_sat_ext2
    double precision :: h_f_boil, s_f_boil, T_sat_boil, v_f_cond, v_f_ext1
    double precision :: x2, x3, y1, y2, Wt, Wp, Wnet, Qin, Qout
    double precision :: eta_th, bwr, m_dot, P_output, SSC
    double precision :: h_fw, h_mix, v_f_ext2
    double precision :: P_i, eta_i, y_i
    double precision, parameter :: Ru = 8.314462d0
    character(len=40) :: fwh_name

    read(*,*,iostat=iostat_val) P_boiler
    if (iostat_val /= 0) then
        write(*,*) 'ERROR: Invalid boiler pressure input.'
        stop
    end if
    read(*,*,iostat=iostat_val) T_boiler
    read(*,*,iostat=iostat_val) P_cond
    read(*,*,iostat=iostat_val) n_extractions
    read(*,*,iostat=iostat_val) P_ext1
    read(*,*,iostat=iostat_val) P_ext2
    read(*,*,iostat=iostat_val) fwh_type
    read(*,*,iostat=iostat_val) eta_turbine
    read(*,*,iostat=iostat_val) eta_pump
    read(*,*,iostat=iostat_val) m_dot
    if (iostat_val /= 0) then
        write(*,*) 'ERROR: Failed to read all Rankine inputs.'
        stop
    end if
    if (P_boiler <= 0.0d0 .or. P_cond <= 0.0d0) then
        write(*,*) 'ERROR: Pressures must be positive.'
        stop
    end if
    if (P_boiler <= P_cond) then
        write(*,*) 'ERROR: Boiler pressure must exceed condenser pressure.'
        stop
    end if
    if (eta_turbine <= 0.0d0 .or. eta_turbine > 1.0d0) eta_turbine = 0.88d0
    if (eta_pump <= 0.0d0 .or. eta_pump > 1.0d0) eta_pump = 0.85d0
    if (n_extractions < 1) n_extractions = 1
    if (n_extractions > 2) n_extractions = 2
    if (P_ext1 <= P_cond .or. P_ext1 >= P_boiler) P_ext1 = sqrt(P_boiler*P_cond)
    if (n_extractions == 2) then
        if (P_ext2 <= P_cond .or. P_ext2 >= P_ext1) &
            P_ext2 = sqrt(P_cond*P_ext1)
    end if
    if (m_dot <= 0.0d0) m_dot = 1.0d0

    if (fwh_type == 1) then
        fwh_name = 'Open feedwater heater (direct contact)'
    else
        fwh_name = 'Closed feedwater heater (shell-tube)'
        fwh_type = 2
    end if

    ! Compute saturation properties at key pressures
    call sat_props(P_cond, T_sat_cond, h_f_cond, h_fg_cond, s_f_cond, s_fg_cond, v_f_cond)
    call sat_props(P_ext1, T_sat_ext1, h_f_ext1, h_fg_ext1, s_f_ext1, s_fg_ext1, v_f_ext1)
    if (n_extractions == 2) then
        call sat_props(P_ext2, T_sat_ext2, h_f_ext2, h_fg_ext2, s_f_ext2, s_fg_ext2, v_f_ext2)
    end if
    call sat_props(P_boiler, T_sat_boil, h_f_boil, h_fg_cond, s_f_boil, s_fg_cond, v_f_cond)

    ! State 1: Turbine inlet (superheated steam at P_boiler, T_boiler)
    call superheat_props(P_boiler, T_boiler, T_sat_boil, h_f_boil, s_f_boil, h1, s1)

    ! State 2: After first extraction (isentropic expansion to P_ext1)
    call sat_props(P_ext1, T_sat_ext1, h_f_ext1, h_fg_ext1, s_f_ext1, s_fg_ext1, v_f_ext1)
    x2 = (s1 - s_f_ext1) / max(s_fg_ext1, 1.0d-10)
    if (x2 > 1.0d0) then
        ! Still superheated at extraction
        call superheat_from_entropy(P_ext1, s1, T_sat_ext1, h_f_ext1, s_f_ext1, s_fg_ext1, h2s)
    else
        h2s = h_f_ext1 + x2 * h_fg_ext1
    end if
    h2a = h1 - eta_turbine * (h1 - h2s)

    ! State 3: Turbine exit (isentropic expansion to P_cond)
    call sat_props(P_cond, T_sat_cond, h_f_cond, h_fg_cond, s_f_cond, s_fg_cond, v_f_cond)
    x3 = (s1 - s_f_cond) / max(s_fg_cond, 1.0d-10)
    if (x3 > 1.0d0) then
        call superheat_from_entropy(P_cond, s1, T_sat_cond, h_f_cond, s_f_cond, s_fg_cond, h3s)
    else
        h3s = h_f_cond + x3 * h_fg_cond
    end if
    h3a = h1 - eta_turbine * (h1 - h3s)

    ! State 4: Condenser exit (saturated liquid at P_cond)
    h4 = h_f_cond

    ! Pump work and extraction fraction calculation
    if (n_extractions == 1) then
        if (fwh_type == 1) then
            ! OPEN FWH: 1 extraction
            ! Pump 1: P_cond → P_ext1
            call sat_props(P_cond, T_sat_cond, h_f_cond, h_fg_cond, s_f_cond, s_fg_cond, v_f_cond)
            h5 = h4 + v_f_cond*(P_ext1 - P_cond)/eta_pump   ! after pump 1
            ! FWH energy balance: y*h2a + (1-y)*h5 = h_f_ext1
            h_fw = h_f_ext1
            y1 = (h_fw - h5) / max(h2a - h5, 1.0d-10)
            if (y1 < 0.0d0) y1 = 0.0d0
            if (y1 > 1.0d0) y1 = 1.0d0
            ! Pump 2: P_ext1 → P_boiler
            h6a = h_fw + v_f_ext1*(P_boiler - P_ext1)/eta_pump
            ! Turbine work per unit mass at boiler
            Wt = (h1 - h2a) + (1.0d0 - y1)*(h2a - h3a)
            ! Pump work
            Wp = (1.0d0 - y1)*(h5 - h4) + (h6a - h_fw)
            Qin = h1 - h6a
        else
            ! CLOSED FWH: 1 extraction
            h5 = h4 + v_f_cond*(P_boiler - P_cond)/eta_pump
            ! Closed FWH: extracted steam heats feedwater
            ! y*h2a + h5 = y*h_f_ext1 + h_fw (drain to trap)
            ! Assume drain cascaded back: h_fw = h5 + y*(h2a - h_f_ext1)
            y1 = (h_f_ext1 - h5) / max((h2a - h_f_ext1) + (h_f_ext1 - h5), 1.0d-10)
            if (y1 < 0.0d0) y1 = 0.0d0
            if (y1 > 1.0d0) y1 = 1.0d0
            h6a = h5 + y1*(h2a - h_f_ext1)
            Wt = (h1 - h2a) + (1.0d0 - y1)*(h2a - h3a)
            Wp = (h5 - h4)
            Qin = h1 - h6a
        end if
        y2 = 0.0d0
    else
        ! 2 extractions — open FWH simplified
        call sat_props(P_ext2, T_sat_ext2, h_f_ext2, h_fg_ext2, s_f_ext2, s_fg_ext2, v_f_ext2)
        ! Intermediate extraction state
        ! For simplicity: second extraction between ext1 and condenser
        ! Recompute h at P_ext2 from isentropic expansion
        x2 = (s1 - s_f_ext2) / max(s_fg_ext2, 1.0d-10)
        if (x2 > 1.0d0) then
            call superheat_from_entropy(P_ext2, s1, T_sat_ext2, h_f_ext2, &
                                        s_f_ext2, s_fg_ext2, h_mix)
        else
            h_mix = h_f_ext2 + x2 * h_fg_ext2
        end if
        h_mix = h1 - eta_turbine*(h1 - h_mix)  ! actual h at ext2

        ! Pump 1: P_cond → P_ext2
        h5 = h4 + v_f_cond*(P_ext2 - P_cond)/eta_pump
        ! Open FWH 1 at P_ext2
        y2 = (h_f_ext2 - h5) / max(h_mix - h5, 1.0d-10)
        if (y2 < 0.0d0) y2 = 0.0d0
        if (y2 > 0.5d0) y2 = 0.5d0

        ! Pump 2: P_ext2 → P_ext1
        h_fw = h_f_ext2 + v_f_ext2*(P_ext1 - P_ext2)/eta_pump
        ! Open FWH 2 at P_ext1
        y1 = (h_f_ext1 - h_fw) / max(h2a - h_fw, 1.0d-10)
        if (y1 < 0.0d0) y1 = 0.0d0
        if (y1 > 0.5d0) y1 = 0.5d0

        ! Pump 3: P_ext1 → P_boiler
        h6a = h_f_ext1 + v_f_ext1*(P_boiler - P_ext1)/eta_pump

        Wt = (h1 - h2a) + (1.0d0-y1)*(h2a - h_mix) + (1.0d0-y1-y2)*(h_mix - h3a)
        Wp = (1.0d0-y1-y2)*(h5-h4) + (1.0d0-y1)*(h_fw-h_f_ext2) + (h6a-h_f_ext1)
        Qin = h1 - h6a
    end if

    Wnet = Wt - Wp
    Qout = (1.0d0 - y1 - y2) * (h3a - h4)
    eta_th = Wnet / max(Qin, 1.0d-10)
    bwr = Wp / max(Wt, 1.0d-10)
    P_output = m_dot * Wnet / 1000.0d0    ! kW
    SSC = 3600.0d0 / max(Wnet, 1.0d-10)   ! kg/kWh

    write(*,'(A)') '============================================================'
    write(*,'(A)') '   RANKINE CYCLE — REGENERATIVE ENGINE'
    write(*,'(A)') '============================================================'
    write(*,*)
    write(*,'(A)') '--- INPUTS --------------------------------------------------'
    write(*,'(A,ES12.4,A)') '  Boiler Pressure           = ', P_boiler, ' Pa'
    write(*,'(A,F12.2,A)')  '  Boiler Temperature        = ', T_boiler, ' K'
    write(*,'(A,ES12.4,A)') '  Condenser Pressure        = ', P_cond, ' Pa'
    write(*,'(A,I8)')       '  Number of Extractions     = ', n_extractions
    write(*,'(A,ES12.4,A)') '  Extraction 1 Pressure     = ', P_ext1, ' Pa'
    if (n_extractions == 2) &
    write(*,'(A,ES12.4,A)') '  Extraction 2 Pressure     = ', P_ext2, ' Pa'
    write(*,'(A,A)')        '  FWH Type                  = ', trim(fwh_name)
    write(*,'(A,F10.4)')    '  Turbine Isentropic Eff    = ', eta_turbine
    write(*,'(A,F10.4)')    '  Pump Isentropic Eff       = ', eta_pump
    write(*,'(A,ES12.4,A)') '  Mass Flow Rate            = ', m_dot, ' kg/s'
    write(*,*)
    write(*,'(A)') '--- SATURATION DATA -----------------------------------------'
    write(*,'(A,F12.2,A)')  '  T_sat (boiler)            = ', T_sat_boil, ' K'
    write(*,'(A,F12.2,A)')  '  T_sat (ext1)              = ', T_sat_ext1, ' K'
    if (n_extractions == 2) &
    write(*,'(A,F12.2,A)')  '  T_sat (ext2)              = ', T_sat_ext2, ' K'
    write(*,'(A,F12.2,A)')  '  T_sat (condenser)         = ', T_sat_cond, ' K'
    write(*,*)
    write(*,'(A)') '--- STATE POINTS (per kg at boiler) -------------------------'
    write(*,'(A)') '  Point   h[kJ/kg]      s[kJ/kgK]     T[K]          P[Pa]'
    write(*,'(A)') '  ----------------------------------------------------------------'
    write(*,'(A,F12.2,2X,F10.4,2X,F12.2,2X,ES12.4)') '  1 turb in  ', h1/1000, s1/1000, T_boiler, P_boiler
    write(*,'(A,F12.2,2X,A,2X,F12.2,2X,ES12.4)')     '  2 ext1     ', h2a/1000, '  ---     ', T_sat_ext1, P_ext1
    write(*,'(A,F12.2,2X,A,2X,F12.2,2X,ES12.4)')     '  3 turb out ', h3a/1000, '  ---     ', T_sat_cond, P_cond
    write(*,'(A,F12.2,2X,A,2X,F12.2,2X,ES12.4)')     '  4 cond out ', h4/1000,  '  ---     ', T_sat_cond, P_cond
    write(*,'(A,F12.2,2X,A,2X,A,2X,ES12.4)')         '  6 boil in  ', h6a/1000, '  ---     ', '  ---       ', P_boiler
    write(*,*)
    write(*,'(A)') '--- EXTRACTION FRACTIONS ------------------------------------'
    write(*,'(A,F10.5)')    '  y1 (extraction 1)         = ', y1
    if (n_extractions == 2) &
    write(*,'(A,F10.5)')    '  y2 (extraction 2)         = ', y2
    write(*,'(A,F10.5)')    '  Condenser fraction        = ', 1.0d0-y1-y2
    write(*,*)
    write(*,'(A)') '--- ENERGY PER UNIT MASS ------------------------------------'
    write(*,'(A,F12.2,A)')  '  Turbine Work Wt           = ', Wt/1000, ' kJ/kg'
    write(*,'(A,F12.2,A)')  '  Pump Work Wp              = ', Wp/1000, ' kJ/kg'
    write(*,'(A,F12.2,A)')  '  Net Work Wnet             = ', Wnet/1000, ' kJ/kg'
    write(*,'(A,F12.2,A)')  '  Heat Input Qin            = ', Qin/1000, ' kJ/kg'
    write(*,'(A,F12.2,A)')  '  Heat Rejected Qout        = ', Qout/1000, ' kJ/kg'
    write(*,*)
    write(*,'(A)') '--- CYCLE PERFORMANCE ---------------------------------------'
    write(*,'(A,F10.4)')    '  Thermal Efficiency        = ', eta_th
    write(*,'(A,F10.2,A)')  '  Thermal Efficiency        = ', eta_th*100.0d0, ' percent'
    write(*,'(A,F10.4)')    '  Back-Work Ratio           = ', bwr
    write(*,'(A,F12.2,A)')  '  Power Output              = ', P_output, ' kW'
    write(*,'(A,F10.4,A)')  '  Specific Steam Consumption= ', SSC, ' kg/kWh'
    write(*,*)

    ! Efficiency vs extraction pressure sweep
    write(*,'(A)') '--- EFFICIENCY VS EXTRACTION PRESSURE SWEEP -----------------'
    write(*,'(A)') '  P_ext1[kPa]   y1            eta_th        Wnet[kJ/kg]'
    write(*,'(A)') '  -----------------------------------------------------------'
    do i = 1, 40
        P_i = P_cond + (P_boiler - P_cond) * dble(i) / 41.0d0
        call compute_single_extraction(P_boiler, T_boiler, P_cond, P_i, &
            eta_turbine, eta_pump, h1, s1, h_f_cond, v_f_cond, eta_i, y_i)
        write(*,'(F12.2,2X,F10.5,2X,F10.5,2X,F12.2)') P_i/1000.0d0, y_i, eta_i, &
            eta_i * (h1 - h_f_cond - v_f_cond*(P_boiler-P_cond)/eta_pump) / 1000.0d0
    end do
    write(*,*)
    write(*,'(A)') '--- CORRELATIONS USED ---------------------------------------'
    write(*,'(A)') '  Simplified water saturation correlations (curve fits).'
    write(*,'(A)') '  Isentropic turbine: h_out = h_in - eta_t*(h_in - h_out_s).'
    write(*,'(A)') '  Pump work: w_p = v_f*(P_out - P_in)/eta_p.'
    write(*,'(A)') '  Open FWH: y*h_ext + (1-y)*h_fw = h_f_sat.'

contains

    subroutine sat_props(P_pa, Tsat, hf, hfg, sf, sfg, vf)
        implicit none
        double precision, intent(in) :: P_pa
        double precision, intent(out) :: Tsat, hf, hfg, sf, sfg, vf
        double precision :: P_MPa, logP
        P_MPa = P_pa / 1.0d6
        if (P_MPa < 0.001d0) P_MPa = 0.001d0
        logP = log(P_MPa)
        ! Curve-fit approximations for water (valid ~5 kPa to 22 MPa)
        Tsat = 373.15d0 + 42.0d0*logP - 0.8d0*logP**2   ! K
        if (Tsat < 290.0d0) Tsat = 290.0d0 + 15.0d0*P_MPa
        if (Tsat > 647.0d0) Tsat = 647.0d0
        hf = (417.0d0 + 390.0d0*logP + 35.0d0*logP**2) * 1000.0d0  ! J/kg
        if (hf < 100.0d3) hf = 100.0d3 + 200.0d3*P_MPa
        if (hf > 2100.0d3) hf = 2100.0d3
        hfg = (2258.0d0 - 180.0d0*logP - 40.0d0*logP**2) * 1000.0d0
        if (hfg < 200.0d3) hfg = 200.0d3
        if (hfg > 2500.0d3) hfg = 2500.0d3
        sf = (1.303d0 + 0.82d0*logP + 0.06d0*logP**2) * 1000.0d0   ! J/(kg K)
        if (sf < 0.3d3) sf = 0.3d3 + 0.5d3*P_MPa
        sfg = hfg / Tsat
        vf = 0.001d0 * (1.0d0 + 0.0002d0*P_MPa)   ! m3/kg
    end subroutine sat_props

    subroutine superheat_props(P_pa, T, Tsat, hf_boil, sf_boil, h_out, s_out)
        implicit none
        double precision, intent(in) :: P_pa, T, Tsat, hf_boil, sf_boil
        double precision, intent(out) :: h_out, s_out
        double precision :: P_MPa, hfg_b, sfg_b, hg, sg, cp_steam, dT
        P_MPa = P_pa / 1.0d6
        hfg_b = (2258.0d0 - 180.0d0*log(P_MPa) - 40.0d0*log(P_MPa)**2)*1000.0d0
        if (hfg_b < 200.0d3) hfg_b = 200.0d3
        hg = hf_boil + hfg_b
        sfg_b = hfg_b / Tsat
        sg = sf_boil + sfg_b
        cp_steam = 2100.0d0   ! J/(kg K) approximate
        dT = T - Tsat
        if (dT < 0.0d0) dT = 0.0d0
        h_out = hg + cp_steam * dT
        s_out = sg + cp_steam * log(max(T/Tsat, 1.0d0))
    end subroutine superheat_props

    subroutine superheat_from_entropy(P_pa, s_target, Tsat, hf, sf, sfg, h_out)
        implicit none
        double precision, intent(in) :: P_pa, s_target, Tsat, hf, sf, sfg
        double precision, intent(out) :: h_out
        double precision :: hfg, hg, sg, cp_steam, T_est, dT
        hfg = sfg * Tsat
        hg = hf + hfg
        sg = sf + sfg
        cp_steam = 2100.0d0
        ! s = sg + cp ln(T/Tsat) => T = Tsat * exp((s-sg)/cp)
        T_est = Tsat * exp((s_target - sg)/cp_steam)
        dT = T_est - Tsat
        if (dT < 0.0d0) dT = 0.0d0
        h_out = hg + cp_steam * dT
    end subroutine superheat_from_entropy

    subroutine compute_single_extraction(Pb, Tb, Pc, Pe, etat, etap, &
                                          h1in, s1in, hfc, vfc, eta_out, y_out)
        implicit none
        double precision, intent(in) :: Pb, Tb, Pc, Pe, etat, etap, h1in, s1in, hfc, vfc
        double precision, intent(out) :: eta_out, y_out
        double precision :: Tse, hfe, hfge, sfe, sfge, vfe, xe, h2si, h2ai
        double precision :: h3si, h3ai, x3i, h5i, h6i, Wti, Wpi, Qini
        double precision :: Tsc, hfc_local, hfgc, sfc, sfgc, vfc2

        call sat_props(Pe, Tse, hfe, hfge, sfe, sfge, vfe)
        call sat_props(Pc, Tsc, hfc_local, hfgc, sfc, sfgc, vfc2)

        xe = (s1in - sfe)/max(sfge,1.0d-10)
        if (xe > 1.0d0) then
            call superheat_from_entropy(Pe, s1in, Tse, hfe, sfe, sfge, h2si)
        else
            h2si = hfe + xe*hfge
        end if
        h2ai = h1in - etat*(h1in - h2si)

        x3i = (s1in - sfc)/max(sfgc,1.0d-10)
        if (x3i > 1.0d0) then
            call superheat_from_entropy(Pc, s1in, Tsc, hfc_local, sfc, sfgc, h3si)
        else
            h3si = hfc_local + x3i*hfgc
        end if
        h3ai = h1in - etat*(h1in - h3si)

        h5i = hfc_local + vfc2*(Pe-Pc)/etap
        y_out = (hfe - h5i)/max(h2ai - h5i, 1.0d-10)
        if (y_out < 0.0d0) y_out = 0.0d0
        if (y_out > 1.0d0) y_out = 1.0d0
        h6i = hfe + vfe*(Pb-Pe)/etap
        Wti = (h1in-h2ai)+(1.0d0-y_out)*(h2ai-h3ai)
        Wpi = (1.0d0-y_out)*(h5i-hfc_local)+(h6i-hfe)
        Qini = h1in - h6i
        eta_out = (Wti-Wpi)/max(Qini,1.0d-10)
    end subroutine compute_single_extraction

end program rankine_regenerative

Solver Description

Model regenerative steam Rankine power cycles containing open or closed feedwater heaters (FWH) with one or two turbine steam extraction ports. Resolves mass extraction fractions ($y_1, y_2$) via enthalpy balances, computes cycle state properties using steam tables, and evaluates net cycle power output, thermal efficiency improvement, specific steam consumption, and back-work ratio.

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:

gfortran -O3 rankine_regenerative.f90 -o rankine_regenerative

Execution Command:

Execute the program by feeding the sample input file into the program using stdin redirection:

rankine_regenerative < input.txt

📥 Downloads & Local Files

Preview of the required input file (input.txt):

! Boiler pressure Pb [Pa]
8.0e6
! Turbine inlet temperature Tb [K]
773.15
! Condenser pressure Pc [Pa]
10.0e3
! Number of extraction stages (1 or 2)
1
! Extraction stage 1 pressure [Pa]
0.8e6
! Extraction stage 2 pressure [Pa] (for n=2)
0.3e6
! Feedwater heater type (1=Open FWH, 2=Closed FWH)
1
! Turbine isentropic efficiency
0.88
! Pump isentropic efficiency
0.85
! Steam mass flow rate [kg/s]
50.0