def test_linesearch_vector_bound_enforcement(self): top = self.top ls = top.model.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS( bound_enforcement='vector') ls.options['c'] = .1 # Setup again because we assigned a new linesearch top.setup() # Test lower bounds: should go to the lower bound and stall top['px.x'] = 2.0 top['comp.y'] = 0. top['comp.z'] = 1.6 top.run_model() for ind in range(3): assert_rel_error(self, top['comp.z'][ind], [1.5], 1e-8) # Test upper bounds: should go to the minimum upper bound and stall top['px.x'] = 0.5 top['comp.y'] = 0. top['comp.z'] = 2.4 top.run_model() for ind in range(3): assert_rel_error(self, top['comp.z'][ind], [2.5], 1e-8)
def test_with_subsolves(self): prob = om.Problem() model = prob.model = DoubleSellarMod() g1 = model.g1 g1.nonlinear_solver = om.NewtonSolver(solve_subsystems=False) g1.nonlinear_solver.options['rtol'] = 1.0e-5 g1.linear_solver = om.DirectSolver() g2 = model.g2 g2.nonlinear_solver = om.NewtonSolver(solve_subsystems=False) g2.nonlinear_solver.options['rtol'] = 1.0e-5 g2.linear_solver = om.DirectSolver() model.nonlinear_solver = om.NewtonSolver() model.linear_solver = om.ScipyKrylov() model.nonlinear_solver.options['solve_subsystems'] = True model.nonlinear_solver.options['max_sub_solves'] = 4 ls = model.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS( bound_enforcement='vector') prob.set_solver_print(level=0) prob.setup() prob.run_model() assert_near_equal(prob['g1.y1'], 0.64, .00001) assert_near_equal(prob['g1.y2'], 0.80, .00001) assert_near_equal(prob['g2.y1'], 0.64, .00001) assert_near_equal(prob['g2.y2'], 0.80, .00001)
def test_circuit_voltage_source(self): import openmdao.api as om from openmdao.test_suite.scripts.circuit_analysis import Circuit p = om.Problem() model = p.model model.add_subsystem('ground', om.IndepVarComp('V', 0., units='V')) # replacing the fixed current source with a BalanceComp to represent a fixed Voltage source # model.add_subsystem('source', om.IndepVarComp('I', 0.1, units='A')) model.add_subsystem('batt', om.IndepVarComp('V', 1.5, units='V')) bal = model.add_subsystem('batt_balance', om.BalanceComp()) bal.add_balance('I', units='A', eq_units='V') model.add_subsystem('circuit', Circuit()) model.add_subsystem('batt_deltaV', om.ExecComp('dV = V1 - V2', V1={'units':'V'}, V2={'units':'V'}, dV={'units':'V'})) # current into the circuit is now the output state from the batt_balance comp model.connect('batt_balance.I', 'circuit.I_in') model.connect('ground.V', ['circuit.Vg','batt_deltaV.V2']) model.connect('circuit.n1.V', 'batt_deltaV.V1') # set the lhs and rhs for the battery residual model.connect('batt.V', 'batt_balance.rhs:I') model.connect('batt_deltaV.dV', 'batt_balance.lhs:I') p.setup() ################### # Solver Setup ################### # change the circuit solver to RunOnce because we're # going to converge at the top level of the model with newton instead p.model.circuit.nonlinear_solver = om.NonlinearRunOnce() p.model.circuit.linear_solver = om.LinearRunOnce() # Put Newton at the top so it can also converge the new BalanceComp residual newton = p.model.nonlinear_solver = om.NewtonSolver() p.model.linear_solver = om.DirectSolver() newton.options['iprint'] = 2 newton.options['maxiter'] = 20 newton.options['solve_subsystems'] = True newton.linesearch = om.ArmijoGoldsteinLS() newton.linesearch.options['maxiter'] = 10 newton.linesearch.options['iprint'] = 2 # set initial guesses from the current source problem p['circuit.n1.V'] = 9.8 p['circuit.n2.V'] = .7 p.run_model() assert_near_equal(p['circuit.n1.V'], 1.5, 1e-5) assert_near_equal(p['circuit.n2.V'], 0.65113362, 1e-5) assert_near_equal(p['circuit.R1.I'], 0.015, 1e-5) assert_near_equal(p['circuit.R2.I'], 8.48866375e-05, 1e-5) assert_near_equal(p['circuit.D1.I'], 8.48866375e-05, 1e-5)
def setup(self): self.add_subsystem('n1', Node(n_in=1, n_out=2), promotes_inputs=[('I_in:0', 'I_in')]) self.add_subsystem('n2', Node()) # leaving defaults self.add_subsystem('R1', Resistor(R=100.), promotes_inputs=[('V_out', 'Vg')]) self.add_subsystem('R2', Resistor(R=10000.)) self.add_subsystem('D1', Diode(), promotes_inputs=[('V_out', 'Vg')]) self.connect('n1.V', ['R1.V_in', 'R2.V_in']) self.connect('R1.I', 'n1.I_out:0') self.connect('R2.I', 'n1.I_out:1') self.connect('n2.V', ['R2.V_out', 'D1.V_in']) self.connect('R2.I', 'n2.I_in:0') self.connect('D1.I', 'n2.I_out:0') self.nonlinear_solver = om.NewtonSolver() self.linear_solver = om.DirectSolver() self.nonlinear_solver.options['iprint'] = 2 self.nonlinear_solver.options['maxiter'] = 10 self.nonlinear_solver.options['solve_subsystems'] = True self.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS() self.nonlinear_solver.linesearch.options['maxiter'] = 10 self.nonlinear_solver.linesearch.options['iprint'] = 2
def test_feature_armijo_print_bound_enforce(self): import numpy as np import openmdao.api as om from openmdao.test_suite.components.implicit_newton_linesearch import ImplCompTwoStatesArrays top = om.Problem() top.model.add_subsystem('px', om.IndepVarComp('x', np.ones((3, 1)))) top.model.add_subsystem('comp', ImplCompTwoStatesArrays()) top.model.connect('px.x', 'comp.x') newt = top.model.nonlinear_solver = om.NewtonSolver( solve_subsystems=False) top.model.nonlinear_solver.options['maxiter'] = 2 top.model.linear_solver = om.ScipyKrylov() ls = newt.linesearch = om.ArmijoGoldsteinLS() ls.options['print_bound_enforce'] = True top.set_solver_print(level=2) top.setup() # Test lower bounds: should go to the lower bound and stall top['px.x'] = 2.0 top['comp.y'] = 0. top['comp.z'] = 1.6 top.run_model() for ind in range(3): assert_near_equal(top['comp.z'][ind], [1.5], 1e-8)
def test_feature_armijo_boundscheck_scalar(self): import numpy as np import openmdao.api as om from openmdao.test_suite.components.implicit_newton_linesearch import ImplCompTwoStatesArrays top = om.Problem() top.model.add_subsystem('px', om.IndepVarComp('x', np.ones((3, 1)))) top.model.add_subsystem('comp', ImplCompTwoStatesArrays()) top.model.connect('px.x', 'comp.x') top.model.nonlinear_solver = om.NewtonSolver() top.model.nonlinear_solver.options['maxiter'] = 10 top.model.linear_solver = om.ScipyKrylov() ls = top.model.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS( bound_enforcement='scalar') top.setup() top.run_model() # Test lower bounds: should stop just short of the lower bound top['px.x'] = 2.0 top['comp.y'] = 0. top['comp.z'] = 1.6 top.run_model()
def test_feature_armijo_boundscheck_wall(self): import numpy as np import openmdao.api as om from openmdao.test_suite.components.implicit_newton_linesearch import ImplCompTwoStatesArrays top = om.Problem() top.model.add_subsystem('comp', ImplCompTwoStatesArrays(), promotes_inputs=['x']) top.model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False) top.model.nonlinear_solver.options['maxiter'] = 10 top.model.linear_solver = om.ScipyKrylov() top.model.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS( bound_enforcement='wall') top.setup() top.set_val('x', np.array([0.5, 0.5, 0.5]).reshape(3, 1)) # Test upper bounds: should go to the upper bound and stall top.set_val('comp.y', 0.) top.set_val('comp.z', 2.4) top.run_model() assert_near_equal(top.get_val('comp.z', indices=0), [2.6], 1e-8) assert_near_equal(top.get_val('comp.z', indices=1), [2.5], 1e-8) assert_near_equal(top.get_val('comp.z', indices=2), [2.65], 1e-8)
def test_feature_armijo_boundscheck_scalar(self): import numpy as np import openmdao.api as om from openmdao.test_suite.components.implicit_newton_linesearch import ImplCompTwoStatesArrays top = om.Problem() top.model.add_subsystem('comp', ImplCompTwoStatesArrays(), promotes_inputs=['x']) top.model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False) top.model.nonlinear_solver.options['maxiter'] = 10 top.model.linear_solver = om.ScipyKrylov() ls = top.model.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS( bound_enforcement='scalar') top.setup() top.set_val('x', np.array([2., 2, 2]).reshape(3, 1)) top.run_model() # Test lower bounds: should stop just short of the lower bound top.set_val('comp.y', 0.) top.set_val('comp.z', 1.6) top.run_model()
def test_feature_armijo_boundscheck_vector(self): top = om.Problem() top.model.add_subsystem('comp', ImplCompTwoStatesArrays(), promotes_inputs=['x']) top.model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False) top.model.nonlinear_solver.options['maxiter'] = 10 top.model.linear_solver = om.ScipyKrylov() top.model.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS( bound_enforcement='vector') top.setup() top.set_val('x', np.array([2., 2, 2]).reshape(3, 1)) # Test lower bounds: should go to the lower bound and stall top.set_val('comp.y', 0.) top.set_val('comp.z', 1.6) top.run_model() for ind in range(3): assert_near_equal(top.get_val('comp.z', indices=ind), [1.5], 1e-8)
def test_feature_goldstein(self): top = om.Problem() top.model.add_subsystem('px', om.IndepVarComp('x', np.ones((3, 1)))) top.model.add_subsystem('comp', ImplCompTwoStatesArrays()) top.model.connect('px.x', 'comp.x') top.model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False) top.model.nonlinear_solver.options['maxiter'] = 10 top.model.linear_solver = om.ScipyKrylov() ls = top.model.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS( bound_enforcement='vector') ls.options['method'] = 'Goldstein' top.setup() # Test lower bounds: should go to the lower bound and stall top['px.x'] = 2.0 top['comp.y'] = 0. top['comp.z'] = 1.6 top.run_model() for ind in range(3): assert_near_equal(top['comp.z'][ind], [1.5], 1e-8)
def test_with_subsolves(self): prob = om.Problem() model = prob.model = DoubleSellar() g1 = model.g1 g1.nonlinear_solver = om.NewtonSolver() g1.nonlinear_solver.options['rtol'] = 1.0e-5 g1.linear_solver = om.DirectSolver() g2 = model.g2 g2.nonlinear_solver = om.NewtonSolver() g2.nonlinear_solver.options['rtol'] = 1.0e-5 g2.linear_solver = om.DirectSolver() model.nonlinear_solver = om.NewtonSolver() model.linear_solver = om.ScipyKrylov() model.nonlinear_solver.options['solve_subsystems'] = True model.nonlinear_solver.options['max_sub_solves'] = 4 ls = model.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS( bound_enforcement='vector') # This is pretty bogus, but it ensures that we get a few LS iterations. ls.options['c'] = 100.0 # FIXME c should be 0 <= c <= 1 prob.set_solver_print(level=0) prob.setup() prob.run_model() assert_rel_error(self, prob['g1.y1'], 0.64, .00001) assert_rel_error(self, prob['g1.y2'], 0.80, .00001) assert_rel_error(self, prob['g2.y1'], 0.64, .00001) assert_rel_error(self, prob['g2.y2'], 0.80, .00001)
def test_feature_armijogoldsteinls_basic(self): import numpy as np import openmdao.api as om from openmdao.test_suite.components.implicit_newton_linesearch import ImplCompTwoStatesArrays top = om.Problem() top.model.add_subsystem('comp', ImplCompTwoStatesArrays(), promotes_inputs=['x']) top.model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False) top.model.nonlinear_solver.options['maxiter'] = 10 top.model.linear_solver = om.ScipyKrylov() top.model.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS() top.setup() top.set_val('x', np.array([2., 2, 2]).reshape(3, 1)) # Test lower bounds: should go to the lower bound and stall top.set_val('comp.y', 0.) top.set_val('comp.z', 1.6) top.run_model() for ind in range(3): assert_near_equal(top.get_val('comp.z', indices=ind), [1.5], 1e-8)
def test_feature_armijogoldsteinls_basic(self): import numpy as np import openmdao.api as om from openmdao.test_suite.components.implicit_newton_linesearch import ImplCompTwoStatesArrays top = om.Problem() top.model.add_subsystem('px', om.IndepVarComp('x', np.ones((3, 1)))) top.model.add_subsystem('comp', ImplCompTwoStatesArrays()) top.model.connect('px.x', 'comp.x') top.model.nonlinear_solver = om.NewtonSolver() top.model.nonlinear_solver.options['maxiter'] = 10 top.model.linear_solver = om.ScipyKrylov() top.model.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS() top.setup() # Test lower bounds: should go to the lower bound and stall top['px.x'] = 2.0 top['comp.y'] = 0. top['comp.z'] = 1.6 top.run_model() for ind in range(3): assert_rel_error(self, top['comp.z'][ind], [1.5], 1e-8)
def test_linesearch_bounds_scalar(self): top = self.top ls = top.model.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS( bound_enforcement='scalar') ls.options['maxiter'] = 10 ls.options['alpha'] = 1.0 # Setup again because we assigned a new linesearch top.setup() # Test lower bound: should stop just short of the lower bound top['px.x'] = 2.0 top['comp.y'] = 0.0 top['comp.z'] = 1.6 top.run_model() self.assertGreaterEqual(top['comp.z'], 1.5) self.assertLessEqual(top['comp.z'], 1.6) # Test lower bound: should stop just short of the upper bound top['px.x'] = 0.5 top['comp.y'] = 0.0 top['comp.z'] = 2.4 top.run_model() self.assertGreaterEqual(top['comp.z'], 2.5) self.assertLessEqual(top['comp.z'], 2.5)
def test_feature_armijo_boundscheck_wall(self): import numpy as np import openmdao.api as om from openmdao.test_suite.components.implicit_newton_linesearch import ImplCompTwoStatesArrays top = om.Problem() top.model.add_subsystem('px', om.IndepVarComp('x', np.ones((3, 1)))) top.model.add_subsystem('comp', ImplCompTwoStatesArrays()) top.model.connect('px.x', 'comp.x') top.model.nonlinear_solver = om.NewtonSolver() top.model.nonlinear_solver.options['maxiter'] = 10 top.model.linear_solver = om.ScipyKrylov() top.model.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS( bound_enforcement='wall') top.setup() # Test upper bounds: should go to the upper bound and stall top['px.x'] = 0.5 top['comp.y'] = 0. top['comp.z'] = 2.4 top.run_model() assert_rel_error(self, top['comp.z'][0], [2.6], 1e-8) assert_rel_error(self, top['comp.z'][1], [2.5], 1e-8) assert_rel_error(self, top['comp.z'][2], [2.65], 1e-8)
def setup(self): npts = self.npts nodes = self.nodes n_in = len(nodes) self.add_subsystem('sc', SolarCell(nodes=nodes, npts=npts), promotes=['*']) self.add_subsystem('el', ElectricPower(n_in=n_in, npts=npts), promotes=['*']) self.add_subsystem('QS', QSmtxComp(nn=self.nn, nodes=nodes, npts=npts), promotes=['*']) self.add_subsystem('temps', TempsComp(n=self.nn, npts=self.npts), promotes=['*']) self.nonlinear_solver = om.NewtonSolver(solve_subsystems=True) self.nonlinear_solver.options['iprint'] = 2 self.nonlinear_solver.options['maxiter'] = 15 self.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS() self.nonlinear_solver.linesearch.options['maxiter'] = 10 self.nonlinear_solver.linesearch.options['iprint'] = 2 self.linear_solver = om.DirectSolver() self.linear_solver.options['assemble_jac'] = False
def thermal_link(model, l_comp, r_comp): l_name = l_comp r_name = r_comp b_name = '{}_bridge'.format(l_comp) # model.add_subsystem(name='eff_length', # subsys=om.ExecComp('L_eff = (L1+L2)/2+L_adiabatic', units='m'), # promotes_inputs=['L_adiabatic',('L1','{}.L_flux'.format(l_name,r_name)], # promotes_outputs=['L_eff']) model.add_subsystem(b_name, Bridge(), promotes_inputs=['A_w','A_wk','D_v','R_g','mu_v','h_fg','P_v','rho_v','L_eff','k_w','k_l','epsilon','T_hp'], promotes_outputs=['k_wk']) model.set_input_defaults('L_eff', val=0.045) # TODO set higher up? # Link Geometry model.connect('{}.size.A_w'.format(l_name),'A_w') # this can come from either component model.connect('{}.size.A_wk'.format(l_name),'A_wk') # this can come from either component model.connect('{}.R_g'.format(r_name),'R_g') model.connect('{}.mu_v'.format(r_name),'mu_v') model.connect('{}.P_v'.format(r_name),'P_v') model.connect('{}.h_fg'.format(r_name),'h_fg') model.connect('{}.rho_v'.format(r_name),'rho_v') model.connect('{}.k_l'.format(r_name),'k_l') model.connect('{}.T_hp'.format(r_name),'T_hp') # Link thermal network # left node 1 model.connect('{}.n1.T'.format(l_name),'{}.Rwa.T_in'.format(b_name)) model.connect('{}.Rwa.q'.format(b_name),'{}.n1.q_out:1'.format(l_name)) # left node 2 model.connect('{}.n2.T'.format(l_name),'{}.Rwka.T_in'.format(b_name)) model.connect('{}.Rwka.q'.format(b_name),'{}.n2.q_out:1'.format(l_name)) # left node 4 model.connect('{}.n4.T'.format(l_name),'{}.Rv.T_in'.format(b_name)) model.connect('{}.Rv.q'.format(b_name),'{}.n4.q_out:0'.format(l_name)) # right node 1 model.connect('{}.n1.T'.format(r_name),'{}.Rwa.T_out'.format(b_name)) model.connect('{}.Rwa.q'.format(b_name),'{}.n1.q_in:1'.format(r_name)) # right node 2 model.connect('{}.n2.T'.format(r_name),'{}.Rwka.T_out'.format(b_name)) model.connect('{}.Rwka.q'.format(b_name),'{}.n2.q_in:1'.format(r_name)) # right node 4 model.connect('{}.n4.T'.format(r_name),'{}.Rv.T_out'.format(b_name)) model.connect('{}.Rv.q'.format(b_name),'{}.n4.q_in:1'.format(r_name)) model.nonlinear_solver = om.NewtonSolver(solve_subsystems=True) model.nonlinear_solver.options['iprint'] = 2 model.nonlinear_solver.options['maxiter'] = 20 model.linear_solver = om.DirectSolver() model.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS() model.nonlinear_solver.linesearch.options['maxiter'] = 10 model.nonlinear_solver.linesearch.options['iprint'] = 2
def test_read_only_bug(self): # this tests for a bug in which guess_nonlinear failed due to the output # vector being left in a read only state after the AnalysisError top = om.Problem() top.model.add_subsystem('px', om.IndepVarComp('x', 7.0)) sub = top.model.add_subsystem('sub', om.Group()) sub.add_subsystem('comp', ImplCompTwoStatesAE()) sub.upper = 20 sub.lower = 25 top.model.connect('px.x', 'sub.comp.x') top.model.nonlinear_solver = om.NewtonSolver() top.model.nonlinear_solver.options['maxiter'] = 2 top.model.nonlinear_solver.options['solve_subsystems'] = True top.model.nonlinear_solver.linesearch = None top.model.linear_solver = om.ScipyKrylov() sub.nonlinear_solver = om.NewtonSolver(solve_subsystems=False) sub.nonlinear_solver.options['maxiter'] = 2 sub.nonlinear_solver.linesearch = None sub.linear_solver = om.ScipyKrylov() ls = top.model.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS( bound_enforcement='wall') ls.options['maxiter'] = 5 ls.options['alpha'] = 10.0 ls.options['retry_on_analysis_error'] = True ls.options['c'] = 1.0 top.setup() top.set_solver_print(level=2) stdout = sys.stdout strout = StringIO() sys.stdout = strout try: top.run_model() finally: sys.stdout = stdout output = strout.getvalue().split('\n') correct = False for line in output: # make sure a line starting with this string is present in stdout if line.startswith('| LS: AG 3'): correct = True break self.assertTrue(correct, msg='Expected line search output not found in stdout')
def setUp(self): top = om.Problem() top.model.add_subsystem('px', om.IndepVarComp('x', 1.0)) top.model.add_subsystem('comp', ImplCompTwoStates()) top.model.add_subsystem('par', ParaboloidAE()) top.model.connect('px.x', 'comp.x') top.model.connect('comp.z', 'par.x') top.model.nonlinear_solver = om.NewtonSolver() top.model.nonlinear_solver.options['maxiter'] = 1 top.model.linear_solver = om.ScipyKrylov() ls = top.model.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS(bound_enforcement='vector') ls.options['maxiter'] = 10 ls.options['alpha'] = 1.0 top.set_solver_print(level=0) self.top = top self.ls = ls
def test_set_total_SP(self): # p = om.Problem() p.model = Thermo(mode='total_SP', method = 'CEA', thermo_kwargs={'composition': constants.CEA_CO2_CO_O2_COMPOSITION, 'spec': species_data.co2_co_o2 }) r = p.model p.setup(check=False) # NOTE: This case is very touchy and requires weird solver settings p.model.nonlinear_solver.options['solve_subsystems'] = True p.model.base_thermo.chem_eq.nonlinear_solver.options['maxiter'] = 1 p.model.base_thermo.chem_eq.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS() p.model.base_thermo.chem_eq.nonlinear_solver.linesearch.options['maxiter'] = 2 p.set_solver_print(level=2) p.final_setup() # p.model.nonlinear_solver.options['maxiter'] = 0 p.set_val('S', 2.35711010759, units="Btu/(lbm*degR)") p.set_val('P', 1.034210, units="bar") p.run_model() assert_near_equal(p['gamma'], 1.19054696779, 1e-4) # 1500K p['T'] = 4000. p['S'] = 1.5852424435 p.run_model() assert_near_equal(p['gamma'], 1.16396871, 1e-4)
def test_circuit_advanced_newton(self): import openmdao.api as om from openmdao.test_suite.scripts.circuit_analysis import Circuit p = om.Problem() model = p.model model.add_subsystem('ground', om.IndepVarComp('V', 0., units='V')) model.add_subsystem('source', om.IndepVarComp('I', 0.1, units='A')) model.add_subsystem('circuit', Circuit()) model.connect('source.I', 'circuit.I_in') model.connect('ground.V', 'circuit.Vg') p.setup() # you can change the NewtonSolver settings in circuit after setup is called newton = p.model.circuit.nonlinear_solver newton.options['iprint'] = 2 newton.options['maxiter'] = 10 newton.options['solve_subsystems'] = True newton.linesearch = om.ArmijoGoldsteinLS() newton.linesearch.options['maxiter'] = 10 newton.linesearch.options['iprint'] = 2 # set some initial guesses p['circuit.n1.V'] = 10. p['circuit.n2.V'] = 1e-3 p.run_model() assert_rel_error(self, p['circuit.n1.V'], 9.90804735, 1e-5) assert_rel_error(self, p['circuit.n2.V'], 0.71278185, 1e-5) assert_rel_error(self, p['circuit.R1.I'], 0.09908047, 1e-5) assert_rel_error(self, p['circuit.R2.I'], 0.00091953, 1e-5) assert_rel_error(self, p['circuit.D1.I'], 0.00091953, 1e-5) # sanity check: should sum to .1 Amps assert_rel_error(self, p['circuit.R1.I'] + p['circuit.D1.I'], .1, 1e-6)
def test_bound_enforce_print_bug(self): # Error during print if bound was one-sided. class OneSidedBounds(ImplCompTwoStatesArrays): def setup(self): self.add_input('x', np.zeros((3, 1))) self.add_output('y', np.zeros((3, 1))) self.add_output('z', 2.0 * np.ones((3, 1)), upper=np.array([2.6, 2.5, 2.65]).reshape( (3, 1))) self.maxiter = 10 self.atol = 1.0e-12 self.declare_partials(of='*', wrt='*') top = om.Problem() top.model.add_subsystem('px', om.IndepVarComp('x', np.ones((3, 1)))) top.model.add_subsystem('comp', OneSidedBounds()) top.model.connect('px.x', 'comp.x') newt = top.model.nonlinear_solver = om.NewtonSolver( solve_subsystems=False) top.model.nonlinear_solver.options['maxiter'] = 2 top.model.linear_solver = om.ScipyKrylov() ls = newt.linesearch = om.ArmijoGoldsteinLS() ls.options['print_bound_enforce'] = True top.set_solver_print(level=2) top.setup() top['px.x'] = 2.0 top['comp.y'] = 0. top['comp.z'] = 1.6 # Should run without an exception being raised. top.run_model()
def test_line_search_deprecated(self): top = om.Problem() top.model.add_subsystem('px', om.IndepVarComp('x', 1.0)) top.model.add_subsystem('comp', ImplCompTwoStates()) top.model.connect('px.x', 'comp.x') top.model.nonlinear_solver = om.NewtonSolver() top.model.nonlinear_solver.options['maxiter'] = 10 top.model.linear_solver = om.ScipyKrylov() msg = "The 'line_search' attribute provides backwards compatibility with OpenMDAO 1.x ; " \ "use 'linesearch' instead." with assert_warning(DeprecationWarning, msg): top.model.nonlinear_solver.line_search = om.ArmijoGoldsteinLS( bound_enforcement='vector') with assert_warning(DeprecationWarning, msg): ls = top.model.nonlinear_solver.line_search ls.options['maxiter'] = 10 ls.options['alpha'] = 1.0 top.setup() # Test lower bound: should go to the lower bound and stall top['px.x'] = 2.0 top['comp.y'] = 0.0 top['comp.z'] = 1.6 top.run_model() assert_rel_error(self, top['comp.z'], 1.5, 1e-8) # Test upper bound: should go to the upper bound and stall top['px.x'] = 0.5 top['comp.y'] = 0.0 top['comp.z'] = 2.4 top.run_model() assert_rel_error(self, top['comp.z'], 2.5, 1e-8)
def test_linesearch_wall_bound_enforcement_wall(self): top = self.top top.model.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS(bound_enforcement='wall') # Setup again because we assigned a new linesearch top.setup() # Test lower bounds: should go to the lower bound and stall top['px.x'] = 2.0 top['comp.y'] = 0. top['comp.z'] = 1.6 top.run_model() for ind in range(3): assert_rel_error(self, top['comp.z'][ind], [1.5], 1e-8) # Test upper bounds: should go to the upper bound and stall top['px.x'] = 0.5 top['comp.y'] = 0. top['comp.z'] = 2.4 top.run_model() for ind in range(3): assert_rel_error(self, top['comp.z'][ind], [self.ub[ind]], 1e-8)
def test_linesearch_wall_bound_enforcement_scalar(self): top = self.top top.model.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS(bound_enforcement='scalar') # Setup again because we assigned a new linesearch top.setup() # Test lower bounds: should stop just short of the lower bound top['px.x'] = 2.0 top['comp.y'] = 0. top['comp.z'] = 1.6 top.run_model() for ind in range(3): self.assertTrue(1.5 <= top['comp.z'][ind] <= 1.6) # Test upper bounds: should stop just short of the minimum upper bound top['px.x'] = 0.5 top['comp.y'] = 0. top['comp.z'] = 2.4 top.run_model() for ind in range(3): self.assertTrue(2.4 <= top['comp.z'][ind] <= self.ub[ind])
def test_linesearch_bounds_wall(self): top = self.top ls = top.model.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS(bound_enforcement='wall') ls.options['maxiter'] = 10 ls.options['alpha'] = 10.0 # Setup again because we assigned a new linesearch top.setup() # Test lower bound: should go to the lower bound and stall top['px.x'] = 2.0 top['comp.y'] = 0.0 top['comp.z'] = 1.6 top.run_model() assert_rel_error(self, top['comp.z'], 1.5, 1e-8) # Test upper bound: should go to the upper bound and stall top['px.x'] = 0.5 top['comp.y'] = 0.0 top['comp.z'] = 2.4 top.run_model() assert_rel_error(self, top['comp.z'], 2.5, 1e-8)
def setup(self): # Evaporator self.add_subsystem('Rex_e', Resistor()) self.add_subsystem('Rwe', Resistor())#, promotes_inputs=[('T_in', 'T_hot')]) # evaporator wall self.add_subsystem('Rwke', Resistor()) # evaporator wick self.add_subsystem('Rinter_e', Resistor()) # Axial self.add_subsystem('Rv', Resistor()) # vapor self.add_subsystem('Rwka', Resistor()) # wick adiabatic self.add_subsystem('Rwa', Resistor()) # wall adiabatic # Condensor self.add_subsystem('Rinter_c', Resistor()) # self.add_subsystem('Rwkc', Resistor()) # condensor wick self.add_subsystem('Rwc', Resistor())#, promotes_inputs=[('T_out', 'T_cold')]) #condensor wall self.add_subsystem('Rex_c', Resistor()) self.add_subsystem('n1', Node(n_in=1, n_out=2)) # 1, 2 out self.add_subsystem('n2', Node(n_in=1, n_out=2)) # 1, 2 out self.add_subsystem('n3', Node(n_in=1, n_out=1)) # 1 self.add_subsystem('n4', Node(n_in=1, n_out=1)) # 1 self.add_subsystem('n5', Node(n_in=1, n_out=1)) # 1 self.add_subsystem('n6', Node(n_in=1, n_out=1)) # 1 self.add_subsystem('n7', Node(n_in=2, n_out=1)) # 2 in, 1 self.add_subsystem('n8', Node(n_in=2, n_out=1)) # 2 in, 1 # node 1 (6 connections, 1 in, 2 out) self.connect('n1.T', ['Rex_e.T_out','Rwe.T_in', 'Rwa.T_in']) # define temperature node as resitor inputs self.connect('Rex_e.q','n1.q_in:0') self.connect('Rwe.q','n1.q_out:0') self.connect('Rwa.q','n1.q_out:1') # node 2 (6 connections, 1 in, 2 out) self.connect('n2.T', ['Rwe.T_out', 'Rwka.T_in','Rwke.T_in']) self.connect('Rwe.q', 'n2.q_in:0') self.connect('Rwka.q', 'n2.q_out:0') self.connect('Rwke.q', 'n2.q_out:1') # node 3 (4 connections) self.connect('n3.T', ['Rwke.T_out','Rinter_e.T_in']) self.connect('Rwke.q', 'n3.q_in:0') self.connect('Rinter_e.q', 'n3.q_out:0') # node 4 (4 connections) self.connect('n4.T', ['Rinter_e.T_out','Rv.T_in']) self.connect('Rinter_e.q', 'n4.q_in:0') self.connect('Rv.q', 'n4.q_out:0') # node 5 (4 connections) self.connect('n5.T', ['Rv.T_out','Rinter_c.T_in']) self.connect('Rv.q', 'n5.q_in:0') self.connect('Rinter_c.q', 'n5.q_out:0') # node 6 (4 connections) self.connect('n6.T', ['Rinter_c.T_out','Rwkc.T_in']) self.connect('Rinter_c.q', 'n6.q_in:0') self.connect('Rwkc.q', 'n6.q_out:0') # node 7 (4 connections, 2 in, 1 out) self.connect('n7.T', ['Rwka.T_out','Rwkc.T_out','Rwc.T_in']) self.connect('Rwka.q', 'n7.q_in:0') self.connect('Rwkc.q', 'n7.q_in:1') self.connect('Rwc.q', 'n7.q_out:0') # node 8 (6 connections, 2 in, 1 out) self.connect('n8.T',['Rwa.T_out','Rwc.T_out','Rex_c.T_in']) self.connect('Rwa.q','n8.q_in:0') self.connect('Rwc.q','n8.q_in:1') self.connect('Rex_c.q','n8.q_out:0') self.nonlinear_solver = om.NewtonSolver(solve_subsystems=True) self.nonlinear_solver.options['iprint'] = 2 self.nonlinear_solver.options['maxiter'] = 20 self.linear_solver = om.DirectSolver() self.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS() self.nonlinear_solver.linesearch.options['maxiter'] = 10 self.nonlinear_solver.linesearch.options['iprint'] = 2
# set the lhs and rhs for the battery residual model.connect('batt.V', 'batt_balance.rhs:I') model.connect('batt_deltaV.dV', 'batt_balance.lhs:I') p.setup() ################### # Solver Setup ################### # change the circuit solver to RunOnce because we're # going to converge at the top level of the model with newton instead p.model.circuit.nonlinear_solver = om.NonlinearRunOnce() p.model.circuit.linear_solver = om.LinearRunOnce() # Put Newton at the top so it can also converge the new BalanceComp residual newton = p.model.nonlinear_solver = om.NewtonSolver() p.model.linear_solver = om.DirectSolver() newton.options['iprint'] = 2 newton.options['maxiter'] = 20 newton.options['solve_subsystems'] = True newton.linesearch = om.ArmijoGoldsteinLS() newton.linesearch.options['maxiter'] = 10 newton.linesearch.options['iprint'] = 2 # set initial guesses from the current source problem p['circuit.n1.V'] = 9.8 p['circuit.n2.V'] = .7 p.run_model()
def setup(self): thermo_spec = pyc.species_data.janaf design = self.options['design'] cooling = self.options['cooling'] self.pyc_add_element( 'fc', pyc.FlightConditions(thermo_data=thermo_spec, elements=pyc.AIR_MIX)) self.pyc_add_element( 'inlet', pyc.Inlet(design=design, thermo_data=thermo_spec, elements=pyc.AIR_MIX)) self.pyc_add_element('fan', pyc.Compressor(map_data=FanMap, design=design, thermo_data=thermo_spec, elements=pyc.AIR_MIX, map_extrap=True, bleed_names=[]), promotes_inputs=[('Nmech', 'Fan_Nmech')]) self.pyc_add_element( 'splitter', pyc.Splitter(design=design, thermo_data=thermo_spec, elements=pyc.AIR_MIX)) self.pyc_add_element( 'duct2', pyc.Duct(design=design, expMN=2.0, thermo_data=thermo_spec, elements=pyc.AIR_MIX)) self.pyc_add_element('lpc', pyc.Compressor(map_data=LPCMap, design=design, thermo_data=thermo_spec, elements=pyc.AIR_MIX, map_extrap=True), promotes_inputs=[('Nmech', 'LP_Nmech')]) self.pyc_add_element('bld25', pyc.BleedOut(design=design, bleed_names=['sbv'])) self.pyc_add_element( 'duct25', pyc.Duct(design=design, expMN=2.0, thermo_data=thermo_spec, elements=pyc.AIR_MIX)) self.pyc_add_element( 'hpc', pyc.Compressor(map_data=HPCMap, design=design, thermo_data=thermo_spec, elements=pyc.AIR_MIX, map_extrap=True, bleed_names=['bld_inlet', 'bld_exit', 'cust']), promotes_inputs=[('Nmech', 'HP_Nmech')]) self.pyc_add_element( 'bld3', pyc.BleedOut(design=design, bleed_names=['bld_inlet', 'bld_exit'])) self.pyc_add_element( 'burner', pyc.Combustor(design=design, thermo_data=thermo_spec, inflow_elements=pyc.AIR_MIX, air_fuel_elements=pyc.AIR_FUEL_MIX, fuel_type='Jet-A(g)')) self.pyc_add_element('hpt', pyc.Turbine(map_data=HPTMap, design=design, thermo_data=thermo_spec, elements=pyc.AIR_FUEL_MIX, map_extrap=True, bleed_names=['bld_inlet', 'bld_exit']), promotes_inputs=[('Nmech', 'HP_Nmech')]) self.pyc_add_element( 'duct45', pyc.Duct(design=design, expMN=2.0, thermo_data=thermo_spec, elements=pyc.AIR_FUEL_MIX)) self.pyc_add_element('lpt', pyc.Turbine(map_data=LPTMap, design=design, thermo_data=thermo_spec, elements=pyc.AIR_FUEL_MIX, map_extrap=True, bleed_names=['bld_inlet', 'bld_exit']), promotes_inputs=[('Nmech', 'LP_Nmech')]) self.pyc_add_element( 'duct5', pyc.Duct(design=design, expMN=2.0, thermo_data=thermo_spec, elements=pyc.AIR_FUEL_MIX)) self.pyc_add_element( 'core_nozz', pyc.Nozzle(nozzType='CV', lossCoef='Cv', thermo_data=thermo_spec, elements=pyc.AIR_FUEL_MIX)) self.pyc_add_element( 'byp_bld', pyc.BleedOut(design=design, bleed_names=['bypBld'])) self.pyc_add_element( 'duct17', pyc.Duct(design=design, expMN=2.0, thermo_data=thermo_spec, elements=pyc.AIR_MIX)) self.pyc_add_element( 'byp_nozz', pyc.Nozzle(nozzType='CV', lossCoef='Cv', thermo_data=thermo_spec, elements=pyc.AIR_MIX)) self.pyc_add_element('fan_shaft', pyc.Shaft(num_ports=2), promotes_inputs=[('Nmech', 'Fan_Nmech')]) self.pyc_add_element('gearbox', pyc.Gearbox(design=design), promotes_inputs=[('N_in', 'LP_Nmech'), ('N_out', 'Fan_Nmech')]) self.pyc_add_element('lp_shaft', pyc.Shaft(num_ports=3), promotes_inputs=[('Nmech', 'LP_Nmech')]) self.pyc_add_element('hp_shaft', pyc.Shaft(num_ports=2), promotes_inputs=[('Nmech', 'HP_Nmech')]) self.pyc_add_element('perf', pyc.Performance(num_nozzles=2, num_burners=1)) self.connect('inlet.Fl_O:tot:P', 'perf.Pt2') self.connect('hpc.Fl_O:tot:P', 'perf.Pt3') self.connect('burner.Wfuel', 'perf.Wfuel_0') self.connect('inlet.F_ram', 'perf.ram_drag') self.connect('core_nozz.Fg', 'perf.Fg_0') self.connect('byp_nozz.Fg', 'perf.Fg_1') self.connect('fan.trq', 'fan_shaft.trq_0') self.connect('gearbox.trq_out', 'fan_shaft.trq_1') self.connect('gearbox.trq_in', 'lp_shaft.trq_0') self.connect('lpc.trq', 'lp_shaft.trq_1') self.connect('lpt.trq', 'lp_shaft.trq_2') self.connect('hpc.trq', 'hp_shaft.trq_0') self.connect('hpt.trq', 'hp_shaft.trq_1') self.connect('fc.Fl_O:stat:P', 'core_nozz.Ps_exhaust') self.connect('fc.Fl_O:stat:P', 'byp_nozz.Ps_exhaust') self.add_subsystem( 'ext_ratio', om.ExecComp( 'ER = core_V_ideal * core_Cv / ( byp_V_ideal * byp_Cv )', core_V_ideal={ 'value': 1000.0, 'units': 'ft/s' }, core_Cv={ 'value': 0.98, 'units': None }, byp_V_ideal={ 'value': 1000.0, 'units': 'ft/s' }, byp_Cv={ 'value': 0.98, 'units': None }, ER={ 'value': 1.4, 'units': None })) self.connect('core_nozz.ideal_flow.V', 'ext_ratio.core_V_ideal') self.connect('byp_nozz.ideal_flow.V', 'ext_ratio.byp_V_ideal') main_order = [ 'fc', 'inlet', 'fan', 'splitter', 'duct2', 'lpc', 'bld25', 'duct25', 'hpc', 'bld3', 'burner', 'hpt', 'duct45', 'lpt', 'duct5', 'core_nozz', 'byp_bld', 'duct17', 'byp_nozz', 'gearbox', 'fan_shaft', 'lp_shaft', 'hp_shaft', 'perf', 'ext_ratio' ] balance = self.add_subsystem('balance', om.BalanceComp()) if design: balance.add_balance('FAR', eq_units='degR', lower=1e-4, val=.017) self.connect('balance.FAR', 'burner.Fl_I:FAR') self.connect('burner.Fl_O:tot:T', 'balance.lhs:FAR') balance.add_balance('lpt_PR', val=10.937, lower=1.001, upper=20, eq_units='hp', rhs_val=0., res_ref=1e4) self.connect('balance.lpt_PR', 'lpt.PR') self.connect('lp_shaft.pwr_net', 'balance.lhs:lpt_PR') balance.add_balance('hpt_PR', val=4.185, lower=1.001, upper=8, eq_units='hp', rhs_val=0., res_ref=1e4) self.connect('balance.hpt_PR', 'hpt.PR') self.connect('hp_shaft.pwr_net', 'balance.lhs:hpt_PR') balance.add_balance('gb_trq', val=23928.0, units='ft*lbf', eq_units='hp', rhs_val=0.0) self.connect('balance.gb_trq', 'gearbox.trq_base') self.connect('fan_shaft.pwr_net', 'balance.lhs:gb_trq') balance.add_balance('hpc_PR', val=14.0, units=None, eq_units=None) self.connect('balance.hpc_PR', ['hpc.PR', 'opr_calc.HPCPR']) # self.connect('perf.OPR', 'balance.lhs:hpc_PR') self.connect('opr_calc.OPR_simple', 'balance.lhs:hpc_PR') balance.add_balance('fan_eff', val=0.9689, units=None, eq_units=None) self.connect('balance.fan_eff', 'fan.eff') self.connect('fan.eff_poly', 'balance.lhs:fan_eff') balance.add_balance('lpc_eff', val=0.8895, units=None, eq_units=None) self.connect('balance.lpc_eff', 'lpc.eff') self.connect('lpc.eff_poly', 'balance.lhs:lpc_eff') # balance.add_balance('hpc_eff', val=0.8470, units=None, eq_units=None) # self.connect('balance.hpc_eff', 'hpc.eff') # self.connect('hpc.eff_poly', 'balance.lhs:hpc_eff') balance.add_balance('hpt_eff', val=0.9226, units=None, eq_units=None) self.connect('balance.hpt_eff', 'hpt.eff') self.connect('hpt.eff_poly', 'balance.lhs:hpt_eff') balance.add_balance('lpt_eff', val=0.9401, units=None, eq_units=None) self.connect('balance.lpt_eff', 'lpt.eff') self.connect('lpt.eff_poly', 'balance.lhs:lpt_eff') self.add_subsystem( 'hpc_CS', om.ExecComp('CS = Win *(pow(Tout/518.67,0.5)/(Pout/14.696))', Win={ 'value': 10.0, 'units': 'lbm/s' }, Tout={ 'value': 14.696, 'units': 'degR' }, Pout={ 'value': 518.67, 'units': 'psi' }, CS={ 'value': 10.0, 'units': 'lbm/s' })) self.connect('duct25.Fl_O:stat:W', 'hpc_CS.Win') self.connect('hpc.Fl_O:tot:T', 'hpc_CS.Tout') self.connect('hpc.Fl_O:tot:P', 'hpc_CS.Pout') self.add_subsystem( 'hpc_EtaBalance', SmallCoreEffBalance(eng_type='large', tech_level=0)) self.connect('hpc_CS.CS', 'hpc_EtaBalance.CS') self.connect('hpc.eff_poly', 'hpc_EtaBalance.eta_p') self.connect('hpc_EtaBalance.eta_a', 'hpc.eff') self.add_subsystem( 'fan_dia', om.ExecComp('FanDia = 2.0*(area/(pi*(1.0-hub_tip**2.0)))**0.5', area={ 'value': 7000.0, 'units': 'inch**2' }, hub_tip={ 'value': 0.3125, 'units': None }, FanDia={ 'value': 100.0, 'units': 'inch' })) self.connect('inlet.Fl_O:stat:area', 'fan_dia.area') self.add_subsystem( 'opr_calc', om.ExecComp('OPR_simple = FPR*LPCPR*HPCPR', FPR={ 'value': 1.3, 'units': None }, LPCPR={ 'value': 3.0, 'units': None }, HPCPR={ 'value': 14.0, 'units': None }, OPR_simple={ 'value': 55.0, 'units': None })) # order_add = ['hpc_CS', 'fan_dia', 'opr_calc'] order_add = ['hpc_CS', 'hpc_EtaBalance', 'fan_dia', 'opr_calc'] else: balance.add_balance('FAR', val=0.017, lower=1e-4, eq_units='lbf') self.connect('balance.FAR', 'burner.Fl_I:FAR') self.connect('perf.Fn', 'balance.lhs:FAR') # self.connect('burner.Fl_O:tot:T', 'balance.lhs:FAR') balance.add_balance('W', units='lbm/s', lower=10., upper=2500., eq_units='inch**2') self.connect('balance.W', 'fc.W') self.connect('core_nozz.Throat:stat:area', 'balance.lhs:W') balance.add_balance('BPR', lower=15., upper=40.) self.connect('balance.BPR', 'splitter.BPR') self.connect('fan.map.RlineMap', 'balance.lhs:BPR') balance.add_balance('fan_Nmech', val=2000.0, units='rpm', lower=500., eq_units='hp', rhs_val=0., res_ref=1e2) self.connect('balance.fan_Nmech', 'Fan_Nmech') self.connect('fan_shaft.pwr_net', 'balance.lhs:fan_Nmech') balance.add_balance('lp_Nmech', val=6000.0, units='rpm', lower=500., eq_units='hp', rhs_val=0., res_ref=1e2) self.connect('balance.lp_Nmech', 'LP_Nmech') self.connect('lp_shaft.pwr_net', 'balance.lhs:lp_Nmech') balance.add_balance('hp_Nmech', val=20000.0, units='rpm', lower=500., eq_units='hp', rhs_val=0., res_ref=1e2) self.connect('balance.hp_Nmech', 'HP_Nmech') self.connect('hp_shaft.pwr_net', 'balance.lhs:hp_Nmech') order_add = [] if cooling: self.add_subsystem( 'hpt_cooling', pyc.TurbineCooling(n_stages=2, thermo_data=pyc.species_data.janaf, T_metal=2460.)) self.add_subsystem('hpt_chargable', pyc.CombineCooling(n_ins=3)) self.pyc_connect_flow('bld3.bld_inlet', 'hpt_cooling.Fl_cool', connect_stat=False) self.pyc_connect_flow('burner.Fl_O', 'hpt_cooling.Fl_turb_I') self.pyc_connect_flow('hpt.Fl_O', 'hpt_cooling.Fl_turb_O') self.connect('hpt_cooling.row_1.W_cool', 'hpt_chargable.W_1') self.connect('hpt_cooling.row_2.W_cool', 'hpt_chargable.W_2') self.connect('hpt_cooling.row_3.W_cool', 'hpt_chargable.W_3') self.connect('hpt.power', 'hpt_cooling.turb_pwr') balance.add_balance('hpt_nochrg_cool_frac', val=0.063660111, lower=0.02, upper=.15, eq_units='lbm/s') self.connect('balance.hpt_nochrg_cool_frac', 'bld3.bld_inlet:frac_W') self.connect('bld3.bld_inlet:stat:W', 'balance.lhs:hpt_nochrg_cool_frac') self.connect('hpt_cooling.row_0.W_cool', 'balance.rhs:hpt_nochrg_cool_frac') balance.add_balance('hpt_chrg_cool_frac', val=0.07037185, lower=0.02, upper=.15, eq_units='lbm/s') self.connect('balance.hpt_chrg_cool_frac', 'bld3.bld_exit:frac_W') self.connect('bld3.bld_exit:stat:W', 'balance.lhs:hpt_chrg_cool_frac') self.connect('hpt_chargable.W_cool', 'balance.rhs:hpt_chrg_cool_frac') order_add = ['hpt_cooling', 'hpt_chargable'] self.set_order(main_order + order_add + ['balance']) self.pyc_connect_flow('fc.Fl_O', 'inlet.Fl_I') self.pyc_connect_flow('inlet.Fl_O', 'fan.Fl_I') self.pyc_connect_flow('fan.Fl_O', 'splitter.Fl_I') self.pyc_connect_flow('splitter.Fl_O1', 'duct2.Fl_I') self.pyc_connect_flow('duct2.Fl_O', 'lpc.Fl_I') self.pyc_connect_flow('lpc.Fl_O', 'bld25.Fl_I') self.pyc_connect_flow('bld25.Fl_O', 'duct25.Fl_I') self.pyc_connect_flow('duct25.Fl_O', 'hpc.Fl_I') self.pyc_connect_flow('hpc.Fl_O', 'bld3.Fl_I') self.pyc_connect_flow('bld3.Fl_O', 'burner.Fl_I') self.pyc_connect_flow('burner.Fl_O', 'hpt.Fl_I') self.pyc_connect_flow('hpt.Fl_O', 'duct45.Fl_I') self.pyc_connect_flow('duct45.Fl_O', 'lpt.Fl_I') self.pyc_connect_flow('lpt.Fl_O', 'duct5.Fl_I') self.pyc_connect_flow('duct5.Fl_O', 'core_nozz.Fl_I') self.pyc_connect_flow('splitter.Fl_O2', 'byp_bld.Fl_I') self.pyc_connect_flow('byp_bld.Fl_O', 'duct17.Fl_I') self.pyc_connect_flow('duct17.Fl_O', 'byp_nozz.Fl_I') self.pyc_connect_flow('hpc.bld_inlet', 'lpt.bld_inlet', connect_stat=False) self.pyc_connect_flow('hpc.bld_exit', 'lpt.bld_exit', connect_stat=False) self.pyc_connect_flow('bld3.bld_inlet', 'hpt.bld_inlet', connect_stat=False) self.pyc_connect_flow('bld3.bld_exit', 'hpt.bld_exit', connect_stat=False) newton = self.nonlinear_solver = om.NewtonSolver() newton.options['atol'] = 1e-4 newton.options['rtol'] = 1e-4 newton.options['iprint'] = 2 newton.options['maxiter'] = 10 newton.options['solve_subsystems'] = True newton.options['max_sub_solves'] = 10 newton.options['reraise_child_analysiserror'] = False # newton.linesearch = om.BoundsEnforceLS() newton.linesearch = om.ArmijoGoldsteinLS() # newton.linesearch.options['maxiter'] = 2 newton.linesearch.options['bound_enforcement'] = 'scalar' newton.linesearch.options['iprint'] = -1 # if design: # newton.linesearch.options['print_bound_enforce'] = True # newton.options['debug_print'] = True self.linear_solver = om.DirectSolver(assemble_jac=True)
def setup(self): newton = self.nonlinear_solver = om.NewtonSolver() newton.options['maxiter'] = 100 newton.options['iprint'] = 2 newton.options['atol'] = 1e-10 newton.options['rtol'] = 1e-10 self.options['assembled_jac_type'] = 'dense' self.linear_solver = om.DirectSolver(assemble_jac=True) # ln_bt = newton.linesearch = om.BoundsEnforceLS() ln_bt = newton.linesearch = om.ArmijoGoldsteinLS() ln_bt.options['maxiter'] = 2 ln_bt.options['bound_enforcement'] = 'scalar' ln_bt.options['iprint'] = -1 #ln_bt.options['maxiter'] = 1 # Once the concentration of a species reaches its minimum, we # can essentially remove it from the problem. This switch controls # whether to do this. self.remove_trace_species = False # multiply a damping function that scales down the residual for trace species self.use_trace_damping = True thermo = self.options['thermo'] mode = self.options['mode'] num_prod = thermo.num_prod num_element = thermo.num_element # Input vars self.add_input( 'init_prod_amounts', val=thermo.init_prod_amounts, shape=(num_prod, ), desc="initial mass fractions of products, before equilibrating") self.add_input('P', val=1.0, units="bar", desc="Pressure") if mode == "T": # T is an input self.add_input('T', val=400., units="degK", desc="Temperature") elif mode == "h" or mode == "S": # T becomes another state variable if mode == "h": # hP solve self.add_input('h', val=0., units="cal/g", desc="Enthalpy") elif mode == "S": # SP solve self.add_input('S', val=0., units="cal/(g*degK)", desc="Entropy") self.T_idx = num_prod + num_element self.add_output('T', val=400., units="degK", desc="Temperature", lower=1., res_ref=100) # State vars self.n_init = np.ones(num_prod) / num_prod / 10 # initial guess for n # for a known solution, these are the orders of magnitude of the variables. # We'll try setting scaling to +/1 1 order around thee values mag = np.array([ 3.23319258e-04, 1.00000000e-10, 1.10131241e-05, 1.00000000e-10, 1.15755853e-08, 2.95692989e-09, 1.00000000e-10, 2.69578794e-02, 1.00000000e-10, 7.23198523e-03 ]) #mag = np.ones(num_prod) self.add_output('n', shape=num_prod, val=self.n_init, desc="mole fractions of the mixture", lower=1e-10, res_ref=10000.) self.add_output( 'pi', val=np.ones(num_element), desc="modified lagrange multipliers from the Gibbs lagrangian") # Explicit Outputs self.add_output( 'b0', shape=num_element, # when converged, b0=b desc='assigned kg-atoms of element i per total kg of reactant ' 'for the initial prod amounts') self.add_output('n_moles', lower=1e-10, val=0.034, shape=1, desc="1/molecular weight of gas") # allocate the newton Jacobian self.size = size = num_prod + num_element if mode != "T": size += 1 # added T as a state variable self._dRdy = np.zeros((size, size)) self._rhs = np.zeros(size) # used for solve_linear # Cached stuff for speed self.H0_T = None self.S0_T = None self.dH0_dT = None self.dS0_dT = None self.sum_n_H0_T = None # self.deriv_options['check_type'] = 'cs' # self.deriv_options['check_step_size'] = 1e-50 # self.deriv_options['type'] = 'fd' # self.deriv_options['step_size'] = 1e-5 self.declare_partials('n', ['n', 'pi', 'P', 'T']) self.declare_partials('pi', ['n', 'init_prod_amounts']) self.declare_partials('b0', ['b0', 'init_prod_amounts']) self.declare_partials('n_moles', 'n') self.declare_partials('n_moles', 'n_moles', val=-1) if mode == 'h': self.declare_partials('T', ['n', 'h', 'T']) elif mode == 'S': self.declare_partials('T', ['n', 'S', 'T', 'P'])