def test_get_elements_and_b0(self): thermo_data = species_data.janaf reactants = {'O': 1, 'H': 1, 'CO2': 1, 'N': 1, 'Ar': 1} expected_elements = {'Ar', 'C', 'H', 'N', 'O'} expected_proportions = [1, 1, 1, 1, 3] thermo = species_data.Thermo(thermo_data_module=thermo_data, init_reacts=reactants) elements = thermo.elements proportions = thermo.get_b0() reactants2 = {'O2': 20.78, 'H2O': 1.0, 'CO2': .01, 'Ar': 0.01} expected_elements2 = {'Ar', 'C', 'H', 'O'} expected_proportions2 = [.01, .01, 2.0, 42.58] thermo2 = species_data.Thermo(thermo_data_module=thermo_data, init_reacts=reactants2) elements2 = thermo2.elements proportions2 = thermo2.get_b0() self.assertEqual(elements, expected_elements) assert_near_equal(proportions, expected_proportions, 1e-4) self.assertEqual(elements2, expected_elements2) assert_near_equal(proportions2, expected_proportions2, 1e-4)
def setup(self): thermo_data = self.options['thermo_data'] n_stages = self.options['n_stages'] n_rows = 2 * n_stages if self.options['owns_x_factor']: indeps = self.add_subsystem('indeps', om.IndepVarComp(), promotes=['*']) indeps.add_output('x_factor', val=1.0) primary_thermo = species_data.Thermo(thermo_data, init_reacts=self.options['primary_elements']) in_flow = FlowIn(fl_name='Fl_turb_I', num_prods=primary_thermo.num_prod, num_elements=primary_thermo.num_element) self.add_subsystem('turb_in_flow', in_flow, promotes_inputs=['Fl_turb_I:tot:*', 'Fl_turb_I:stat:*']) in_flow = FlowIn(fl_name='Fl_turb_O', num_prods=primary_thermo.num_prod, num_elements=primary_thermo.num_element) self.add_subsystem('turb_out_flow', in_flow, promotes_inputs=['Fl_turb_O:tot:*', 'Fl_turb_O:stat:*']) cool_thermo = species_data.Thermo(thermo_data, init_reacts=self.options['cool_elements']) in_flow = FlowIn(fl_name='Fl_cool', num_prods=cool_thermo.num_prod, num_elements=cool_thermo.num_element) self.add_subsystem('cool_in_flow', in_flow, promotes_inputs=['Fl_cool:tot:*', 'Fl_cool:stat:*']) # these are the inputs to the component p_inputs_all = ['x_factor', ('Pt_in', 'Fl_turb_I:tot:P'), ('Pt_out', 'Fl_turb_O:tot:P'), ('Tt_cool','Fl_cool:tot:T'), ('ht_cool','Fl_cool:tot:h'), ('n_cool','Fl_cool:tot:n'), 'turb_pwr'] p_row_inputs = [('W_primary', 'Fl_turb_I:stat:W'), ('Tt_primary', 'Fl_turb_I:tot:T'), ('ht_primary', 'Fl_turb_I:tot:h'), ('n_primary', 'Fl_turb_I:tot:n')] self.add_subsystem('row_0', Row(n_stages=n_stages, i_row=0, T_safety=self.options['T_safety'], T_metal=self.options['T_metal'], thermo_data=thermo_data), promotes_inputs=p_inputs_all+p_row_inputs) for i in range(1,n_rows): prev_row = 'row_{}'.format(i-1) curr_row = 'row_{}'.format(i) self.add_subsystem('row_{}'.format(i), Row(n_stages=n_stages, i_row=i, T_safety=self.options['T_safety'], T_metal=self.options['T_metal'], thermo_data=thermo_data), promotes_inputs=p_inputs_all) self.connect('{}.W_out'.format(prev_row), '{}.W_primary'.format(curr_row)) self.connect('{}.Fl_O:tot:T'.format(prev_row), '{}.Tt_primary'.format(curr_row)) self.connect('{}.Fl_O:tot:h'.format(prev_row), '{}.ht_primary'.format(curr_row)) self.connect('{}.Fl_O:tot:n'.format(prev_row), '{}.n_primary'.format(curr_row))
def test_errors(self): product_elements = {'O2': 1} with self.assertRaises(ValueError) as cm: thermo = species_data.Thermo( thermo_data_module=species_data.co2_co_o2, init_elements=product_elements) self.assertEqual( str(cm.exception), "The provided element `O2` is a product in your provided thermo data, but is not an element." ) bad_elements = {'H': 1} with self.assertRaises(ValueError) as cm: thermo = species_data.Thermo( thermo_data_module=species_data.co2_co_o2, init_elements=bad_elements) self.assertEqual( str(cm.exception), "The provided element `H` is not used in any products in your thermo data." ) with self.assertRaises(ValueError) as cm: thermo = species_data.Thermo( thermo_data_module=species_data.co2_co_o2) self.assertEqual( str(cm.exception), 'You have not provided elements or initial reactants (init_reacts). In order to set thermodynamic data, one of the two must be provided.' ) with self.assertRaises(ValueError) as cm: thermo = species_data.Thermo( thermo_data_module=species_data.co2_co_o2, init_reacts=CO2_CO_O2_MIX, init_elements=CO2_CO_O2_ELEMENTS) self.assertEqual( str(cm.exception), 'You have provided both elements and initial reactants (init_reacts). In order to set thermodynamic data, you must only provide one or the other.' )
def setUp(self): self.thermo = species_data.Thermo(species_data.co2_co_o2) p = self.prob = Problem() p.model = Group() p.model.suppress_solver_output = True p.model.add_subsystem('props', PropsCalcs(thermo=self.thermo), promotes=['*']) p.model.add_subsystem('T', IndepVarComp('T', 4000., units='degK'), promotes=['*']) p.model.add_subsystem('P', IndepVarComp('P', 1.034210, units='bar'), promotes=['*']) n = np.array([0.02040741, 0.0023147, 0.0102037]) p.model.add_subsystem('n', IndepVarComp('n', n), promotes=['*']) result_T = np.array([-1.74791977, 1.81604241, -0.24571810]) p.model.add_subsystem('r_T', IndepVarComp('result_T', result_T), promotes=['*']) result_P = np.array([0.48300853, 0.48301125, -0.01522548]) p.model.add_subsystem('r_P', IndepVarComp('result_P', result_P), promotes=['*']) p.setup(check=False) p['n_moles'] = 0.03292581
def setUp(self): self.thermo = species_data.Thermo(species_data.co2_co_o2) p = self.prob = Problem() p.model = Group() p.model.suppress_solver_output = True p.model.add_subsystem( 'props_rhs', PropsRHS(thermo=self.thermo), promotes=['T', 'n', 'b0', 'rhs_T', 'rhs_P', 'lhs_TP', 'n_moles']) p.model.add_subsystem('T', IndepVarComp('T', 4000., units='degK'), promotes=['*']) p.model.add_subsystem('P', IndepVarComp('P', 1.034210, units='bar'), promotes=['*']) n = np.array([0.02040741, 0.0023147, 0.0102037]) p.model.add_subsystem('n', IndepVarComp('n', n), promotes=['*']) b = np.array([0.02272211, 0.04544422]) p.model.add_subsystem('b0', IndepVarComp('b0', b), promotes=['*']) p.model.add_subsystem('n_moles_desvar', IndepVarComp('n_moles', 0.03292581), promotes=['*']) p.setup(check=False) p['n_moles'] = 0.03292581
def setup(self): thermo_data = self.options['thermo_data'] elements = self.options['elements'] thermo = species_data.Thermo(thermo_data, init_reacts=elements) self.air_prods = thermo.products self.num_prod = len(self.air_prods) # inputs set_TP = SetTotal(mode="T", fl_name="Fl_O:tot", thermo_data=thermo_data, init_reacts=elements) params = ('T','P', 'init_prod_amounts') self.add_subsystem('totals', set_TP, promotes_inputs=params, promotes_outputs=('Fl_O:tot:*',)) # if self.options['statics']: set_stat_MN = SetStatic(mode="MN", thermo_data=thermo_data, init_reacts=elements, fl_name="Fl_O:stat") self.add_subsystem('exit_static', set_stat_MN, promotes_inputs=('MN', 'W'), promotes_outputs=('Fl_O:stat:*', )) self.connect('totals.h','exit_static.ht') self.connect('totals.S','exit_static.S') self.connect('Fl_O:tot:P','exit_static.guess:Pt') self.connect('totals.gamma', 'exit_static.guess:gamt')
def setUp(self): thermo = species_data.Thermo(species_data.janaf, constants.AIR_MIX) self.tp_set = Problem( SetTotal(thermo_data=species_data.janaf, mode='T')) self.hp_set = Problem( SetTotal(thermo_data=species_data.janaf, mode='h')) self.sp_set = Problem( SetTotal(thermo_data=species_data.janaf, mode='S')) self.tp_set.model.set_input_defaults('b0', thermo.b0) self.hp_set.model.set_input_defaults('b0', thermo.b0) self.sp_set.model.set_input_defaults('b0', thermo.b0) self.tp_set.model.set_input_defaults('T', 518., units="degR") self.tp_set.model.set_input_defaults('P', 14.7, units="psi") self.tp_set.setup(check=False) self.hp_set.model.set_input_defaults('P', 14.7, units="psi") self.hp_set.model.set_input_defaults('h', 1., units="Btu/lbm") self.hp_set.setup(check=False) self.sp_set.model.set_input_defaults('P', 14.7, units="psi") self.sp_set.model.set_input_defaults( 'S', 1., units="Btu/(lbm*degR)") # 'cal/(g*degK)' self.sp_set.setup(check=False)
def setUp(self): self.thermo = species_data.Thermo(species_data.co2_co_o2) p = self.p = Problem(model=Group()) p.model.suppress_solver_output = True indeps = p.model.add_subsystem('pressure', IndepVarComp(), promotes=['*']) indeps.add_output('P', 1.034210, units="bar")
def test_set_total_hp(self): thermo = species_data.Thermo(species_data.co2_co_o2, init_reacts=constants.CO2_CO_O2_MIX) init_reacts = {'CO': 1, 'CO2': 1, 'O2': 1} # 4000k p = Problem() p.model = SetTotal(thermo_data=species_data.co2_co_o2, init_reacts=init_reacts, mode="h") p.model.set_input_defaults('b0', thermo.b0) p.model.set_input_defaults('h', 340, units='cal/g') p.model.set_input_defaults('P', 1.034210, units='bar') p.model.suppress_solver_output = True r = p.model p.set_solver_print(level=2) p.setup(check=False) p.run_model() expected_concentrations = np.array( [0.61989858, 0.07015213, 0.30994929]) n = p['n'] n_moles = p['n_moles'] concentrations = n / n_moles assert_near_equal(concentrations, expected_concentrations, 1e-4) expected_n_moles = 0.0329281722301 assert_near_equal(n_moles, expected_n_moles, 1e-4) assert_near_equal(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() 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_near_equal(concentrations, expected_concentrations, 1e-4) expected_n_moles = 0.022726185333 assert_near_equal(n_moles, expected_n_moles, 1e-4) assert_near_equal(p['gamma'], 1.16379012007, 1e-4)
def test_set_total_sp(self): thermo = species_data.Thermo(species_data.co2_co_o2, init_reacts=constants.CO2_CO_O2_MIX) init_reacts = {'CO': 1, 'CO2': 1, 'O2': 1} # 4000k p = Problem() p.model = SetTotal(thermo_data=species_data.co2_co_o2, init_reacts=init_reacts, mode="S") p.model.set_input_defaults('b0', thermo.b0) p.model.set_input_defaults('S', 2.35711010759, units="Btu/(lbm*degR)") p.model.set_input_defaults('P', 1.034210, units="bar") p.model.suppress_solver_output = True r = p.model p.set_solver_print(level=2) p.setup(check=False) p.run_model() np.seterr(all='raise') expected_concentrations = np.array( [0.62003271, 0.06995092, 0.31001638]) n = p['n'] n_moles = p['n_moles'] concentrations = n / n_moles assert_near_equal(concentrations, expected_concentrations, 1e-4) expected_n_moles = 0.0329313730421 assert_near_equal(n_moles, expected_n_moles, 1e-4) assert_near_equal(p['gamma'], 1.19054696779, 1e-4) # 1500K p['S'] = 1.5852424435 p.run_model() 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_near_equal(concentrations, expected_concentrations, 1e-4) expected_n_moles = 0.022726185333 assert_near_equal(n_moles, expected_n_moles, 1e-4) assert_near_equal(p['gamma'], 1.16381209181, 1e-4)
def test_std_day(self): thermo = species_data.Thermo(species_data.janaf, constants.AIR_MIX) top = Problem() top.model = SetTotal(thermo_data=species_data.janaf, mode="T") top.model.set_input_defaults('b0', thermo.b0) top.model.set_input_defaults('T', 287.778, units='degK') top.model.set_input_defaults('P', 1.02069, units='bar') top.setup(check=False) top.run_model() assert_near_equal(top['gamma'], 1.40023310084, 1e-4)
def test_element_filter(self): elements1_provided = {'C': 1, 'O': 1} products1_expected = ['CO', 'CO2', 'O2'] thermo1 = species_data.Thermo( thermo_data_module=species_data.co2_co_o2, init_elements=elements1_provided) elements1_expected = {'C', 'O'} products1 = thermo1.products elements1 = thermo1.elements elements2_provided = {'Ar': 1, 'C': 1, 'N': 1, 'O': 1} products2_expected = [ 'Ar', 'CO', 'CO2', 'N', 'NO', 'NO2', 'NO3', 'N2', 'O', 'O2' ] thermo2 = species_data.Thermo(thermo_data_module=species_data.janaf, init_elements=elements2_provided) elements2_expected = {'Ar', 'C', 'N', 'O'} products2 = thermo2.products elements2 = thermo2.elements elements3_provided = {'Ar': 1, 'C': 1, 'H': 1, 'N': 1} products3_expected = ['Ar', 'CH4', 'C2H4', 'H', 'H2', 'N', 'NH3', 'N2'] thermo3 = species_data.Thermo(thermo_data_module=species_data.janaf, init_elements=elements3_provided) elements3_expected = {'Ar', 'C', 'H', 'N'} products3 = thermo3.products elements3 = thermo3.elements self.assertEqual(products1, products1_expected) self.assertEqual(elements1, elements1_expected) self.assertEqual(products2, products2_expected) self.assertEqual(elements2, elements2_expected) self.assertEqual(products3, products3_expected) self.assertEqual(elements3, elements3_expected)
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_tp(self): thermo = species_data.Thermo(species_data.co2_co_o2, constants.CO2_CO_O2_MIX) init_reacts = {'CO': 1, 'CO2': 1, 'O2': 1} # 4000k p = Problem() p.model = SetTotal(thermo_data=species_data.co2_co_o2, init_reacts=init_reacts, mode="T") p.model.set_input_defaults('b0', thermo.b0) p.model.set_input_defaults('T', 4000., units='degK') p.model.set_input_defaults('P', 1.034210, units="bar") r = p.model p.set_solver_print(level=2) p.setup(check=False) p.run_model() expected_concentrations = np.array( [0.62003271, 0.06995092, 0.31001638]) n = p['n'] n_moles = p['n_moles'] concentrations = n / n_moles assert_near_equal(concentrations, expected_concentrations, 1e-4) expected_n_moles = 0.0329313730421 assert_near_equal(n_moles, expected_n_moles, 1e-4) assert_near_equal(p['gamma'], 1.19054696779, 1e-4) # 1500K p['T'] = 1500 # degK p['P'] = 1.034210 # bar p.run_model() 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_near_equal(n_moles, expected_n_moles, 1e-4) assert_near_equal(p['gamma'], 1.16380, 1e-4)
def test_mid_temp(self): thermo = species_data.Thermo(species_data.janaf, constants.AIR_MIX) top = Problem() top.model = SetTotal(thermo_data=species_data.janaf, mode="T") top.model.set_input_defaults('b0', thermo.b0) top.model.set_input_defaults('T', 1500, units='degK') top.model.set_input_defaults('P', 1.02069, units='bar') top.setup(check=False) top.run_model() assert_near_equal(top['gamma'], 1.30444205736, 1e-4) # 1.30444 assert_near_equal(top['flow:S'], 2.05758694175, 1e-4) # NPSS 2.05717
def setUp(self): self.thermo = species_data.Thermo(species_data.co2_co_o2, init_reacts=constants.CO2_CO_O2_MIX) p = self.prob = Problem() p.model = Group() p.model.suppress_solver_output = True p.model.add_subsystem( 'props_rhs', PropsRHS(thermo=self.thermo), promotes=['T', 'n', 'b0', 'rhs_T', 'rhs_P', 'lhs_TP', 'n_moles']) p.model.set_input_defaults('T', 4000., units='degK') n = np.array([0.02040741, 0.0023147, 0.0102037]) p.model.set_input_defaults('n', n) b = np.array([0.02272211, 0.04544422]) p.model.set_input_defaults('b0', b) p.model.set_input_defaults('n_moles', 0.03292581) p.setup(check=False) p['n_moles'] = 0.03292581
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): 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', 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 = 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.linesearch = BoundsEnforceLS() newton.linesearch.options['bound_enforcement'] = 'scalar' newton.linesearch.options['iprint'] = -1 self.linear_solver = DirectSolver(assemble_jac=True)
self.drhsT_dn[:num_element] = aij * H0_T self.drhsT_dn[num_element] = H0_T J['rhs_T', 'T'] = self.drhsT_dT.reshape((-1, 1)) J['rhs_T', 'n'] = self.drhsT_dn # derivs of rhsP are constants, specified in setup # derivs of lhs_TP are constants, specified in setup if __name__ == "__main__": from openmdao.api import Problem, Group, IndepVarComp, LinearSystemComp thermo = species_data.Thermo(species_data.co2_co_o2) p = Problem() p.model = Group() indeps = p.model.add_subsystem('indeps', IndepVarComp(), promotes=['*']) indeps.add_output('T', val=2761.56784655, units='degK') indeps.add_output('n', val=np.array([2.272e-02, 1.000e-10, 1.136e-02])) indeps.add_output('b0', val=np.array([0.023, 0.045])) indeps.add_output('n_moles', val=0.0340831628675) props_rhs = p.model.add_subsystem('props_rhs', PropsRHS(thermo=thermo), promotes=["*"]) p.model.add_subsystem('ln_T',
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): bleeds = self.options['bleed_names'] self.main_flow_elements = self.options['main_flow_elements'] thermo_data = self.options['thermo_data'] self.mixed_elements = self.main_flow_elements.copy() self.mixed_elements.update(self.options['bld_flow_elements']) main_flow_thermo = species_data.Thermo(thermo_data, init_reacts=self.mixed_elements) self.main_flow_prods = main_flow_thermo.products self.main_flow_wt_mole = main_flow_thermo.wt_mole self.n_main_flow_prods = len(self.main_flow_prods) bld_flow_thermo = species_data.Thermo( thermo_data, init_reacts=self.options['bld_flow_elements']) self.bld_flow_prods = bld_flow_thermo.products self.bld_flow_wt_mole = bld_flow_thermo.wt_mole self.n_bld_flow_prods = len(self.bld_flow_prods) # primary inputs and outputs self.add_input('Pt_in', val=0.0, units='psi', desc='turbine entrance pressure') self.add_input('Pt_out', val=0.0, units='psi', desc='turbine exit pressure') self.add_input('W_in', val=0.0, units='lbm/s', desc='turbine entrance mass flow rate') self.add_input('n_in', val=np.zeros(self.n_main_flow_prods), desc='turbine entrance flow composition') self.add_output('W_out', shape=1, units='lbm/s', desc='turbine exit mass flow rate') self.add_output('n_out', shape=self.n_main_flow_prods, desc='turbine exit flow composition') # bleed inputs and outputs for BN in bleeds: self.add_input( BN + ':frac_P', val=0.0, desc='fraction of pressure drop where bleed flow introduced') self.add_input(BN + ':W', val=0.0, units='lbm/s', desc='bleed mass flow rate') self.add_input(BN + ':n', val=np.zeros(self.n_bld_flow_prods), desc='bleed flow composition') self.add_output(BN + ':Pt', shape=1, units='psi', desc='pressure of incomming bleed flow', lower=1e-3) self.declare_partials(BN + ':Pt', ['Pt_in', 'Pt_out', BN + ':frac_P']) self.declare_partials('W_out', BN + ':W', val=1.0) self.declare_partials('n_out', [BN + ':W', BN + ':n']) # create mapping for main and bleed flow self.main_flow_idx_map = { prod: i for i, prod in enumerate(self.main_flow_prods) } self.bld_flow_idx_map = { prod: i for i, prod in enumerate(self.bld_flow_prods) } n_main = len(self.main_flow_prods) n_bld = len(self.bld_flow_prods) self.mix_mat = np.zeros((n_main, n_bld), dtype=int) for j, prod in enumerate(self.bld_flow_prods): i = self.main_flow_idx_map[prod] self.mix_mat[i, j] = 1 self.declare_partials('W_out', 'W_in', val=1.0) self.declare_partials('n_out', ['W_in', 'n_in'])
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'] 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 setup(self): thermo_data = self.options['thermo_data'] elements = self.options['elements'] statics = self.options['statics'] design = self.options['design'] num_prod = species_data.Thermo(thermo_data, init_reacts=elements).num_prod # Create inlet flowstation flow_in = FlowIn(fl_name='Fl_I', num_prods=num_prod) self.add_subsystem('flow_in', flow_in, promotes_inputs=('Fl_I:*', )) # Split the flows self.add_subsystem('split_calc', BPRcalc(), promotes_inputs=('BPR', ('W_in', 'Fl_I:stat:W'))) # Set Fl_out1 totals based on T, P real_flow1 = SetTotal(thermo_data=thermo_data, mode='T', init_reacts=elements, fl_name="Fl_O1:tot") self.add_subsystem('real_flow1', real_flow1, promotes_inputs=(('init_prod_amounts', 'Fl_I:tot:n'), ('P', 'Fl_I:tot:P'), ('T', 'Fl_I:tot:T')), promotes_outputs=('Fl_O1:tot:*', )) # Set Fl_out2 totals based on T, P real_flow2 = SetTotal(thermo_data=thermo_data, mode='T', init_reacts=elements, fl_name="Fl_O2:tot") self.add_subsystem('real_flow2', real_flow2, promotes_inputs=(('init_prod_amounts', 'Fl_I:tot:n'), ('P', 'Fl_I:tot:P'), ('T', 'Fl_I:tot:T')), promotes_outputs=('Fl_O2:tot:*', )) if statics: if design: # Calculate static properties out1_stat = SetStatic(mode="MN", thermo_data=thermo_data, init_reacts=elements, fl_name="Fl_O1:stat") prom_in = [('init_prod_amounts', 'Fl_I:tot:n'), ('MN', 'MN1')] prom_out = ['Fl_O1:stat:*'] self.add_subsystem('out1_stat', out1_stat, promotes_inputs=prom_in, promotes_outputs=prom_out) self.connect('Fl_O1:tot:S', 'out1_stat.S') self.connect('Fl_O1:tot:h', 'out1_stat.ht') self.connect('Fl_O1:tot:P', 'out1_stat.guess:Pt') self.connect('Fl_O1:tot:gamma', 'out1_stat.guess:gamt') self.connect('split_calc.W1', 'out1_stat.W') out2_stat = SetStatic(mode="MN", thermo_data=thermo_data, init_reacts=elements, fl_name="Fl_O2:stat") prom_in = [('init_prod_amounts', 'Fl_I:tot:n'), ('MN', 'MN2')] prom_out = ['Fl_O2:stat:*'] self.add_subsystem('out2_stat', out2_stat, promotes_inputs=prom_in, promotes_outputs=prom_out) self.connect('Fl_O2:tot:S', 'out2_stat.S') self.connect('Fl_O2:tot:h', 'out2_stat.ht') self.connect('Fl_O2:tot:P', 'out2_stat.guess:Pt') self.connect('Fl_O2:tot:gamma', 'out2_stat.guess:gamt') self.connect('split_calc.W2', 'out2_stat.W') else: # Calculate static properties out1_stat = SetStatic(mode="area", thermo_data=thermo_data, init_reacts=elements, fl_name="Fl_O1:stat") prom_in = [('init_prod_amounts', 'Fl_I:tot:n'), ('area', 'area1')] prom_out = ['Fl_O1:stat:*'] self.add_subsystem('out1_stat', out1_stat, promotes_inputs=prom_in, promotes_outputs=prom_out) self.connect('Fl_O1:tot:S', 'out1_stat.S') self.connect('Fl_O1:tot:h', 'out1_stat.ht') self.connect('Fl_O1:tot:P', 'out1_stat.guess:Pt') self.connect('Fl_O1:tot:gamma', 'out1_stat.guess:gamt') self.connect('split_calc.W1', 'out1_stat.W') out2_stat = SetStatic(mode="area", thermo_data=thermo_data, init_reacts=elements, fl_name="Fl_O2:stat") prom_in = [('init_prod_amounts', 'Fl_I:tot:n'), ('area', 'area2')] prom_out = ['Fl_O2:stat:*'] self.add_subsystem('out2_stat', out2_stat, promotes_inputs=prom_in, promotes_outputs=prom_out) self.connect('Fl_O2:tot:S', 'out2_stat.S') self.connect('Fl_O2:tot:h', 'out2_stat.ht') self.connect('Fl_O2:tot:P', 'out2_stat.guess:Pt') self.connect('Fl_O2:tot:gamma', 'out2_stat.guess:gamt') self.connect('split_calc.W2', 'out2_stat.W') else: self.add_subsystem('W1_passthru', PassThrough('split_calc_W1', 'Fl_O1:stat:W', 1.0, units="lbm/s"), promotes=['*']) self.add_subsystem('W2_passthru', PassThrough('split_calc_W2', 'Fl_O2:stat:W', 1.0, units="lbm/s"), promotes=['*']) self.connect('split_calc.W1', 'split_calc_W1') self.connect('split_calc.W2', 'split_calc_W2')
def test_values(self): thermo1 = species_data.Thermo(thermo_data_module=species_data.janaf, init_reacts=AIR_MIX) thermo2 = species_data.Thermo(thermo_data_module=species_data.janaf, init_elements=AIR_ELEMENTS) thermo3 = species_data.Thermo( thermo_data_module=species_data.co2_co_o2, init_elements=CO2_CO_O2_ELEMENTS) T1 = np.ones(thermo1.num_prod) * 800 T2 = np.ones(thermo2.num_prod) * 800 T3 = np.ones(thermo3.num_prod) * 800 H01 = thermo1.H0(T1) H02 = thermo2.H0(T2) H03 = thermo3.H0(T3) H0_expected = np.array([ 1.56828125, -14.33638055, -55.73109232, 72.63079725, 16.05970705, 8.50490177, 15.48013356, 2.2620009, 39.06512544, 2.38109781 ]) H0_expected3 = np.array([-14.33638055, -55.73109232, 2.38109781]) S01 = thermo1.S0(T1) S02 = thermo2.S0(T2) S03 = thermo3.S0(T3) S0_expected = np.array([ 21.09120423, 27.33539665, 30.96900291, 20.90543864, 28.99563162, 34.04699324, 37.65697408, 26.58210226, 21.90362596, 28.37546079 ]) S0_expected3 = np.array([27.33539665, 30.96900291, 28.37546079]) Cp01 = thermo1.Cp0(T1) Cp02 = thermo2.Cp0(T2) Cp03 = thermo3.Cp0(T3) Cp0_expected = np.array([ 2.5, 3.83668584, 6.18585395, 2.5, 3.94173049, 6.06074564, 8.81078156, 3.78063693, 2.52375035, 4.05857378 ]) Cp0_expected3 = np.array([3.83668584, 6.18585395, 4.05857378]) HJ1 = thermo1.H0_applyJ(T1, 1.) HJ2 = thermo2.H0_applyJ(T2, 1.) HJ3 = thermo3.H0_applyJ(T3, 1.) HJ_expected = np.array([ 0.00116465, 0.02271633, 0.07739618, -0.0876635, -0.01514747, -0.0030552, -0.00833669, 0.0018983, -0.04567672, 0.00209684 ]) HJ_expected3 = np.array([0.02271633, 0.07739618, 0.00209684]) SJ1 = thermo1.S0_applyJ(T1, 1) SJ2 = thermo2.S0_applyJ(T2, 1) SJ3 = thermo3.S0_applyJ(T3, 1) SJ_expected = np.array([ 0.003125, 0.00479586, 0.00773232, 0.003125, 0.00492716, 0.00757593, 0.01101348, 0.0047258, 0.00315469, 0.00507322 ]) SJ_expected3 = np.array([0.00479586, 0.00773232, 0.00507322]) CpJ1 = thermo1.Cp0_applyJ(T1, 1) CpJ2 = thermo2.Cp0_applyJ(T2, 1) CpJ3 = thermo3.Cp0_applyJ(T3, 1) CpJ_expected = np.array([ 0.0, 8.49157682e-04, 2.05623736e-03, 0.0, 8.39005783e-04, 1.91861539e-03, 2.54742879e-03, 8.12550383e-04, -5.62484525e-05, 8.19626699e-04 ]) CpJ_expected3 = np.array( [8.49157682e-04, 2.05623736e-03, 8.19626699e-04]) b01 = thermo1.b0 b02 = thermo2.b0 b03 = thermo3.b0 b0_expected = np.array( [3.23319258e-04, 1.10132241e-05, 5.39157736e-02, 1.44860147e-02]) b0_expected3 = np.array([0.02272211, 0.04544422]) tol = 1e-4 assert_near_equal(H01, H0_expected, tol) assert_near_equal(S01, S0_expected, tol) assert_near_equal(Cp01, Cp0_expected, tol) assert_near_equal(HJ1, HJ_expected, tol) assert_near_equal(SJ1, SJ_expected, tol) assert_near_equal(CpJ1, CpJ_expected, tol) assert_near_equal(b01, b0_expected, tol) assert_near_equal(H02, H0_expected, tol) assert_near_equal(S02, S0_expected, tol) assert_near_equal(Cp02, Cp0_expected, tol) assert_near_equal(HJ2, HJ_expected, tol) assert_near_equal(SJ2, SJ_expected, tol) assert_near_equal(CpJ2, CpJ_expected, tol) assert_near_equal(b02, b0_expected, tol) assert_near_equal(H03, H0_expected3, tol) assert_near_equal(S03, S0_expected3, tol) assert_near_equal(Cp03, Cp0_expected3, tol) assert_near_equal(HJ3, HJ_expected3, tol) assert_near_equal(SJ3, SJ_expected3, tol) assert_near_equal(CpJ3, CpJ_expected3, tol) assert_near_equal(b03, b0_expected3, tol)
units="lbm/s"), promotes=['*']) # if not design: # self.set_input_defaults('area', val=1, units='in**2') self.set_input_defaults('Fl_I:tot:b0', gas_thermo.b0) if __name__ == "__main__": from pycycle import constants p = om.Problem() p.model = Inlet() thermo = species_data.Thermo(species_data.janaf, constants.AIR_MIX) p.model.set_input_defaults('Fl_I:tot:T', 284, units='degK') p.model.set_input_defaults('Fl_I:tot:P', 5.0, units='lbf/inch**2') # p.model.set_input_defaults('Fl_I:tot:n', thermo.init_prod_amounts) # p.model.set_input_defaults('Fl_I:tot:b0', thermo.b0) p.model.set_input_defaults('Fl_I:stat:V', 0.0, units='ft/s') #keep p.model.set_input_defaults('Fl_I:stat:W', 1, units='kg/s') p.setup() #view_model(p) p.run_model() # print(p.get_val('Fl_I:tot:T', units='degK')) p.model.list_outputs(units=True) # generates regression testing setup
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) 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) # Create inlet flow station in_flow = FlowIn(fl_name='Fl_I', num_prods=self.num_prod) 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'), ('init_prod_amounts', 'Fl_I:tot:n') ]) 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) self.add_subsystem(BN, bld_flow, promotes_inputs=['{}:*'.format(BN)]) # Calculate bleed parameters blds = Bleeds(bleed_names=bleeds, main_flow_elements=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=[('init_prod_amounts', BN + ":tot:n"), ('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=[('init_prod_amounts', BN + ":tot:n")]) 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=[('init_prod_amounts', 'Fl_I:tot:n') ]) 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.n_out", "real_flow.init_prod_amounts") self.add_subsystem('FAR_passthru', PassThrough('Fl_I:FAR', 'Fl_O:FAR', 0.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.n_out', '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('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.n_out', '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('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' ])
# Replace J for tiny values of n with identity if self.remove_trace_species: n = outputs['n'] for j in range(num_prod): if n[j] <= 1.0e-10: dRdy[j, :] = 0.0 dRdy[j, j] = -1.0 if __name__ == "__main__": import time from pycycle.cea import species_data # thermo = species_data.Thermo(species_data.co2_co_o2) thermo = species_data.Thermo(species_data.janaf) prob = om.Problem() prob.model = om.Group() prob.model.nonlinear_solver = om.NonLinearRunOnce() prob.model.linear_solver = om.LinearRunOnce() des_vars = prob.model.add_subsystem('des_vars', om.IndepVarComp(), promotes=["*"]) des_vars.add_output('P', 1.034210, units='psi') des_vars.add_output('h', -24.26682261, units='cal/g') des_vars.add_output('init_prod_amounts', thermo.init_prod_amounts) chemeq = prob.model.add_subsystem('chemeq', ChemEq(thermo=thermo, mode="h"),
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)