Skip to content

Commit

Permalink
Merge pull request #555 from Sof222/develop
Browse files Browse the repository at this point in the history
Turboelectric HTS Dynamo Ducted Fan Network
  • Loading branch information
planes committed Jul 14, 2022
2 parents a3b8af4 + 1979784 commit ae190f9
Show file tree
Hide file tree
Showing 38 changed files with 1,829 additions and 296 deletions.
1 change: 1 addition & 0 deletions regression/automatic_regression.py
Expand Up @@ -105,6 +105,7 @@
'scripts/test_input_output/test_xml_read_write.py',
'scripts/test_input_output/test_freemind_write.py',
'scripts/turboelectric_HTS_ducted_fan_network/turboelectric_HTS_ducted_fan_network.py',
'scripts/turboelectric_HTS_dynamo_ducted_fan_network/turboelectric_HTS_dynamo_ducted_fan_network.py',
'scripts/variable_cruise_distance/variable_cruise_distance.py',
'scripts/V_n_diagram/V_n_diagram_regression.py',
'scripts/VTOL/test_Multicopter.py',
Expand Down
Expand Up @@ -23,7 +23,7 @@
Data, Units,
)
from SUAVE.Methods.Propulsion.ducted_fan_sizing import ducted_fan_sizing

### @ingroup Regression-scripts-turboelectric_HTS_ducted_fan_network
def main():

Expand All @@ -32,10 +32,9 @@ def main():

return


def energy_network():

# ------------------------------------------------------------------
# ------------------------------------------------------------------
# Evaluation Conditions
# ------------------------------------------------------------------

Expand Down Expand Up @@ -276,7 +275,7 @@ def energy_network():

# ------------------------------------------------------------------
# Component 4 - Electronic Speed Controller (ESC)

efan.esc = SUAVE.Components.Energy.Distributors.HTS_DC_Supply() # Could make this where the ESC is defined as a Siemens SD104
efan.esc.tag = 'esc'

Expand Down

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion trunk/SUAVE/Attributes/Cryogens/Cryogen.py
@@ -1,7 +1,7 @@
## @ingroup Attributes-Cryogens
# Cryogen.py
#
# Created: Feb 2020, K. Hamilton
# Created: Feb 2020, K. Hamilton - Through New Zealand Ministry of Business Innovation and Employment Research Contract RTVU2004


# ----------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion trunk/SUAVE/Attributes/Cryogens/Liquid_H2.py
@@ -1,7 +1,7 @@
## @ingroup Attributes-Cryogens
# Liquid H2
#
# Created: Feb 2020, K. Hamilton
# Created: Feb 2020, K. Hamilton - Through New Zealand Ministry of Business Innovation and Employment Research Contract RTVU2004

# ----------------------------------------------------------------------
# Imports
Expand Down
5 changes: 3 additions & 2 deletions trunk/SUAVE/Attributes/Solids/Copper.py
@@ -1,7 +1,7 @@
## @ingroup Attributes-Solids
# Copper.py
#
# Created: Feb 2020, K. Hamilton
# Created: Feb 2020, K. Hamilton - Through New Zealand Ministry of Business Innovation and Employment Research Contract RTVU2004
# Modified: Jan 2022, S. Claridge

#-------------------------------------------------------------------------------
Expand Down Expand Up @@ -62,6 +62,7 @@ def __defaults__(self):
self.density = 8960.0 # [kg/(m**3)]
self.conductivity_electrical = 58391886.09 # [mhos/m]
self.conductivity_thermal = 392.4 # [W/(m*K)]
self.interpolate = False

# Lookup table arrays. Temperature in K, thermal conductivity in W/(m*K)
temperatures = np.array([4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, 18.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 120.0, 140.0, 160.0, 180.0, 200.0, 220.0, 240.0, 260.0, 280.0, 300.0])
Expand All @@ -79,7 +80,7 @@ def __defaults__(self):
self.c_electrical = interpolate.interp1d(temperatures, conductivities, kind = 'cubic', fill_value='extrapolate')



def thermal_conductivity(self, temperature):

# Create output variable
Expand Down
47 changes: 31 additions & 16 deletions trunk/SUAVE/Components/Energy/Converters/Motor_HTS_Rotor.py
@@ -1,7 +1,7 @@
## @ingroup Components-Energy-Converters
# Motor_HTS_Rotor.py
#
# Created: Feb 2020, K. Hamilton
# Created: Feb 2020, K. Hamilton - Through New Zealand Ministry of Business Innovation and Employment Research Contract RTVU2004
# Modified: Nov 2021, S. Claridge

# ----------------------------------------------------------------------
Expand Down Expand Up @@ -49,17 +49,23 @@ def __defaults__(self):
Properties Used:
None
"""
self.temperature = 0.0 # Temperature inside of the rotor [K]
self.skin_temp = 300.0 # Temperature of the outside of the rotor [K]
self.current = 0.0 # HTS coil current. [A]
self.resistance = 0.0 # Resistance of the HTS oils. [ohm]
self.length = 0.0 # Physical size of rotor exterior [m]
self.diameter = 0.0 # Physical size of rotor exterior [m]
self.surface_area = 0.0 # Surface area of the rotor. [m2]
self.R_value = 125.0 # R_Value of the cryostat wall. [K.m2/W]
self.number_of_engines = 2.0 # Number of rotors on the vehicle
self.temperature = 0.0 # Temperature inside of the rotor [K]
self.skin_temp = 300.0 # Temperature of the outside of the rotor [K]
self.current = 0.0 # HTS coil current. [A]
self.resistance = 0.0 # Resistance of the HTS oils. [ohm]
self.length = 0.0 # Physical size of rotor exterior [m]
self.diameter = 0.0 # Physical size of rotor exterior [m]
self.surface_area = 0.0 # Surface area of the rotor. [m2]
self.R_value = 125.0 # R_Value of the cryostat wall. [K.m2/W]
self.number_of_engines = 2.0 # Number of rotors on the vehicle
self.inputs.hts_current = 0.0 #[A]
self.inputs.ambient_temp = 0.0 #[K]

self.outputs.coil_power = 0.0 #[W]
self.outputs.coil_voltage = 0.0
self.outputs.cryo_load = 0.0 #[W]

def power(self, current, ambient_temp):
def power(self, conditions):
""" Calculates the electrical power draw from the HTS coils, and the total heating load on the HTS rotor cryostat.
Assumptions:
Expand All @@ -71,26 +77,35 @@ def power(self, current, ambient_temp):
N/A
Inputs:
current [A]
ambient_temp [K]
self.inputs
current [A]
ambient_temp [K]
Outputs:
input_power [W]
cryogenic_load [W]
self.outputs
coil_power [W]
cryogenic_load [W]
coil_voltage [V]
Properties Used:
self.
temperature [K]
resistance [ohm]
surface_area [m2]
R_value [K.m2/W]
"""

# unpack
cryo_temp = self.temperature
coil_R = self.resistance
surface_area = self.surface_area
r_value = self.R_value

current = self.inputs.hts_current
ambient_temp = self.inputs.ambient_temp


# Calculate HTS coil power
# This is both the electrical power required to operate the coil, and the thermal load imparted by the coil into the cryostat.
coil_power = coil_R * current**2
Expand All @@ -108,4 +123,4 @@ def power(self, current, ambient_temp):
self.outputs.coil_voltage = coil_voltage
self.outputs.cryo_load = cryo_load

return coil_power
return coil_power
2 changes: 1 addition & 1 deletion trunk/SUAVE/Components/Energy/Converters/Turboelectric.py
@@ -1,7 +1,7 @@
## @ingroup Components-Energy-Converters
# Turboelectric.py
#
# Created: Nov 2019, K. Hamilton
# Created: Nov 2019, K. Hamilton - Through New Zealand Ministry of Business Innovation and Employment Research Contract RTVU2004
# Modified: Nov 2021, S. Claridge
# ----------------------------------------------------------------------
# Imports
Expand Down
130 changes: 30 additions & 100 deletions trunk/SUAVE/Components/Energy/Cooling/Cryocooler.py
Expand Up @@ -14,6 +14,7 @@
# package imports
from SUAVE.Core import Data
from SUAVE.Components.Energy.Energy_Component import Energy_Component
from SUAVE.Methods.Cryogenics.Cryocooler.cryocooler_model import cryocooler_model
import numpy as np

# ----------------------------------------------------------------------
Expand All @@ -29,116 +30,45 @@ class Cryocooler(Energy_Component):
def __defaults__(self):

# Initialise cryocooler properties as null values
self.cooler_type = ''
self.rated_power = 0.0
self.min_cryo_temp = 0.0
self.ambient_temp = 300.0
self.cooler_type = ''
self.rated_power = 0.0
self.min_cryo_temp = 0.0
self.ambient_temp = 300.0
self.inputs.cooling_power = 0.0
self.inputs.cryo_temp = 0.0
self.mass_properties.mass = 0.0
self.rated_power = 0.0
self.outputs.input_power = 0.0

def energy_calc(self, cooling_power, cryo_temp, amb_temp):
def energy_calc(self, conditions):

""" Calculate the power required by the cryocooler based on the cryocooler type, the required cooling power, and the temperature conditions.
Assumptions:
Based on mass data for Cryomech cryocoolers as per the datasheets for ground based non-massreduced coolers available via the cryomech website: https://www.cryomech.com/cryocoolers/.
The mass is calculated for the requested power level, the cryocooler should be sized for the maximum power level required as its mass will not change during the flight.
The efficiency scales with required cooling power and temperature only.
The temperature difference and efficiency are taken not to scale with ambient temperature. This should not matter in the narrow range of temperatures in which aircraft operate, i.e. for ambient temperatures between -50 and 50 C.
Source:
https://www.cryomech.com/cryocoolers/
Inputs:
"""Calculate the instantaneous required energy input
cooling_power - cooling power required of the cryocooler [watts]
cryo_temp - cryogenic output temperature required [kelvin]
amb_temp - ambient temperature the cooler will reject heat to, defaults to 19C [kelvin]
cooler_type - cryocooler type used
Outputs:
input_power - electrical input power required by the cryocooler [watts]
mass - mass of the cryocooler and supporting components [kilogram]
Properties Used:
Assumptions:
N/A
"""
# Prevent unrealistic temperature changes.
if np.amin(cryo_temp) < 1.:

cryo_temp = np.maximum(cryo_temp, 5.)
print("Warning: Less than zero kelvin not possible, setting cryogenic temperature target to 5K.")

# Warn if ambient temperature is very low.
if np.amin(amb_temp) < 200.:

print("Warning: Suprisingly low ambient temperature, check altitude.")

# Calculate the shift in achievable minimum temperature based on the the ambient temperature (temp_amb) and the datasheet operating temperature (19C, 292.15K)
temp_offset = 292.15 - amb_temp

# Calculate the required temperature difference the cryocooler must produce.
temp_diff = amb_temp-cryo_temp

# Disable if the target temperature is greater than the ambient temp. Technically cooling like this is possible, however there are better cooling technologies to use if this is the required scenario.
if np.amin(temp_diff) < 0.:

temp_diff = np.maximum(temp_diff, 0.)
print("Warning: Temperature conditions are not well suited to cryocooler use. Cryocooler disabled.")
# Set the parameters of the cooler based on the cooler type and the operating conditions. The default ambient operating temperature (19C) is used as a base.
if self.cooler_type == 'fps': #Free Piston Stirling

temp_minRT = 35.0 # Minimum temperature achievable by this type of cooler when rejecting to an ambient temperature of 19C (K)
temp_min = temp_minRT - temp_offset # Updated minimum achievable temperature based on the supplied ambient temperature (K)
eff = 0.0014*(cryo_temp-temp_min) # Efficiency function. This is a line fit from a survey of Cryomech coolers in November 2019
input_power = cooling_power/eff # Electrical input power (W)
mass = 0.0098*input_power+1.0769 # Total cooler mass function. Fit from November 2019 Cryomech data. (kg)

elif self.cooler_type == 'GM': #Gifford McMahon

temp_minRT = 5.4
temp_min = temp_minRT - temp_offset
eff = 0.0005*(cryo_temp-temp_min)
input_power = cooling_power/eff
mass = 0.0129*input_power+63.08

elif self.cooler_type == 'sPT': #Single Pulsetube

temp_minRT = 16.0
temp_min = temp_minRT - temp_offset
eff = 0.0002*(cryo_temp-temp_min)
input_power = cooling_power/eff
mass = 0.0079*input_power+51.124

elif self.cooler_type == 'dPT': #Double Pulsetube

temp_minRT = 8.0
temp_min = temp_minRT - temp_offset
eff = 0.00001*(cryo_temp-temp_min)
input_power = cooling_power/eff
mass = 0.0111*input_power+73.809

else:

print("Warning: Unknown Cryocooler type")
return[0.0,0.0]

# Warn if the cryogenic temperature is unachievable
diff = cryo_temp - temp_min
Source:
N/A
if np.amin(diff) < 0.0:
Inputs:
self.inputs
cryo_temp [K]
cooling_power [W]
eff = 0.0
input_power = None
mass = None
Outputs:
self.outputs.
input_power [W]
print("Warning: The required cryogenic temperature of " + str(cryo_temp) + " is not achievable using a " + self.cooler_type + " cryocooler at an ambient temperature of " + str(amb_temp) + ". The minimum temperature achievable is " + str(temp_min))
Properties Used:
self.mass_properties.mass = mass
self.rated_power = input_power
self.
cooler_type
return [input_power, mass]
"""
output = cryocooler_model(self)
self.outputs.input_power = output[0]

return output[0]



0 comments on commit ae190f9

Please sign in to comment.