Simple Blowdown System Performance Estimate

June 22, 2020

Here we'll briefly walk through a simple performance estimate for a blowdown propulsion system. This is useful for assessing the orbital maneuver capability of a proposed design and determining the end-of-life (EOL) pressure.

In this case we'll assume the system is using LMP-103S and the associated monopropellant thrusters for burns.

Model Definition

We start with importing a few packages and declaring the characteristics of the propellant & pressurant as:

import numpy as np
import matplotlib.pyplot as plt

import itertools
from math import exp, sqrt, pi, acos, sin, cos, log

class Propellant(object):
    def density(T):
        # Input: T = temperature in deg C
        # Output: density in kg/m3
        return 4E-15 * T ** 2 - 0.8436 * T + 1259.1

    def vapor_press(T):
        # Input: T = temperature in deg C
        # Output: vapor pressure in bar
        return 0.000002 * T ** 3 - 0.00003 * T ** 2 + 0.0032 * T + 0.0418

    def helium_z(p):
        # Input: p = pressure in bar
        # Output: non dimensional compressibility factor
        return -5E-17 * (p * 100) ** 3 + 3E-12 * (p * 100) ** 2 + 5E-6 * (p * 100) + 1

Now we'll write the performance models for the thrusters our system is using, here we have the 1N HPGP thruster:

class ECAPS_Model(object):
    def thrust(p):
        # Input: p = pressure in bar
        # Output: thrust in N (from ATP family data)
        return -0.000214 * p ** 2 + 0.052037 * p - 0.019460

    def isp(p):
        # Input: p = pressure in bar
        # Output: isp in seconds (steady state)
        return (243.68 * np.log(p) + 1594 - 0.1 * p ** 2.15) / 9.806

With the propellant and the performance models finished, we need to write a simple function that takes a given system definition and calculates the blowdown performance at discrete propellant mass steps:

def Delta_V(tank_vol, m_dry, m_prop, temp, initial_press):
    # Inputs: tank volume in liters, spacecraft dry mass in kg, propellant mass in kg, 
    #         temperature in C, and intiitaly system pressure in bar
    # Output: Delta-V profile in m/s, propellant mass profile in kg,
    #         system pressure profile in bar 

    def ullage(tank_vol, m_prop, temp):
        # Inputs: take volume in liters, propellant mass, and propellant temperature in C
        # Outputs: ullage volume in m3
        return (tank_vol * 0.001) - (m_prop / Propellant.density(temp))

    # calculate helium mass in the system
    m_helium = ((initial_press * 100 - Propellant.vapor_press(temp) * 100) \
    * ullage(tank_vol, m_prop, temp)) / (Propellant.helium_z(initial_press) \
    * 2.0772 * (temp + 273.15))

    # define stop condition, we'll assume 98% expulsion
    residual = m_prop - (m_prop * 0.98)

    # total dry mass of the spacecraft as residual could be large depending on design
    m_dry = m_dry + m_helium + residual
    
    # define results storage
    DV_total = [0]
    m_prop_list = [m_prop]
    pressure_profile = [initial_press]

    # calculate delta-V with the rocket equation through the blowdown
    while m_prop >= residual:
        
        # step through propellant mass
        step_start_mass = m_dry + m_prop
        m_prop -= 0.1
        step_end_mass = m_dry + m_prop

        # calculate new system pressure after mass is consumed
        press = ((m_helium * Propellant.helium_z(initial_press / 2) * \
        2.0772 * (temp + 273.15)) / ullage(tank_vol, m_prop, temp)) / 100

        # calc the delta-V imparted by this mass 'chunk' at this system state
        DV_step = ECAPS_Model.isp(press) * 9.806 * np.log(step_start_mass / step_end_mass)

        # store results
        m_prop_list.append(m_prop)
        DV_total.append(DV_total[-1] + DV_step)
        pressure_profile.append(press)

    return DV_total, m_prop_list, pressure_profile

The above function is a good estimate of the blowdown system's performance given an initial state.

System Design Evaluation

With our model completed, we can evaluate the performance of a given system design by taking the following as inputs:

ParameterValueUnit
Spacecraft Dry Mass100kg
Propellant Mass10kg
Total Tank Volume11.5liters
Temperature20C
Initial Pressure18.5bar

Now we call our Delta_V function defined about to step through the blowdown curve as mass is expelled from the system:

DV_total, m_prop_list, pressure_profile = Delta_V(total_tank_vol, m_dry, m_prop, \
                                                  temp, initial_press)

And we plot the results with:

# define the axes
fig, ax1 = plt.subplots(figsize = (16, 8))
ax2 = ax1.twinx()

# plot the data
ax1.plot(m_prop_list, pressure_profile, color = 'blue')
ax2.plot(m_prop_list, DV_total, ls = '--', color = next(colors), label = 'Thruster Mode: SS')

# dress up the axes
ax1.set_ylabel('Tank Pressure [bar]', fontsize = 14)
ax1.set_xlabel('Propellant Remaining [kg]', fontsize = 14)
ax1.set_title('Estimated System Performance', fontsize = 14)
ax1.grid(True)
ax1.set_xlim(xmin = 0)
ax1.set_ylim(ymin = 4)

ax2.set_ylabel('Cumulative Delta V [m/s] (dashed line)', fontsize = 14)
ax2.set_ylim(ymin = 0)
ax2.invert_xaxis()
ax2.legend(loc = 9, prop = {'size': 14})

ax1.tick_params(axis = 'both', which = 'major', labelsize = 14)
ax2.tick_params(axis = 'y', which = 'major', labelsize = 14)

Which displays a plot of the pressure profile and cumulative similar to:

Estimated System Performance - Example Plot