def test_solve_linear_maxiter(self): # Test that using options that should not exist in class cause an error solver = DirectSolver() msg = "\"Option '%s' cannot be set because it has not been declared.\"" for option in ['atol', 'rtol', 'maxiter', 'err_on_maxiter']: with self.assertRaises(KeyError) as context: solver.options[option] = 1 self.assertEqual(str(context.exception), msg % option)
def test_no_promotion_errors(self): """ Tests for error-handling for invalid variable names and keys. """ g = Group(assembled_jac_type='dense') g.linear_solver = DirectSolver(assemble_jac=True) c = g.add_subsystem('c', ExecComp('y=2*x')) p = Problem() model = p.model model.add_subsystem('g', g) p.setup(check=False) # ------------------------------------------------------------------- msg = 'Variable name "{}" not found.' # inputs with assertRaisesRegex(self, KeyError, msg.format('x')): p['x'] = 5.0 p.final_setup() p._initial_condition_cache = {} with assertRaisesRegex(self, KeyError, msg.format('x')): x = p['x'] # outputs with assertRaisesRegex(self, KeyError, msg.format('y')): p['y'] = 5.0 p.final_setup() p._initial_condition_cache = {} with assertRaisesRegex(self, KeyError, msg.format('y')): y = p['y'] msg = 'Variable name "{}" not found.' inputs, outputs, residuals = g.get_nonlinear_vectors() # inputs with assertRaisesRegex(self, KeyError, msg.format('x')): inputs['x'] = 5.0 with assertRaisesRegex(self, KeyError, msg.format('x')): x = inputs['x'] with assertRaisesRegex(self, KeyError, msg.format('g.c.x')): inputs['g.c.x'] = 5.0 with assertRaisesRegex(self, KeyError, msg.format('g.c.x')): gcx = inputs['g.c.x'] # outputs with assertRaisesRegex(self, KeyError, msg.format('y')): outputs['y'] = 5.0 with assertRaisesRegex(self, KeyError, msg.format('y')): y = outputs['y'] with assertRaisesRegex(self, KeyError, msg.format('g.c.y')): outputs['g.c.y'] = 5.0 with assertRaisesRegex(self, KeyError, msg.format('g.c.y')): out = outputs['g.c.y'] msg = 'Variable name pair \("{}", "{}"\) not found.' jac = g.linear_solver._assembled_jac # d(output)/d(input) with assertRaisesRegex(self, KeyError, msg.format('y', 'x')): jac['y', 'x'] = 5.0 with assertRaisesRegex(self, KeyError, msg.format('y', 'x')): dydx = jac['y', 'x'] # allow absolute keys now #with assertRaisesRegex(self, KeyError, msg.format('g.c.y', 'g.c.x')): #jac['g.c.y', 'g.c.x'] = 5.0 #with assertRaisesRegex(self, KeyError, msg.format('g.c.y', 'g.c.x')): #deriv = jac['g.c.y', 'g.c.x'] # d(output)/d(output) with assertRaisesRegex(self, KeyError, msg.format('y', 'y')): jac['y', 'y'] = 5.0 with assertRaisesRegex(self, KeyError, msg.format('y', 'y')): dydy = jac['y', 'y']
def __init__(self, num_segments=15, transcription_order=3, transcription_type='LGR', solve_segments=False, ivc_pert=None, use_polynomial_control=True, read_coloring_file=True): self.num_segments = num_segments self.transcription_order = transcription_order self.transcription_type = transcription_type self.solve_segments = solve_segments self.use_polynomial_control = use_polynomial_control self.p = Problem(model=Group()) self.p.driver = pyOptSparseDriver() self.p.driver.options['optimizer'] = 'SNOPT' self.p.driver.options['dynamic_simul_derivs'] = False self.p.driver.opt_settings['Major iterations limit'] = 1000 # self.p.driver.opt_settings['iSumm'] = 6 self.p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-9 self.p.driver.opt_settings['Major optimality tolerance'] = 1.0E-9 self.p.driver.opt_settings['Function precision'] = 1.0E-12 self.p.driver.opt_settings['Linesearch tolerance'] = 0.1 self.p.driver.opt_settings['Major step limit'] = 0.5 self.p.driver.options['print_results'] = False if read_coloring_file: fname = os.environ['HOME'] + '/UserApps/pyStatReduce/pystatreduce/examples/supersonic_interceptor/coloring_files/total_coloring.pkl' self.p.driver.use_fixed_coloring(fname) # self.p.driver.use_fixed_coloring('/users/pandak/UserApps/pyStatReduce/pystatreduce/examples/supersonic_interceptor/coloring_files/total_coloring.pkl') # Add an indep_var_comp that will talk to external calls from pyStatReduce if ivc_pert is None: seed_perturbation = np.zeros(self.transcription_order*self.num_segments) else: seed_perturbation = ivc_pert random_perturbations = self.p.model.add_subsystem('random_perturbations', IndepVarComp()) random_perturbations.add_output('rho_pert', val=seed_perturbation, units='kg/m**3', desc="perturbations introduced into the density data") lgl = dm.GaussLobatto(num_segments=self.num_segments, order=self.transcription_order, solve_segments=self.solve_segments) lgr = dm.Radau(num_segments=self.num_segments, order=self.transcription_order, solve_segments=self.solve_segments) rk4 = dm.RungeKutta(num_segments=100) traj = dm.Trajectory() if self.transcription_type is 'RK4': phase = dm.Phase(ode_class=MinTimeClimbODE, transcription=rk4) elif self.transcription_type is 'LGL': phase = dm.Phase(ode_class=MinTimeClimbODE, transcription=lgl) elif self.transcription_type is 'LGR': phase = dm.Phase(ode_class=MinTimeClimbODE, transcription=lgr) else: raise NotImplementedError traj.add_phase('phase0', phase) self.p.model.add_subsystem('traj', traj) phase.set_time_options(fix_initial=True, duration_bounds=(50, 400), duration_ref=100.0) phase.set_state_options('r', fix_initial=True, lower=0, upper=1.0E6, ref=1.0E3, defect_ref=1.0E3, units='m',solve_segments=self.solve_segments) phase.set_state_options('h', fix_initial=True, lower=0, upper=20000.0, ref=1.0E2, defect_ref=1.0E2, units='m', solve_segments=self.solve_segments) phase.set_state_options('v', fix_initial=True, lower=10.0, ref=1.0E2, defect_ref=1.0E2, units='m/s', solve_segments=self.solve_segments) phase.set_state_options('gam', fix_initial=True, lower=-1.5, upper=1.5, ref=1.0, defect_ref=1.0, units='rad', solve_segments=self.solve_segments) phase.set_state_options('m', fix_initial=True, lower=10.0, upper=1.0E5, ref=1.0E3, defect_ref=1.0E3, solve_segments=self.solve_segments) if self.use_polynomial_control: phase.add_polynomial_control('alpha', units='deg', lower=-8., upper=8., order=5) else: phase.add_control('alpha', units='deg', lower=-8.0, upper=8.0, scaler=1.0, rate_continuity=True, rate_continuity_scaler=100.0, rate2_continuity=False) # # Add the random parameters to dymos # phase.add_input_parameter('rho_pert', shape=(60,), dynamic=False, units='kg/m**3') # Add the density perturbation as a control phase.add_control('rho_pert', units='kg/m**3', opt=False) self.p.model.connect('random_perturbations.rho_pert', 'traj.phase0.controls:rho_pert') phase.add_design_parameter('S', val=49.2386, units='m**2', opt=False) phase.add_design_parameter('Isp', val=1600.0, units='s', opt=False) phase.add_design_parameter('throttle', val=1.0, opt=False) phase.add_boundary_constraint('h', loc='final', equals=20000, scaler=1.0E-3, units='m') phase.add_boundary_constraint('aero.mach', loc='final', equals=1.0) phase.add_boundary_constraint('gam', loc='final', equals=0.0, units='rad') phase.add_path_constraint(name='h', lower=100.0, upper=20000, ref=20000) phase.add_path_constraint(name='aero.mach', lower=0.1, upper=1.8) # Minimize time at the end of the phase phase.add_objective('time', loc='final', ref=1.0) self.p.model.linear_solver = DirectSolver() self.p.setup() self.p['traj.phase0.t_initial'] = 0.0 self.p['traj.phase0.t_duration'] = 300.0 self.p['traj.phase0.states:r'] = phase.interpolate(ys=[0.0, 111319.54], nodes='state_input') self.p['traj.phase0.states:h'] = phase.interpolate(ys=[100.0, 20000.0], nodes='state_input') self.p['traj.phase0.states:v'] = phase.interpolate(ys=[135.964, 283.159], nodes='state_input') self.p['traj.phase0.states:gam'] = phase.interpolate(ys=[0.0, 0.0], nodes='state_input') self.p['traj.phase0.states:m'] = phase.interpolate(ys=[19030.468, 16841.431], nodes='state_input') if self.transcription_type is 'RK4' or self.transcription_type is 'LGR': if self.use_polynomial_control: self.p['traj.phase0.polynomial_controls:alpha'] = np.array([[4.86918595], [1.30322324], [1.41897019], [1.10227365], [3.58780732], [5.36233472]]) self.p['traj.phase0.t_duration'] = 346.13171325 else: # self.p['traj.phase0.controls:alpha'] = phase.interpolate(ys=[0.0, 0.0], nodes='control_input') self.p['traj.phase0.controls:alpha'] = np.array([[ 5.28001465], [ 3.13975533], [ 1.98865951], [ 2.05967779], [ 2.22378148], [ 1.66812216], [ 1.30331958], [ 0.69713879], [ 0.95481437], [ 1.30067776], [ 1.89992733], [ 1.61608848], [ 1.25793436], [ 0.61321823], [ 0.78469243], [ 1.09529382], [ 1.75985378], [ 2.06015107], [ 2.00622047], [ 1.80482513], [ 1.54044227], [ 1.46002774], [ 1.31279412], [ 1.22493615], [ 1.22498241], [ 1.2379623 ], [ 1.24779616], [ 1.24895759], [ 1.24532979], [ 1.22320548], [ 1.21206765], [ 1.18520735], [ 1.15116935], [ 1.14112692], [ 1.22312977], [ 1.67973464], [ 1.90722158], [ 2.4858537 ], [ 3.32375899], [ 3.59849829], [ 3.9384917 ], [ 3.44095692], [ 3.04996246], [ 1.07581437], [-4.76838553]]) elif self.solve_segments is True: self.p['traj.phase0.t_duration'] = 346.13171325
def min_time_climb_problem(num_seg=3, transcription_order=5, transcription='gauss-lobatto', top_level_densejacobian=True): p = Problem(model=Group()) p.driver = pyOptSparseDriver() p.driver.options['optimizer'] = 'SNOPT' p.driver.opt_settings['Major iterations limit'] = 500 p.driver.opt_settings['Iterations limit'] = 1000000000 p.driver.opt_settings['iSumm'] = 6 p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-10 p.driver.opt_settings['Major optimality tolerance'] = 1.0E-10 p.driver.opt_settings['Verify level'] = 1 p.driver.opt_settings['Function precision'] = 1.0E-6 p.driver.opt_settings['Linesearch tolerance'] = .1 p.driver.opt_settings['Major step limit'] = .1 p.driver.options['dynamic_simul_derivs'] = True phase = Phase(transcription, ode_class=MinTimeClimbODE, num_segments=num_seg, transcription_order=transcription_order) p.model.add_subsystem('phase', phase) phase.set_time_options(opt_initial=False, duration_bounds=(50, 1e8), duration_ref=100.0) phase.set_state_options('r', fix_initial=True, lower=0, upper=1.0E8, scaler=1.0E-4, defect_scaler=1.0E-3, units='m') phase.set_state_options('h', fix_initial=True, lower=0, upper=20000.0, scaler=1.0E-3, defect_scaler=1.0E-3, units='m') phase.set_state_options('v', fix_initial=True, lower=10.0, upper=500., scaler=1.0E-2, defect_scaler=1.0E-2, units='m/s') phase.set_state_options('gam', fix_initial=True, lower=-1.5, upper=1.5, ref=1.0, defect_scaler=1.0, units='rad') phase.set_state_options('m', fix_initial=True, lower=10.0, upper=1.0E5, scaler=1.0E-3, defect_scaler=1.0E-3, units='kg') phase.add_control('alpha', units='deg', lower=-8.0, upper=8.0, scaler=1.0, rate_continuity=True) phase.add_design_parameter('S', val=49.2386, units='m**2', opt=False) # phase.add_design_parameter('throttle', val=1.0, opt=False) phase.add_control('throttle', val=1.0, opt=True, lower=0., upper=1., rate_continuity=False) phase.add_boundary_constraint('h', loc='final', equals=100., scaler=1.0E-3, units='m') # phase.add_boundary_constraint('aero.mach', loc='final', equals=1., units=None) # phase.add_boundary_constraint('gam', loc='final', equals=0.0, units='rad') phase.add_boundary_constraint('r', loc='final', equals=1e6, units='m') phase.add_path_constraint(name='h', lower=100.0, upper=20000, ref=20000) phase.add_path_constraint(name='aero.mach', lower=0.1, upper=1.8) phase.add_path_constraint(name='prop.m_dot', upper=0.) # phase.add_path_constraint(name='flight_dynamics.r_dot', lower=0.) # Minimize time at the end of the phase # phase.add_objective('time', loc='final', ref=100.0) phase.add_objective('m', loc='final', ref=-1000.0) p.model.linear_solver = DirectSolver(assemble_jac=True) p.model.options['assembled_jac_type'] = 'csc' p.setup(mode='fwd', check=True) p['phase.t_initial'] = 0.0 p['phase.t_duration'] = 2000. p['phase.states:r'] = phase.interpolate(ys=[0.0, 1e6], nodes='state_input') p['phase.states:h'] = phase.interpolate(ys=[100.0, 1e4], nodes='state_input') p['phase.states:v'] = phase.interpolate(ys=[135.964, 283.159], nodes='state_input') p['phase.states:gam'] = phase.interpolate(ys=[0.0, 0.0], nodes='state_input') p['phase.states:m'] = phase.interpolate(ys=[30e3, 29e3], nodes='state_input') # p['phase.controls:alpha'] = phase.interpolate(ys=[0.50, 0.50], nodes='all') return p
def test_circuit_voltage_source(self): from openmdao.api import ArmijoGoldsteinLS, Problem, IndepVarComp, BalanceComp, ExecComp from openmdao.api import NewtonSolver, DirectSolver, NonlinearRunOnce, LinearRunOnce from openmdao.test_suite.test_examples.test_circuit_analysis import Circuit p = Problem() model = p.model model.add_subsystem('ground', IndepVarComp('V', 0., units='V')) # replacing the fixed current source with a BalanceComp to represent a fixed Voltage source # model.add_subsystem('source', IndepVarComp('I', 0.1, units='A')) model.add_subsystem('batt', IndepVarComp('V', 1.5, units='V')) bal = model.add_subsystem('batt_balance', BalanceComp()) bal.add_balance('I', units='A', eq_units='V') model.add_subsystem('circuit', Circuit()) model.add_subsystem( 'batt_deltaV', 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 = NonlinearRunOnce() p.model.circuit.linear_solver = LinearRunOnce() # Put Newton at the top so it can also converge the new BalanceComp residual newton = p.model.nonlinear_solver = NewtonSolver() p.model.linear_solver = DirectSolver() newton.options['iprint'] = 2 newton.options['maxiter'] = 20 newton.options['solve_subsystems'] = True newton.linesearch = 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_rel_error(self, p['circuit.n1.V'], 1.5, 1e-5) assert_rel_error(self, p['circuit.n2.V'], 0.676232, 1e-5) assert_rel_error(self, p['circuit.R1.I'], 0.015, 1e-5) assert_rel_error(self, p['circuit.R2.I'], 8.23767999e-05, 1e-5) assert_rel_error(self, p['circuit.D1.I'], 8.23767999e-05, 1e-5)
def test_no_promotion_errors(self): """ Tests for error-handling for invalid variable names and keys. """ g = Group(assembled_jac_type='dense') g.linear_solver = DirectSolver(assemble_jac=True) g.add_subsystem('c', ExecComp('y=2*x')) p = Problem() model = p.model model.add_subsystem('g', g) p.setup() # ------------------------------------------------------------------- msg = '\'Group (<model>): Variable "{}" not found.\'' # inputs with self.assertRaises(KeyError) as ctx: p['x'] = 5.0 p.final_setup() self.assertEqual(str(ctx.exception), msg.format('x')) p._initial_condition_cache = {} with self.assertRaises(KeyError) as ctx: p['x'] self.assertEqual(str(ctx.exception), msg.format('x')) # outputs with self.assertRaises(KeyError) as ctx: p['y'] = 5.0 p.final_setup() self.assertEqual(str(ctx.exception), msg.format('y')) p._initial_condition_cache = {} with self.assertRaises(KeyError) as ctx: p['y'] self.assertEqual(str(ctx.exception), msg.format('y')) msg = '\'Variable name "{}" not found.\'' inputs, outputs, residuals = g.get_nonlinear_vectors() # inputs with self.assertRaisesRegex(KeyError, msg.format('x')): inputs['x'] = 5.0 with self.assertRaisesRegex(KeyError, msg.format('x')): inputs['x'] with self.assertRaisesRegex(KeyError, msg.format('g.c.x')): inputs['g.c.x'] = 5.0 with self.assertRaisesRegex(KeyError, msg.format('g.c.x')): inputs['g.c.x'] # outputs with self.assertRaisesRegex(KeyError, msg.format('y')): outputs['y'] = 5.0 with self.assertRaisesRegex(KeyError, msg.format('y')): outputs['y'] with self.assertRaisesRegex(KeyError, msg.format('g.c.y')): outputs['g.c.y'] = 5.0 with self.assertRaisesRegex(KeyError, msg.format('g.c.y')): outputs['g.c.y'] msg = r'Variable name pair \("{}", "{}"\) not found.' jac = g.linear_solver._assembled_jac # d(output)/d(input) with self.assertRaisesRegex(KeyError, msg.format('y', 'x')): jac['y', 'x'] = 5.0 with self.assertRaisesRegex(KeyError, msg.format('y', 'x')): jac['y', 'x'] # allow absolute keys now # with self.assertRaisesRegex(KeyError, msg.format('g.c.y', 'g.c.x')): # jac['g.c.y', 'g.c.x'] = 5.0 # with self.assertRaisesRegex(KeyError, msg.format('g.c.y', 'g.c.x')): # deriv = jac['g.c.y', 'g.c.x'] # d(output)/d(output) with self.assertRaisesRegex(KeyError, msg.format('y', 'y')): jac['y', 'y'] = 5.0 with self.assertRaisesRegex(KeyError, msg.format('y', 'y')): jac['y', 'y']
def test_with_promotion_errors(self): """ Tests for error-handling for invalid variable names and keys. """ c1 = IndepVarComp('x') c2 = ExecComp('y=2*x') c3 = ExecComp('z=3*x') g = Group(assembled_jac_type='dense') g.add_subsystem('c1', c1, promotes=['*']) g.add_subsystem('c2', c2, promotes=['*']) g.add_subsystem('c3', c3, promotes=['*']) g.linear_solver = DirectSolver(assemble_jac=True) model = Group() model.add_subsystem('g', g, promotes=['*']) p = Problem(model) p.setup() # Conclude setup but don't run model. p.final_setup() # ------------------------------------------------------------------- msg1 = 'Variable name "{}" not found.' msg2 = "The promoted name x is invalid because it refers to multiple inputs: " \ "[g.c2.x ,g.c3.x]. Access the value from the connected output variable x instead." inputs, outputs, residuals = g.get_nonlinear_vectors() # inputs with self.assertRaises(Exception) as context: inputs['x'] = 5.0 self.assertEqual(str(context.exception), msg2) with self.assertRaises(Exception) as context: self.assertEqual(inputs['x'], 5.0) self.assertEqual(str(context.exception), msg2) with self.assertRaisesRegex(KeyError, msg1.format('g.c2.x')): inputs['g.c2.x'] = 5.0 with self.assertRaisesRegex(KeyError, msg1.format('g.c2.x')): self.assertEqual(inputs['g.c2.x'], 5.0) # outputs with self.assertRaisesRegex(KeyError, msg1.format('g.c2.y')): outputs['g.c2.y'] = 5.0 with self.assertRaisesRegex(KeyError, msg1.format('g.c2.y')): self.assertEqual(outputs['g.c2.y'], 5.0) msg1 = r'Variable name pair \("{}", "{}"\) not found.' jac = g.linear_solver._assembled_jac # d(outputs)/d(inputs) with self.assertRaises(Exception) as context: jac['y', 'x'] = 5.0 self.assertEqual(str(context.exception), msg2) with self.assertRaises(Exception) as context: self.assertEqual(jac['y', 'x'], 5.0) self.assertEqual(str(context.exception), msg2)
ivc.add_output('T_0', 0.015, units='N',desc='Constant Thrust Value') #Building Model p = Problem() model = p.modelomponent is the basic building block of a model. You will always define components as a subclass of either ExplicitComponent or ImplicitComponent. Since our simple paraboloid function is explicit, we’ll use the ExplicitComponent. You see two methods defined: model.add_subsystem('init_cond', ivc, promotes=['*']) model.add_subsystem('comp', FullComp(), promotes=['*']) #Optimization Set-Up p.driver = ScipyOptimizeDriver() p.driver.options['optimizer'] = 'SLSQP' # p.driver.options['optimizer'] = 'COBYLA' p.driver.options model.linear_solver = DirectSolver(iprint=2) # model.add_design_var('eta_sa', lower = 0.01, upper=1) model.add_design_var('M_ps', lower=0.01, upper=100) model.add_constraint('con1',) model.add_objective('t_tot') #Case Recorder Setting recorder = SqliteRecorder('test.sql') p.driver.add_recorder(recorder) p.add_recorder(recorder) #Set-up and Run p.setup() p.set_solver_print(2) p.run_driver()
def test_csc_masking(self): class CCBladeResidualComp(ImplicitComponent): def initialize(self): self.options.declare('num_nodes', types=int) self.options.declare('num_radial', types=int) def setup(self): num_nodes = self.options['num_nodes'] num_radial = self.options['num_radial'] self.add_input('chord', shape=(1, num_radial)) self.add_input('theta', shape=(1, num_radial)) self.add_output('phi', lower=-0.5 * np.pi, upper=0.0, shape=(num_nodes, num_radial)) self.add_output('Tp', shape=(num_nodes, num_radial)) of_names = ('phi', 'Tp') row_col = np.arange(num_radial) for name in of_names: self.declare_partials(name, 'chord', rows=row_col, cols=row_col) self.declare_partials(name, 'theta', rows=row_col, cols=row_col, val=0.0) self.declare_partials(name, 'phi', rows=row_col, cols=row_col) self.declare_partials('Tp', 'Tp', rows=row_col, cols=row_col, val=1.) def linearize(self, inputs, outputs, partials): partials['phi', 'chord'] = np.array([1., 2, 3, 4]) partials['phi', 'phi'] = np.array([5., 6, 7, 8]) partials['Tp', 'chord'] = np.array([9., 10, 11, 12]) partials['Tp', 'phi'] = np.array([13., 14, 15, 16]) prob = Problem() model = prob.model comp = IndepVarComp() comp.add_output('chord', val=np.ones((4, ))) model.add_subsystem('indep_var_comp', comp, promotes=['*']) comp = CCBladeResidualComp(num_nodes=1, num_radial=4, assembled_jac_type='csc') comp.linear_solver = DirectSolver(assemble_jac=True) model.add_subsystem('ccblade_comp', comp, promotes_inputs=['chord'], promotes_outputs=['Tp']) prob.setup(mode='fwd') prob.run_model() totals = prob.compute_totals(of=['Tp'], wrt=['chord'], return_format='array') expected = np.array([[-6.4, 0., 0., 0.], [0., -5.33333333, 0., 0.], [0., 0., -4.57142857, 0.], [0., 0., 0., -4.]]) np.testing.assert_allclose(totals, expected)
def test_two_burn_orbit_raise_for_docs(self): import numpy as np import matplotlib.pyplot as plt from openmdao.api import Problem, pyOptSparseDriver, DirectSolver, SqliteRecorder from openmdao.utils.assert_utils import assert_rel_error from openmdao.utils.general_utils import set_pyoptsparse_opt from dymos import Phase, Trajectory from dymos.examples.finite_burn_orbit_raise.finite_burn_eom import FiniteBurnODE traj = Trajectory() p = Problem(model=traj) p.driver = pyOptSparseDriver() _, optimizer = set_pyoptsparse_opt('SNOPT', fallback=False) p.driver.options['optimizer'] = 'SNOPT' p.driver.options['dynamic_simul_derivs'] = True traj.add_design_parameter('c', opt=False, val=1.5) # First Phase (burn) burn1 = Phase('gauss-lobatto', ode_class=FiniteBurnODE, num_segments=10, transcription_order=3, compressed=True) burn1 = traj.add_phase('burn1', burn1) burn1.set_time_options(fix_initial=True, duration_bounds=(.5, 10)) burn1.set_state_options('r', fix_initial=True, fix_final=False, defect_scaler=100.0) burn1.set_state_options('theta', fix_initial=True, fix_final=False, defect_scaler=100.0) burn1.set_state_options('vr', fix_initial=True, fix_final=False, defect_scaler=100.0) burn1.set_state_options('vt', fix_initial=True, fix_final=False, defect_scaler=100.0) burn1.set_state_options('accel', fix_initial=True, fix_final=False) burn1.set_state_options('deltav', fix_initial=True, fix_final=False) burn1.add_control('u1', rate_continuity=True, rate2_continuity=True, units='deg', scaler=0.01, rate_continuity_scaler=0.001, rate2_continuity_scaler=0.001, lower=-30, upper=30) # Second Phase (Coast) coast = Phase('gauss-lobatto', ode_class=FiniteBurnODE, num_segments=10, transcription_order=3, compressed=True) traj.add_phase('coast', coast) coast.set_time_options(initial_bounds=(0.5, 20), duration_bounds=(.5, 10), duration_ref=10) coast.set_state_options('r', fix_initial=False, fix_final=False, defect_scaler=100.0) coast.set_state_options('theta', fix_initial=False, fix_final=False, defect_scaler=100.0) coast.set_state_options('vr', fix_initial=False, fix_final=False, defect_scaler=100.0) coast.set_state_options('vt', fix_initial=False, fix_final=False, defect_scaler=100.0) coast.set_state_options('accel', fix_initial=True, fix_final=True) coast.set_state_options('deltav', fix_initial=False, fix_final=False) coast.add_control('u1', opt=False, val=0.0, units='deg') # Third Phase (burn) burn2 = Phase('gauss-lobatto', ode_class=FiniteBurnODE, num_segments=10, transcription_order=3, compressed=True) traj.add_phase('burn2', burn2) burn2.set_time_options(initial_bounds=(0.5, 20), duration_bounds=(.5, 10), initial_ref=10) burn2.set_state_options('r', fix_initial=False, fix_final=True, defect_scaler=100.0) burn2.set_state_options('theta', fix_initial=False, fix_final=False, defect_scaler=100.0) burn2.set_state_options('vr', fix_initial=False, fix_final=True, defect_scaler=100.0) burn2.set_state_options('vt', fix_initial=False, fix_final=True, defect_scaler=100.0) burn2.set_state_options('accel', fix_initial=False, fix_final=False, defect_scaler=1.0) burn2.set_state_options('deltav', fix_initial=False, fix_final=False, defect_scaler=1.0) burn2.add_control('u1', rate_continuity=True, rate2_continuity=True, units='deg', scaler=0.01, rate_continuity_scaler=0.001, rate2_continuity_scaler=0.001, lower=-30, upper=30) burn2.add_objective('deltav', loc='final', scaler=1.0) # Link Phases traj.link_phases(phases=['burn1', 'coast', 'burn2'], vars=['time', 'r', 'theta', 'vr', 'vt', 'deltav']) traj.link_phases(phases=['burn1', 'burn2'], vars=['accel']) # Finish Problem Setup p.model.options['assembled_jac_type'] = 'csc' p.model.linear_solver = DirectSolver(assemble_jac=True) p.driver.add_recorder( SqliteRecorder('two_burn_orbit_raise_example_for_docs.db')) p.setup(check=True) # Set Initial Guesses p.set_val('design_parameters:c', value=1.5) p.set_val('burn1.t_initial', value=0.0) p.set_val('burn1.t_duration', value=2.25) p.set_val('burn1.states:r', value=burn1.interpolate(ys=[1, 1.5], nodes='state_input')) p.set_val('burn1.states:theta', value=burn1.interpolate(ys=[0, 1.7], nodes='state_input')) p.set_val('burn1.states:vr', value=burn1.interpolate(ys=[0, 0], nodes='state_input')) p.set_val('burn1.states:vt', value=burn1.interpolate(ys=[1, 1], nodes='state_input')) p.set_val('burn1.states:accel', value=burn1.interpolate(ys=[0.1, 0], nodes='state_input')) p.set_val( 'burn1.states:deltav', value=burn1.interpolate(ys=[0, 0.1], nodes='state_input'), ) p.set_val('burn1.controls:u1', value=burn1.interpolate(ys=[-3.5, 13.0], nodes='control_input')) p.set_val('coast.t_initial', value=2.25) p.set_val('coast.t_duration', value=3.0) p.set_val('coast.states:r', value=coast.interpolate(ys=[1.3, 1.5], nodes='state_input')) p.set_val('coast.states:theta', value=coast.interpolate(ys=[2.1767, 1.7], nodes='state_input')) p.set_val('coast.states:vr', value=coast.interpolate(ys=[0.3285, 0], nodes='state_input')) p.set_val('coast.states:vt', value=coast.interpolate(ys=[0.97, 1], nodes='state_input')) p.set_val('coast.states:accel', value=coast.interpolate(ys=[0, 0], nodes='state_input')) p.set_val('coast.controls:u1', value=coast.interpolate(ys=[0, 0], nodes='control_input')) p.set_val('burn2.t_initial', value=5.25) p.set_val('burn2.t_duration', value=1.75) p.set_val('burn2.states:r', value=burn2.interpolate(ys=[1, 3], nodes='state_input')) p.set_val('burn2.states:theta', value=burn2.interpolate(ys=[0, 4.0], nodes='state_input')) p.set_val('burn2.states:vr', value=burn2.interpolate(ys=[0, 0], nodes='state_input')) p.set_val('burn2.states:vt', value=burn2.interpolate(ys=[1, np.sqrt(1 / 3)], nodes='state_input')) p.set_val('burn2.states:accel', value=burn2.interpolate(ys=[0.1, 0], nodes='state_input')) p.set_val('burn2.states:deltav', value=burn2.interpolate(ys=[0.1, 0.2], nodes='state_input')) p.set_val('burn2.controls:u1', value=burn2.interpolate(ys=[1, 1], nodes='control_input')) p.run_driver() assert_rel_error(self, traj.get_values('deltav', flat=True)[-1], 0.3995, tolerance=2.0E-3) # Plot results exp_out = traj.simulate(times=50, num_procs=3) fig = plt.figure(figsize=(8, 4)) fig.suptitle('Two Burn Orbit Raise Solution') ax_u1 = plt.subplot2grid((2, 2), (0, 0)) ax_deltav = plt.subplot2grid((2, 2), (1, 0)) ax_xy = plt.subplot2grid((2, 2), (0, 1), rowspan=2) span = np.linspace(0, 2 * np.pi, 100) ax_xy.plot(np.cos(span), np.sin(span), 'k--', lw=1) ax_xy.plot(3 * np.cos(span), 3 * np.sin(span), 'k--', lw=1) ax_xy.set_xlim(-4.5, 4.5) ax_xy.set_ylim(-4.5, 4.5) ax_xy.set_xlabel('x ($R_e$)') ax_xy.set_ylabel('y ($R_e$)') ax_u1.set_xlabel('time ($TU$)') ax_u1.set_ylabel('$u_1$ ($deg$)') ax_u1.grid(True) ax_deltav.set_xlabel('time ($TU$)') ax_deltav.set_ylabel('${\Delta}v$ ($DU/TU$)') ax_deltav.grid(True) t_sol = traj.get_values('time') x_sol = traj.get_values('pos_x') y_sol = traj.get_values('pos_y') dv_sol = traj.get_values('deltav') u1_sol = traj.get_values('u1', units='deg') t_exp = exp_out.get_values('time') x_exp = exp_out.get_values('pos_x') y_exp = exp_out.get_values('pos_y') dv_exp = exp_out.get_values('deltav') u1_exp = exp_out.get_values('u1', units='deg') for phase_name in ['burn1', 'coast', 'burn2']: ax_u1.plot(t_sol[phase_name], u1_sol[phase_name], 'ro', ms=3) ax_u1.plot(t_exp[phase_name], u1_exp[phase_name], 'b-') ax_deltav.plot(t_sol[phase_name], dv_sol[phase_name], 'ro', ms=3) ax_deltav.plot(t_exp[phase_name], dv_exp[phase_name], 'b-') ax_xy.plot(x_sol[phase_name], y_sol[phase_name], 'ro', ms=3, label='implicit' if phase_name == 'burn1' else None) ax_xy.plot(x_exp[phase_name], y_exp[phase_name], 'b-', label='explicit' if phase_name == 'burn1' else None) plt.show()
def min_time_climb(optimizer='SLSQP', num_seg=3, transcription='gauss-lobatto', transcription_order=3, top_level_jacobian='csc', simul_derivs=True, force_alloc_complex=False): p = Problem(model=Group()) p.driver = pyOptSparseDriver() p.driver.options['optimizer'] = optimizer if simul_derivs: p.driver.options['dynamic_simul_derivs'] = True if optimizer == 'SNOPT': p.driver.opt_settings['Major iterations limit'] = 1000 p.driver.opt_settings['iSumm'] = 6 p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-6 p.driver.opt_settings['Major optimality tolerance'] = 1.0E-6 p.driver.opt_settings['Function precision'] = 1.0E-6 p.driver.opt_settings['Linesearch tolerance'] = 0.10 p.driver.opt_settings['Major step limit'] = 0.5 # p.driver.opt_settings['Verify level'] = 3 phase = Phase(transcription, ode_class=MinTimeClimbODE, num_segments=num_seg, compressed=True, transcription_order=transcription_order) p.model.add_subsystem('phase0', phase) phase.set_time_options(fix_initial=True, duration_bounds=(50, 400), duration_ref=100.0) phase.set_state_options('r', fix_initial=True, lower=0, upper=1.0E6, scaler=1.0E-3, defect_scaler=1.0E-2, units='m') phase.set_state_options('h', fix_initial=True, lower=0, upper=20000.0, scaler=1.0E-3, defect_scaler=1.0E-3, units='m') phase.set_state_options('v', fix_initial=True, lower=10.0, scaler=1.0E-2, defect_scaler=1.0E-2, units='m/s') phase.set_state_options('gam', fix_initial=True, lower=-1.5, upper=1.5, ref=1.0, defect_scaler=1.0, units='rad') phase.set_state_options('m', fix_initial=True, lower=10.0, upper=1.0E5, scaler=1.0E-3, defect_scaler=1.0E-3) phase.add_control('alpha', units='deg', lower=-8.0, upper=8.0, scaler=1.0, continuity=True, rate_continuity=True, rate2_continuity=False) phase.add_design_parameter('S', val=49.2386, units='m**2', opt=False) phase.add_design_parameter('Isp', val=1600.0, units='s', opt=False) phase.add_design_parameter('throttle', val=1.0, opt=False) phase.add_boundary_constraint('h', loc='final', equals=20000, scaler=1.0E-3, units='m') phase.add_boundary_constraint('aero.mach', loc='final', equals=1.0, units=None) phase.add_boundary_constraint('gam', loc='final', equals=0.0, units='rad') phase.add_path_constraint(name='h', lower=100.0, upper=20000, ref=20000) phase.add_path_constraint(name='aero.mach', lower=0.1, upper=1.8) phase.add_path_constraint(name='alpha', lower=-8, upper=8) # Minimize time at the end of the phase phase.add_objective('time', loc='final') p.model.options['assembled_jac_type'] = top_level_jacobian.lower() p.model.linear_solver = DirectSolver(assemble_jac=True) p.setup(check=True, force_alloc_complex=force_alloc_complex) p['phase0.t_initial'] = 0.0 p['phase0.t_duration'] = 298.46902 p['phase0.states:r'] = phase.interpolate(ys=[0.0, 111319.54], nodes='state_input') p['phase0.states:h'] = phase.interpolate(ys=[100.0, 20000.0], nodes='state_input') p['phase0.states:v'] = phase.interpolate(ys=[135.964, 283.159], nodes='state_input') p['phase0.states:gam'] = phase.interpolate(ys=[0.0, 0.0], nodes='state_input') p['phase0.states:m'] = phase.interpolate(ys=[19030.468, 16841.431], nodes='state_input') p['phase0.controls:alpha'] = phase.interpolate(ys=[0.0, 0.0], nodes='control_input') p.run_driver() if SHOW_PLOTS: exp_out = phase.simulate(times=np.linspace(0, p['phase0.t_duration'], 100)) import matplotlib.pyplot as plt plt.plot(phase.get_values('time'), phase.get_values('h'), 'ro') plt.plot(exp_out.get_values('time'), exp_out.get_values('h'), 'b-') plt.xlabel('time (s)') plt.ylabel('altitude (m)') plt.figure() plt.plot(phase.get_values('v'), phase.get_values('h'), 'ro') plt.plot(exp_out.get_values('v'), exp_out.get_values('h'), 'b-') plt.xlabel('airspeed (m/s)') plt.ylabel('altitude (m)') plt.figure() plt.plot(phase.get_values('time'), phase.get_values('alpha'), 'ro') plt.plot(exp_out.get_values('time'), exp_out.get_values('alpha'), 'b-') plt.xlabel('time (s)') plt.ylabel('alpha (rad)') plt.figure() plt.plot(phase.get_values('time'), phase.get_values('prop.thrust', units='lbf'), 'ro') plt.plot(exp_out.get_values('time'), exp_out.get_values('prop.thrust', units='lbf'), 'b-') plt.xlabel('time (s)') plt.ylabel('thrust (lbf)') plt.show() return p
promotes_inputs=['*'], promotes_outputs=['*']) self.connect('T_motor_initial', 'v0v1.propmodel.motorheatsink.T_initial') self.connect('T_res_initial', 'v0v1.propmodel.reservoir.T_initial') if __name__ == "__main__": num_nodes = 11 prob = Problem() prob.model = ElectricTBMAnalysisGroup() prob.model.nonlinear_solver = NewtonSolver(iprint=2) prob.model.options['assembled_jac_type'] = 'csc' prob.model.linear_solver = DirectSolver(assemble_jac=True) prob.model.nonlinear_solver.options['solve_subsystems'] = True prob.model.nonlinear_solver.options['maxiter'] = 20 prob.model.nonlinear_solver.options['atol'] = 1e-8 prob.model.nonlinear_solver.options['rtol'] = 1e-8 prob.model.nonlinear_solver.linesearch = BoundsEnforceLS( bound_enforcement='scalar', print_bound_enforce=False) prob.model.add_design_var('mission_range', lower=100, upper=300, scaler=1e-2) prob.model.add_constraint('descent.propmodel.batt1.SOC_final', lower=0.0) prob.model.add_objective('mission_range', scaler=-1.0) prob.driver = ScipyOptimizeDriver() prob.driver.options['dynamic_simul_derivs'] = True
prob_ref['overhang'] = 8.5 prob_ref['drive.distance_hub2mb'] = 3.5 prob_ref['significant_wave_height'] = 4.52 prob_ref['significant_wave_period'] = 9.45 prob_ref['monopile'] = True prob_ref['foundation_height'] = -30. prob_ref['water_depth'] = 30. prob_ref['suctionpile_depth'] = 45. prob_ref['wind_reference_height'] = 150. prob_ref['hub_height'] = 150. prob_ref['tower_section_height'] = np.array([10., 10., 10., 10., 10., 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 13.6679]) prob_ref['tower_outer_diameter'] = np.array([10., 10., 10., 10., 10., 10., 9.8457, 9.47, 9.041, 8.5638, 8.1838, 8.0589, 7.9213, 7.8171, 7.3356, 6.5]) prob_ref['tower_wall_thickness'] = np.array([0.1, 0.1, 0.1, 0.1, 0.1, 0.0431, 0.041, 0.0397, 0.0384, 0.037, 0.0348, 0.0313, 0.0279, 0.0248, 0.0299]) prob_ref.model.nonlinear_solver = NonlinearRunOnce() prob_ref.model.linear_solver = DirectSolver() print('Running at Initial Position:') prob_ref.run_driver() #prob_ref.model.list_inputs(units=True) #refBlade.write_ontology(fname_output, prob_ref['blade_out'], refBlade.wt_ref) print(prob_ref['hub_height']) print(prob_ref['rna_mass']) print('mIxx', prob_ref['tow.pre.mIxx']) print('mIyy', prob_ref['tow.pre.mIyy']) print('mIzz', prob_ref['tow.pre.mIzz']) print('mIxy', prob_ref['tow.pre.mIxy']) print('mIxz', prob_ref['tow.pre.mIxz']) print('mIyz', prob_ref['tow.pre.mIyz']) print('rna_F', prob_ref['tow.pre.rna_F']) print('rna_M', prob_ref['tow.pre.rna_M'])
def test_record_solver_linear_direct_solver(self, m): self.setup_endpoints(m) recorder = WebRecorder(self._accepted_token, suppress_output=True) self.setup_sellar_model() self.prob.model.nonlinear_solver = NewtonSolver() # used for analytic derivatives self.prob.model.nonlinear_solver.linear_solver = DirectSolver() linear_solver = self.prob.model.nonlinear_solver.linear_solver linear_solver.recording_options['record_abs_error'] = True linear_solver.recording_options['record_rel_error'] = True linear_solver.recording_options['record_solver_residuals'] = True self.prob.model.nonlinear_solver.linear_solver.add_recorder(recorder) self.prob.setup(check=False) t0, t1 = run_driver(self.prob) expected_solver_output = [ { 'name': 'px.x', 'values': [0.0] }, { 'name': 'pz.z', 'values': [0.0, 0.0] }, { 'name': 'd1.y1', 'values': [0.00045069] }, { 'name': 'd2.y2', 'values': [-0.00225346] }, { 'name': 'obj_cmp.obj', 'values': [0.00045646] }, { 'name': 'con_cmp1.con1', 'values': [-0.00045069] }, { 'name': 'con_cmp2.con2', 'values': [-0.00225346] }, ] expected_solver_residuals = [ { 'name': 'px.x', 'values': [0.0] }, { 'name': 'pz.z', 'values': [-0., -0.] }, { 'name': 'd1.y1', 'values': [0.0] }, { 'name': 'd2.y2', 'values': [-0.00229801] }, { 'name': 'obj_cmp.obj', 'values': [5.75455956e-06] }, { 'name': 'con_cmp1.con1', 'values': [-0.] }, { 'name': 'con_cmp2.con2', 'values': [-0.] }, ] solver_iteration = json.loads(self.solver_iterations) self.assertAlmostEqual(0.0, solver_iteration['abs_err']) self.assertAlmostEqual(0.0, solver_iteration['rel_err']) for o in expected_solver_output: self.assert_array_close(o, solver_iteration['solver_output']) for r in expected_solver_residuals: self.assert_array_close(r, solver_iteration['solver_residuals'])
def test_sellar_specify_linear_direct_solver(self): prob = Problem() model = prob.model model.add_subsystem('px', IndepVarComp('x', 1.0), promotes=['x']) model.add_subsystem('pz', IndepVarComp('z', np.array([5.0, 2.0])), promotes=['z']) proms = [ 'x', 'z', 'y1', 'state_eq.y2_actual', 'state_eq.y2_command', 'd1.y2', 'd2.y2' ] sub = model.add_subsystem('sub', Group(), promotes=proms) subgrp = sub.add_subsystem( 'state_eq_group', Group(), promotes=['state_eq.y2_actual', 'state_eq.y2_command']) subgrp.linear_solver = ScipyKrylov() subgrp.add_subsystem('state_eq', StateConnection()) sub.add_subsystem('d1', SellarDis1withDerivatives(), promotes=['x', 'z', 'y1']) sub.add_subsystem('d2', SellarDis2withDerivatives(), promotes=['z', 'y1']) model.connect('state_eq.y2_command', 'd1.y2') model.connect('d2.y2', 'state_eq.y2_actual') model.add_subsystem('obj_cmp', ExecComp('obj = x**2 + z[1] + y1 + exp(-y2)', z=np.array([0.0, 0.0]), x=0.0, y1=0.0, y2=0.0), promotes=['x', 'z', 'y1', 'obj']) model.connect('d2.y2', 'obj_cmp.y2') model.add_subsystem('con_cmp1', ExecComp('con1 = 3.16 - y1'), promotes=['con1', 'y1']) model.add_subsystem('con_cmp2', ExecComp('con2 = y2 - 24.0'), promotes=['con2']) model.connect('d2.y2', 'con_cmp2.y2') model.nonlinear_solver = NewtonSolver() # Use bad settings for this one so that problem doesn't converge. # That way, we test that we are really using Newton's Lin Solver # instead. sub.linear_solver = ScipyKrylov() sub.linear_solver.options['maxiter'] = 1 # The good solver model.nonlinear_solver.linear_solver = DirectSolver() prob.set_solver_print(level=0) prob.setup(check=False) prob.run_model() assert_rel_error(self, prob['y1'], 25.58830273, .00001) assert_rel_error(self, prob['state_eq.y2_command'], 12.05848819, .00001) # Make sure we aren't iterating like crazy self.assertLess(model.nonlinear_solver._iter_count, 8) self.assertEqual(model.linear_solver._iter_count, 0)
def test_solve_linear_ksp_precon_left(self): """Solve implicit system with PETScKrylov using a preconditioner.""" group = TestImplicitGroup(lnSolverClass=PETScKrylov) precon = group.linear_solver.precon = DirectSolver(assemble_jac=False) group.linear_solver.options['precon_side'] = 'left' group.linear_solver.options['ksp_type'] = 'richardson' p = Problem(group) p.setup(check=False) p.set_solver_print(level=0) # Conclude setup but don't run model. p.final_setup() d_inputs, d_outputs, d_residuals = group.get_linear_vectors() # forward d_residuals.set_const(1.0) d_outputs.set_const(0.0) group.run_linearize() group.run_solve_linear(['linear'], 'fwd') output = d_outputs._data assert_rel_error(self, output, group.expected_solution, 1e-15) # reverse d_outputs.set_const(1.0) d_residuals.set_const(0.0) group.run_linearize() group.run_solve_linear(['linear'], 'rev') output = d_residuals._data assert_rel_error(self, output, group.expected_solution, 3e-15) # test the direct solver and make sure KSP correctly recurses for _linearize precon = group.linear_solver.precon = DirectSolver(assemble_jac=False) group.linear_solver.options['precon_side'] = 'left' group.linear_solver.options['ksp_type'] = 'richardson' p.setup(check=False) # Conclude setup but don't run model. p.final_setup() d_inputs, d_outputs, d_residuals = group.get_linear_vectors() # forward d_residuals.set_const(1.0) d_outputs.set_const(0.0) group.linear_solver._linearize() group.run_solve_linear(['linear'], 'fwd') output = d_outputs._data assert_rel_error(self, output, group.expected_solution, 1e-15) # reverse d_outputs.set_const(1.0) d_residuals.set_const(0.0) group.linear_solver._linearize() group.run_solve_linear(['linear'], 'rev') output = d_residuals._data assert_rel_error(self, output, group.expected_solution, 3e-15)
def test_group_assembled_jac_with_ext_mat(self): class TwoSellarDis1(ExplicitComponent): """ Component containing Discipline 1 -- no derivatives version. """ def setup(self): self.add_input('z', val=np.zeros(2)) self.add_input('x', val=np.zeros(2)) self.add_input('y2', val=np.ones(2)) self.add_output('y1', val=np.ones(2)) self.declare_partials(of='*', wrt='*') def compute(self, inputs, outputs): z1 = inputs['z'][0] z2 = inputs['z'][1] x1 = inputs['x'] y2 = inputs['y2'] outputs['y1'][0] = z1**2 + z2 + x1[0] - 0.2 * y2[0] outputs['y1'][1] = z1**2 + z2 + x1[0] - 0.2 * y2[0] def compute_partials(self, inputs, partials): """ Jacobian for Sellar discipline 1. """ partials['y1', 'y2'] = np.array([[-0.2, 0.], [0., -0.2]]) partials['y1', 'z'] = np.array([[2.0 * inputs['z'][0], 1.0], [2.0 * inputs['z'][0], 1.0]]) partials['y1', 'x'] = np.eye(2) class TwoSellarDis2(ExplicitComponent): def setup(self): self.add_input('z', val=np.zeros(2)) self.add_input('y1', val=np.ones(2)) self.add_output('y2', val=np.ones(2)) self.declare_partials('*', '*', method='fd') def compute(self, inputs, outputs): z1 = inputs['z'][0] z2 = inputs['z'][1] y1 = inputs['y1'] # Note: this may cause some issues. However, y1 is constrained to be # above 3.16, so lets just let it converge, and the optimizer will # throw it out if y1[0].real < 0.0: y1[0] *= -1 if y1[1].real < 0.0: y1[1] *= -1 outputs['y2'][0] = y1[0]**.5 + z1 + z2 outputs['y2'][1] = y1[1]**.5 + z1 + z2 def compute_partials(self, inputs, J): y1 = inputs['y1'] if y1[0].real < 0.0: y1[0] *= -1 if y1[1].real < 0.0: y1[1] *= -1 J['y2', 'y1'] = np.array([[.5 * y1[0]**-.5, 0.], [0., .5 * y1[1]**-.5]]) J['y2', 'z'] = np.array([[1.0, 1.0], [1.0, 1.0]]) prob = Problem() model = prob.model model.add_subsystem('px', IndepVarComp('x', np.array([1.0, 1.0])), promotes=['x']) model.add_subsystem('pz', IndepVarComp('z', np.array([5.0, 2.0])), promotes=['z']) sup = model.add_subsystem('sup', Group(), promotes=['*']) sub1 = sup.add_subsystem('sub1', Group(), promotes=['*']) sub2 = sup.add_subsystem('sub2', Group(), promotes=['*']) d1 = sub1.add_subsystem('d1', TwoSellarDis1(), promotes=['x', 'z', 'y1', 'y2']) sub2.add_subsystem('d2', TwoSellarDis2(), promotes=['z', 'y1', 'y2']) model.add_subsystem('con_cmp1', ExecComp('con1 = 3.16 - y1[0] - y1[1]', y1=np.array([0.0, 0.0])), promotes=['con1', 'y1']) model.add_subsystem('con_cmp2', ExecComp('con2 = y2[0] + y2[1] - 24.0', y2=np.array([0.0, 0.0])), promotes=['con2', 'y2']) model.linear_solver = LinearBlockGS() sup.linear_solver = LinearBlockGS() sub1.linear_solver = DirectSolver(assemble_jac=True) sub2.linear_solver = DirectSolver(assemble_jac=True) prob.set_solver_print(level=0) prob.setup(check=False, mode='rev') prob.run_model() of = ['con1', 'con2'] wrt = ['x', 'z'] # Make sure we don't get a size mismatch. derivs = prob.compute_totals(of=of, wrt=wrt)
def test_cruise_results(self): p = Problem(model=Group()) if optimizer == 'SNOPT': p.driver = pyOptSparseDriver() p.driver.options['optimizer'] = optimizer p.driver.options['dynamic_simul_derivs'] = True p.driver.opt_settings['Major iterations limit'] = 100 p.driver.opt_settings['Major step limit'] = 0.05 p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-6 p.driver.opt_settings['Major optimality tolerance'] = 1.0E-6 p.driver.opt_settings["Linesearch tolerance"] = 0.10 p.driver.opt_settings['iSumm'] = 6 p.driver.opt_settings['Verify level'] = 3 else: p.driver = ScipyOptimizeDriver() p.driver.options['dynamic_simul_derivs'] = True phase = Phase('gauss-lobatto', ode_class=AircraftODE, num_segments=1, transcription_order=13) # Pass Reference Area from an external source assumptions = p.model.add_subsystem('assumptions', IndepVarComp()) assumptions.add_output('S', val=427.8, units='m**2') assumptions.add_output('mass_empty', val=1.0, units='kg') assumptions.add_output('mass_payload', val=1.0, units='kg') p.model.add_subsystem('phase0', phase) phase.set_time_options(initial_bounds=(0, 0), duration_bounds=(3600, 3600), duration_ref=3600) phase.set_state_options('range', units='km', fix_initial=True, fix_final=False, scaler=0.01, defect_scaler=0.01) phase.set_state_options('mass_fuel', fix_final=True, upper=20000.0, lower=0.0, scaler=1.0E-4, defect_scaler=1.0E-2) phase.add_control('alt', units='km', opt=False, rate_param='climb_rate') phase.add_control('mach', units=None, opt=False) phase.add_input_parameter('S', units='m**2') phase.add_input_parameter('mass_empty', units='kg') phase.add_input_parameter('mass_payload', units='kg') phase.add_path_constraint('propulsion.tau', lower=0.01, upper=1.0) p.model.connect('assumptions.S', 'phase0.input_parameters:S') p.model.connect('assumptions.mass_empty', 'phase0.input_parameters:mass_empty') p.model.connect('assumptions.mass_payload', 'phase0.input_parameters:mass_payload') phase.add_objective('time', loc='final', ref=3600) p.model.linear_solver = DirectSolver(assemble_jac=True) p.model.options['assembled_jac_type'] = 'csc' p.setup() p['phase0.t_initial'] = 0.0 p['phase0.t_duration'] = 1.515132 * 3600.0 p['phase0.states:range'] = phase.interpolate(ys=(0, 1296.4), nodes='state_input') p['phase0.states:mass_fuel'] = phase.interpolate(ys=(12236.594555, 0), nodes='state_input') p['phase0.controls:mach'] = 0.8 p['phase0.controls:alt'] = 5.0 p['assumptions.S'] = 427.8 p['assumptions.mass_empty'] = 0.15E6 p['assumptions.mass_payload'] = 84.02869 * 400 p.run_driver() tas = phase.get_values('tas_comp.TAS', units='m/s') time = phase.get_values('time', units='s') range = phase.get_values('range', units='m') assert_rel_error(self, range, tas * time, tolerance=1.0E-9)
def test_assembled_jacobian_unsupported_cases(self): class ParaboloidApply(ImplicitComponent): def setup(self): self.add_input('x', val=0.0) self.add_input('y', val=0.0) self.add_output('f_xy', val=0.0) def linearize(self, inputs, outputs, jacobian): return def apply_linear(self, inputs, outputs, d_inputs, d_outputs, d_residuals, mode): d_residuals['x'] += ( np.exp(outputs['x']) - 2 * inputs['a']**2 * outputs['x']) * d_outputs['x'] d_residuals['x'] += (-2 * inputs['a'] * outputs['x']**2) * d_inputs['a'] # One level deep prob = Problem() model = prob.model = Group(assembled_jac_type='dense') model.linear_solver = DirectSolver(assemble_jac=True) model.add_subsystem('p1', IndepVarComp('x', val=1.0)) model.add_subsystem('p2', IndepVarComp('y', val=1.0)) model.add_subsystem('comp', ParaboloidApply()) model.connect('p1.x', 'comp.x') model.connect('p2.y', 'comp.y') prob.setup() msg = "AssembledJacobian not supported for matrix-free subcomponent." with self.assertRaisesRegex(Exception, msg): prob.run_model() # Nested prob = Problem() model = prob.model = Group(assembled_jac_type='dense') model.linear_solver = DirectSolver(assemble_jac=True) sub = model.add_subsystem('sub', Group()) model.add_subsystem('p1', IndepVarComp('x', val=1.0)) model.add_subsystem('p2', IndepVarComp('y', val=1.0)) sub.add_subsystem('comp', ParaboloidApply()) model.connect('p1.x', 'sub.comp.x') model.connect('p2.y', 'sub.comp.y') prob.setup() msg = "AssembledJacobian not supported for matrix-free subcomponent." with self.assertRaisesRegex(Exception, msg): prob.run_model() # Try a component that is derived from a matrix-free one class FurtherDerived(ParaboloidApply): def do_nothing(self): pass prob = Problem() model = prob.model = Group(assembled_jac_type='dense') model.linear_solver = DirectSolver(assemble_jac=True) model.add_subsystem('p1', IndepVarComp('x', val=1.0)) model.add_subsystem('p2', IndepVarComp('y', val=1.0)) model.add_subsystem('comp', FurtherDerived()) model.connect('p1.x', 'comp.x') model.connect('p2.y', 'comp.y') prob.setup() msg = "AssembledJacobian not supported for matrix-free subcomponent." with self.assertRaisesRegex(Exception, msg): prob.run_model() # Make sure regular comps don't give an error. prob = Problem() model = prob.model = Group(assembled_jac_type='dense') model.linear_solver = DirectSolver(assemble_jac=True) model.add_subsystem('p1', IndepVarComp('x', val=1.0)) model.add_subsystem('p2', IndepVarComp('y', val=1.0)) model.add_subsystem('comp', Paraboloid()) model.connect('p1.x', 'comp.x') model.connect('p2.y', 'comp.y') prob.setup() prob.final_setup() class ParaboloidJacVec(Paraboloid): def linearize(self, inputs, outputs, jacobian): return def compute_jacvec_product(self, inputs, d_inputs, d_outputs, d_residuals, mode): d_residuals['x'] += ( np.exp(outputs['x']) - 2 * inputs['a']**2 * outputs['x']) * d_outputs['x'] d_residuals['x'] += (-2 * inputs['a'] * outputs['x']**2) * d_inputs['a'] # One level deep prob = Problem() model = prob.model = Group(assembled_jac_type='dense') model.linear_solver = DirectSolver(assemble_jac=True) model.add_subsystem('p1', IndepVarComp('x', val=1.0)) model.add_subsystem('p2', IndepVarComp('y', val=1.0)) model.add_subsystem('comp', ParaboloidJacVec()) model.connect('p1.x', 'comp.x') model.connect('p2.y', 'comp.y') prob.setup() msg = "AssembledJacobian not supported for matrix-free subcomponent." with self.assertRaisesRegex(Exception, msg): prob.run_model()
def test_nested_promotion_errors(self): """ Tests for error-handling for promoted input variable names. """ c1 = IndepVarComp('x') c2 = ExecComp('y=2*x') c3 = ExecComp('z=3*x') g = Group(assembled_jac_type='dense') g.add_subsystem('c2', c2, promotes=['*']) g.add_subsystem('c3', c3, promotes=['*']) g.linear_solver = DirectSolver(assemble_jac=True) model = Group() model.add_subsystem('c1', c1, promotes=['*']) model.add_subsystem('g', g) p = Problem(model) p.setup() # ------------------------------------------------------------------- msg1 = "The promoted name g.x is invalid because it refers to multiple inputs: " \ "[g.c2.x, g.c3.x] that are not connected to an output variable." # inputs (g.x is not connected) # with self.assertRaisesRegex(RuntimeError, msg1.format('g.x')): with self.assertRaises(Exception) as context: p['g.x'] = 5.0 p.final_setup() self.assertEqual(str(context.exception), msg1) # Repeat test for post final_setup when vectors are allocated. p = Problem(model) p.setup() p.final_setup() # ------------------------------------------------------------------- # inputs (g.x is not connected) with self.assertRaises(Exception) as context: p['g.x'] = 5.0 p.final_setup() self.assertEqual(str(context.exception), msg1) # Start from a clean state again p = Problem(model) p.setup() with self.assertRaises(Exception) as context: self.assertEqual(p['g.x'], 5.0) self.assertEqual(str(context.exception), msg1) msg2 = "The promoted name x is invalid because it refers to multiple inputs: " \ "[g.c2.x, g.c3.x] that are not connected to an output variable." jac = g.linear_solver._assembled_jac # d(outputs)/d(inputs) with self.assertRaises(Exception) as context: jac['y', 'x'] = 5.0 self.assertEqual(str(context.exception), msg2) with self.assertRaises(Exception) as context: self.assertEqual(jac['y', 'x'], 5.0) self.assertEqual(str(context.exception), msg2) # ------------------------------------------------------------------- # Repeat test for post final_setup when vectors are allocated. p = Problem(model) p.setup() p.final_setup() with self.assertRaises(Exception) as context: self.assertEqual(p['g.x'], 5.0) self.assertEqual(str(context.exception), msg1) # d(outputs)/d(inputs) with self.assertRaises(Exception) as context: jac['y', 'x'] = 5.0 self.assertEqual(str(context.exception), msg2) with self.assertRaises(Exception) as context: self.assertEqual(jac['y', 'x'], 5.0) self.assertEqual(str(context.exception), msg2) # ------------------------------------------------------------------- msg1 = "The promoted name g.x is invalid because it refers to multiple inputs: " \ "[g.c2.x ,g.c3.x]. Access the value from the connected output variable x instead." # From here, 'g.x' has a valid source. model.connect('x', 'g.x') p = Problem(model) p.setup() # inputs (g.x is connected to x) p['g.x'] = 5.0 with self.assertRaises(Exception) as context: p.final_setup() self.assertEqual(str(context.exception), msg1) # Repeat test for post final_setup when vectors are allocated. p = Problem(model) p.setup() p.final_setup() # inputs (g.x is connected to x) with self.assertRaises(Exception) as context: p['g.x'] = 5.0 self.assertEqual(str(context.exception), msg1) # Final test, the getitem p = Problem(model) p.setup() with self.assertRaises(Exception) as context: self.assertEqual(p['g.x'], 5.0) self.assertEqual(str(context.exception), msg1) # d(outputs)/d(inputs) with self.assertRaises(Exception) as context: jac['y', 'x'] = 5.0 self.assertEqual(str(context.exception), msg2) with self.assertRaises(Exception) as context: self.assertEqual(jac['y', 'x'], 5.0) # Start from a clean state again self.assertEqual(str(context.exception), msg2) # Repeat test for post final_setup when vectors are allocated. p = Problem(model) p.setup() p.final_setup() with self.assertRaises(Exception) as context: self.assertEqual(p['g.x'], 5.0) self.assertEqual(str(context.exception), msg1) # d(outputs)/d(inputs) with self.assertRaises(Exception) as context: jac['y', 'x'] = 5.0 self.assertEqual(str(context.exception), msg2) with self.assertRaises(Exception) as context: self.assertEqual(jac['y', 'x'], 5.0) self.assertEqual(str(context.exception), msg2)
def test_brachistochrone_recording_for_docs(self): import numpy as np import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt from openmdao.api import Problem, Group, ScipyOptimizeDriver, DirectSolver, \ SqliteRecorder, CaseReader from openmdao.utils.assert_utils import assert_rel_error from dymos import Phase from dymos.examples.brachistochrone.brachistochrone_ode import BrachistochroneODE p = Problem(model=Group()) p.driver = ScipyOptimizeDriver() phase = Phase('gauss-lobatto', ode_class=BrachistochroneODE, num_segments=10) p.model.add_subsystem('phase0', phase) phase.set_time_options(initial_bounds=(0, 0), duration_bounds=(.5, 10)) phase.set_state_options('x', fix_initial=True, fix_final=True) phase.set_state_options('y', fix_initial=True, fix_final=True) phase.set_state_options('v', fix_initial=True) phase.add_control('theta', units='deg', rate_continuity=False, lower=0.01, upper=179.9) phase.add_design_parameter('g', units='m/s**2', opt=False, val=9.80665) # Minimize time at the end of the phase phase.add_objective('time', loc='final', scaler=10) p.model.linear_solver = DirectSolver(assemble_jac=True) p.model.options['assembled_jac_type'] = 'csc' # Recording rec = SqliteRecorder('brachistochrone_solution.db') p.driver.recording_options['record_desvars'] = True p.driver.recording_options['record_responses'] = True p.driver.recording_options['record_objectives'] = True p.driver.recording_options['record_constraints'] = True p.model.recording_options['record_metadata'] = True p.driver.add_recorder(rec) p.model.add_recorder(rec) phase.add_recorder(rec) p.setup() p['phase0.t_initial'] = 0.0 p['phase0.t_duration'] = 2.0 p['phase0.states:x'] = phase.interpolate(ys=[0, 10], nodes='state_input') p['phase0.states:y'] = phase.interpolate(ys=[10, 5], nodes='state_input') p['phase0.states:v'] = phase.interpolate(ys=[0, 9.9], nodes='state_input') p['phase0.controls:theta'] = phase.interpolate(ys=[5, 100.5], nodes='control_input') # Solve for the optimal trajectory p.run_driver() # Test the results assert_rel_error(self, phase.get_values('time')[-1], 1.8016, tolerance=1.0E-3) cr = CaseReader('brachistochrone_solution.db') outputs = dict([ (o[0], o[1]) for o in cr.list_outputs(units=True, shape=True, out_stream=None) ]) assert_rel_error( self, p['phase0.controls:theta'], outputs['phase0.indep_controls.controls:theta']['value']) phase0_options = cr.system_metadata['phase0']['component_options'] num_segments = phase0_options['num_segments'] transcription_order = phase0_options['transcription_order'] segment_ends = phase0_options['segment_ends'] ode_class = phase0_options['ode_class'] print(num_segments) print(transcription_order) print(ode_class) print(segment_ends)
class PlanesIntersection(Group): def setup(self): self.add_subsystem('p3', Plane3()) self.add_subsystem('p1', Plane1()) self.add_subsystem('p2', Plane2()) self.connect('p1.y', 'p2.y') self.connect('p1.y', 'p3.y') self.connect('p2.x', 'p3.x') self.connect('p2.x', 'p1.x') self.connect('p3.z', 'p1.z') self.connect('p3.z', 'p2.z') if __name__ == '__main__': prob = Problem() prob.model = PlanesIntersection() a = prob.model.nonlinear_solver = NewtonSolver() a = prob.model.linear_solver = DirectSolver() a.options['maxiter'] = 10 prob.setup() # view_model(prob) prob.run_model() print(prob['p1.y'], prob['p1.x'], prob['p1.z'])
def test_solve_subsystems_internals(self): # Here we test that this feature is doing what it should do by counting the # number of calls in various places. class CountNewton(NewtonSolver): """ This version of Newton also counts how many times it runs in total.""" def __init__(self, **kwargs): super(CountNewton, self).__init__(**kwargs) self.total_count = 0 def _iter_execute(self): super(CountNewton, self)._iter_execute() self.total_count += 1 class CountDS(DirectSolver): """ This version of Newton also counts how many times it linearizes""" def __init__(self, **kwargs): super(DirectSolver, self).__init__(**kwargs) self.lin_count = 0 def _linearize(self): super(CountDS, self)._linearize() self.lin_count += 1 prob = Problem(model=DoubleSellar()) model = prob.model # each SubSellar group converges itself g1 = model.g1 g1.nonlinear_solver = CountNewton() g1.nonlinear_solver.options['rtol'] = 1.0e-5 g1.linear_solver = CountDS() # used for derivatives g2 = model.g2 g2.nonlinear_solver = CountNewton() g2.nonlinear_solver.options['rtol'] = 1.0e-5 g2.linear_solver = DirectSolver() # Converge the outer loop with Gauss Seidel, with a looser tolerance. model.nonlinear_solver = NewtonSolver() model.linear_solver = ScipyKrylov() # Enfore behavior: max_sub_solves = 0 means we run once during init model.nonlinear_solver.options['maxiter'] = 5 model.nonlinear_solver.options['solve_subsystems'] = True model.nonlinear_solver.options['max_sub_solves'] = 0 prob.set_solver_print(level=0) prob.setup() prob.run_model() # Verifying subsolvers ran self.assertEqual(g1.nonlinear_solver.total_count, 2) self.assertEqual(g2.nonlinear_solver.total_count, 2) self.assertEqual(g1.linear_solver.lin_count, 2) prob = Problem(model=DoubleSellar()) model = prob.model # each SubSellar group converges itself g1 = model.g1 g1.nonlinear_solver = CountNewton() g1.nonlinear_solver.options['rtol'] = 1.0e-5 g1.linear_solver = CountDS() # used for derivatives g2 = model.g2 g2.nonlinear_solver = CountNewton() g2.nonlinear_solver.options['rtol'] = 1.0e-5 g2.linear_solver = DirectSolver() # Converge the outer loop with Gauss Seidel, with a looser tolerance. model.nonlinear_solver = NewtonSolver() model.linear_solver = ScipyKrylov() # Enforce Behavior: baseline model.nonlinear_solver.options['maxiter'] = 5 model.nonlinear_solver.options['solve_subsystems'] = True model.nonlinear_solver.options['max_sub_solves'] = 5 prob.set_solver_print(level=0) prob.setup() prob.run_model() # Verifying subsolvers ran self.assertEqual(g1.nonlinear_solver.total_count, 5) self.assertEqual(g2.nonlinear_solver.total_count, 5) self.assertEqual(g1.linear_solver.lin_count, 5) prob = Problem(model=DoubleSellar()) model = prob.model # each SubSellar group converges itself g1 = model.g1 g1.nonlinear_solver = CountNewton() g1.nonlinear_solver.options['rtol'] = 1.0e-5 g1.linear_solver = CountDS() # used for derivatives g2 = model.g2 g2.nonlinear_solver = CountNewton() g2.nonlinear_solver.options['rtol'] = 1.0e-5 g2.linear_solver = DirectSolver() # Converge the outer loop with Gauss Seidel, with a looser tolerance. model.nonlinear_solver = NewtonSolver() model.linear_solver = ScipyKrylov() # Enfore behavior: max_sub_solves = 1 means we run during init and first iteration of iter_execute model.nonlinear_solver.options['maxiter'] = 5 model.nonlinear_solver.options['solve_subsystems'] = True model.nonlinear_solver.options['max_sub_solves'] = 1 prob.set_solver_print(level=0) prob.setup() prob.run_model() # Verifying subsolvers ran self.assertEqual(g1.nonlinear_solver.total_count, 4) self.assertEqual(g2.nonlinear_solver.total_count, 4) self.assertEqual(g1.linear_solver.lin_count, 4)
def setup(self): thermo_spec = species_data.janaf design = self.options['design'] # Add engine elements self.add_subsystem( 'fc', FlightConditions(thermo_data=thermo_spec, elements=AIR_MIX)) self.add_subsystem( 'inlet', Inlet(design=design, thermo_data=thermo_spec, elements=AIR_MIX)) self.add_subsystem('comp', Compressor( map_data=AXI5, design=design, thermo_data=thermo_spec, elements=AIR_MIX, ), promotes_inputs=[('Nmech', 'HP_Nmech')]) self.add_subsystem( 'burner', Combustor(design=design, thermo_data=thermo_spec, inflow_elements=AIR_MIX, air_fuel_elements=AIR_FUEL_MIX, fuel_type='JP-7')) self.add_subsystem('turb', Turbine( map_data=LPT2269, design=design, thermo_data=thermo_spec, elements=AIR_FUEL_MIX, ), promotes_inputs=[('Nmech', 'HP_Nmech')]) self.add_subsystem('pt', Turbine( map_data=LPT2269, design=design, thermo_data=thermo_spec, elements=AIR_FUEL_MIX, ), promotes_inputs=[('Nmech', 'LP_Nmech')]) self.add_subsystem( 'nozz', Nozzle(nozzType='CV', lossCoef='Cv', thermo_data=thermo_spec, elements=AIR_FUEL_MIX)) self.add_subsystem('HP_shaft', Shaft(num_ports=2), promotes_inputs=[('Nmech', 'HP_Nmech')]) self.add_subsystem('LP_shaft', Shaft(num_ports=1), promotes_inputs=[('Nmech', 'LP_Nmech')]) self.add_subsystem('perf', Performance(num_nozzles=1, num_burners=1)) # Connect flow stations connect_flow(self, 'fc.Fl_O', 'inlet.Fl_I', connect_w=False) connect_flow(self, 'inlet.Fl_O', 'comp.Fl_I') connect_flow(self, 'comp.Fl_O', 'burner.Fl_I') connect_flow(self, 'burner.Fl_O', 'turb.Fl_I') connect_flow(self, 'turb.Fl_O', 'pt.Fl_I') connect_flow(self, 'pt.Fl_O', 'nozz.Fl_I') # Connect turbomachinery elements to shaft self.connect('comp.trq', 'HP_shaft.trq_0') self.connect('turb.trq', 'HP_shaft.trq_1') self.connect('pt.trq', 'LP_shaft.trq_0') # Connnect nozzle exhaust to freestream static conditions self.connect('fc.Fl_O:stat:P', 'nozz.Ps_exhaust') # Connect outputs to pefromance element self.connect('inlet.Fl_O:tot:P', 'perf.Pt2') self.connect('comp.Fl_O:tot:P', 'perf.Pt3') self.connect('burner.Wfuel', 'perf.Wfuel_0') self.connect('inlet.F_ram', 'perf.ram_drag') self.connect('nozz.Fg', 'perf.Fg_0') self.connect('LP_shaft.pwr_net', 'perf.power') # Add balances for design and off-design balance = self.add_subsystem('balance', BalanceComp()) if design: balance.add_balance('W', val=27.0, units='lbm/s', eq_units=None) self.connect('balance.W', 'inlet.Fl_I:stat:W') self.connect('nozz.PR', 'balance.lhs:W') 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('turb_PR', val=3.0, lower=1.001, upper=8, eq_units='hp', rhs_val=0.) self.connect('balance.turb_PR', 'turb.PR') self.connect('HP_shaft.pwr_net', 'balance.lhs:turb_PR') balance.add_balance('pt_PR', val=3.0, lower=1.001, upper=8, eq_units='hp') self.connect('balance.pt_PR', 'pt.PR') self.connect('LP_shaft.pwr_net', 'balance.lhs:pt_PR') else: balance.add_balance('FAR', eq_units='hp', lower=1e-4, val=.3) self.connect('balance.FAR', 'burner.Fl_I:FAR') self.connect('LP_shaft.pwr_net', 'balance.lhs:FAR') balance.add_balance('HP_Nmech', val=1.5, units='rpm', lower=500., eq_units='hp', rhs_val=0.) self.connect('balance.HP_Nmech', 'HP_Nmech') self.connect('HP_shaft.pwr_net', 'balance.lhs:HP_Nmech') balance.add_balance('W', val=27.0, units='lbm/s', eq_units='inch**2') self.connect('balance.W', 'inlet.Fl_I:stat:W') self.connect('nozz.Throat:stat:area', 'balance.lhs:W') # Setup solver to converge engine self.set_order([ 'balance', 'fc', 'inlet', 'comp', 'burner', 'turb', 'pt', 'nozz', 'HP_shaft', 'LP_shaft', 'perf' ]) newton = self.nonlinear_solver = NewtonSolver() newton.options['atol'] = 1e-6 newton.options['rtol'] = 1e-6 newton.options['iprint'] = 2 newton.options['maxiter'] = 15 newton.options['solve_subsystems'] = True newton.options['max_sub_solves'] = 100 newton.linesearch = BoundsEnforceLS() # newton.linesearch = ArmijoGoldsteinLS() # newton.linesearch.options['c'] = .0001 newton.linesearch.options['bound_enforcement'] = 'scalar' newton.linesearch.options['iprint'] = -1 self.linear_solver = DirectSolver(assemble_jac=True)
def setup(self): F = 4 * 10**7 indeps = self.add_subsystem("indeps", IndepVarComp()) indeps.add_output( "n0_x_reaction_direction", 0, units="rad", desc= "Direction of horizontal reaction force of pinned joint on node 0") indeps.add_output( "n0_y_reaction_direction", math.pi / 2, units="rad", desc= "Direction of vertical reaction force of pinned joint on node 0") indeps.add_output( "n1_x_reaction_direction", 0, units="rad", desc="Direction of reaction force of roller joint on node 1") indeps.add_output("n0_beam0", math.pi * 7 / 4, units="rad", desc="Direction of beam 0 at node 0") indeps.add_output("n0_beam1", math.pi * 3 / 2, units="rad", desc="Direction of beam 1 at node 0") indeps.add_output("n1_beam1", math.pi / 2, units="rad", desc="Direction of beam 1 at node 1") indeps.add_output("n1_beam2", 0, units="rad", desc="Direction of beam 2 at node 1") indeps.add_output("n1_beam3", math.pi * 5 / 3, units="rad", desc="Direction of beam 3 at node 1") indeps.add_output("n2_beam3", math.pi * 2 / 3, units="rad", desc="Direction of beam 2 at node 2") indeps.add_output("n2_beam4", math.pi / 3, units="rad", desc="Direction of beam 4 at node 2") indeps.add_output("n3_beam4", math.pi * 5 / 3, units="rad", desc="Direction of beam 4 at node 3") indeps.add_output("n3_beam2", math.pi, units="rad", desc="Direction of beam 5 at node 3") indeps.add_output("n3_beam0", math.pi * 3 / 4, units="rad", desc="Direction of beam 0 at node 4") indeps.add_output("ext", F, units="N", desc="Force applied to beam structure") indeps.add_output("ext_direction", math.pi * 3 / 2, units="rad", desc="Direction of force applied to beam structure") indeps.add_output("A0", 1) indeps.add_output("A1", 1) indeps.add_output("A2", 1) indeps.add_output("A3", 1) indeps.add_output("A4", 1) indeps.add_output("L1") indeps.add_output("L2") cycle = self.add_subsystem("cycle", Group()) cycle.add_subsystem("node0", Node(n_loads=2, n_reactions=2)) cycle.add_subsystem("node1", Node(n_loads=3, n_reactions=1)) cycle.add_subsystem("node2", Node(n_loads=2, n_external_forces=1)) cycle.add_subsystem("node3", Node(n_loads=3)) cycle.add_subsystem("beam0", Beam()) cycle.add_subsystem("beam1", Beam()) cycle.add_subsystem("beam2", Beam()) cycle.add_subsystem("beam3", Beam()) cycle.add_subsystem("beam4", Beam()) #Node 0 connections self.connect("indeps.n0_x_reaction_direction", "cycle.node0.direction0_reaction") self.connect("indeps.n0_y_reaction_direction", "cycle.node0.direction1_reaction") self.connect("indeps.n0_beam0", "cycle.node0.direction0_load") self.connect("indeps.n0_beam1", "cycle.node0.direction1_load") #Node 1 connections self.connect("indeps.n1_x_reaction_direction", "cycle.node1.direction0_reaction") self.connect("indeps.n1_beam1", "cycle.node1.direction0_load") self.connect("indeps.n1_beam2", "cycle.node1.direction1_load") self.connect("indeps.n1_beam3", "cycle.node1.direction2_load") #Node 2 connections self.connect("indeps.n2_beam3", "cycle.node2.direction0_load") self.connect("indeps.n2_beam4", "cycle.node2.direction1_load") self.connect("indeps.ext", "cycle.node2.force0_ext") self.connect("indeps.ext_direction", "cycle.node2.direction0_ext") #Node 3 connections self.connect("indeps.n3_beam0", "cycle.node3.direction0_load") self.connect("indeps.n3_beam2", "cycle.node3.direction1_load") self.connect("indeps.n3_beam4", "cycle.node3.direction2_load") #Inter-node connections self.connect("cycle.node0.load_out0", "cycle.beam0.force0") self.connect("cycle.node0.load_out1", "cycle.beam1.force0") self.connect("cycle.node1.load_out0", "cycle.beam1.force1") self.connect("cycle.node1.load_out1", "cycle.beam2.force0") self.connect("cycle.node1.load_out2", "cycle.beam3.force0") self.connect("cycle.node2.load_out0", "cycle.beam3.force1") self.connect("cycle.node2.load_out1", "cycle.beam4.force0") self.connect("cycle.node3.load_out0", "cycle.beam0.force1") self.connect("cycle.node3.load_out1", "cycle.beam2.force1") self.connect("cycle.node3.load_out2", "cycle.beam4.force1") self.connect("cycle.beam0.beam_force", ["cycle.node0.load_in0", "cycle.node3.load_in0"]) self.connect("cycle.beam1.beam_force", ["cycle.node0.load_in1", "cycle.node1.load_in0"]) self.connect("cycle.beam2.beam_force", ["cycle.node1.load_in1", "cycle.node3.load_in1"]) self.connect("cycle.beam3.beam_force", ["cycle.node1.load_in2", "cycle.node2.load_in0"]) self.connect("cycle.beam4.beam_force", ["cycle.node2.load_in1", "cycle.node3.load_in2"]) cycle.nonlinear_solver = NewtonSolver() cycle.nonlinear_solver.options['atol'] = 1e-7 cycle.nonlinear_solver.options['solve_subsystems'] = True cycle.nonlinear_solver.options["iprint"] = 2 cycle.linear_solver = DirectSolver() self.add_subsystem( "obj_cmp", ExecComp("obj = L1 * (A3 + A1 + A2 + A4) + L2 * A0")) self.add_subsystem("con0", ExecComp("con = 400 - abs(sigma)")) self.add_subsystem("con1", ExecComp("con = 400 - abs(sigma)")) self.add_subsystem("con2", ExecComp("con = 400 - abs(sigma)")) self.add_subsystem("con3", ExecComp("con = 400 - abs(sigma)")) self.add_subsystem("con4", ExecComp("con = 400 - abs(sigma)")) self.connect("indeps.L1", ["obj_cmp.L1"]) self.connect("indeps.L2", ["obj_cmp.L2"]) self.connect("cycle.beam0.sigma", ["con0.sigma"]) self.connect("cycle.beam1.sigma", ["con1.sigma"]) self.connect("cycle.beam2.sigma", ["con2.sigma"]) self.connect("cycle.beam3.sigma", ["con3.sigma"]) self.connect("cycle.beam4.sigma", ["con4.sigma"]) self.connect("indeps.A0", ["cycle.beam0.A", "obj_cmp.A0"]) self.connect("indeps.A1", ["cycle.beam1.A", "obj_cmp.A1"]) self.connect("indeps.A2", ["cycle.beam2.A", "obj_cmp.A2"]) self.connect("indeps.A3", ["cycle.beam3.A", "obj_cmp.A3"]) self.connect("indeps.A4", ["cycle.beam4.A", "obj_cmp.A4"])
def brachistochrone_min_time(transcription='gauss-lobatto', num_segments=8, transcription_order=3, compressed=True, sim_record='brach_min_time_sim.db', optimizer='SLSQP', dynamic_simul_derivs=True, force_alloc_complex=False, solve_segments=False, run_driver=True): p = Problem(model=Group()) if optimizer == 'SNOPT': p.driver = pyOptSparseDriver() p.driver.options['optimizer'] = optimizer p.driver.opt_settings['Major iterations limit'] = 100 p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-6 p.driver.opt_settings['Major optimality tolerance'] = 1.0E-6 p.driver.opt_settings['iSumm'] = 6 else: p.driver = ScipyOptimizeDriver() p.driver.options['dynamic_simul_derivs'] = dynamic_simul_derivs if transcription == 'runge-kutta': transcription = RungeKutta(num_segments=num_segments, compressed=compressed) elif transcription == 'gauss-lobatto': transcription = GaussLobatto(num_segments=num_segments, order=transcription_order, compressed=compressed) elif transcription == 'radau-ps': transcription = Radau(num_segments=num_segments, order=transcription_order, compressed=compressed) phase = Phase(ode_class=BrachistochroneVectorStatesODE, transcription=transcription) p.model.add_subsystem('phase0', phase) phase.set_time_options(fix_initial=True, duration_bounds=(.5, 10)) fix_final = not solve_segments # can't fix final position if you're solving the segments phase.set_state_options('pos', fix_initial=True, fix_final=fix_final, solve_segments=solve_segments) phase.set_state_options('v', fix_initial=True, fix_final=False, solve_segments=solve_segments) phase.add_control('theta', continuity=True, rate_continuity=True, units='deg', lower=0.01, upper=179.9) phase.add_design_parameter('g', units='m/s**2', opt=False, val=9.80665) # Minimize time at the end of the phase phase.add_objective('time', loc='final', scaler=10) p.model.linear_solver = DirectSolver() p.setup(check=True, force_alloc_complex=force_alloc_complex) p['phase0.t_initial'] = 0.0 p['phase0.t_duration'] = 2.0 pos0 = [0, 10] posf = [10, 5] p['phase0.states:pos'] = phase.interpolate(ys=[pos0, posf], nodes='state_input') p['phase0.states:v'] = phase.interpolate(ys=[0, 9.9], nodes='state_input') p['phase0.controls:theta'] = phase.interpolate(ys=[5, 100], nodes='control_input') p['phase0.design_parameters:g'] = 9.80665 p.run_model() if run_driver: p.run_driver() # Plot results if SHOW_PLOTS: p.run_driver() exp_out = phase.simulate(record_file=sim_record) fig, ax = plt.subplots() fig.suptitle('Brachistochrone Solution') x_imp = p.get_val('phase0.timeseries.states:pos')[:, 0] y_imp = p.get_val('phase0.timeseries.states:pos')[:, 1] x_exp = exp_out.get_val('phase0.timeseries.states:pos')[:, 0] y_exp = exp_out.get_val('phase0.timeseries.states:pos')[:, 1] ax.plot(x_imp, y_imp, 'ro', label='implicit') ax.plot(x_exp, y_exp, 'b-', label='explicit') ax.set_xlabel('x (m)') ax.set_ylabel('y (m)') ax.grid(True) ax.legend(loc='upper right') fig, ax = plt.subplots() fig.suptitle('Brachistochrone Solution') x_imp = p.get_val('phase0.timeseries.time') y_imp = p.get_val('phase0.timeseries.control_rates:theta_rate2') x_exp = exp_out.get_val('phase0.timeseries.time') y_exp = exp_out.get_val('phase0.timeseries.control_rates:theta_rate2') ax.plot(x_imp, y_imp, 'ro', label='implicit') ax.plot(x_exp, y_exp, 'b-', label='explicit') ax.set_xlabel('time (s)') ax.set_ylabel('theta rate2 (rad/s**2)') ax.grid(True) ax.legend(loc='lower right') plt.show() return p
def test_result(self): prob = Problem(model=Group()) ivc = IndepVarComp() ivc.add_output(name='M', val=0.0, units='deg', desc='Mean anomaly') ivc.add_output(name='ecc', val=0.0, units=None, desc='orbit eccentricity') bal = BalanceComp() bal.add_balance(name='E', val=0.0, units='rad', eq_units='rad', rhs_name='M') # Override the guess_nonlinear method, always initialize E to the value of M def guess_func(inputs, outputs, residuals): outputs['E'] = inputs['M'] bal.guess_nonlinear = guess_func # ExecComp used to compute the LHS of Kepler's equation. lhs_comp = ExecComp('lhs=E - ecc * sin(E)', lhs={ 'value': 0.0, 'units': 'rad' }, E={ 'value': 0.0, 'units': 'rad' }, ecc={'value': 0.0}) prob.model.add_subsystem(name='ivc', subsys=ivc, promotes_outputs=['M', 'ecc']) prob.model.add_subsystem(name='balance', subsys=bal, promotes_inputs=['M'], promotes_outputs=['E']) prob.model.add_subsystem(name='lhs_comp', subsys=lhs_comp, promotes_inputs=['E', 'ecc']) # Explicit connections prob.model.connect('lhs_comp.lhs', 'balance.lhs:E') # Setup solvers prob.model.linear_solver = DirectSolver() prob.model.nonlinear_solver = NewtonSolver() prob.model.nonlinear_solver.options['maxiter'] = 100 prob.model.nonlinear_solver.options['iprint'] = 0 prob.setup() prob['M'] = 85.0 prob['ecc'] = 0.6 prob.run_model() assert_almost_equal(np.degrees(prob['E']), 115.9, decimal=1) print('E (deg) = ', np.degrees(prob['E'][0]))
def test_brachistochrone_vector_ode_path_constraints_rk_partial_indices( self): p = Problem(model=Group()) p.driver = ScipyOptimizeDriver() p.driver.options['dynamic_simul_derivs'] = True phase = Phase(ode_class=BrachistochroneVectorStatesODE, transcription=RungeKutta(num_segments=20)) p.model.add_subsystem('phase0', phase) phase.set_time_options(fix_initial=True, duration_bounds=(.5, 10)) phase.set_state_options('pos', fix_initial=True, fix_final=False) phase.set_state_options('v', fix_initial=True, fix_final=False) phase.add_control('theta', continuity=True, rate_continuity=True, units='deg', lower=0.01, upper=179.9) phase.add_design_parameter('g', units='m/s**2', opt=False, val=9.80665) phase.add_boundary_constraint('pos', loc='final', equals=[10, 5]) phase.add_path_constraint('pos_dot', shape=(2, ), units='m/s', indices=[1], lower=-4, upper=4) phase.add_timeseries_output('pos_dot', shape=(2, ), units='m/s') # Minimize time at the end of the phase phase.add_objective('time', loc='final', scaler=10) p.model.linear_solver = DirectSolver() p.setup(check=True, force_alloc_complex=True) p['phase0.t_initial'] = 0.0 p['phase0.t_duration'] = 2.0 pos0 = [0, 10] posf = [10, 5] p['phase0.states:pos'] = phase.interpolate(ys=[pos0, posf], nodes='state_input') p['phase0.states:v'] = phase.interpolate(ys=[0, 9.9], nodes='state_input') p['phase0.controls:theta'] = phase.interpolate(ys=[5, 100], nodes='control_input') p['phase0.design_parameters:g'] = 9.80665 p.run_driver() assert_rel_error(self, np.min(p.get_val('phase0.timeseries.pos_dot')[:, -1]), -4, tolerance=1.0E-2) # Plot results if SHOW_PLOTS: exp_out = phase.simulate(times_per_seg=20) fig, ax = plt.subplots() fig.suptitle('Brachistochrone Solution') x_imp = p.get_val('phase0.timeseries.states:pos')[:, 0] y_imp = p.get_val('phase0.timeseries.states:pos')[:, 1] x_exp = exp_out.get_val('phase0.timeseries.states:pos')[:, 0] y_exp = exp_out.get_val('phase0.timeseries.states:pos')[:, 1] ax.plot(x_imp, y_imp, 'ro', label='implicit') ax.plot(x_exp, y_exp, 'b-', label='explicit') ax.set_xlabel('x (m)') ax.set_ylabel('y (m)') ax.grid(True) ax.legend(loc='upper right') fig, ax = plt.subplots() fig.suptitle('Brachistochrone Solution\nVelocity') t_imp = p.get_val('phase0.timeseries.time') t_exp = exp_out.get_val('phase0.timeseries.time') xdot_imp = p.get_val('phase0.timeseries.pos_dot')[:, 0] ydot_imp = p.get_val('phase0.timeseries.pos_dot')[:, 1] xdot_exp = exp_out.get_val('phase0.timeseries.pos_dot')[:, 0] ydot_exp = exp_out.get_val('phase0.timeseries.pos_dot')[:, 1] ax.plot(t_imp, xdot_imp, 'bo', label='implicit') ax.plot(t_exp, xdot_exp, 'b-', label='explicit') ax.plot(t_imp, ydot_imp, 'ro', label='implicit') ax.plot(t_exp, ydot_exp, 'r-', label='explicit') ax.set_xlabel('t (s)') ax.set_ylabel('v (m/s)') ax.grid(True) ax.legend(loc='upper right') fig, ax = plt.subplots() fig.suptitle('Brachistochrone Solution') x_imp = p.get_val('phase0.timeseries.time') y_imp = p.get_val('phase0.timeseries.control_rates:theta_rate2') x_exp = exp_out.get_val('phase0.timeseries.time') y_exp = exp_out.get_val( 'phase0.timeseries.control_rates:theta_rate2') ax.plot(x_imp, y_imp, 'ro', label='implicit') ax.plot(x_exp, y_exp, 'b-', label='explicit') ax.set_xlabel('time (s)') ax.set_ylabel('theta rate2 (rad/s**2)') ax.grid(True) ax.legend(loc='lower right') plt.show() return p
def setup(self): surfaces = self.options['surfaces'] coupled = Group() for surface in surfaces: name = surface['name'] # Connect the output of the loads component with the FEM # displacement parameter. This links the coupling within the coupled # group that necessitates the subgroup solver. coupled.connect(name + '_loads.loads', name + '.loads') # Perform the connections with the modified names within the # 'aero_states' group. coupled.connect(name + '.normals', 'aero_states.' + name + '_normals') coupled.connect(name + '.def_mesh', 'aero_states.' + name + '_def_mesh') # Connect the results from 'coupled' to the performance groups coupled.connect(name + '.def_mesh', name + '_loads.def_mesh') coupled.connect('aero_states.' + name + '_sec_forces', name + '_loads.sec_forces') # Connect the results from 'aero_states' to the performance groups self.connect('coupled.aero_states.' + name + '_sec_forces', name + '_perf' + '.sec_forces') # Connection performance functional variables self.connect(name + '_perf.CL', 'total_perf.' + name + '_CL') self.connect(name + '_perf.CD', 'total_perf.' + name + '_CD') self.connect('coupled.aero_states.' + name + '_sec_forces', 'total_perf.' + name + '_sec_forces') self.connect('coupled.' + name + '.chords', name + '_perf.aero_funcs.chords') # Connect parameters from the 'coupled' group to the performance # groups for the individual surfaces. self.connect('coupled.' + name + '.disp', name + '_perf.disp') self.connect('coupled.' + name + '.S_ref', name + '_perf.S_ref') self.connect('coupled.' + name + '.widths', name + '_perf.widths') # self.connect('coupled.' + name + '.chords', name + '_perf.chords') self.connect('coupled.' + name + '.lengths', name + '_perf.lengths') self.connect('coupled.' + name + '.cos_sweep', name + '_perf.cos_sweep') # Connect parameters from the 'coupled' group to the total performance group. self.connect('coupled.' + name + '.S_ref', 'total_perf.' + name + '_S_ref') self.connect('coupled.' + name + '.widths', 'total_perf.' + name + '_widths') self.connect('coupled.' + name + '.chords', 'total_perf.' + name + '_chords') self.connect('coupled.' + name + '.b_pts', 'total_perf.' + name + '_b_pts') # Add components to the 'coupled' group for each surface. # The 'coupled' group must contain all components and parameters # needed to converge the aerostructural system. coupled_AS_group = CoupledAS(surface=surface) if surface['distributed_fuel_weight']: promotes = ['load_factor'] else: promotes = [] coupled.add_subsystem(name, coupled_AS_group, promotes_inputs=promotes) # Add a single 'aero_states' component for the whole system within the # coupled group. coupled.add_subsystem('aero_states', VLMStates(surfaces=surfaces), promotes_inputs=['v', 'alpha', 'rho']) # Explicitly connect parameters from each surface's group and the common # 'aero_states' group. for surface in surfaces: name = surface['name'] # Add a loads component to the coupled group coupled.add_subsystem(name + '_loads', LoadTransfer(surface=surface)) """ ### Change the solver settings here ### """ # Set solver properties for the coupled group # coupled.linear_solver = ScipyIterativeSolver() # coupled.linear_solver.precon = LinearRunOnce() coupled.nonlinear_solver = NonlinearBlockGS(use_aitken=True) coupled.nonlinear_solver.options['maxiter'] = 50 coupled.nonlinear_solver.options['atol'] = 5e-6 coupled.nonlinear_solver.options['rtol'] = 1e-12 # coupled.linear_solver = DirectSolver() coupled.linear_solver = DirectSolver(assemble_jac=True) coupled.options['assembled_jac_type'] = 'csc' # coupled.nonlinear_solver = NewtonSolver(solve_subsystems=True) # coupled.nonlinear_solver.options['maxiter'] = 50 coupled.nonlinear_solver.options['iprint'] = 0 """ ### End change of solver settings ### """ # Add the coupled group to the model problem self.add_subsystem('coupled', coupled, promotes_inputs=['v', 'alpha', 'rho']) for surface in surfaces: name = surface['name'] # Add a performance group which evaluates the data after solving # the coupled system perf_group = CoupledPerformance(surface=surface) self.add_subsystem(name + '_perf', perf_group, promotes_inputs=['rho', 'v', 'alpha', 're', 'Mach_number']) # Add functionals to evaluate performance of the system. # Note that only the interesting results are promoted here; not all # of the parameters. self.add_subsystem('total_perf', TotalPerformance(surfaces=surfaces, user_specified_Sref=self.options['user_specified_Sref'], internally_connect_fuelburn=self.options['internally_connect_fuelburn']), promotes_inputs=['v', 'rho', 'empty_cg', 'total_weight', 'CT', 'speed_of_sound', 'R', 'Mach_number', 'W0', 'load_factor', 'S_ref_total'], promotes_outputs=['L_equals_W', 'fuelburn', 'CL', 'CD', 'CM', 'cg'])
def test_result(self): import numpy as np from numpy.testing import assert_almost_equal from openmdao.api import Problem, Group, IndepVarComp, BalanceComp, \ ExecComp, DirectSolver, NewtonSolver prob = Problem(model=Group()) ivc = IndepVarComp() ivc.add_output(name='M', val=0.0, units='deg', desc='Mean anomaly') ivc.add_output(name='ecc', val=0.0, units=None, desc='orbit eccentricity') bal = BalanceComp() def guess_function(inputs, outputs): return inputs['M'] bal.add_balance(name='E', val=0.0, units='rad', eq_units='rad', rhs_name='M', guess_func=guess_function) # ExecComp used to compute the LHS of Kepler's equation. lhs_comp = ExecComp('lhs=E - ecc * sin(E)', lhs={ 'value': 0.0, 'units': 'rad' }, E={ 'value': 0.0, 'units': 'rad' }, ecc={'value': 0.0}) prob.model.add_subsystem(name='ivc', subsys=ivc, promotes_outputs=['M', 'ecc']) prob.model.add_subsystem(name='balance', subsys=bal, promotes_inputs=['M'], promotes_outputs=['E']) prob.model.add_subsystem(name='lhs_comp', subsys=lhs_comp, promotes_inputs=['E', 'ecc']) # Explicit connections prob.model.connect('lhs_comp.lhs', 'balance.lhs:E') # Setup solvers prob.model.linear_solver = DirectSolver() prob.model.nonlinear_solver = NewtonSolver() prob.model.nonlinear_solver.options['maxiter'] = 100 prob.model.nonlinear_solver.options['iprint'] = 0 prob.setup() prob['M'] = 85.0 prob['ecc'] = 0.6 prob.run_model() assert_almost_equal(np.degrees(prob['E']), 115.9, decimal=1) print('E (deg) = ', np.degrees(prob['E'][0]))
def test_solve_linear_ksp_precon(self): """Solve implicit system with PETScKrylov using a preconditioner.""" group = TestImplicitGroup(lnSolverClass=PETScKrylov) precon = group.linear_solver.precon = LinearBlockGS() p = Problem(group) p.setup(vector_class=PETScVector, check=False) p.set_solver_print(level=0) # Conclude setup but don't run model. p.final_setup() d_inputs, d_outputs, d_residuals = group.get_linear_vectors() # forward d_residuals.set_const(1.0) d_outputs.set_const(0.0) group.run_solve_linear(['linear'], 'fwd') output = d_outputs._data assert_rel_error(self, output[1], group.expected_solution[0], 1e-15) assert_rel_error(self, output[5], group.expected_solution[1], 1e-15) self.assertTrue(precon._iter_count > 0) # reverse d_outputs.set_const(1.0) d_residuals.set_const(0.0) group.run_solve_linear(['linear'], 'rev') output = d_residuals._data assert_rel_error(self, output[1], group.expected_solution[0], 3e-15) assert_rel_error(self, output[5], group.expected_solution[1], 3e-15) self.assertTrue(precon._iter_count > 0) # test the direct solver and make sure KSP correctly recurses for _linearize precon = group.linear_solver.precon = DirectSolver() p.setup(vector_class=PETScVector, check=False) # Conclude setup but don't run model. p.final_setup() d_inputs, d_outputs, d_residuals = group.get_linear_vectors() # forward d_residuals.set_const(1.0) d_outputs.set_const(0.0) group.linear_solver._linearize() group.run_solve_linear(['linear'], 'fwd') output = d_outputs._data assert_rel_error(self, output[1], group.expected_solution[0], 1e-15) assert_rel_error(self, output[5], group.expected_solution[1], 1e-15) # reverse d_outputs.set_const(1.0) d_residuals.set_const(0.0) group.linear_solver._linearize() group.run_solve_linear(['linear'], 'rev') output = d_residuals._data assert_rel_error(self, output[1], group.expected_solution[0], 3e-15) assert_rel_error(self, output[5], group.expected_solution[1], 3e-15)