def test_case_Area(self): p = Problem() indeps = p.model.add_subsystem('indeps', IndepVarComp(), promotes=['*']) indeps.add_output('T', val=518., units='degR') indeps.add_output('P', val=14.7, units='psi') indeps.add_output('W', val=1.5, units='lbm/s') indeps.add_output('area', val=np.inf, units='inch**2') p.model.add_subsystem('set_total_TP', SetTotal(thermo_data=janaf)) p.model.add_subsystem('set_static_A', SetStatic(mode='area', thermo_data=janaf)) p.model.connect('T', 'set_total_TP.T') p.model.connect('P', ['set_total_TP.P', 'set_static_A.guess:Pt']) p.model.connect('set_total_TP.flow:S', 'set_static_A.S') p.model.connect('set_total_TP.flow:h', 'set_static_A.ht') # p.model.connect('P', 'set_static_A.P') p.model.connect('W', 'set_static_A.W') p.model.connect('area', 'set_static_A.area') p.model.connect('set_total_TP.flow:gamma', 'set_static_A.guess:gamt') #p.model.connect('set_total_TP.flow:n', 'set_static_A.n_guess') p.set_solver_print(level=-1) p.setup(check=False) # from openmdao.api import view_model # view_model(p) # exit(0) # 4 cases to check against for i, data in enumerate(ref_data): p['T'] = data[h_map['Tt']] p['P'] = data[h_map['Pt']] p['area'] = data[h_map['A']] # p['set_static_A.Ps'] = data[h_map['Ps']] p['W'] = data[h_map['W']] if i is 5: # supersonic case p['set_static_A.guess:MN'] = 3. # print("###################################") # print(p['T'], p['P'], p['area'], p['W']) # print("###################################") p.run_model() # check outputs npss_vars = ('Ps', 'Ts', 'MN', 'hs', 'rhos', 'gams', 'V', 'A', 's', 'ht') Ps, Ts, MN, hs, rhos, gams, V, A, S, ht = tuple( [data[h_map[v_name]] for v_name in npss_vars]) Ps_computed = p['set_static_A.flow:P'] Ts_computed = p['set_static_A.flow:T'] hs_computed = p['set_static_A.flow:h'] rhos_computed = p['set_static_A.flow:rho'] gams_computed = p['set_static_A.flow:gamma'] V_computed = p['set_static_A.flow:V'] A_computed = p['area'] MN_computed = p['set_static_A.MN'] # I think these area already converted in the file: Ken # V_SI = cu(V, 'ft/s', 'm/s') # A_SI = cu(A, 'inch**2', 'm**2') # print(p['T'], p['P']) # print("Ps", Ps_computed, Ps) # print("Ts", Ts_computed, Ts) # print("gamma", gams_computed, gams) # print("V", V_computed, V) # print("A", A_computed, A) # print("MN", MN_computed, MN) # print("rhos", rhos_computed, rhos) # print() tol = 1.0e-4 assert_rel_error(self, gams_computed, gams, tol) assert_rel_error(self, MN_computed, MN, tol) assert_rel_error(self, Ps_computed, Ps, tol) assert_rel_error(self, Ts_computed, Ts, tol) assert_rel_error(self, hs_computed, hs, tol) assert_rel_error(self, rhos_computed, rhos, tol) assert_rel_error(self, gams_computed, gams, tol) assert_rel_error(self, V_computed, V, tol) assert_rel_error(self, A_computed, A, tol)
def setup(self): thermo_data = self.options['thermo_data'] inflow_elements = self.options['inflow_elements'] air_fuel_elements = self.options['air_fuel_elements'] design = self.options['design'] statics = self.options['statics'] fuel_type = self.options['fuel_type'] air_fuel_thermo = Thermo(thermo_data, init_reacts=air_fuel_elements) self.air_fuel_prods = air_fuel_thermo.products air_thermo = Thermo(thermo_data, init_reacts=inflow_elements) self.air_prods = air_thermo.products self.num_air_fuel_prod = len(self.air_fuel_prods) self.num_air_prod = len(self.air_prods) # Create combustor flow station in_flow = FlowIn(fl_name='Fl_I', num_prods=self.num_air_prod) self.add_subsystem('in_flow', in_flow, promotes=['Fl_I:tot:*', 'Fl_I:stat:*']) # Perform combustor engineering calculations self.add_subsystem('mix_fuel', MixFuel(thermo_data=thermo_data, inflow_elements=inflow_elements, fuel_type=fuel_type), promotes=[ 'Fl_I:stat:W', 'Fl_I:FAR', 'Fl_I:tot:n', 'Fl_I:tot:h', 'Wfuel', 'Wout' ]) # Pressure loss prom_in = [('Pt_in', 'Fl_I:tot:P'), 'dPqP'] self.add_subsystem('p_loss', PressureLoss(), promotes_inputs=prom_in) # Calculate vitiated flow station properties vit_flow = SetTotal(thermo_data=thermo_data, mode='h', init_reacts=air_fuel_elements, fl_name="Fl_O:tot") self.add_subsystem('vitiated_flow', vit_flow, promotes_outputs=['Fl_O:*']) self.connect("mix_fuel.mass_avg_h", "vitiated_flow.h") self.connect("mix_fuel.init_prod_amounts", "vitiated_flow.init_prod_amounts") self.connect("p_loss.Pt_out", "vitiated_flow.P") if statics: if design: # Calculate static properties. out_stat = SetStatic(mode="MN", thermo_data=thermo_data, init_reacts=air_fuel_elements, fl_name="Fl_O:stat") prom_in = ['MN'] prom_out = ['Fl_O:stat:*'] self.add_subsystem('out_stat', out_stat, promotes_inputs=prom_in, promotes_outputs=prom_out) self.connect("mix_fuel.init_prod_amounts", "out_stat.init_prod_amounts") self.connect('Fl_O:tot:S', 'out_stat.S') self.connect('Fl_O:tot:h', 'out_stat.ht') self.connect('Fl_O:tot:P', 'out_stat.guess:Pt') self.connect('Fl_O:tot:gamma', 'out_stat.guess:gamt') self.connect('Wout', 'out_stat.W') else: # Calculate static properties. out_stat = SetStatic(mode="area", thermo_data=thermo_data, init_reacts=air_fuel_elements, fl_name="Fl_O:stat") prom_in = ['area'] prom_out = ['Fl_O:stat:*'] self.add_subsystem('out_stat', out_stat, promotes_inputs=prom_in, promotes_outputs=prom_out) self.connect("mix_fuel.init_prod_amounts", "out_stat.init_prod_amounts") self.connect('Fl_O:tot:S', 'out_stat.S') self.connect('Fl_O:tot:h', 'out_stat.ht') self.connect('Fl_O:tot:P', 'out_stat.guess:Pt') self.connect('Fl_O:tot:gamma', 'out_stat.guess:gamt') self.connect('Wout', 'out_stat.W') else: self.add_subsystem('W_passthru', PassThrough('Wout', 'Fl_O:stat:W', 1.0, units="lbm/s"), promotes=['*']) self.add_subsystem('FAR_pass_thru', PassThrough('Fl_I:FAR', 'Fl_O:FAR', 0.0), promotes=['*'])
def setup(self): thermo_data = self.options['thermo_data'] elements = self.options['elements'] bleed_elements = self.options['bleed_elements'] map_data = self.options['map_data'] designFlag = self.options['design'] bleeds = self.options['bleed_names'] statics = self.options['statics'] interp_method = self.options['map_interp_method'] map_extrap = self.options['map_extrap'] gas_thermo = species_data.Thermo(thermo_data, init_reacts=elements) self.gas_prods = gas_thermo.products self.num_prod = len(self.gas_prods) num_element = gas_thermo.num_element bld_thermo = species_data.Thermo(thermo_data, init_reacts=bleed_elements) self.bld_prods = bld_thermo.products self.num_bld_prod = len(self.bld_prods) num_bld_element = bld_thermo.num_element # Create inlet flow station in_flow = FlowIn(fl_name='Fl_I', num_prods=self.num_prod, num_elements=num_element) self.add_subsystem('in_flow', in_flow, promotes_inputs=['Fl_I:*']) self.add_subsystem('corrinputs', CorrectedInputsCalc(), promotes_inputs=[ 'Nmech', ('W_in', 'Fl_I:stat:W'), ('Pt', 'Fl_I:tot:P'), ('Tt', 'Fl_I:tot:T') ], promotes_outputs=['Np', 'Wp']) turb_map = TurbineMap(map_data=map_data, design=designFlag, interp_method=interp_method, extrap=map_extrap) if designFlag: self.add_subsystem( 'map', turb_map, promotes_inputs=['Np', 'Wp', 'PR', 'eff'], promotes_outputs=['s_PR', 's_Wp', 's_eff', 's_Np']) else: self.add_subsystem( 'map', turb_map, promotes_inputs=['Np', 'Wp', 's_PR', 's_Wp', 's_eff', 's_Np'], promotes_outputs=['PR', 'eff']) # Calculate pressure drop across turbine self.add_subsystem('press_drop', PressureDrop(), promotes_inputs=['PR', ('Pt_in', 'Fl_I:tot:P')]) # Calculate ideal flow station properties self.add_subsystem('ideal_flow', SetTotal(thermo_data=thermo_data, mode='S', init_reacts=elements), promotes_inputs=[('S', 'Fl_I:tot:S'), ('b0', 'Fl_I:tot:b0')]) self.connect("press_drop.Pt_out", "ideal_flow.P") # # Calculate enthalpy drop across turbine # self.add_subsystem("enth_drop", EnthalpyDrop(), promotes=['eff']) # self.connect("Fl_I:tot:h", "enth_drop.ht_in") # self.connect("ideal_flow.h", "enth_drop.ht_out_ideal") for BN in bleeds: bld_flow = FlowIn(fl_name=BN, num_prods=self.num_bld_prod, num_elements=num_bld_element) self.add_subsystem(BN, bld_flow, promotes_inputs=['{}:*'.format(BN)]) self.set_input_defaults('{}:tot:b0'.format(BN), bld_thermo.b0) # Calculate bleed parameters blds = Bleeds(bleed_names=bleeds, thermo_data=thermo_data, main_flow_elements=elements, bld_flow_elements=bleed_elements) self.add_subsystem('blds', blds, promotes_inputs=[('W_in', 'Fl_I:stat:W'), ('Pt_in', 'Fl_I:tot:P'), ('n_in', 'Fl_I:tot:n')] + ['{}:frac_P'.format(BN) for BN in bleeds] + [('{}:W'.format(BN), '{}:stat:W'.format(BN)) for BN in bleeds] + [('{}:n'.format(BN), '{}:tot:n'.format(BN)) for BN in bleeds], promotes_outputs=['W_out']) self.connect('press_drop.Pt_out', 'blds.Pt_out') bleed_names2 = [] for BN in bleeds: # self.connect(BN+':stat:W','blds.{}:W'.format(BN)) # self.connect(BN+':tot:n','blds.{}:n'.format(BN)) # self.connect(BN+':stat:W','blds.%s:'%BN) # Determine bleed inflow properties bleed_names2.append(BN + '_inflow') self.add_subsystem(BN + '_inflow', SetTotal(thermo_data=thermo_data, mode='h', init_reacts=bleed_elements), promotes_inputs=[('b0', BN + ":tot:b0"), ('h', BN + ':tot:h')]) self.connect('blds.' + BN + ':Pt', BN + "_inflow.P") # Ideally expand bleeds to exit pressure bleed_names2.append(BN + '_ideal') self.add_subsystem(BN + '_ideal', SetTotal(thermo_data=thermo_data, mode='S', init_reacts=bleed_elements), promotes_inputs=[('b0', BN + ":tot:b0")]) self.connect(BN + "_inflow.flow:S", BN + "_ideal.S") self.connect("press_drop.Pt_out", BN + "_ideal.P") # Calculate shaft power and exit enthalpy with cooling flows production self.add_subsystem('pwr_turb', EnthalpyAndPower(bleed_names=bleeds), promotes_inputs=[ 'Nmech', 'eff', 'W_out', ('W_in', 'Fl_I:stat:W'), ('ht_in', 'Fl_I:tot:h') ] + [(BN + ':W', BN + ':stat:W') for BN in bleeds] + [(BN + ':ht', BN + ':tot:h') for BN in bleeds] + [(BN + ':ht_ideal', BN + '_ideal.h') for BN in bleeds], promotes_outputs=['power', 'trq', 'ht_out_b4bld']) self.connect('ideal_flow.h', 'pwr_turb.ht_out_ideal') # Calculate real flow station properties before bleed air is added real_flow_b4bld = SetTotal(thermo_data=thermo_data, mode='h', init_reacts=elements, fl_name="Fl_O_b4bld:tot") self.add_subsystem('real_flow_b4bld', real_flow_b4bld, promotes_inputs=[('b0', 'Fl_I:tot:b0')]) self.connect('ht_out_b4bld', 'real_flow_b4bld.h') self.connect('press_drop.Pt_out', 'real_flow_b4bld.P') # Calculate Polytropic efficiency self.add_subsystem('eff_poly_calc', eff_poly_calc(), promotes_inputs=[ 'PR', ('S_in', 'Fl_I:tot:S'), ('Rt', 'Fl_I:tot:R') ], promotes_outputs=['eff_poly']) self.connect('real_flow_b4bld.Fl_O_b4bld:tot:S', 'eff_poly_calc.S_out') # Calculate real flow station properties real_flow = SetTotal(thermo_data=thermo_data, mode='h', init_reacts=elements, fl_name="Fl_O:tot") self.add_subsystem('real_flow', real_flow, promotes_outputs=['Fl_O:tot:*']) self.connect("pwr_turb.ht_out", "real_flow.h") self.connect("press_drop.Pt_out", "real_flow.P") self.connect("blds.b0_out", "real_flow.b0") self.add_subsystem('FAR_passthru', PassThrough('Fl_I:FAR', 'Fl_O:FAR', 1.0), promotes=['*']) # Calculate static properties if statics: if designFlag: # SetStaticMN out_stat = SetStatic(mode='MN', thermo_data=thermo_data, init_reacts=elements, fl_name="Fl_O:stat") self.add_subsystem('out_stat', out_stat, promotes_inputs=['MN'], promotes_outputs=['Fl_O:stat:*']) self.connect('blds.b0_out', 'out_stat.b0') self.connect('Fl_O:tot:S', 'out_stat.S') self.connect('Fl_O:tot:h', 'out_stat.ht') self.connect('W_out', 'out_stat.W') self.connect('Fl_O:tot:P', 'out_stat.guess:Pt') self.connect('Fl_O:tot:gamma', 'out_stat.guess:gamt') else: # SetStaticArea out_stat = SetStatic(mode='area', thermo_data=thermo_data, init_reacts=elements, fl_name="Fl_O:stat") self.add_subsystem('out_stat', out_stat, promotes_inputs=['area'], promotes_outputs=['Fl_O:stat:*']) self.connect('blds.b0_out', 'out_stat.b0') self.connect('Fl_O:tot:S', 'out_stat.S') self.connect('Fl_O:tot:h', 'out_stat.ht') self.connect('W_out', 'out_stat.W') self.connect('Fl_O:tot:P', 'out_stat.guess:Pt') self.connect('Fl_O:tot:gamma', 'out_stat.guess:gamt') self.set_order( ['in_flow', 'corrinputs', 'map', 'press_drop', 'ideal_flow'] + bleeds + ['blds'] + bleed_names2 + [ 'pwr_turb', 'real_flow_b4bld', 'eff_poly_calc', 'real_flow', 'FAR_passthru', 'out_stat' ]) else: self.add_subsystem('W_passthru', PassThrough('W_out', 'Fl_O:stat:W', 1.0, units="lbm/s"), promotes=['*']) self.set_order( ['in_flow', 'corrinputs', 'map', 'press_drop', 'ideal_flow'] + bleeds + ['blds'] + bleed_names2 + [ 'pwr_turb', 'real_flow_b4bld', 'eff_poly_calc', 'real_flow', 'FAR_passthru', 'W_passthru' ]) self.set_input_defaults('Fl_I:FAR', val=0., units=None) self.set_input_defaults('eff', val=0.99, units=None) self.set_input_defaults('Fl_I:tot:b0', gas_thermo.b0)
def setup(self): thermo_data = self.options['thermo_data'] elements = self.options['elements'] nozzType = self.options['nozzType'] lossCoef = self.options['lossCoef'] gas_thermo = species_data.Thermo(thermo_data, init_reacts=elements) self.gas_prods = gas_thermo.products num_prod = len(self.gas_prods) self.add_subsystem('mach_choked', om.IndepVarComp( 'MN', 1.000, )) # Create inlet flow station in_flow = FlowIn(fl_name="Fl_I", num_prods=num_prod) self.add_subsystem('in_flow', in_flow, promotes_inputs=['Fl_I:*']) # PR_bal = self.add_subsystem('PR_bal', BalanceComp()) # PR_bal.add_balance('PR', units=None, eq_units='lbf/inch**2', lower=1.001) # self.connect('PR_bal.PR', 'PR') # self.connect('Ps_exhaust', 'PR_bal.lhs:PR') # self.connect('Ps_calc', 'PR_bal.rhs:PR') self.add_subsystem('PR_bal', PR_bal(), promotes_inputs=['*'], promotes_outputs=['*']) # Calculate pressure at the throat prom_in = [('Pt_in', 'Fl_I:tot:P'), 'PR', 'dPqP'] self.add_subsystem('press_calcs', PressureCalcs(), promotes_inputs=prom_in, promotes_outputs=['Ps_calc']) # Calculate throat total flow properties throat_total = SetTotal(thermo_data=thermo_data, mode="h", init_reacts=elements, fl_name="Fl_O:tot") prom_in = [('h', 'Fl_I:tot:h'), ('init_prod_amounts', 'Fl_I:tot:n')] self.add_subsystem('throat_total', throat_total, promotes_inputs=prom_in, promotes_outputs=['Fl_O:*']) self.connect('press_calcs.Pt_th', 'throat_total.P') # Calculate static properties for sonic flow prom_in = [('ht', 'Fl_I:tot:h'), ('W', 'Fl_I:stat:W'), ('init_prod_amounts', 'Fl_I:tot:n')] self.add_subsystem('staticMN', SetStatic(mode="MN", thermo_data=thermo_data, init_reacts=elements), promotes_inputs=prom_in) self.connect('throat_total.S', 'staticMN.S') self.connect('mach_choked.MN', 'staticMN.MN') self.connect('press_calcs.Pt_th', 'staticMN.guess:Pt') self.connect('throat_total.gamma', 'staticMN.guess:gamt') # self.connect('Fl_I.flow:flow_products','staticMN.init_prod_amounts') # Calculate static properties based on exit static pressure prom_in = [('ht', 'Fl_I:tot:h'), ('W', 'Fl_I:stat:W'), ('Ps', 'Ps_calc'), ('init_prod_amounts', 'Fl_I:tot:n')] self.add_subsystem('staticPs', SetStatic(mode="Ps", thermo_data=thermo_data, init_reacts=elements), promotes_inputs=prom_in) self.connect('throat_total.S', 'staticPs.S') # self.connect('press_calcs.Ps_calc', 'staticPs.Ps') # self.connect('Fl_I.flow:flow_products','staticPs.init_prod_amounts') # Calculate ideal exit flow properties prom_in = [('ht', 'Fl_I:tot:h'), ('S', 'Fl_I:tot:S'), ('W', 'Fl_I:stat:W'), ('Ps', 'Ps_calc'), ('init_prod_amounts', 'Fl_I:tot:n')] self.add_subsystem('ideal_flow', SetStatic(mode="Ps", thermo_data=thermo_data, init_reacts=elements), promotes_inputs=prom_in) # self.connect('press_calcs.Ps_calc', 'ideal_flow.Ps') # self.connect('Fl_I.flow:flow_products','ideal_flow.init_prod_amounts') # Determine throat and exit flow properties based on nozzle type and exit static pressure mux = Mux(nozzType=nozzType, fl_out_name='Fl_O') prom_in = [('Ps:W', 'Fl_I:stat:W'), ('MN:W', 'Fl_I:stat:W'), ('Ps:P', 'Ps_calc'), 'Ps_calc'] self.add_subsystem('mux', mux, promotes_inputs=prom_in, promotes_outputs=['*:stat:*']) self.connect('throat_total.S', 'mux.S') self.connect('staticPs.h', 'mux.Ps:h') self.connect('staticPs.T', 'mux.Ps:T') self.connect('staticPs.rho', 'mux.Ps:rho') self.connect('staticPs.gamma', 'mux.Ps:gamma') self.connect('staticPs.Cp', 'mux.Ps:Cp') self.connect('staticPs.Cv', 'mux.Ps:Cv') self.connect('staticPs.V', 'mux.Ps:V') self.connect('staticPs.Vsonic', 'mux.Ps:Vsonic') self.connect('staticPs.MN', 'mux.Ps:MN') self.connect('staticPs.area', 'mux.Ps:area') self.connect('staticMN.h', 'mux.MN:h') self.connect('staticMN.T', 'mux.MN:T') self.connect('staticMN.Ps', 'mux.MN:P') self.connect('staticMN.rho', 'mux.MN:rho') self.connect('staticMN.gamma', 'mux.MN:gamma') self.connect('staticMN.Cp', 'mux.MN:Cp') self.connect('staticMN.Cv', 'mux.MN:Cv') self.connect('staticMN.V', 'mux.MN:V') self.connect('staticMN.Vsonic', 'mux.MN:Vsonic') self.connect('mach_choked.MN', 'mux.MN:MN') self.connect('staticMN.area', 'mux.MN:area') # Calculate nozzle performance paramters based on perf_calcs = PerformanceCalcs(lossCoef=lossCoef) if lossCoef == "Cv": other_inputs = ['Cv', 'Ps_calc'] else: other_inputs = ['Cfg', 'Ps_calc'] prom_in = [('W_in', 'Fl_I:stat:W')] + other_inputs self.add_subsystem('perf_calcs', perf_calcs, promotes_inputs=prom_in, promotes_outputs=['Fg']) self.connect('ideal_flow.V', 'perf_calcs.V_ideal') # self.connect('ideal_flow.area', 'perf_calcs.A_ideal') if lossCoef == 'Cv': self.connect('Fl_O:stat:V', 'perf_calcs.V_actual') self.connect('Fl_O:stat:area', 'perf_calcs.A_actual') self.connect('Fl_O:stat:P', 'perf_calcs.Ps_actual') if self.options['internal_solver']: newton = self.nonlinear_solver = om.NewtonSolver() newton.options['atol'] = 1e-10 newton.options['rtol'] = 1e-10 newton.options['maxiter'] = 20 newton.options['iprint'] = 2 newton.options['solve_subsystems'] = True newton.options['reraise_child_analysiserror'] = False newton.linesearch = om.BoundsEnforceLS() newton.linesearch.options['bound_enforcement'] = 'scalar' newton.linesearch.options['iprint'] = -1 self.linear_solver = om.DirectSolver(assemble_jac=True)
def setup(self): mode = self.options['mode'] thermo_data = self.options['thermo_data'] init_reacts = self.options['init_reacts'] fl_name = self.options['fl_name'] thermo = species_data.Thermo(thermo_data, init_reacts) statics = SetTotal(mode='S', fl_name=fl_name, thermo_data=thermo_data, init_reacts=init_reacts, for_statics=mode) # have to promote things differently depending on which mode we are if mode == 'Ps': self.add_subsystem('statics', statics, promotes_inputs=[('P', 'Ps'), 'S', 'ht', 'W', 'init_prod_amounts'], promotes_outputs=[ 'MN', 'V', 'Vsonic', 'area', 'T', 'h', 'gamma', 'Cp', 'Cv', 'rho', 'n', 'n_moles' ]) elif mode == 'MN': self.add_subsystem('statics', statics, promotes_inputs=[ 'MN', 'S', 'ht', 'W', 'guess:*', 'init_prod_amounts' ], promotes_outputs=[ 'V', 'Vsonic', 'area', 'Ps', 'T', 'h', 'gamma', 'Cp', 'Cv', 'rho', 'n', 'n_moles' ]) else: self.add_subsystem('statics', statics, promotes_inputs=[ 'area', 'S', 'ht', 'W', 'guess:*', 'init_prod_amounts' ], promotes_outputs=[ 'V', 'Vsonic', 'MN', 'Ps', 'T', 'h', 'gamma', 'Cp', 'Cv', 'rho', 'n', 'n_moles' ]) p_inputs = ('T', 'P', 'h', 'S', 'gamma', 'Cp', 'Cv', 'rho', 'n', 'n_moles') p_outputs = tuple( ['{0}:{1}'.format(fl_name, in_name) for in_name in p_inputs]) # need to redefine this so that P gets promoted as P. Needed the first definition for the list comprehension p_inputs = ('T', ('P', 'Ps'), 'h', 'S', 'gamma', 'Cp', 'Cv', 'rho', 'n', 'n_moles') self.add_subsystem('flow', EngUnitProps(thermo=thermo, fl_name=fl_name), promotes_inputs=p_inputs, promotes_outputs=p_outputs) p_inputs = ('area', 'W', 'V', 'Vsonic', 'MN') p_outputs = tuple( ['{0}:{1}'.format(fl_name, in_name) for in_name in p_inputs]) eng_units_statics = EngUnitStaticProps(thermo, fl_name) self.add_subsystem('flow_static', eng_units_statics, promotes_inputs=p_inputs, promotes_outputs=p_outputs)
def test_set_total_sp(self): thermo = species_data.Thermo(species_data.co2_co_o2) # 4000k p = Problem() p.model = SetTotal(thermo_data=species_data.co2_co_o2, mode="S") p.model.suppress_solver_output = True r = p.model r.add_subsystem('n_init', IndepVarComp('init_prod_amounts', thermo.init_prod_amounts), promotes=["*"]) r.add_subsystem('S_init', IndepVarComp('S', 2.35711010759, units="Btu/(lbm*degR)"), promotes=["*"]) r.add_subsystem('P_init', IndepVarComp('P', 1.034210, units="bar"), promotes=["*"]) p.set_solver_print(level=2) p.setup(check=False) p.run_model() np.seterr(all='raise') # goal_concentrations = np.array([0.61976,0.07037,0.30988]) # original # cea mole fractions expected_concentrations = np.array( [0.62003271, 0.06995092, 0.31001638]) # [ 2.35337787e-01 1.16205327e+03 1.17668894e-01] n = p['n'] n_moles = p['n_moles'] concentrations = n / n_moles assert_rel_error(self, concentrations, expected_concentrations, 1e-4) expected_n_moles = 0.0329313730421 assert_rel_error(self, n_moles, expected_n_moles, 1e-4) assert_rel_error(self, p['gamma'], 1.19054696779, 1e-4) # 1500K p['S'] = 1.5852424435 # p.model.chem_eq.DEBUG=True p.run_model() # [0.00036, 0.99946, 0.00018]) expected_concentrations = np.array( [3.58768646e-04, 9.99461847e-01, 1.79384323e-04]) n = p['n'] n_moles = p['n_moles'] concentrations = n / n_moles assert_rel_error(self, concentrations, expected_concentrations, 1e-4) expected_n_moles = 0.022726185333 assert_rel_error(self, n_moles, expected_n_moles, 1e-4) assert_rel_error(self, p['gamma'], 1.16381209181, 1e-4)
def test_set_total_hp(self): thermo = species_data.Thermo(species_data.co2_co_o2) # 4000k p = Problem() p.model = SetTotal(thermo_data=species_data.co2_co_o2, mode="h") p.model.suppress_solver_output = True r = p.model r.add_subsystem('n_init', IndepVarComp('init_prod_amounts', thermo.init_prod_amounts), promotes=["*"]) r.add_subsystem('h_init', IndepVarComp('h', 340, units='cal/g'), promotes=["*"]) r.add_subsystem('P_init', IndepVarComp('P', 1.034210, units='bar'), promotes=["*"]) p.set_solver_print(level=2) p.setup(check=False) p.run_model() # goal_concentrations = np.array([0.61976,0.07037,0.30988]) # original # cea mole fractions expected_concentrations = np.array( [0.61989858, 0.07015213, 0.30994929]) n = p['n'] n_moles = p['n_moles'] concentrations = n / n_moles assert_rel_error(self, concentrations, expected_concentrations, 1e-4) expected_n_moles = 0.0329281722301 assert_rel_error(self, n_moles, expected_n_moles, 1e-4) assert_rel_error(self, p['gamma'], 1.19039688581, 1e-4) # 1500K p['h'] = -1801.35537381 # seems to want to start from a different guess than the last converged point p['n'] = np.array([.33333, .33333, .33333]) p.run_model() # [0.00036, 0.99946, 0.00018]) expected_concentrations = np.array( [3.58768646e-04, 9.99461847e-01, 1.79384323e-04]) n = p['n'] n_moles = p['n_moles'] concentrations = n / n_moles # print(expected_concentrations) # print(concentrations) # print(p['T']) assert_rel_error(self, concentrations, expected_concentrations, 1e-4) expected_n_moles = 0.022726185333 assert_rel_error(self, n_moles, expected_n_moles, 1e-4) assert_rel_error(self, p['gamma'], 1.16379012007, 1e-4)
def setup(self): thermo_data = self.options['thermo_data'] elements = self.options['elements'] statics = self.options['statics'] design = self.options['design'] expMN = self.options['expMN'] gas_thermo = species_data.Thermo(thermo_data, init_reacts=elements) gas_prods = gas_thermo.products num_prod = len(gas_prods) # Create inlet flowstation flow_in = FlowIn(fl_name='Fl_I', num_prods=num_prod) self.add_subsystem('flow_in', flow_in, promotes=['Fl_I:tot:*', 'Fl_I:stat:*']) if expMN > 1e-10: # Calcluate pressure losses as function of Mach number if design: self.add_subsystem( 'dPqP_MN', MachPressureLossMap(design=design, expMN=expMN), promotes_inputs=['dPqP', ('MN_in', 'Fl_I:stat:MN')], promotes_outputs=['s_dPqP']) else: self.add_subsystem( 'dPqP_MN', MachPressureLossMap(design=design, expMN=expMN), promotes_inputs=['s_dPqP', ('MN_in', 'Fl_I:stat:MN')], promotes_outputs=['dPqP']) #Pressure Loss Component prom_in = [('Pt_in', 'Fl_I:tot:P'), 'dPqP'] self.add_subsystem('p_loss', PressureLoss(), promotes_inputs=prom_in) # Energy Calc Component prom_in = [('W_in', 'Fl_I:stat:W'), ('ht_in', 'Fl_I:tot:h'), 'Q_dot'] self.add_subsystem('q_calc', qCalc(), promotes_inputs=prom_in) # Total Calc real_flow = SetTotal(thermo_data=thermo_data, mode='h', init_reacts=elements, fl_name="Fl_O:tot") prom_in = [('init_prod_amounts', 'Fl_I:tot:n')] self.add_subsystem('real_flow', real_flow, promotes_inputs=prom_in, promotes_outputs=['Fl_O:*']) self.connect("q_calc.ht_out", "real_flow.h") self.connect("p_loss.Pt_out", "real_flow.P") if statics: if design: # Calculate static properties out_stat = SetStatic(mode="MN", thermo_data=thermo_data, init_reacts=elements, fl_name="Fl_O:stat") prom_in = [('init_prod_amounts', 'Fl_I:tot:n'), ('W', 'Fl_I:stat:W'), 'MN'] prom_out = ['Fl_O:stat:*'] self.add_subsystem('out_stat', out_stat, promotes_inputs=prom_in, promotes_outputs=prom_out) self.connect('Fl_O:tot:S', 'out_stat.S') self.connect('Fl_O:tot:h', 'out_stat.ht') self.connect('Fl_O:tot:P', 'out_stat.guess:Pt') self.connect('Fl_O:tot:gamma', 'out_stat.guess:gamt') else: # Calculate static properties out_stat = SetStatic(mode="area", thermo_data=thermo_data, init_reacts=elements, fl_name="Fl_O:stat") prom_in = [('init_prod_amounts', 'Fl_I:tot:n'), ('W', 'Fl_I:stat:W'), 'area'] prom_out = ['Fl_O:stat:*'] self.add_subsystem('out_stat', out_stat, promotes_inputs=prom_in, promotes_outputs=prom_out) self.connect('Fl_O:tot:S', 'out_stat.S') self.connect('Fl_O:tot:h', 'out_stat.ht') self.connect('Fl_O:tot:P', 'out_stat.guess:Pt') self.connect('Fl_O:tot:gamma', 'out_stat.guess:gamt') else: self.add_subsystem('W_passthru', PassThrough('Fl_I:stat:W', 'Fl_O:stat:W', 1.0, units="lbm/s"), promotes=['*']) self.add_subsystem('FAR_passthru', PassThrough('Fl_I:FAR', 'Fl_O:FAR', 0.0), promotes=['*'])
def test_set_total_tp(self): thermo = species_data.Thermo(species_data.co2_co_o2) # 4000k p = Problem() p.model = SetTotal(thermo_data=species_data.co2_co_o2, mode="T") r = p.model r.add_subsystem('n_init', IndepVarComp('init_prod_amounts', thermo.init_prod_amounts), promotes=["*"]) r.add_subsystem('T_init', IndepVarComp('T', 4000., units='degK'), promotes=["*"]) r.add_subsystem('P_init', IndepVarComp('P', 1.034210, units="bar"), promotes=["*"]) p.set_solver_print(level=2) p.setup(check=False) # from openmdao.api import view_tree # view_tree(p) p.run_model() # p.check_partial_derivatives() # goal_concentrations = np.array([0.61976,0.07037,0.30988]) # original # cea mole fractions expected_concentrations = np.array( [0.62003271, 0.06995092, 0.31001638]) n = p['n'] n_moles = p['n_moles'] concentrations = n / n_moles # print(expected_concentrations) # print(concentrations) assert_rel_error(self, concentrations, expected_concentrations, 1e-4) expected_n_moles = 0.0329313730421 assert_rel_error(self, n_moles, expected_n_moles, 1e-4) assert_rel_error(self, p['gamma'], 1.19054696779, 1e-4) # 1500K p['T'] = 1500 # degK p['P'] = 1.034210 # bar p.run_model() # [0.00036, 0.99946, 0.00018]) expected_concentrations = np.array( [3.58768646e-04, 9.99461847e-01, 1.79384323e-04]) n = p['n'] n_moles = p['n_moles'] concentrations = n / n_moles expected_n_moles = 0.022726185333 assert_rel_error(self, n_moles, expected_n_moles, 1e-4) assert_rel_error(self, p['gamma'], 1.16380, 1e-4)
def setup(self): #(self, mapclass=NCP01map(), design=True, thermo_data=species_data.janaf, elements=AIR_MIX, bleeds=[],statics=True): map_data = self.options['map_data'] interp_method = self.options['map_interp_method'] map_extrap = self.options['map_extrap'] # self.linear_solver = ScipyGMRES() # self.linear_solver.options['atol'] = 2e-8 # self.linear_solver.options['maxiter'] = 100 # self.linear_solver.options['restart'] = 100 # self.nonlinear_solver = Newton() # self.nonlinear_solver.options['utol'] = 1e-9 design = self.options['design'] bleeds = self.options['bleed_names'] thermo_data = self.options['thermo_data'] elements = self.options['elements'] statics = self.options['statics'] thermo = species_data.Thermo(thermo_data, init_reacts=elements) num_prod = thermo.num_prod # Create inlet flow station flow_in = FlowIn(fl_name='Fl_I', num_prods=num_prod) self.add_subsystem('flow_in', flow_in, promotes_inputs=['Fl_I:*']) self.add_subsystem('corrinputs', CorrectedInputsCalc(), promotes_inputs=( 'Nmech', ('W_in', 'Fl_I:stat:W'), ('Pt', 'Fl_I:tot:P'), ('Tt', 'Fl_I:tot:T')), promotes_outputs=('Nc', 'Wc')) map_calcs = CompressorMap(map_data=self.options['map_data'], design=design, interp_method=interp_method, extrap=map_extrap) self.add_subsystem('map', map_calcs, promotes=['s_Nc','s_eff','s_Wc','s_PR','Nc','Wc', 'PR','eff','SMN','SMW']) # Calculate pressure rise across compressor self.add_subsystem('press_rise', PressureRise(), promotes_inputs=[ 'PR', ('Pt_in', 'Fl_I:tot:P')]) # Calculate ideal flow station properties self.add_subsystem('ideal_flow', SetTotal(thermo_data=thermo_data, mode='S', init_reacts=elements), promotes_inputs=[('S', 'Fl_I:tot:S'), ('init_prod_amounts', 'Fl_I:tot:n')]) self.connect("press_rise.Pt_out", "ideal_flow.P") # Calculate enthalpy rise across compressor self.add_subsystem("enth_rise", EnthalpyRise(), promotes_inputs=['eff', ('inlet_ht', 'Fl_I:tot:h')]) self.connect("ideal_flow.h", "enth_rise.ideal_ht") # Calculate real flow station properties real_flow = SetTotal(thermo_data=thermo_data, mode='h', init_reacts=elements, fl_name="Fl_O:tot") self.add_subsystem('real_flow', real_flow, promotes_inputs=[ ('init_prod_amounts', 'Fl_I:tot:n')], promotes_outputs=['Fl_O:tot:*']) self.connect("enth_rise.ht_out", "real_flow.h") self.connect("press_rise.Pt_out", "real_flow.P") #clculate Polytropic Efficiency self.add_subsystem('eff_poly_calc', eff_poly_calc(), promotes_inputs=[('PR','PR'), ('S_in','Fl_I:tot:S'), ('S_out','Fl_O:tot:S'), # ('Cp','Fl_I:tot:Cp'), # ('Cv','Fl_I:tot:Cv'), ('Rt', 'Fl_I:tot:R')], promotes_outputs=['eff_poly'] ) # Calculate shaft power consumption blds_pwr = BleedsAndPower(bleed_names=bleeds) bld_inputs = ['frac_W', 'frac_P', 'frac_work'] bld_in_vars = ['{0}:{1}'.format( bn, in_name) for bn, in_name in itertools.product(bleeds, bld_inputs)] bld_out_globs = ['{}:*'.format(bn) for bn in bleeds] self.add_subsystem('blds_pwr', blds_pwr, promotes_inputs=['Nmech', ('W_in', 'Fl_I:stat:W'), ('ht_in', 'Fl_I:tot:h'), ('Pt_in', 'Fl_I:tot:P'), ('Pt_out', 'Fl_O:tot:P'), ] + bld_in_vars, promotes_outputs=['power', 'trq', 'W_out'] + bld_out_globs) self.connect('enth_rise.ht_out', 'blds_pwr.ht_out') bleed_names = [] for BN in bleeds: bleed_names.append(BN + '_flow') bleed_flow = SetTotal(thermo_data=thermo_data, mode='h', init_reacts=elements, fl_name=BN + ":tot") self.add_subsystem(BN + '_flow', bleed_flow, promotes_inputs=[ ('init_prod_amounts', 'Fl_I:tot:n')], promotes_outputs=['{}:tot:*'.format(BN)]) self.connect(BN + ':ht', BN + "_flow.h") self.connect(BN + ':Pt', BN + "_flow.P") self.add_subsystem('FAR_passthru', PassThrough( 'Fl_I:FAR', 'Fl_O:FAR', 0.0), promotes=['*']) if statics: if design: # Calculate static properties out_stat = SetStatic( mode='MN', thermo_data=thermo_data, init_reacts=elements, fl_name="Fl_O:stat") self.add_subsystem('out_stat', out_stat, promotes_inputs=[ 'MN', ('init_prod_amounts', 'Fl_I:tot:n')], promotes_outputs=['Fl_O:stat:*']) self.connect('Fl_O:tot:S', 'out_stat.S') self.connect('Fl_O:tot:h', 'out_stat.ht') self.connect('W_out', 'out_stat.W') self.connect('Fl_O:tot:P', 'out_stat.guess:Pt') self.connect('Fl_O:tot:gamma', 'out_stat.guess:gamt') else: # Calculate static properties out_stat = SetStatic( mode='area', thermo_data=thermo_data, init_reacts=elements, fl_name="Fl_O:stat") self.add_subsystem('out_stat', out_stat, promotes_inputs=[ 'area', ('init_prod_amounts', 'Fl_I:tot:n')], promotes_outputs=['Fl_O:stat:*']) self.connect('Fl_O:tot:S', 'out_stat.S') self.connect('Fl_O:tot:h', 'out_stat.ht') self.connect('W_out', 'out_stat.W') self.connect('Fl_O:tot:P', 'out_stat.guess:Pt') self.connect('Fl_O:tot:gamma', 'out_stat.guess:gamt') self.set_order(['flow_in', 'corrinputs', 'map', 'press_rise','ideal_flow', 'enth_rise', 'real_flow','eff_poly_calc' ,'blds_pwr', 'FAR_passthru'] + bleed_names + ['out_stat']) else: self.add_subsystem('W_passthru', PassThrough('W_out', 'Fl_O:stat:W', 1.0, units="lbm/s"), promotes=['*']) self.set_order(['flow_in', 'corrinputs', 'map', 'press_rise','ideal_flow', 'enth_rise', 'real_flow','eff_poly_calc' , 'blds_pwr', 'FAR_passthru'] + bleed_names + ['W_passthru'])
def setup(self): thermo_data = self.options['thermo_data'] elements = self.options['elements'] statics = self.options['statics'] design = self.options['design'] gas_thermo = species_data.Thermo(thermo_data, init_reacts=elements) gas_prods = gas_thermo.products num_prod = len(gas_prods) # Create inlet flow station flow_in = FlowIn(fl_name='Fl_I', num_prods=num_prod) self.add_subsystem('flow_in', flow_in, promotes=['Fl_I:tot:*', 'Fl_I:stat:*']) # Perform inlet engineering calculations self.add_subsystem('calcs_inlet', Calcs(), promotes_inputs=[ 'ram_recovery', ('Pt_in', 'Fl_I:tot:P'), ('V_in', 'Fl_I:stat:V'), ('W_in', 'Fl_I:stat:W') ], promotes_outputs=['F_ram']) # Calculate real flow station properties real_flow = SetTotal(thermo_data=thermo_data, mode="T", init_reacts=elements, fl_name="Fl_O:tot") self.add_subsystem('real_flow', real_flow, promotes_inputs=[('T', 'Fl_I:tot:T'), ('init_prod_amounts', 'Fl_I:tot:n') ], promotes_outputs=['Fl_O:*']) self.connect("calcs_inlet.Pt_out", "real_flow.P") self.add_subsystem('FAR_passthru', PassThrough('Fl_I:FAR', 'Fl_O:FAR', 0.0), promotes=['*']) if statics: if design: # Calculate static properties self.add_subsystem('out_stat', SetStatic(mode="MN", thermo_data=thermo_data, init_reacts=elements, fl_name="Fl_O:stat"), promotes_inputs=[ ('init_prod_amounts', 'Fl_I:tot:n'), ('W', 'Fl_I:stat:W'), 'MN' ], promotes_outputs=['Fl_O:stat:*']) self.connect('Fl_O:tot:S', 'out_stat.S') self.connect('Fl_O:tot:h', 'out_stat.ht') self.connect('Fl_O:tot:P', 'out_stat.guess:Pt') self.connect('Fl_O:tot:gamma', 'out_stat.guess:gamt') else: # Calculate static properties out_stat = SetStatic(mode="area", thermo_data=thermo_data, init_reacts=elements, fl_name="Fl_O:stat") prom_in = [('init_prod_amounts', 'Fl_I:tot:n'), ('W', 'Fl_I:stat:W'), 'area'] prom_out = ['Fl_O:stat:*'] self.add_subsystem('out_stat', out_stat, promotes_inputs=prom_in, promotes_outputs=prom_out) self.connect('Fl_O:tot:S', 'out_stat.S') self.connect('Fl_O:tot:h', 'out_stat.ht') self.connect('Fl_O:tot:P', 'out_stat.guess:Pt') self.connect('Fl_O:tot:gamma', 'out_stat.guess:gamt') else: self.add_subsystem('W_passthru', PassThrough('Fl_I:stat:W', 'Fl_O:stat:W', 0.0, units="lbm/s"), promotes=['*'])
def setup(self): thermo_data = self.options['thermo_data'] elements = self.options['elements'] statics = self.options['statics'] design = self.options['design'] bleeds = self.options['bleed_names'] gas_thermo = species_data.Thermo(thermo_data, init_reacts=elements) gas_prods = gas_thermo.products num_prod = len(gas_prods) # Create inlet flowstation flow_in = FlowIn(fl_name='Fl_I', num_prods=num_prod) self.add_subsystem('flow_in', flow_in, promotes=['Fl_I:tot:*', 'Fl_I:stat:*']) # Bleed flow calculations blds = BleedCalcs(bleed_names=bleeds) bld_port_globs = ['{}:*'.format(bn) for bn in bleeds] self.add_subsystem('bld_calcs', blds, promotes_inputs=[('W_in', 'Fl_I:stat:W'), '*:frac_W'], promotes_outputs=['W_out'] + bld_port_globs) bleed_names = [] for BN in bleeds: bleed_names.append(BN + '_flow') bleed_flow = SetTotal(thermo_data=thermo_data, mode='T', init_reacts=elements, fl_name=BN + ":tot") self.add_subsystem(BN + '_flow', bleed_flow, promotes_inputs=[('init_prod_amounts', 'Fl_I:tot:n'), ('T', 'Fl_I:tot:T'), ('P', 'Fl_I:tot:P')], promotes_outputs=['{}:tot:*'.format(BN)]) # Total Calc real_flow = SetTotal(thermo_data=thermo_data, mode='T', init_reacts=elements, fl_name="Fl_O:tot") prom_in = [('init_prod_amounts', 'Fl_I:tot:n'), ('T', 'Fl_I:tot:T'), ('P', 'Fl_I:tot:P')] self.add_subsystem('real_flow', real_flow, promotes_inputs=prom_in, promotes_outputs=['Fl_O:*']) if statics: if design: # Calculate static properties out_stat = SetStatic(mode="MN", thermo_data=thermo_data, init_reacts=elements, fl_name="Fl_O:stat") prom_in = [('init_prod_amounts', 'Fl_I:tot:n'), 'MN'] prom_out = ['Fl_O:stat:*'] self.add_subsystem('out_stat', out_stat, promotes_inputs=prom_in, promotes_outputs=prom_out) self.connect('Fl_O:tot:S', 'out_stat.S') self.connect('Fl_O:tot:h', 'out_stat.ht') self.connect('Fl_O:tot:P', 'out_stat.guess:Pt') self.connect('Fl_O:tot:gamma', 'out_stat.guess:gamt') self.connect('W_out', 'out_stat.W') else: # Calculate static properties out_stat = SetStatic(mode="area", thermo_data=thermo_data, init_reacts=elements, fl_name="Fl_O:stat") prom_in = [('init_prod_amounts', 'Fl_I:tot:n'), 'area'] prom_out = ['Fl_O:stat:*'] self.add_subsystem('out_stat', out_stat, promotes_inputs=prom_in, promotes_outputs=prom_out) self.connect('Fl_O:tot:S', 'out_stat.S') self.connect('Fl_O:tot:h', 'out_stat.ht') self.connect('Fl_O:tot:P', 'out_stat.guess:Pt') self.connect('Fl_O:tot:gamma', 'out_stat.guess:gamt') self.connect('W_out', 'out_stat.W') else: self.add_subsystem('W_passthru', PassThrough('W_out', 'Fl_O:stat:W', 1.0, units="lbm/s"), promotes=['*']) self.add_subsystem('FAR_passthru', PassThrough('Fl_I:FAR', 'Fl_O:FAR', 0.0), promotes=['*'])
def test_case_MN(self): p = Problem() indeps = p.model.add_subsystem('indeps', IndepVarComp(), promotes=['*']) indeps.add_output('T', val=518., units='degR') indeps.add_output('P', val=14.7, units='psi') indeps.add_output('W', val=1.5, units='lbm/s') indeps.add_output('MN', val=1.5, units=None) p.model.add_subsystem('set_total_TP', SetTotal(thermo_data=janaf)) p.model.add_subsystem('set_static_MN', SetStatic(mode='MN', thermo_data=janaf)) p.model.connect('T', 'set_total_TP.T') p.model.connect('P', ['set_total_TP.P', 'set_static_MN.guess:Pt']) p.model.connect('set_total_TP.flow:S', 'set_static_MN.S') p.model.connect('set_total_TP.flow:h', 'set_static_MN.ht') p.model.connect('set_total_TP.flow:gamma', 'set_static_MN.guess:gamt') p.model.connect('W', 'set_static_MN.W') p.model.connect('MN', 'set_static_MN.MN') p.set_solver_print(level=-1) p.setup(check=False) # from openmdao.api import view_model # view_model(p) # exit() # 4 cases to check against for i, data in enumerate(ref_data): p['T'] = data[h_map['Tt']] p['P'] = data[h_map['Pt']] p['MN'] = data[h_map['MN']] p['W'] = data[h_map['W']] # p.print_all_convergence() # p.set_solver_print(level=2) # print("###################################") # print(p['T'], p['P'], p['MN'], p['W']) # print("###################################") p.run_model() # check outputs npss_vars = ('Ps', 'Ts', 'MN', 'hs', 'rhos', 'gams', 'V', 'A', 's', 'ht') Ps, Ts, MN, hs, rhos, gams, V, A, S, ht = tuple( [data[h_map[v_name]] for v_name in npss_vars]) Ps_computed = p['set_static_MN.flow:P'] Ts_computed = p['set_static_MN.flow:T'] hs_computed = p['set_static_MN.flow:h'] rhos_computed = p['set_static_MN.flow:rho'] gams_computed = p['set_static_MN.flow:gamma'] V_computed = p['set_static_MN.flow:V'] A_computed = p['set_static_MN.flow:area'] MN_computed = p['set_static_MN.flow:MN'] if MN < 2: tol = 1e-4 else: # The MN 2.0 case doesn't get as close tol = 1e-2 # print("foo", p['set_total_TP.flow:T'], p['set_total_TP.flow:P'], p['set_total_TP.flow:gamma']) # print("Ps", Ps_computed, Ps) # print("Ts", Ts_computed, Ts) # print("hs", hs_computed, hs) # print("gamma", gams_computed, gams) # print("V", V_computed, V) # print("A", A_computed, A) # print("MN", MN_computed, MN) # print("rhos", rhos_computed, rhos) # print() assert_rel_error(self, MN_computed, MN, tol) assert_rel_error(self, gams_computed, gams, tol) assert_rel_error(self, Ps_computed, Ps, tol) assert_rel_error(self, Ts_computed, Ts, tol) assert_rel_error(self, hs_computed, hs, tol) assert_rel_error(self, rhos_computed, rhos, tol) assert_rel_error(self, V_computed, V, tol) assert_rel_error(self, A_computed, A, tol)
def setup(self): design = self.options['design'] thermo_data = self.options['thermo_data'] flow1_elements = self.options['Fl_I1_elements'] flow1_thermo = Thermo(thermo_data, init_reacts=flow1_elements) n_flow1_prods = len(flow1_thermo.products) in_flow = FlowIn(fl_name='Fl_I1', num_prods=n_flow1_prods) self.add_subsystem('in_flow1', in_flow, promotes=['Fl_I1:*']) flow2_elements = self.options['Fl_I2_elements'] flow2_thermo = Thermo(thermo_data, init_reacts=flow2_elements) n_flow2_prods = len(flow2_thermo.products) in_flow = FlowIn(fl_name='Fl_I2', num_prods=n_flow2_prods) self.add_subsystem('in_flow2', in_flow, promotes=['Fl_I2:*']) if design: # internal flow station to compute the area that is needed to match the static pressures if self.options['designed_stream'] == 1: Fl1_stat = SetStatic(mode="Ps", thermo_data=thermo_data, init_reacts=flow1_elements, fl_name="Fl_I1_calc:stat") self.add_subsystem('Fl_I1_stat_calc', Fl1_stat, promotes_inputs=[('init_prod_amounts', 'Fl_I1:stat:n'), ('S', 'Fl_I1:tot:S'), ('ht', 'Fl_I1:tot:h'), ('W', 'Fl_I1:stat:W'), ('Ps', 'Fl_I2:stat:P')], promotes_outputs=['Fl_I1_calc:stat*']) self.add_subsystem('area_calc', AreaSum(), promotes_inputs=['Fl_I2:stat:area'], promotes_outputs=[('area_sum', 'area')]) self.connect('Fl_I1_calc:stat:area', 'area_calc.Fl_I1:stat:area') else: Fl2_stat = SetStatic(mode="Ps", thermo_data=thermo_data, init_reacts=flow2_elements, fl_name="Fl_I2_calc:stat") self.add_subsystem('Fl_I2_stat_calc', Fl2_stat, promotes_inputs=[('init_prod_amounts', 'Fl_I2:tot:n'), ('S', 'Fl_I2:tot:S'), ('ht', 'Fl_I2:tot:h'), ('W', 'Fl_I2:stat:W'), ('Ps', 'Fl_I1:stat:P')], promotes_outputs=['Fl_I2_calc:stat:*']) self.add_subsystem('area_calc', AreaSum(), promotes_inputs=['Fl_I1:stat:area'], promotes_outputs=[('area_sum', 'area')]) self.connect('Fl_I2_calc:stat:area', 'area_calc.Fl_I2:stat:area') else: if self.options['designed_stream'] == 1: Fl1_stat = SetStatic(mode="area", thermo_data=thermo_data, init_reacts=flow1_elements, fl_name="Fl_I1_calc:stat") self.add_subsystem('Fl_I1_stat_calc', Fl1_stat, promotes_inputs=[ ('init_prod_amounts', 'Fl_I1:tot:n'), ('S', 'Fl_I1:tot:S'), ('ht', 'Fl_I1:tot:h'), ('W', 'Fl_I1:stat:W'), ('guess:Pt', 'Fl_I1:tot:P'), ('guess:gamt', 'Fl_I1:tot:gamma') ], promotes_outputs=['Fl_I1_calc:stat*']) else: Fl2_stat = SetStatic(mode="area", thermo_data=thermo_data, init_reacts=flow2_elements, fl_name="Fl_I2_calc:stat") self.add_subsystem('Fl_I2_stat_calc', Fl2_stat, promotes_inputs=[ ('init_prod_amounts', 'Fl_I2:tot:n'), ('S', 'Fl_I2:tot:S'), ('ht', 'Fl_I2:tot:h'), ('W', 'Fl_I2:stat:W'), ('guess:Pt', 'Fl_I2:tot:P'), ('guess:gamt', 'Fl_I2:tot:gamma') ], promotes_outputs=['Fl_I2_calc:stat*']) self.add_subsystem('extraction_ratio', om.ExecComp('ER=Pt1/Pt2', Pt1={'units': 'Pa'}, Pt2={'units': 'Pa'}), promotes_inputs=[('Pt1', 'Fl_I1:tot:P'), ('Pt2', 'Fl_I2:tot:P')], promotes_outputs=['ER']) mix_flow = MixFlow(thermo_data=thermo_data, Fl_I1_elements=self.options['Fl_I1_elements'], Fl_I2_elements=self.options['Fl_I2_elements']) if self.options['designed_stream'] == 1: self.add_subsystem('mix_flow', mix_flow, promotes_inputs=[ 'Fl_I1:tot:h', 'Fl_I1:tot:n', ('Fl_I1:stat:W', 'Fl_I1_calc:stat:W'), ('Fl_I1:stat:P', 'Fl_I1_calc:stat:P'), ('Fl_I1:stat:V', 'Fl_I1_calc:stat:V'), ('Fl_I1:stat:area', 'Fl_I1_calc:stat:area'), 'Fl_I2:tot:h', 'Fl_I2:tot:n', 'Fl_I2:stat:W', 'Fl_I2:stat:P', 'Fl_I2:stat:V', 'Fl_I2:stat:area' ]) else: self.add_subsystem('mix_flow', mix_flow, promotes_inputs=[ 'Fl_I1:tot:h', 'Fl_I1:tot:n', 'Fl_I1:stat:W', 'Fl_I1:stat:P', 'Fl_I1:stat:V', 'Fl_I1:stat:area', 'Fl_I2:tot:h', 'Fl_I2:tot:n', ('Fl_I2:stat:W', 'Fl_I2_calc:stat:W'), ('Fl_I2:stat:P', 'Fl_I2_calc:stat:P'), ('Fl_I2:stat:V', 'Fl_I2_calc:stat:V'), ('Fl_I2:stat:area', 'Fl_I2_calc:stat:area') ]) # group to converge for the impulse balance conv = self.add_subsystem('impulse_converge', om.Group(), promotes=['*']) if self.options['internal_solver']: newton = conv.nonlinear_solver = om.NewtonSolver() newton.options['maxiter'] = 30 newton.options['atol'] = 1e-2 newton.options['solve_subsystems'] = True newton.options['max_sub_solves'] = 20 newton.linesearch = om.BoundsEnforceLS() newton.linesearch.options['bound_enforcement'] = 'scalar' newton.linesearch.options['iprint'] = -1 conv.linear_solver = om.DirectSolver(assemble_jac=True) out_tot = SetTotal(thermo_data=thermo_data, mode='h', init_reacts=self.options['Fl_I1_elements'], fl_name="Fl_O:tot") conv.add_subsystem('out_tot', out_tot, promotes_outputs=['Fl_O:tot:*']) self.connect('mix_flow.n_mix', 'out_tot.init_prod_amounts') self.connect('mix_flow.ht_mix', 'out_tot.h') # note: gets Pt from the balance comp out_stat = SetStatic(mode="area", thermo_data=thermo_data, init_reacts=self.options['Fl_I1_elements'], fl_name="Fl_O:stat") conv.add_subsystem('out_stat', out_stat, promotes_outputs=['Fl_O:stat:*'], promotes_inputs=[ 'area', ]) self.connect('mix_flow.n_mix', 'out_stat.init_prod_amounts') self.connect('mix_flow.W_mix', 'out_stat.W') conv.connect('Fl_O:tot:S', 'out_stat.S') self.connect('mix_flow.ht_mix', 'out_stat.ht') conv.connect('Fl_O:tot:P', 'out_stat.guess:Pt') conv.connect('Fl_O:tot:gamma', 'out_stat.guess:gamt') conv.add_subsystem('imp_out', Impulse()) conv.connect('Fl_O:stat:P', 'imp_out.P') conv.connect('Fl_O:stat:area', 'imp_out.area') conv.connect('Fl_O:stat:V', 'imp_out.V') conv.connect('Fl_O:stat:W', 'imp_out.W') balance = conv.add_subsystem('balance', om.BalanceComp()) balance.add_balance('P_tot', val=100, units='psi', eq_units='N', lower=1e-3, upper=10000) conv.connect('balance.P_tot', 'out_tot.P') conv.connect('imp_out.impulse', 'balance.lhs:P_tot') self.connect( 'mix_flow.impulse_mix', 'balance.rhs:P_tot' ) #note that this connection comes from outside the convergence group
def test_case_Ps(self): p = Problem() indeps = p.model.add_subsystem('indeps', IndepVarComp(), promotes=['*']) indeps.add_output('T', val=518., units='degR') indeps.add_output('P', val=14.7, units='psi') indeps.add_output('Ps', val=13.0, units='psi') indeps.add_output('W', val=1., units='lbm/s') p.model.add_subsystem('set_total_TP', SetTotal(thermo_data=janaf)) p.model.add_subsystem('set_static_Ps', SetStatic(mode='Ps', thermo_data=janaf)) p.model.connect('set_total_TP.flow:S', 'set_static_Ps.S') p.model.connect('set_total_TP.flow:h', 'set_static_Ps.ht') p.model.connect('T', 'set_total_TP.T') p.model.connect('P', 'set_total_TP.P') p.model.connect('Ps', 'set_static_Ps.Ps') p.model.connect('W', 'set_static_Ps.W') p.setup(check=False) p.set_solver_print(level=-1) # from openmdao.api import view_model # view_model(p) # exit() # 4 cases to check against for i, data in enumerate(ref_data): p['T'] = data[h_map['Tt']] p['P'] = data[h_map['Pt']] p['Ps'] = data[h_map['Ps']] p['W'] = data[h_map['W']] p.run_model() # check outputs npss_vars = ('Ps', 'Ts', 'MN', 'hs', 'rhos', 'gams', 'V', 'A', 's', 'ht') Ps, Ts, MN, hs, rhos, gams, V, A, S, ht = tuple( [data[h_map[v_name]] for v_name in npss_vars]) Ps_computed = p['set_static_Ps.flow:P'] Ts_computed = p['set_static_Ps.flow:T'] hs_computed = p['set_static_Ps.flow:h'] rhos_computed = p['set_static_Ps.flow:rho'] gams_computed = p['set_static_Ps.flow:gamma'] V_computed = p['set_static_Ps.flow:V'] A_computed = p['set_static_Ps.flow:area'] MN_computed = p['set_static_Ps.flow:MN'] if MN >= .05: tol = 3e-4 else: tol = .2 # MN values off for low MN cases don't match well, but NPSS doesn't solve well down there # # print(p['T'], p['P']) # print("Ps", Ps_computed, Ps) # print("Ts", Ts_computed, Ts) # print("hs", hs_computed, hs) # print("gamma", gams_computed, gams) # print("V", V_computed, V) # print("A", A_computed, A) # print("MN", MN_computed, MN) # print("rhos", rhos_computed, rhos) # print() assert_rel_error(self, MN_computed, MN, tol) assert_rel_error(self, gams_computed, gams, tol) assert_rel_error(self, Ps_computed, Ps, tol) assert_rel_error(self, Ts_computed, Ts, tol) assert_rel_error(self, hs_computed, hs, tol) assert_rel_error(self, rhos_computed, rhos, tol) assert_rel_error(self, V_computed, V, tol) assert_rel_error(self, A_computed, A, tol) p.check_partials(includes=['set_static_Ps.statics.ps_calc'], compact_print=True)
def test_case_Ps(self): thermo = Thermo(janaf, init_reacts=constants.AIR_MIX) p = Problem() p.model.add_subsystem('set_total_TP', SetTotal(thermo_data=janaf), promotes=['b0']) p.model.add_subsystem('set_static_Ps', SetStatic(mode='Ps', thermo_data=janaf), promotes=['b0']) p.model.set_input_defaults('b0', thermo.b0) p.model.set_input_defaults('set_total_TP.T', val=518., units='degR') p.model.set_input_defaults('set_total_TP.P', val=14.7, units='psi') p.model.set_input_defaults('set_static_Ps.Ps', val=13.0, units='psi') p.model.set_input_defaults('set_static_Ps.W', val=1., units='lbm/s') p.model.connect('set_total_TP.flow:S', 'set_static_Ps.S') p.model.connect('set_total_TP.flow:h', 'set_static_Ps.ht') p.setup(check=False) p.set_solver_print(level=-1) # 4 cases to check against for i, data in enumerate(ref_data): p['set_total_TP.T'] = data[h_map['Tt']] p['set_total_TP.P'] = data[h_map['Pt']] p['set_static_Ps.Ps'] = data[h_map['Ps']] p['set_static_Ps.W'] = data[h_map['W']] p.run_model() # check outputs npss_vars = ('Ps', 'Ts', 'MN', 'hs', 'rhos', 'gams', 'V', 'A', 's', 'ht') Ps, Ts, MN, hs, rhos, gams, V, A, S, ht = tuple( [data[h_map[v_name]] for v_name in npss_vars]) Ps_computed = p['set_static_Ps.flow:P'] Ts_computed = p['set_static_Ps.flow:T'] hs_computed = p['set_static_Ps.flow:h'] rhos_computed = p['set_static_Ps.flow:rho'] gams_computed = p['set_static_Ps.flow:gamma'] V_computed = p['set_static_Ps.flow:V'] A_computed = p['set_static_Ps.flow:area'] MN_computed = p['set_static_Ps.flow:MN'] if MN >= .05: tol = 3e-4 else: tol = .2 # MN values off for low MN cases don't match well, but NPSS doesn't solve well down there assert_near_equal(MN_computed, MN, tol) assert_near_equal(gams_computed, gams, tol) assert_near_equal(Ps_computed, Ps, tol) assert_near_equal(Ts_computed, Ts, tol) assert_near_equal(hs_computed, hs, tol) assert_near_equal(rhos_computed, rhos, tol) assert_near_equal(V_computed, V, tol) assert_near_equal(A_computed, A, tol) p.check_partials(includes=['set_static_Ps.statics.ps_calc'], compact_print=True)