diff --git a/Model/costanalysis(2)/__pycache__/operating_cost.cpython-36.pyc b/Model/costanalysis(2)/__pycache__/operating_cost.cpython-36.pyc deleted file mode 100644 index 96b5426..0000000 Binary files a/Model/costanalysis(2)/__pycache__/operating_cost.cpython-36.pyc and /dev/null differ diff --git a/Model/costanalysis(2)/costanalysis/__pycache__/CostBuildup.cpython-36.pyc b/Model/costanalysis(2)/costanalysis/__pycache__/CostBuildup.cpython-36.pyc deleted file mode 100644 index 9a7f7b9..0000000 Binary files a/Model/costanalysis(2)/costanalysis/__pycache__/CostBuildup.cpython-36.pyc and /dev/null differ diff --git a/Model/costanalysis(2)/costanalysis/__pycache__/ToolingCost.cpython-36.pyc b/Model/costanalysis(2)/costanalysis/__pycache__/ToolingCost.cpython-36.pyc deleted file mode 100644 index c840bda..0000000 Binary files a/Model/costanalysis(2)/costanalysis/__pycache__/ToolingCost.cpython-36.pyc and /dev/null differ diff --git a/Model/costanalysis(2)/costanalysis/__pycache__/cost_buildup.cpython-36.pyc b/Model/costanalysis(2)/costanalysis/__pycache__/cost_buildup.cpython-36.pyc deleted file mode 100644 index 5c0a6f8..0000000 Binary files a/Model/costanalysis(2)/costanalysis/__pycache__/cost_buildup.cpython-36.pyc and /dev/null differ diff --git a/Model/costanalysis(2)/costanalysis/__pycache__/tooling_cost.cpython-36.pyc b/Model/costanalysis(2)/costanalysis/__pycache__/tooling_cost.cpython-36.pyc deleted file mode 100644 index d055b51..0000000 Binary files a/Model/costanalysis(2)/costanalysis/__pycache__/tooling_cost.cpython-36.pyc and /dev/null differ diff --git a/Model/costanalysis(2)/costanalysis/cost_buildup.py b/Model/costanalysis(2)/costanalysis/cost_buildup.py deleted file mode 100644 index 5bf7527..0000000 --- a/Model/costanalysis(2)/costanalysis/cost_buildup.py +++ /dev/null @@ -1,81 +0,0 @@ -# Estimate tooling cost of a vehicle by summing tooling costs for all major -# components -# -# Inputs: -# rProp - Prop/rotor radius [m] -# cruiseOutput - Structure with cruise performance data -# -# Outputs: -# toolCostPerVehicle - Estimate of tool cost per vehicle [$] -# -# Functions Called: -# toolingCost.m - -#function toolCostPerVehicle = costBuildup(rProp,cruiseOutput) -import numpy as np -from .tooling_cost import ToolingCost - -def CostBuildup(r_prop,c_ref, b_ref): - # Inputs - fuselage_width = 1 - fuselage_length = 5 - toc = 0.15 # Wing / canard thickness - prop_radius = r_prop - prop_chord = 0.15 * prop_radius - x_hinge = 0.8 - winglet = 0.2 - - parts_per_tool = 1000 - - fuselage_height = 1.3 # Guess - span = b_ref - chord = c_ref - - # tool_cost_per_vechile = 100 # used as test value - - # Wing Tooling - wing_tool_cost = np.array([0, 0, 0, 0]) - wing_tool_cost[0] = ToolingCost((span - fuselage_width)/2, toc*chord, chord*0.2) # Leading Edge - wing_tool_cost[1] = ToolingCost((span - fuselage_width)/2, toc*chord*0.7, chord*0.2) # Aft spar - wing_tool_cost[2] = ToolingCost((span - fuselage_width)/2, chord*0.75, 0.02)*2 # Upper/Lower skin - wing_tool_cost[3] = ToolingCost(span, toc*chord, chord*.20) # Forward spar - wing_tool_cost = 2*(2*sum(wing_tool_cost[0:3])+wing_tool_cost[3]) # Total wing tooling cost (matched tooling) - - # Winglet Tooling - winglet_tool_cost = np.array([0, 0, 0, 0]) - winglet_tool_cost[0] = ToolingCost(winglet*span/2, toc*chord, chord*.2) # Leading edge - winglet_tool_cost[1] = ToolingCost(winglet*span/2,toc*chord*0.7,chord*.2) # Aft spar - winglet_tool_cost[2] = ToolingCost(winglet*span/2,chord*0.75,0.02)*2 # Upper/Lower skin - winglet_tool_cost[3] = ToolingCost(winglet*span/2,toc*chord,chord*.20) # Forward spar - winglet_tool_cost = 4*sum(winglet_tool_cost) # Total winglet tooling cost (matched tooling) - - # Canard Tooling - canard_tool_cost = wing_tool_cost # Total canard tooling cost - - # Fuselage Tooling - fuselage_tool_cost = np.array([0, 0, 0, 0]) - fuselage_tool_cost[0] = ToolingCost(fuselage_length*.8,fuselage_height,fuselage_width/2)*2 # Right/Left skin - fuselage_tool_cost[1] = ToolingCost(fuselage_length*.8,fuselage_width/2,fuselage_height/4) # Keel - fuselage_tool_cost[2] = ToolingCost(fuselage_width,fuselage_height,0.02)*2 # Fwd/Aft Bulkhead - fuselage_tool_cost[3] = ToolingCost(fuselage_length*.1,fuselage_width,fuselage_height/3) # Nose/Tail cone - fuselage_tool_cost = 2*sum(fuselage_tool_cost) # Total fuselage tooling cost (matched tooling) - - # Prop Tooling - prop_tool_cost = np.array([0, 0]) - prop_tool_cost[0] = ToolingCost(prop_radius,prop_chord,prop_chord*toc/2)*2 # Skin - prop_tool_cost[1] = ToolingCost(prop_radius,prop_chord*toc,prop_chord/4)*2 # Spar tool - prop_tool_cost = 4*sum(prop_tool_cost) # Total propeller tooling cost (left/right hand) (matched tooling) - - # Control Surface (2 tools) - control_tool_cost = np.array([0, 0]) - control_tool_cost[0] = ToolingCost((span-fuselage_width)/2,(1-x_hinge)*chord,chord*toc/4) # Skin - control_tool_cost[1] = ToolingCost((span-fuselage_width)/2,(1-x_hinge)*chord,chord*toc/4) # Skin - control_tool_cost = 8*sum(control_tool_cost) # Total wing tooling (matched tooling) - - # Total tool cost - total_tool_cost = wing_tool_cost + canard_tool_cost + fuselage_tool_cost + prop_tool_cost + control_tool_cost + winglet_tool_cost - - tool_cost_per_vechile = total_tool_cost / parts_per_tool - - return tool_cost_per_vechile - diff --git a/Model/costanalysis(2)/costanalysis/tooling_cost.py b/Model/costanalysis(2)/costanalysis/tooling_cost.py deleted file mode 100644 index 8fc7005..0000000 --- a/Model/costanalysis(2)/costanalysis/tooling_cost.py +++ /dev/null @@ -1,62 +0,0 @@ -# Estimates tooling cost based on part dimensions including material, rough -# machining, and finishing machining -# -# Inputs: -# length - part length [m] -# width - part width [m] -# depth - part depth [m] -# -# Output: -# cost - Tool cost [$] -# -import math - -def ToolingCost(length, width, depth): - # Material - tool_side_offset = 0.09 # Offset on each side of tool - tool_depth_offset = 0.03 # Offset at bottom of tool - tool_cost = 10000 # Cost be m^3 of tooling material [$/m^3] - - tool_volume = (length + 2 * tool_side_offset) * (width + 2 * tool_side_offset) * (depth + tool_depth_offset) - material_cost = tool_cost * tool_volume # Tooling material costs - - # Machining (Rough Pass) - rough_SFM = 200 # Roughing surface feet per minute - rough_FPT = 0.003 # Roughing feed per tooth [in] - rough_cost_rate = 150/3600 # Cost to rough [$/s] - rough_bit_diam = 0.05 # Rougher diameter [m] - - rough_bit_depth = rough_bit_diam/4 # Rougher cut depth [m] - rough_RPM = 3.82 * rough_SFM / (39.37 * rough_bit_diam) # Roughing RPM - rough_feed = rough_FPT * rough_RPM * 2 * 0.00042 # Roughing Feed [m/s] - rough_bit_step = 0.8 * rough_bit_diam # Rougher step size - - cut_volume = length * math.pi * depth * width / 4 # Amount of material to rough out - rough_time = cut_volume / (rough_feed * rough_bit_step * rough_bit_depth) # Time for roughing - rough_cost = rough_time * rough_cost_rate # Roughing cost - - # Machining (Finish Pass) - finish_SFM = 400 # Roughing surface feet per minute - finish_FPT = 0.004 # Roughing feed per tooth [in] - finish_cost_rate = 175/3600 # Cost to finish [$/s] - finish_bit_diam = 0.006 # Finish diameter [m] - finish_passes = 5 # Number of surface passes - - finish_RPM = 3.82 * finish_SFM / (39.37 * finish_bit_diam) # Roughing RPM - finish_feed = finish_FPT * finish_RPM * 2 * 0.00042 # Roughing Feed [m/s] - - def EllipsePerimeter(a, b): - h = (a - b)**2 / (a + b)**2 - p = math.pi*(a+b)*(1+3*h/(10+(4-3*h)**0.5)) - return p - - finish_bit_step = 0.8 * finish_bit_diam # Rougher step size - cut_area = length * EllipsePerimeter(width/2,depth)/2; # Amount of material to rough out - finish_time = cut_area / (finish_feed * finish_bit_step) * finish_passes; # Time for roughing - finish_cost = finish_time * finish_cost_rate; # Roughing cost - - # Total Cost - cost = material_cost + rough_cost + finish_cost - - return cost - diff --git a/Model/costanalysis(2)/operating_cost.py b/Model/costanalysis(2)/operating_cost.py deleted file mode 100644 index 4f370e3..0000000 --- a/Model/costanalysis(2)/operating_cost.py +++ /dev/null @@ -1,121 +0,0 @@ -from openmdao.api import ExplicitComponent -from .costanalysis.cost_buildup import CostBuildup - -class OperatingCost(ExplicitComponent): - - - def setup(self): - self.add_input('r_prop', desc='Radius Propeller [m]') # 1 - self.add_input('cruise_speed', desc='Cruise Speed [m/s]') # 102.82 - self.add_input('avg_dist', desc='Average Distance of trip [m]') # 193121 - self.add_input('shaft_power', desc='Shaft Power [kW]' ) # 156 - self.add_input('We/W0', desc = 'Empty Weight Fraction') - self.add_input('W0', desc = 'Gross Weight') - #self.add_input('mass_struct', desc='Mass of Structure [kg]') # 180 - self.add_input('mass_batt', desc='Mass of Battery [kg]') # 627.66 - self.add_input('mass_motor',desc = 'Mass of Motor [kg]') # 635.8 - #self.add_input('b_ref', desc= 'Span of one wing [m]') # 13.21 / 2 - #self.add_input('c_ref', desc= 'Ref Chord [m]') # 1 - self.add_input('S', desc = 'Wing Reference Area (both) [m^2]') - self.add_input('AR', desc = 'Aspect Ratio') - self.add_input('P_C', desc= 'Power at Cruise [kW]') # power to weight 0.22 - - self.add_output('Cost', desc = 'Cost per trip [$]') - - self.declare_partials(of='*', wrt='*', method='fd') - - def compute(self, inputs, outputs): - - r_prop = inputs['r_prop'] - cruise_speed = inputs['cruise_speed'] - avg_dist = inputs['avg_dist'] - shaft_power = inputs['shaft_power'] - mass_struct = inputs['We/W0']*inputs['W0'] - inputs['mass_motor'] - mass_batt = inputs['mass_batt'] - mass_motor = inputs['mass_motor'] - S_single = inputs['S']/2 - b_ref = (inputs['AR'] * S_single)**0.5 - c_ref = S_single / b_ref - power_to_weight = inputs['P_C'] / inputs['W0'] - - # Assumptions - flight_hours_per_year = 600 - flight_time = avg_dist/cruise_speed - flights_per_year = flight_hours_per_year / (flight_time / 3600) - vehicle_life_years = 10 - n_vehicles_per_facility = 200 - - # Tooling Cost - tool_cost_per_vehicle = CostBuildup(r_prop,b_ref, c_ref) - - # Material Cost - material_cost_per_kg = 220 - material_cost = material_cost_per_kg * mass_struct - # Battery Cost - power_to_weight_hr = power_to_weight * flight_time / 3600 - battery_cost_per_kg = 700 * power_to_weight_hr # Roughly $700/kW-hr * P/W [kW-hr /kg] - battery_cost = battery_cost_per_kg * mass_batt - # Motor Cost - motor_cost_per_kg = 150 # Approx $1500 for 10 kg motor + controller ? - motor_cost = motor_cost_per_kg * mass_motor - - # Servo cost - n_servo = 14 # 8 props, 4 surfaces, 2 tilt - servo_cost = n_servo * 800 # Estimate $800 per servo in large quantities - - # Avionics cost - avionics_cost = 30000 - - # BRS (Ballistics Recovery System) cost - BRS_cost = 5200 - - # Total acquisition cost - acquisition_cost = battery_cost + motor_cost + servo_cost + avionics_cost + BRS_cost + material_cost + tool_cost_per_vehicle - acquisition_cost_per_flight = acquisition_cost/(flights_per_year * vehicle_life_years) - - # Insurance Cost - # Follow R22 for estimate of 6.5# of acquisition cost - insurance_cost_per_year = acquisition_cost * 0.065 - insurance_cost_per_flight = insurance_cost_per_year/flights_per_year - - # Facility rental cost - vehicle_footprint = 1.2 * (8 * r_prop + 1) * (4 * r_prop + 3); # m^2, 20# for movement around aircraft for maintenance, etc. - area_cost = 10.7639 * 2 * 12; # $/m^2, $2/ft^2 per month assumed - - # Facility Cost = Vehicle footprint + 10x footprint for operations - # averaged over # of vehicles at each facility - facility_cost_per_year = (vehicle_footprint + 10*vehicle_footprint/n_vehicles_per_facility) * area_cost - facility_cost_per_flight_hour = facility_cost_per_year/flight_hours_per_year - facility_cost_per_flight = facility_cost_per_flight_hour * flight_time / 3600 - - # Electricity Cost - # E * $/kWhr including 90# charging efficiency - # Average US electricity cost is $0.12 per kW-hr, up to $0.20 per kW-hr in CA - E = shaft_power * flight_time / 3600 - energy_cost_per_flight = 0.12 * E / 0.9 - - # Battery Replacement Cost - batt_life_cycles = 2000 - battery_repl_cost_per_flight = battery_cost/batt_life_cycles - - # Motor Replacement Cost - motor_life_hrs = 6000 - motor_repl_cost_per_flight = flight_time / 3600 / motor_life_hrs * motor_cost - - # Servo Replacement Cost - servo_life_hrs = 6000 - servo_repl_cost_per_flight = flight_time / 3600 / servo_life_hrs * servo_cost - - # Maintenace Cost - human_cost_per_hour = 60 - man_hr_per_flight_hour = 0.10 # periodic maintenance estimate - man_hr_per_flight = 0.2 # Inspection, battery swap estimate - labor_cost_per_flight = (man_hr_per_flight_hour * flight_time / 3600 + man_hr_per_flight) * human_cost_per_hour - - # Cost Per Flight - cost_per_flight = acquisition_cost_per_flight + insurance_cost_per_flight + facility_cost_per_flight + \ - energy_cost_per_flight + battery_repl_cost_per_flight + motor_repl_cost_per_flight + \ - servo_repl_cost_per_flight + labor_cost_per_flight - - outputs['Cost'] = cost_per_flight - diff --git a/Model/costanalysis/OperatingCost.py b/Model/costanalysis/OperatingCost.py index 8de4738..7ce5490 100644 --- a/Model/costanalysis/OperatingCost.py +++ b/Model/costanalysis/OperatingCost.py @@ -56,7 +56,7 @@ def setup(self): self.add_input('shaft_power',desc = 'shaft power') self.add_input('mass_struct',desc = 'structural mass') self.add_input('mass_batt',desc = 'battery mass') - self.add_input('mass_motor',desc = 'motor mass') + #self.add_input('mass_motor',desc = 'motor mass') self.add_input('b_ref',desc = 'span') self.add_input('power_to_weight',desc = 'power to weight ratio') diff --git a/solver.py b/solver.py index 7476aa7..9ac1473 100644 --- a/solver.py +++ b/solver.py @@ -5,6 +5,7 @@ from Model.Weight.gross_weight_comp import GrossWeightComp from Model.Weight.thrust_weight_comp import ThrustWeightComp from Model.Weight.weight_buildup_comp import EmptyWeightComp +from Model.costanalysis1.operating_cost import OperatingCost prob = Problem(model=Group()) @@ -16,6 +17,7 @@ ivc.add_output('Wb',val=600) #[kg], battery weight ivc.add_output('Wp',val=454) #[kg], weight of passangers #ivc.add_output('We_W0') # empty to gross fraction +ivc.add_output('Wm',val=50) ivc.add_output('m') ivc.add_output('r') @@ -42,7 +44,7 @@ model.add_subsystem('range',RangeComp()) model.add_subsystem('cruiseP',CruiseComp()) # cruise power model.add_subsystem('emptyW',EmptyWeightComp()) -#model.add_subsystem('T_W',ThrustWeightComp()) +model.add_subsystem('cost',OperatingCost()) # conencting to gross_weights comp model.connect('Wb','weight.Wb') @@ -91,6 +93,20 @@ model.connect('cruiseP.P_C','range.P_C') model.connect('V','range.V') +# connecting to cost analysis +model.connect('r','cost.r_prop') +model.connect('V','cost.cruise_speed') +model.connect('range.R','cost.avg_dist') +model.connect('weight.We_W0','cost.We/W0') +model.connect('weight.W0','cost.W0') +model.connect('Wb','cost.mass_batt') +model.connect('Wm','cost.mass_motor') +model.connect('Neg','cost.Neg') +model.connect('S','cost.S') +model.connect('AR','cost.AR') +model.connect('FOM.PH','cost.shaft_power') +model.connect('cruiseP.P_C','cost.P_C') + prob.driver = ScipyOptimizeDriver() prob.driver.options['optimizer'] = 'SLSQP' @@ -108,10 +124,11 @@ model.add_constraint('range.R',equals=340) model.add_constraint('weight.Wb_W0',lower=0.25,upper=0.30) # batt to gross #model.add_constraint('FOM.PH',upper=550) -model.add_constraint('cruiseP.P_C',upper=100) +model.add_constraint('cruiseP.P_C',upper=80) #model.add_constraint('cruiseP.cl',upper=0.4) +model.add_objective('cost.Cost',scaler=-1) -model.add_objective('FOM.PH',scaler=-1) +#model.add_objective('FOM.PH',scaler=-1) prob.setup() @@ -141,6 +158,7 @@ print('Required Power for Hover:',prob['FOM.PH'],'[kW]') print('Required Power for Cruise:',prob['cruiseP.P_C'],'[kW]') print('Max Trip Range @',prob['V'],'[m/s]:',prob['range.R'],'[km]','Time',prob['range.t'],'[hr]') +print('Cost per trip (2025?): $',prob['cost.Cost']*1.146) print('cl',prob['cruiseP.cl']) print('cd',prob['cruiseP.cd']) print('cd0',prob['cruiseP.cd0']) diff --git a/solver_withcost.py b/solver_withcost.py index fe4623b..cfdd525 100644 --- a/solver_withcost.py +++ b/solver_withcost.py @@ -1,10 +1,10 @@ -from openmdao.api import Problem, Group, IndepVarComp, ExecComp, ScipyOptimizeDriver, pyOptSparseDriver +from openmdao.api import Problem, Group, IndepVarComp, ExecComp, ScipyOptimizeDriver from Model.Propulsion.power_comp import PowerComp from Model.Propulsion.range_comp import RangeComp from Model.Propulsion.cruise_comp import CruiseComp from Model.Weight.gross_weight_comp import GrossWeightComp # from Model.Weight.thrust_weight_comp import ThrustWeightComp -from Model.costanalysis(2).operating_cost import OperatingCost +from Model.costanalysis1.operating_cost import OperatingCost prob = Problem(model=Group()) @@ -95,13 +95,13 @@ # Setup optimization algorithm -prob.driver = pyOptSparseDriver() -prob.driver.options['optimizer'] = "SLSQP" -prob.driver.hist_file = 'hist.hst' -# prob.driver = ScipyOptimizeDriver() -# prob.driver.options['optimizer'] = 'SLSQP' -# prob.driver.options['tol'] = 1e-9 -# prob.driver.options['disp'] = True +#prob.driver = pyOptSparseDriver() +#prob.driver.options['optimizer'] = "SLSQP" +#prob.driver.hist_file = 'hist.hst' +prob.driver = ScipyOptimizeDriver() +prob.driver.options['optimizer'] = 'SLSQP' +prob.driver.options['tol'] = 1e-9 +prob.driver.options['disp'] = True model.add_design_var('r',lower=0.5,upper=1.5) model.add_design_var('We/W0',lower=0.40,upper=0.70) # 30% - 70%, from lecture