def make_prob(self, transcription, n_segs, order, compressed): p = om.Problem(model=om.Group()) gd = GridData(num_segments=n_segs, segment_ends=np.arange(n_segs + 1), transcription=transcription, transcription_order=order, compressed=compressed) state_options = { 'x': { 'units': 'm', 'shape': (1, ), 'fix_initial': True, 'fix_final': False, 'solve_segments': False, 'connected_initial': False, 'val': 1.0, 'lower': None, 'upper': None }, 'v': { 'units': 'm/s', 'shape': (3, 2), 'fix_initial': False, 'fix_final': True, 'solve_segments': True, 'connected_initial': False, 'val': np.ones((3, 2)), 'lower': None, 'upper': None } } indep_comp = om.IndepVarComp() p.model.add_subsystem('indep', indep_comp, promotes_outputs=['*']) indep_comp.add_output('dt_dstau', val=np.zeros((gd.subset_num_nodes['col']))) indep_comp.add_output('f_approx:x', val=np.zeros((gd.subset_num_nodes['col'], 1)), units='m') indep_comp.add_output('f_computed:x', val=np.zeros((gd.subset_num_nodes['col'], 1)), units='m') indep_comp.add_output('f_approx:v', val=np.zeros((gd.subset_num_nodes['col'], 3, 2)), units='m/s') indep_comp.add_output('f_computed:v', val=np.zeros((gd.subset_num_nodes['col'], 3, 2)), units='m/s') p.model.add_subsystem('defect_comp', subsys=CollocationComp( grid_data=gd, state_options=state_options)) indep = StateIndependentsComp(grid_data=gd, state_options=state_options) p.model.add_subsystem('state_indep', indep, promotes_outputs=['*']) p.model.connect('f_approx:x', 'defect_comp.f_approx:x') p.model.connect('f_approx:v', 'defect_comp.f_approx:v') p.model.connect('f_computed:x', 'defect_comp.f_computed:x') p.model.connect('f_computed:v', 'defect_comp.f_computed:v') p.model.connect('dt_dstau', 'defect_comp.dt_dstau') p.model.connect('defect_comp.defects:v', 'state_indep.defects:v') self.state_idx_map = {} for state_name, options in state_options.items(): self._make_state_idx_map(state_name, options, gd, self.state_idx_map) p.model.state_indep.configure_io(self.state_idx_map) p.setup(force_alloc_complex=True) p['dt_dstau'] = np.random.random(gd.subset_num_nodes['col']) p['f_approx:x'] = np.random.random((gd.subset_num_nodes['col'], 1)) p['f_approx:v'] = np.random.random((gd.subset_num_nodes['col'], 3, 2)) p['f_computed:x'] = np.random.random((gd.subset_num_nodes['col'], 1)) p['f_computed:v'] = np.random.random( (gd.subset_num_nodes['col'], 3, 2)) p.run_model() p.model.run_apply_nonlinear() return p
def test_distrib_desvar_get_set(self): comm = MPI.COMM_WORLD size = 3 if comm.rank == 0 else 2 class DistribComp(om.ExplicitComponent): def setup(self): self.options['distributed'] = True self.add_input('w', val=1.) # this will connect to a non-distributed IVC self.add_input('x', shape=size) # this will connect to a distributed IVC self.add_output('y', shape=1) # all-gathered output, duplicated on all procs self.add_output('z', shape=size) # distributed output self.declare_partials('y', 'x') self.declare_partials('y', 'w') self.declare_partials('z', 'x') def compute(self, inputs, outputs): x = inputs['x'] local_y = np.sum((x-5)**2) y_g = np.zeros(self.comm.size) self.comm.Allgather(local_y, y_g) outputs['y'] = np.sum(y_g) + (inputs['w']-10)**2 outputs['z'] = x**2 def compute_partials(self, inputs, J): x = inputs['x'] J['y', 'x'] = 2*(x-5) J['y', 'w'] = 2*(inputs['w']-10) J['z', 'x'] = np.diag(2*x) p = om.Problem() model = p.model driver = p.driver # distributed indep var, 'x' d_ivc = model.add_subsystem('d_ivc', om.IndepVarComp(distributed=True), promotes=['*']) d_ivc.add_output('x', 2*np.ones(size)) # non-distributed indep var, 'w' ivc = model.add_subsystem('ivc', om.IndepVarComp(distributed=False), promotes=['*']) ivc.add_output('w', size) # distributed component, 'dc' model.add_subsystem('dc', DistribComp(), promotes=['*']) # distributed design var, 'x' model.add_design_var('x', lower=-100, upper=100) model.add_objective('y') # driver that supports distributed design vars driver.supports._read_only = False driver.supports['distributed_design_vars'] = True # run model p.setup() p.run_model() # get distributed design var driver.get_design_var_values(get_remote=None) assert_near_equal(driver.get_design_var_values(get_remote=True)['d_ivc.x'], [2, 2, 2, 2, 2]) assert_near_equal(driver.get_design_var_values(get_remote=False)['d_ivc.x'], 2*np.ones(size)) # set distributed design var, set_remote=True driver.set_design_var('d_ivc.x', [3, 3, 3, 3, 3], set_remote=True) assert_near_equal(driver.get_design_var_values(get_remote=True)['d_ivc.x'], [3, 3, 3, 3, 3]) # set distributed design var, set_remote=False if comm.rank == 0: driver.set_design_var('d_ivc.x', 5.0*np.ones(size), set_remote=False) else: driver.set_design_var('d_ivc.x', 9.0*np.ones(size), set_remote=False) assert_near_equal(driver.get_design_var_values(get_remote=True)['d_ivc.x'], [5, 5, 5, 9, 9]) # run driver p.run_driver() assert_near_equal(p.get_val('dc.y', get_remote=True), [81, 96]) assert_near_equal(p.get_val('dc.z', get_remote=True), [25, 25, 25, 81, 81])
def test_list_inputs_outputs(self): prob = om.Problem() model = prob.model indep = model.add_subsystem('indep', om.IndepVarComp()) indep.add_discrete_output('x', 11) model.add_subsystem('expl', ModCompEx(3)) model.add_subsystem('impl', ModCompIm(3)) model.connect('indep.x', ['expl.x', 'impl.x']) prob.setup() # # list vars before model has been run (relative names) # expl_inputs = prob.model.expl.list_inputs(out_stream=None) expected = {'a': {'value': [10.]}, 'x': {'value': 10}} self.assertEqual(dict(expl_inputs), expected) impl_inputs = prob.model.impl.list_inputs(out_stream=None) expected = {'x': {'value': 10}} self.assertEqual(dict(impl_inputs), expected) expl_outputs = prob.model.expl.list_outputs(out_stream=None) expected = {'b': {'value': [0.]}, 'y': {'value': 0}} self.assertEqual(dict(expl_outputs), expected) impl_outputs = prob.model.impl.list_outputs(out_stream=None) expected = {'y': {'value': 0}} self.assertEqual(dict(impl_outputs), expected) # # run model # prob.run_model() # # list inputs, not hierarchical # stream = StringIO() prob.model.list_inputs(values=True, hierarchical=False, out_stream=stream) text = stream.getvalue() self.assertEqual(1, text.count("3 Input(s) in 'model'")) # make sure they are in the correct order self.assertTrue( text.find('expl.a') < text.find('expl.x') < text.find('impl.x')) # # list inputs, hierarchical # stream = StringIO() prob.model.list_inputs(values=True, hierarchical=True, out_stream=stream) text = stream.getvalue() self.assertEqual(1, text.count("3 Input(s) in 'model'")) self.assertEqual(1, text.count('\nexpl')) self.assertEqual(1, text.count('\n a')) self.assertEqual(1, text.count('\nimpl')) self.assertEqual(2, text.count('\n x')) # both implicit & explicit # # list outputs, not hierarchical # stream = StringIO() prob.model.list_outputs(values=True, residuals=True, hierarchical=False, out_stream=stream) text = stream.getvalue() self.assertEqual(text.count('3 Explicit Output'), 1) self.assertEqual(text.count('1 Implicit Output'), 1) # make sure they are in the correct order self.assertTrue( text.find('indep.x') < text.find('expl.b') < text.find('expl.y') < text.find('impl.y')) # # list outputs, hierarchical # stream = StringIO() prob.model.list_outputs(values=True, residuals=True, hierarchical=True, out_stream=stream) text = stream.getvalue() self.assertEqual(text.count('\nindep'), 1) self.assertEqual(text.count('\n x'), 1) self.assertEqual(text.count('\nexpl'), 1) self.assertEqual(text.count('\n b'), 1) self.assertEqual(text.count('\nimpl'), 1) self.assertEqual(text.count('\n y'), 2) # both implicit & explicit
'fem_origin': 0.35, # normalized chordwise location of the spar 't_over_c_cp': np.array([0.15]), # maximum airfoil thickness 'thickness_cp': np.ones((3)) * .1, 'wing_weight_ratio': 2., 'struct_weight_relief': False, # True to add the weight of the structure to the loads on the structure 'distributed_fuel_weight': False, 'exact_failure_constraint': False, } ## Part-2: Initialize your problem and add flow conditions ------------ # Create the problem and assign the model group prob = om.Problem() ny = surf_dict['mesh'].shape[1] indep_var_comp = om.IndepVarComp() indep_var_comp.add_output('loads', val=np.ones((ny, 6)) * 2e5, units='N') indep_var_comp.add_output('load_factor', val=1.) struct_group = SpatialBeamAlone(surface=surf_dict) # Add indep_vars to the structural group struct_group.add_subsystem('indep_vars', indep_var_comp, promotes=['*']) prob.model.add_subsystem(surf_dict['name'], struct_group) ## Part-3: Add your design variables, constraints, and objective # Import the Scipy Optimizer and set the driver of the problem to use # it, which defaults to an SLSQP optimization method prob.driver = om.ScipyOptimizeDriver() prob.driver.options['disp'] = True
def test_units_with_scaling(self): prob = om.Problem() model = prob.model ivc = om.IndepVarComp() ivc.add_output('x', 35.0, units='degF') model.add_subsystem('p', ivc, promotes=['x']) model.add_subsystem('comp1', om.ExecComp('y1 = 2.0*x', x={'value': 2.0, 'units': 'degF'}, y1={'value': 2.0, 'units': 'degF'}), promotes=['x', 'y1']) model.add_subsystem('comp2', om.ExecComp('y2 = 3.0*x', x={'value': 2.0, 'units': 'degF'}, y2={'value': 2.0, 'units': 'degF'}), promotes=['x', 'y2']) model.add_design_var('x', units='degC', lower=0.0, upper=100.0, scaler=3.5, adder=77.0) model.add_constraint('y1', units='degC', lower=0.0, upper=100.0, scaler=3.5, adder=77.0) model.add_objective('y2', units='degC', scaler=3.5, adder=77.0) recorder = om.SqliteRecorder('cases.sql') prob.driver.add_recorder(recorder) prob.driver.recording_options['record_objectives'] = True prob.driver.recording_options['record_constraints'] = True prob.driver.recording_options['record_desvars'] = True prob.setup() prob.run_driver() dv = prob.driver.get_design_var_values() assert_near_equal(dv['p.x'][0], ((3.0 * 5 / 9) + 77.0) * 3.5, 1e-8) obj = prob.driver.get_objective_values(driver_scaling=True) assert_near_equal(obj['comp2.y2'][0], ((73.0 * 5 / 9) + 77.0) * 3.5, 1e-8) con = prob.driver.get_constraint_values(driver_scaling=True) assert_near_equal(con['comp1.y1'][0], ((38.0 * 5 / 9) + 77.0) * 3.5, 1e-8) meta = model.get_design_vars() assert_near_equal(meta['p.x']['lower'], ((0.0) + 77.0) * 3.5, 1e-7) assert_near_equal(meta['p.x']['upper'], ((100.0) + 77.0) * 3.5, 1e-7) meta = model.get_constraints() assert_near_equal(meta['comp1.y1']['lower'], ((0.0) + 77.0) * 3.5, 1e-7) assert_near_equal(meta['comp1.y1']['upper'], ((100.0) + 77.0) * 3.5, 1e-7) stdout = sys.stdout strout = StringIO() sys.stdout = strout try: prob.list_problem_vars(desvar_opts=['units'], objs_opts=['units'], cons_opts=['units']) finally: sys.stdout = stdout output = strout.getvalue().split('\n') self.assertTrue('275.33' in output[5]) self.assertTrue('343.3888' in output[12]) self.assertTrue('411.444' in output[19]) self.assertTrue('degC' in output[5]) self.assertTrue('degC' in output[12]) self.assertTrue('degC' in output[19]) totals = prob.check_totals(out_stream=None, driver_scaling=True) for key, val in totals.items(): assert_near_equal(val['rel error'][0], 0.0, 1e-6) cr = om.CaseReader("cases.sql") cases = cr.list_cases('driver') case = cr.get_case(cases[0]) dv = case.get_design_vars() assert_near_equal(dv['p.x'][0], ((3.0 * 5 / 9) + 77.0) * 3.5, 1e-8) obj = case.get_objectives() assert_near_equal(obj['comp2.y2'][0], ((73.0 * 5 / 9) + 77.0) * 3.5, 1e-8) con = case.get_constraints() assert_near_equal(con['comp1.y1'][0], ((38.0 * 5 / 9) + 77.0) * 3.5, 1e-8)
def setUp(self): self.p = om.Problem(model=om.Group()) ivp = self.p.model.add_subsystem('ivc', subsys=om.IndepVarComp(), promotes_outputs=['*']) ndn = 20 nn = 30 ivp.add_output('phase0:x', val=np.zeros((ndn, 1)), units='m') ivp.add_output('phase0:u', val=np.zeros((nn, 3)), units='deg') ivp.add_output('phase0:v', val=np.zeros((nn, 3, 3)), units='N') ivp.add_output('phase1:x', val=np.zeros((ndn, 1)), units='m') ivp.add_output('phase1:u', val=np.zeros((nn, 3)), units='deg') ivp.add_output('phase1:v', val=np.zeros((nn, 3, 3)), units='N') linkage_comp = PhaseLinkageComp() linkage_comp.add_linkage('L01a', vars=('x', ), equals=0.0, shape=(1, ), units='m') linkage_comp.add_linkage('L01b', vars=('u', ), equals=0.0, shape=(3, ), units='deg') linkage_comp.add_linkage('L01c', vars=('v', ), equals=0.0, shape=(3, 3), units='N') self.p.model.add_subsystem('linkage_comp', subsys=linkage_comp) self.p.model.connect('phase0:x', 'linkage_comp.L01a_x:lhs', src_indices=[-1], flat_src_indices=True) self.p.model.connect('phase1:x', 'linkage_comp.L01a_x:rhs', src_indices=[0], flat_src_indices=True) self.p.model.connect('phase0:u', 'linkage_comp.L01b_u:lhs', src_indices=np.arange(-3, 0, dtype=int), flat_src_indices=True) self.p.model.connect('phase1:u', 'linkage_comp.L01b_u:rhs', src_indices=np.arange(0, 3, dtype=int), flat_src_indices=True) self.p.model.connect('phase0:v', 'linkage_comp.L01c_v:lhs', src_indices=np.arange(-9, 0, dtype=int).reshape( (3, 3)), flat_src_indices=True) self.p.model.connect('phase1:v', 'linkage_comp.L01c_v:rhs', src_indices=np.arange(0, 9, dtype=int).reshape( (3, 3)), flat_src_indices=True) self.p.setup() self.p['phase0:x'] = np.random.rand(*self.p['phase0:x'].shape) self.p['phase0:u'] = np.random.rand(*self.p['phase0:u'].shape) self.p['phase0:v'] = np.random.rand(*self.p['phase0:v'].shape) self.p['phase1:x'] = np.random.rand(*self.p['phase1:x'].shape) self.p['phase1:u'] = np.random.rand(*self.p['phase1:u'].shape) self.p['phase1:v'] = np.random.rand(*self.p['phase1:v'].shape) self.p.run_model()
def test_simplified_ode_timeseries_output(self): """ # upgrade_doc: begin simplified_ode_output_timeseries phase.add_timeseries_output('tas_comp.TAS', shape=(1,), units='m/s') # upgrade_doc: end simplified_ode_output_timeseries """ import openmdao.api as om import dymos as dm from dymos.examples.aircraft_steady_flight.aircraft_ode import AircraftODE p = om.Problem(model=om.Group()) p.driver = om.ScipyOptimizeDriver() p.driver.declare_coloring() transcription = dm.GaussLobatto(num_segments=1, order=13, compressed=False) phase = dm.Phase(ode_class=AircraftODE, transcription=transcription) p.model.add_subsystem('phase0', phase) # Pass Reference Area from an external source assumptions = p.model.add_subsystem('assumptions', om.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') phase.set_time_options(initial_bounds=(0, 0), duration_bounds=(3600, 3600), duration_ref=3600) phase.set_time_options(initial_bounds=(0, 0), duration_bounds=(3600, 3600), duration_ref=3600) phase.add_state('range', units='km', fix_initial=True, fix_final=False, scaler=0.01, rate_source='range_rate_comp.dXdt:range', defect_scaler=0.01) phase.add_state('mass_fuel', units='kg', fix_final=True, upper=20000.0, lower=0.0, rate_source='propulsion.dXdt:mass_fuel', scaler=1.0E-4, defect_scaler=1.0E-2) phase.add_state('alt', rate_source='climb_rate', units='km', fix_initial=True) phase.add_control('mach', targets=['tas_comp.mach', 'aero.mach'], units=None, opt=False) phase.add_control('climb_rate', targets=['gam_comp.climb_rate'], units='m/s', opt=False) phase.add_parameter( 'S', targets=['aero.S', 'flight_equilibrium.S', 'propulsion.S'], units='m**2') phase.add_parameter('mass_empty', targets=['mass_comp.mass_empty'], units='kg') phase.add_parameter('mass_payload', targets=['mass_comp.mass_payload'], units='kg') phase.add_path_constraint('propulsion.tau', lower=0.01, upper=1.0, shape=(1, )) # upgrade_doc: begin simplified_ode_output_timeseries phase.add_timeseries_output('tas_comp.TAS') # upgrade_doc: end simplified_ode_output_timeseries p.model.connect('assumptions.S', 'phase0.parameters:S') p.model.connect('assumptions.mass_empty', 'phase0.parameters:mass_empty') p.model.connect('assumptions.mass_payload', 'phase0.parameters:mass_payload') phase.add_objective('time', loc='final', ref=3600) p.model.linear_solver = om.DirectSolver() 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.states:alt'] = 5.0 p['phase0.controls:mach'] = 0.8 p['phase0.controls:climb_rate'] = 0.0 p['assumptions.S'] = 427.8 p['assumptions.mass_empty'] = 0.15E6 p['assumptions.mass_payload'] = 84.02869 * 400 dm.run_problem(p) time = p.get_val('phase0.timeseries.time') tas = p.get_val('phase0.timeseries.TAS', units='km/s') range = p.get_val('phase0.timeseries.states:range') assert_near_equal(range, tas * time, tolerance=1.0E-4) exp_out = phase.simulate() time = exp_out.get_val('phase0.timeseries.time') tas = exp_out.get_val('phase0.timeseries.TAS', units='km/s') range = exp_out.get_val('phase0.timeseries.states:range') assert_near_equal(range, tas * time, tolerance=1.0E-4)
def test_array_list_vars_options(self): class ArrayAdder(om.ExplicitComponent): """ Just a simple component that has array inputs and outputs """ def __init__(self, size): super(ArrayAdder, self).__init__() self.size = size def setup(self): self.add_input('x', val=np.zeros(self.size), units='inch') self.add_output('y', val=np.zeros(self.size), units='ft') def compute(self, inputs, outputs): outputs['y'] = inputs['x'] + 10.0 size = 100 # how many items in the array prob = om.Problem() prob.model.add_subsystem('des_vars', om.IndepVarComp('x', np.ones(size), units='inch'), promotes=['x']) prob.model.add_subsystem('mult', ArrayAdder(size), promotes=['x', 'y']) prob.setup() prob['x'] = np.ones(size) prob.run_driver() # logging inputs # out_stream - not hierarchical - extras - no print_arrays stream = cStringIO() prob.model.list_inputs(values=True, units=True, hierarchical=False, print_arrays=False, out_stream=stream) text = stream.getvalue() self.assertEqual(1, text.count("1 Input(s) in 'model'")) self.assertEqual(1, text.count('mult.x')) num_non_empty_lines = sum([1 for s in text.splitlines() if s.strip()]) self.assertEqual(5, num_non_empty_lines) # out_stream - hierarchical - extras - no print_arrays stream = cStringIO() prob.model.list_inputs(values=True, units=True, hierarchical=True, print_arrays=False, out_stream=stream) text = stream.getvalue() self.assertEqual(1, text.count("1 Input(s) in 'model'")) num_non_empty_lines = sum([1 for s in text.splitlines() if s.strip()]) self.assertEqual(7, num_non_empty_lines) self.assertEqual(1, text.count('top')) self.assertEqual(1, text.count(' mult')) self.assertEqual(1, text.count(' x')) # logging outputs # out_stream - not hierarchical - extras - no print_arrays stream = cStringIO() prob.model.list_outputs(values=True, units=True, shape=True, bounds=True, residuals=True, scaling=True, hierarchical=False, print_arrays=False, out_stream=stream) text = stream.getvalue() self.assertEqual(text.count('2 Explicit Output'), 1) # make sure they are in the correct order self.assertTrue(text.find("des_vars.x") < text.find('mult.y')) num_non_empty_lines = sum([1 for s in text.splitlines() if s.strip()]) self.assertEqual(8, num_non_empty_lines) # Promoted names - no print arrays stream = cStringIO() prob.model.list_outputs(values=True, prom_name=True, print_arrays=False, out_stream=stream) text = stream.getvalue() self.assertEqual(text.count(' x |10.0| x'), 1) self.assertEqual(text.count(' y |110.0| y'), 1) num_non_empty_lines = sum([1 for s in text.splitlines() if s.strip()]) self.assertEqual(num_non_empty_lines, 11) # Hierarchical - no print arrays stream = cStringIO() prob.model.list_outputs(values=True, units=True, shape=True, bounds=True, residuals=True, scaling=True, hierarchical=True, print_arrays=False, out_stream=stream) text = stream.getvalue() self.assertEqual(text.count('top'), 1) self.assertEqual(text.count(' des_vars'), 1) self.assertEqual(text.count(' x'), 1) self.assertEqual(text.count(' mult'), 1) self.assertEqual(text.count(' y'), 1) num_non_empty_lines = sum([1 for s in text.splitlines() if s.strip()]) self.assertEqual(num_non_empty_lines, 11) # Need to explicitly set this to make sure all ways of running this test # result in the same format of the output. When running this test from the # top level via testflo, the format comes out different than if the test is # run individually opts = { 'edgeitems': 3, 'infstr': 'inf', 'linewidth': 75, 'nanstr': 'nan', 'precision': 8, 'suppress': False, 'threshold': 1000, } from distutils.version import LooseVersion if LooseVersion(np.__version__) >= LooseVersion("1.14"): opts['legacy'] = '1.13' with printoptions(**opts): # logging outputs # out_stream - not hierarchical - extras - print_arrays stream = cStringIO() prob.model.list_outputs(values=True, units=True, shape=True, bounds=True, residuals=True, scaling=True, hierarchical=False, print_arrays=True, out_stream=stream) text = stream.getvalue() self.assertEqual(text.count('2 Explicit Output'), 1) self.assertEqual(text.count('value:'), 2) self.assertEqual(text.count('resids:'), 2) self.assertEqual(text.count('['), 4) # make sure they are in the correct order self.assertTrue(text.find("des_vars.x") < text.find('mult.y')) num_non_empty_lines = sum( [1 for s in text.splitlines() if s.strip()]) self.assertEqual(46, num_non_empty_lines) # Hierarchical stream = cStringIO() prob.model.list_outputs(values=True, units=True, shape=True, bounds=True, residuals=True, scaling=True, hierarchical=True, print_arrays=True, out_stream=stream) text = stream.getvalue() self.assertEqual(text.count('2 Explicit Output'), 1) self.assertEqual(text.count('value:'), 2) self.assertEqual(text.count('resids:'), 2) self.assertEqual(text.count('['), 4) self.assertEqual(text.count('top'), 1) self.assertEqual(text.count(' des_vars'), 1) self.assertEqual(text.count(' x'), 1) self.assertEqual(text.count(' mult'), 1) self.assertEqual(text.count(' y'), 1) num_non_empty_lines = sum( [1 for s in text.splitlines() if s.strip()]) self.assertEqual(num_non_empty_lines, 49)
def test_for_docs_array_list_vars_options(self): import numpy as np import openmdao.api as om from openmdao.utils.general_utils import printoptions class ArrayAdder(om.ExplicitComponent): """ Just a simple component that has array inputs and outputs """ def __init__(self, size): super(ArrayAdder, self).__init__() self.size = size def setup(self): self.add_input('x', val=np.zeros(self.size), units='inch') self.add_output('y', val=np.zeros(self.size), units='ft') def compute(self, inputs, outputs): outputs['y'] = inputs['x'] + 10.0 size = 30 prob = om.Problem() prob.model.add_subsystem('des_vars', om.IndepVarComp('x', np.ones(size), units='inch'), promotes=['x']) prob.model.add_subsystem('mult', ArrayAdder(size), promotes=['x', 'y']) prob.setup() prob['x'] = np.arange(size) prob.run_driver() prob.model.list_inputs(values=True, units=True, hierarchical=True, print_arrays=True) with printoptions(edgeitems=3, infstr='inf', linewidth=75, nanstr='nan', precision=8, suppress=False, threshold=1000, formatter=None): prob.model.list_outputs(values=True, implicit=False, units=True, shape=True, bounds=True, residuals=True, scaling=True, hierarchical=False, print_arrays=True) prob.model.list_outputs(values=True, implicit=False, units=True, shape=True, bounds=True, residuals=True, scaling=True, hierarchical=True, print_arrays=True)
def test_for_feature_docs_list_vars_options(self): import openmdao.api as om prob = om.Problem() model = prob.model model.add_subsystem( 'p1', om.IndepVarComp( 'x', 12.0, lower=1.0, upper=100.0, ref=1.1, ref0=2.1, units='inch', )) model.add_subsystem( 'p2', om.IndepVarComp( 'y', 1.0, lower=2.0, upper=200.0, ref=1.2, res_ref=2.2, units='ft', )) model.add_subsystem( 'comp', om.ExecComp('z=x+y', x={ 'value': 0.0, 'units': 'inch' }, y={ 'value': 0.0, 'units': 'inch' }, z={ 'value': 0.0, 'units': 'inch' })) model.connect('p1.x', 'comp.x') model.connect('p2.y', 'comp.y') prob.setup() prob.set_solver_print(level=0) prob.run_model() inputs = prob.model.list_inputs(units=True) print(inputs) outputs = prob.model.list_outputs(implicit=False, values=True, units=True, shape=True, bounds=True, residuals=True, scaling=True, hierarchical=False, print_arrays=False) self.assertEqual(sorted(outputs), [ ('comp.z', { 'value': [24.], 'resids': [0.], 'units': 'inch', 'shape': (1, ), 'lower': None, 'upper': None, 'ref': 1.0, 'ref0': 0.0, 'res_ref': 1.0 }), ('p1.x', { 'value': [12.], 'resids': [0.], 'units': 'inch', 'shape': (1, ), 'lower': [1.], 'upper': [100.], 'ref': 1.1, 'ref0': 2.1, 'res_ref': 1.1 }), ('p2.y', { 'value': [1.], 'resids': [0.], 'units': 'ft', 'shape': (1, ), 'lower': [2.], 'upper': [200.], 'ref': 1.2, 'ref0': 0.0, 'res_ref': 2.2 }), ]) outputs = prob.model.list_outputs(implicit=False, values=True, units=True, shape=True, bounds=True, residuals=True, scaling=True, hierarchical=True, print_arrays=False)
def test_hierarchy_list_vars_options(self): prob = om.Problem() model = prob.model model.add_subsystem('pz', om.IndepVarComp('z', np.array([5.0, 2.0]))) sub1 = model.add_subsystem('sub1', om.Group()) sub2 = sub1.add_subsystem('sub2', om.Group()) g1 = sub2.add_subsystem('g1', SubSellar()) g2 = model.add_subsystem('g2', SubSellar()) model.connect('pz.z', 'sub1.sub2.g1.z') model.connect('sub1.sub2.g1.y2', 'g2.x') model.connect('g2.y2', 'sub1.sub2.g1.x') model.nonlinear_solver = om.NewtonSolver() model.linear_solver = om.ScipyKrylov() model.nonlinear_solver.options['solve_subsystems'] = True model.nonlinear_solver.options['max_sub_solves'] = 0 g1.nonlinear_solver = om.NewtonSolver() g1.linear_solver = om.LinearBlockGS() g2.nonlinear_solver = om.NewtonSolver() g2.linear_solver = om.ScipyKrylov() g2.linear_solver.precon = om.LinearBlockGS() g2.linear_solver.precon.options['maxiter'] = 2 prob.setup() prob.run_driver() # logging inputs # out_stream - not hierarchical - extras - no print_arrays stream = cStringIO() prob.model.list_inputs(values=True, units=True, hierarchical=False, print_arrays=False, out_stream=stream) text = stream.getvalue() self.assertEqual(1, text.count("10 Input(s) in 'model'")) # make sure they are in the correct order self.assertTrue( text.find("sub1.sub2.g1.d1.z") < text.find('sub1.sub2.g1.d1.x') < text.find('sub1.sub2.g1.d1.y2') < text.find('sub1.sub2.g1.d2.z') < text.find('sub1.sub2.g1.d2.y1') < text.find('g2.d1.z') < text.find( 'g2.d1.x') < text.find('g2.d1.y2') < text.find( 'g2.d2.z') < text.find('g2.d2.y1')) num_non_empty_lines = sum([1 for s in text.splitlines() if s.strip()]) self.assertEqual(14, num_non_empty_lines) # out_stream - hierarchical - extras - no print_arrays stream = cStringIO() prob.model.list_inputs(values=True, units=True, hierarchical=True, print_arrays=False, out_stream=stream) text = stream.getvalue() self.assertEqual(1, text.count("10 Input(s) in 'model'")) num_non_empty_lines = sum([1 for s in text.splitlines() if s.strip()]) self.assertEqual(23, num_non_empty_lines) self.assertEqual(1, text.count('top')) self.assertEqual(1, text.count(' sub1')) self.assertEqual(1, text.count(' sub2')) self.assertEqual(1, text.count(' g1')) self.assertEqual(1, text.count(' d1')) self.assertEqual(2, text.count(' z')) # logging outputs # out_stream - not hierarchical - extras - no print_arrays stream = cStringIO() prob.model.list_outputs(values=True, units=True, shape=True, bounds=True, residuals=True, scaling=True, hierarchical=False, print_arrays=False, out_stream=stream) text = stream.getvalue() self.assertEqual(text.count('5 Explicit Output'), 1) # make sure they are in the correct order self.assertTrue( text.find("pz.z") < text.find('sub1.sub2.g1.d1.y1') < text.find( 'sub1.sub2.g1.d2.y2') < text.find('g2.d1.y1') < text.find( 'g2.d2.y2')) num_non_empty_lines = sum([1 for s in text.splitlines() if s.strip()]) self.assertEqual(11, num_non_empty_lines) # Hierarchical stream = cStringIO() prob.model.list_outputs(values=True, units=True, shape=True, bounds=True, residuals=True, scaling=True, hierarchical=True, print_arrays=False, out_stream=stream) text = stream.getvalue() self.assertEqual(text.count('top'), 1) self.assertEqual(text.count(' y1'), 1) self.assertEqual(text.count(' g2'), 1) num_non_empty_lines = sum([1 for s in text.splitlines() if s.strip()]) self.assertEqual(num_non_empty_lines, 21)
def test_simple_list_vars_options(self): import openmdao.api as om prob = om.Problem() model = prob.model model.add_subsystem( 'p1', om.IndepVarComp('x', 12.0, lower=1.0, upper=100.0, ref=1.1, ref0=2.1, units='inch')) model.add_subsystem( 'p2', om.IndepVarComp('y', 1.0, lower=2.0, upper=200.0, ref=1.2, res_ref=2.2, units='ft')) model.add_subsystem( 'comp', om.ExecComp('z=x+y', x={ 'value': 0.0, 'units': 'inch' }, y={ 'value': 0.0, 'units': 'inch' }, z={ 'value': 0.0, 'units': 'inch' })) model.connect('p1.x', 'comp.x') model.connect('p2.y', 'comp.y') prob.setup() # list outputs before model has been run will raise an exception msg = "Group (<model>): Unable to list outputs on a Group until model has been run." try: prob.model.list_outputs() except Exception as err: self.assertEqual(str(err), msg) else: self.fail("Exception expected") # list_inputs on a component before run is okay, using relative names expl_inputs = prob.model.comp.list_inputs(out_stream=None) expected = {'x': {'value': 0.}, 'y': {'value': 0.}} self.assertEqual(dict(expl_inputs), expected) expl_inputs = prob.model.comp.list_inputs(includes='x', out_stream=None) self.assertEqual(dict(expl_inputs), {'x': {'value': 0.}}) expl_inputs = prob.model.comp.list_inputs(excludes='x', out_stream=None) self.assertEqual(dict(expl_inputs), {'y': {'value': 0.}}) # specifying prom_name should not cause an error expl_inputs = prob.model.comp.list_inputs(prom_name=True, out_stream=None) self.assertEqual( dict(expl_inputs), { 'x': { 'value': 0., 'prom_name': 'x' }, 'y': { 'value': 0., 'prom_name': 'y' }, }) # list_outputs on a component before run is okay, using relative names expl_outputs = prob.model.p1.list_outputs(out_stream=None) expected = {'x': {'value': 12.}} self.assertEqual(dict(expl_outputs), expected) expl_outputs = prob.model.p1.list_outputs(includes='x', out_stream=None) self.assertEqual(dict(expl_outputs), expected) expl_outputs = prob.model.p1.list_outputs(excludes='x', out_stream=None) self.assertEqual(dict(expl_outputs), {}) # specifying residuals_tol should not cause an error expl_outputs = prob.model.p1.list_outputs(residuals_tol=.01, out_stream=None) self.assertEqual(dict(expl_outputs), expected) # specifying prom_name should not cause an error expl_outputs = prob.model.p1.list_outputs(prom_name=True, out_stream=None) self.assertEqual(dict(expl_outputs), {'x': { 'value': 12., 'prom_name': 'x' }}) # run model prob.set_solver_print(level=0) prob.run_model() # list_inputs tests # Can't do exact equality here because units cause comp.y to be slightly different than 12.0 stream = cStringIO() inputs = prob.model.list_inputs(units=True, shape=True, out_stream=stream) tol = 1e-7 for actual, expected in zip(sorted(inputs), [('comp.x', { 'value': [12.], 'shape': (1, ), 'units': 'inch' }), ('comp.y', { 'value': [12.], 'shape': (1, ), 'units': 'inch' })]): self.assertEqual(expected[0], actual[0]) self.assertEqual(expected[1]['units'], actual[1]['units']) self.assertEqual(expected[1]['shape'], actual[1]['shape']) assert_rel_error(self, expected[1]['value'], actual[1]['value'], tol) text = stream.getvalue() self.assertEqual(1, text.count("Input(s) in 'model'")) self.assertEqual(1, text.count('varname')) self.assertEqual(1, text.count('value')) self.assertEqual(1, text.count('shape')) self.assertEqual(1, text.count('top')) self.assertEqual(1, text.count(' comp')) self.assertEqual(1, text.count(' x')) self.assertEqual(1, text.count(' y')) num_non_empty_lines = sum([1 for s in text.splitlines() if s.strip()]) self.assertEqual(8, num_non_empty_lines) # list_outputs tests # list outputs for implicit comps - should get none outputs = prob.model.list_outputs(implicit=True, explicit=False, out_stream=None) self.assertEqual(outputs, []) # list outputs with out_stream - just check to see if it was logged to stream = cStringIO() outputs = prob.model.list_outputs(out_stream=stream) text = stream.getvalue() self.assertEqual(1, text.count('Explicit Output')) self.assertEqual(1, text.count('Implicit Output')) # list outputs with out_stream and all the optional display values True stream = cStringIO() outputs = prob.model.list_outputs(values=True, units=True, shape=True, bounds=True, residuals=True, scaling=True, hierarchical=False, print_arrays=False, out_stream=stream) self.assertEqual([ ('comp.z', { 'value': [24.], 'resids': [0.], 'units': 'inch', 'shape': (1, ), 'lower': None, 'upper': None, 'ref': 1.0, 'ref0': 0.0, 'res_ref': 1.0 }), ('p1.x', { 'value': [12.], 'resids': [0.], 'units': 'inch', 'shape': (1, ), 'lower': [1.], 'upper': [100.], 'ref': 1.1, 'ref0': 2.1, 'res_ref': 1.1 }), ('p2.y', { 'value': [1.], 'resids': [0.], 'units': 'ft', 'shape': (1, ), 'lower': [2.], 'upper': [200.], 'ref': 1.2, 'ref0': 0.0, 'res_ref': 2.2 }), ], sorted(outputs)) text = stream.getvalue() self.assertEqual(1, text.count('varname')) self.assertEqual(1, text.count('value')) self.assertEqual(1, text.count('resids')) self.assertEqual(1, text.count('units')) self.assertEqual(1, text.count('shape')) self.assertEqual(1, text.count('lower')) self.assertEqual(1, text.count('upper')) self.assertEqual(3, text.count('ref')) self.assertEqual(1, text.count('ref0')) self.assertEqual(1, text.count('res_ref')) self.assertEqual(1, text.count('p1.x')) self.assertEqual(1, text.count('p2.y')) self.assertEqual(1, text.count('comp.z')) num_non_empty_lines = sum([1 for s in text.splitlines() if s.strip()]) self.assertEqual(9, num_non_empty_lines)
def test_steady_aircraft_for_docs(self): import matplotlib.pyplot as plt import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal import dymos as dm from dymos.examples.aircraft_steady_flight.aircraft_ode import AircraftODE from dymos.examples.plotting import plot_results from dymos.utils.lgl import lgl p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.options['optimizer'] = 'SLSQP' p.driver.declare_coloring() num_seg = 15 seg_ends, _ = lgl(num_seg + 1) traj = p.model.add_subsystem('traj', dm.Trajectory()) phase = traj.add_phase('phase0', dm.Phase(ode_class=AircraftODE, transcription=dm.Radau(num_segments=num_seg, segment_ends=seg_ends, order=3, compressed=False))) # Pass Reference Area from an external source assumptions = p.model.add_subsystem('assumptions', om.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') phase.set_time_options(fix_initial=True, duration_bounds=(300, 10000), duration_ref=5600) phase.add_state('range', units='NM', rate_source='range_rate_comp.dXdt:range', fix_initial=True, fix_final=False, ref=1e-3, defect_ref=1e-3, lower=0, upper=2000) phase.add_state('mass_fuel', units='lbm', rate_source='propulsion.dXdt:mass_fuel', fix_initial=True, fix_final=True, upper=1.5E5, lower=0.0, ref=1e2, defect_ref=1e2) phase.add_state('alt', units='kft', rate_source='climb_rate', fix_initial=True, fix_final=True, lower=0.0, upper=60, ref=1e-3, defect_ref=1e-3) phase.add_control('climb_rate', units='ft/min', opt=True, lower=-3000, upper=3000, targets=['gam_comp.climb_rate'], rate_continuity=True, rate2_continuity=False) phase.add_control('mach', targets=['tas_comp.mach', 'aero.mach'], units=None, opt=False) phase.add_parameter('S', targets=['aero.S', 'flight_equilibrium.S', 'propulsion.S'], units='m**2') phase.add_parameter('mass_empty', targets=['mass_comp.mass_empty'], units='kg') phase.add_parameter('mass_payload', targets=['mass_comp.mass_payload'], units='kg') phase.add_path_constraint('propulsion.tau', lower=0.01, upper=2.0, shape=(1,)) p.model.connect('assumptions.S', 'traj.phase0.parameters:S') p.model.connect('assumptions.mass_empty', 'traj.phase0.parameters:mass_empty') p.model.connect('assumptions.mass_payload', 'traj.phase0.parameters:mass_payload') phase.add_objective('range', loc='final', ref=-1.0e-4) phase.add_timeseries_output('aero.CL') phase.add_timeseries_output('aero.CD') p.setup() p['traj.phase0.t_initial'] = 0.0 p['traj.phase0.t_duration'] = 3600.0 p['traj.phase0.states:range'][:] = phase.interpolate(ys=(0, 724.0), nodes='state_input') p['traj.phase0.states:mass_fuel'][:] = phase.interpolate(ys=(30000, 1e-3), nodes='state_input') p['traj.phase0.states:alt'][:] = 10.0 p['traj.phase0.controls:mach'][:] = 0.8 p['assumptions.S'] = 427.8 p['assumptions.mass_empty'] = 0.15E6 p['assumptions.mass_payload'] = 84.02869 * 400 dm.run_problem(p) assert_near_equal(p.get_val('traj.phase0.timeseries.states:range', units='NM')[-1], 726.85, tolerance=1.0E-2) exp_out = traj.simulate() assert_near_equal(p.get_val('traj.phase0.timeseries.CL')[0], exp_out.get_val('traj.phase0.timeseries.CL')[0], tolerance=1.0E-9) assert_near_equal(p.get_val('traj.phase0.timeseries.CD')[0], exp_out.get_val('traj.phase0.timeseries.CD')[0], tolerance=1.0E-9) plot_results([('traj.phase0.timeseries.states:range', 'traj.phase0.timeseries.states:alt', 'range (NM)', 'altitude (kft)'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.states:mass_fuel', 'time (s)', 'fuel mass (lbm)'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.CL', 'time (s)', 'lift coefficient'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.CD', 'time (s)', 'drag coefficient')], title='Commercial Aircraft Optimization', p_sol=p, p_sim=exp_out) plt.show()
def test_nonlinear_circuit_analysis(self): import numpy as np import openmdao.api as om class Resistor(om.ExplicitComponent): """Computes current across a resistor using Ohm's law.""" def initialize(self): self.options.declare('R', default=1., desc='Resistance in Ohms') def setup(self): self.add_input('V_in', units='V') self.add_input('V_out', units='V') self.add_output('I', units='A') # partial derivs are constant, so we can assign their values in setup R = self.options['R'] self.declare_partials('I', 'V_in', val=1 / R) self.declare_partials('I', 'V_out', val=-1 / R) def compute(self, inputs, outputs): deltaV = inputs['V_in'] - inputs['V_out'] outputs['I'] = deltaV / self.options['R'] class Diode(om.ExplicitComponent): """Computes current across a diode using the Shockley diode equation.""" def initialize(self): self.options.declare('Is', default=1e-15, desc='Saturation current in Amps') self.options.declare('Vt', default=.025875, desc='Thermal voltage in Volts') def setup(self): self.add_input('V_in', units='V') self.add_input('V_out', units='V') self.add_output('I', units='A') # non-linear component, so we'll declare the partials here but compute them in compute_partials self.declare_partials('I', 'V_in') self.declare_partials('I', 'V_out') def compute(self, inputs, outputs): deltaV = inputs['V_in'] - inputs['V_out'] Is = self.options['Is'] Vt = self.options['Vt'] outputs['I'] = Is * (np.exp(deltaV / Vt) - 1) def compute_partials(self, inputs, J): deltaV = inputs['V_in'] - inputs['V_out'] Is = self.options['Is'] Vt = self.options['Vt'] I = Is * np.exp(deltaV / Vt) J['I', 'V_in'] = I/Vt J['I', 'V_out'] = -I/Vt class Node(om.ImplicitComponent): """Computes voltage residual across a node based on incoming and outgoing current.""" def initialize(self): self.options.declare('n_in', default=1, types=int, desc='number of connections with + assumed in') self.options.declare('n_out', default=1, types=int, desc='number of current connections + assumed out') def setup(self): self.add_output('V', val=5., units='V') for i in range(self.options['n_in']): i_name = 'I_in:{}'.format(i) self.add_input(i_name, units='A') self.declare_partials('V', i_name, val=1) for i in range(self.options['n_out']): i_name = 'I_out:{}'.format(i) self.add_input(i_name, units='A') self.declare_partials('V', i_name, val=-1) # note: we don't declare any partials wrt `V` here, # because the residual doesn't directly depend on it def apply_nonlinear(self, inputs, outputs, residuals): residuals['V'] = 0. for i_conn in range(self.options['n_in']): residuals['V'] += inputs['I_in:{}'.format(i_conn)] for i_conn in range(self.options['n_out']): residuals['V'] -= inputs['I_out:{}'.format(i_conn)] class Circuit(om.Group): 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 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() # set some initial guesses p['circuit.n1.V'] = 10. p['circuit.n2.V'] = 1e-3 p.run_model() assert_near_equal(p['circuit.n1.V'], 9.90804735, 1e-5) assert_near_equal(p['circuit.n2.V'], 0.71278185, 1e-5) assert_near_equal(p['circuit.R1.I'], 0.09908047, 1e-5) assert_near_equal(p['circuit.R2.I'], 0.00091953, 1e-5) assert_near_equal(p['circuit.D1.I'], 0.00091953, 1e-5) # sanity check: should sum to .1 Amps assert_near_equal(p['circuit.R1.I'] + p['circuit.D1.I'], .1, 1e-6)
def test_partial_deriv_plot(self): class ArrayComp2D(om.ExplicitComponent): """ A fairly simple array component with an intentional error in compute_partials. """ def setup(self): self.JJ = np.array([[1.0, 0.0, 0.0, 7.0], [0.0, 2.5, 0.0, 0.0], [-1.0, 0.0, 8.0, 0.0], [0.0, 4.0, 0.0, 6.0]]) # Params self.add_input('x1', np.zeros([4])) # Unknowns self.add_output('y1', np.zeros([4])) self.declare_partials(of='*', wrt='*') def compute(self, inputs, outputs): """ Execution. """ outputs['y1'] = self.JJ.dot(inputs['x1']) def compute_partials(self, inputs, partials): """ Analytical derivatives. """ # create some error to force the diff plot to show something error = np.zeros((4, 4)) err = 1e-7 error[0][3] = err error[1][2] = -2.0 * err partials[('y1', 'x1')] = self.JJ + error prob = om.Problem() model = prob.model model.add_subsystem('x_param1', om.IndepVarComp('x1', np.ones((4))), promotes=['x1']) model.add_subsystem('mycomp', ArrayComp2D(), promotes=['x1', 'y1']) prob.setup(check=False, mode='fwd') check_partials_data = prob.check_partials(out_stream=None) # plot with defaults fig, ax = om.partial_deriv_plot('y1', 'x1', check_partials_data, title="Defaults") # Instead of seeing if the images created by matplotlib match what we expect, which # is a fragile thing to do in testing, check a data structure inside matplotlib's # objects. We will assume matplotlib draws the correct thing. expected_array = np.array([[1., 0., 0., 1.], [0., 1., 0., 0.], [1., 0., 1., 0.], [0., 1., 0., 1.]]) actual_array = ax[0].images[0]._A.data assert_near_equal(expected_array, actual_array, 1e-8) expected_array = np.array([[1., 0., 0., 1.], [0., 1., 1., 0.], [1., 0., 1., 0.], [0., 1., 0., 1.]]) actual_array = ax[1].images[0]._A.data assert_near_equal(expected_array, actual_array, 1e-8) expected_array = np.array([[9.31322575e-10, 0.0, 0.0, 1.0e-07], [0.0, 0.0, -2.0e-07, 0.0], [0.0, 0.0, 9.31322575e-10, 0.0], [0.0, 0.0, 0.0, 1.86264515e-09]]) actual_array = ax[2].images[0]._A.data assert_near_equal(expected_array, actual_array, 1e-8) # plot with specified jac_method fig, ax = om.partial_deriv_plot('y1', 'x1', check_partials_data, jac_method="J_fwd", title="specified jac_method") expected_array = np.array([[1., 0., 0., 1.], [0., 1., 0., 0.], [1., 0., 1., 0.], [0., 1., 0., 1.]]) actual_array = ax[0].images[0]._A.data assert_near_equal(expected_array, actual_array, 1e-8) expected_array = np.array([[1., 0., 0., 1.], [0., 1., 1., 0.], [1., 0., 1., 0.], [0., 1., 0., 1.]]) actual_array = ax[1].images[0]._A.data assert_near_equal(expected_array, actual_array, 1e-8) expected_array = np.array([[9.31322575e-10, 0.0, 0.0, 1.0e-07], [0.0, 0.0, -2.0e-07, 0.0], [0.0, 0.0, 9.31322575e-10, 0.0], [0.0, 0.0, 0.0, 1.86264515e-09]]) actual_array = ax[2].images[0]._A.data assert_near_equal(expected_array, actual_array, 1e-8) # plot in non-binary mode fig, ax = om.partial_deriv_plot('y1', 'x1', check_partials_data, binary=False, title="non-binary") expected_array = np.array([[1., 0., 0., 7.], [0., 2.5, 0., 0.], [-1., 0., 8., 0.], [0., 4., 0., 6.]]) actual_array = ax[0].images[0]._A.data assert_near_equal(expected_array, actual_array, 1e-8) expected_array = np.array([[1.0e+00, 0.0, 0.0, 7.00000010e+00], [0.0, 2.5e+00, -2.0e-07, 0.0], [-1.0e+00, 0.0, 8.0e+00, 0.0], [0.0, 4.0e+00, 0.0, 6.0e+00]]) actual_array = ax[1].images[0]._A.data assert_near_equal(expected_array, actual_array, 1e-8) expected_array = np.array([[9.31322575e-10, 0.0, 0.0, 1.0e-07], [0.0, 0.0, -2.0e-07, 0.0], [0.0, 0.0, 9.31322575e-10, 0.0], [0.0, 0.0, 0.0, 1.86264515e-09]]) actual_array = ax[2].images[0]._A.data assert_near_equal(expected_array, actual_array, 1e-8) # plot with different tol values # Not obvious how to test this other than image matching om.partial_deriv_plot('y1', 'x1', check_partials_data, tol=1e-5, title="tol greater than err") om.partial_deriv_plot('y1', 'x1', check_partials_data, tol=1e-10, title="tol less than err")
# -*- coding: utf-8 -*- """ Created on Tue Nov 26 17:03:44 2019 @author: Morimoto Lab """ import openmdao.api as om import numpy as np from model import Paraboloid # We'll use the component that was defined in the last tutorial N = 20 # build the model prob = om.Problem() indeps = prob.model.add_subsystem('indeps', om.IndepVarComp()) """indeps.add_output('x', 3.0) indeps.add_output('y', -4.0)""" indeps.add_output('length1', np.ones(N) * 20) indeps.add_output('length2', np.ones(N) * 2) """indeps.add_output('length3', np.ones(10))""" indeps.add_output('length4', np.ones(N) * 10) """indeps.add_output('kappa1', 1)""" indeps.add_output('kappa2', 1) """indeps.add_output('kappa3', 1)""" indeps.add_output('kb1', 1) indeps.add_output('kb2', 1) indeps.add_output('kb3', 1) indeps.add_output('l22', np.ones(N) * 10) indeps.add_output('psi2', np.ones(N))
def setup(self): ivc = om.IndepVarComp() # opts = self.options gd = self.options['grid_data'] control_options = self.options['control_options'] time_units = self.options['time_units'] if len(control_options) < 1: return opt_controls = [ name for (name, opts) in iteritems(control_options) if opts['opt'] ] if len(opt_controls) > 0: ivc = self.add_subsystem('indep_controls', subsys=om.IndepVarComp(), promotes_outputs=['*']) self.add_subsystem('control_interp_comp', subsys=ControlInterpComp( time_units=time_units, grid_data=gd, control_options=control_options), promotes_inputs=['*'], promotes_outputs=['*']) for name, options in iteritems(control_options): if options['opt']: num_input_nodes = gd.subset_num_nodes['control_input'] desvar_indices = list( range(gd.subset_num_nodes['control_input'])) if options['fix_initial']: desvar_indices.pop(0) if options['fix_final']: desvar_indices.pop() if len(desvar_indices) > 0: coerce_desvar = CoerceDesvar( gd.subset_num_nodes['control_disc'], desvar_indices, options) lb = -INF_BOUND if coerce_desvar( 'lower') is None else coerce_desvar('lower') ub = INF_BOUND if coerce_desvar( 'upper') is None else coerce_desvar('upper') self.add_design_var(name='controls:{0}'.format(name), lower=lb, upper=ub, scaler=coerce_desvar('scaler'), adder=coerce_desvar('adder'), ref0=coerce_desvar('ref0'), ref=coerce_desvar('ref'), indices=desvar_indices) ivc.add_output(name='controls:{0}'.format(name), val=options['val'], shape=(num_input_nodes, np.prod(options['shape'])), units=options['units'])
def setup(self): E = self.options['E'] L = self.options['L'] b = self.options['b'] volume = self.options['volume'] max_bending = self.options['max_bending'] num_elements = self.options['num_elements'] num_nodes = num_elements + 1 num_cp = self.options['num_cp'] num_load_cases = self.options['num_load_cases'] parallel_derivs = self.options['parallel_derivs'] inputs_comp = om.IndepVarComp() inputs_comp.add_output('h_cp', shape=num_cp) self.add_subsystem('inputs_comp', inputs_comp) x_interp = sine_distribution(num_elements) comp = om.SplineComp(method='bsplines', num_cp=num_cp, x_interp_val=x_interp) comp.add_spline(y_cp_name='h_cp', y_interp_name='h') self.add_subsystem('interp', comp) I_comp = MomentOfInertiaComp(num_elements=num_elements, b=b) self.add_subsystem('I_comp', I_comp) comp = LocalStiffnessMatrixComp(num_elements=num_elements, E=E, L=L) self.add_subsystem('local_stiffness_matrix_comp', comp) # Parallel Subsystem for load cases. par = self.add_subsystem('parallel', om.ParallelGroup()) # Determine how to split cases up over the available procs. nprocs = self.comm.size divide = divide_cases(num_load_cases, nprocs) for j, this_proc in enumerate(divide): num_rhs = len(this_proc) name = 'sub_%d' % j sub = par.add_subsystem(name, om.Group()) # Load is a sinusoidal distributed force of varying spatial frequency. force_vector = np.zeros((2 * num_nodes, num_rhs)) for i, k in enumerate(this_proc): end = 1.5 * np.pi if num_load_cases > 1: end += k * 0.5 * np.pi / (num_load_cases - 1) x = np.linspace(0, end, num_nodes) f = -np.sin(x) force_vector[0:-1:2, i] = f comp = MultiStatesComp(num_elements=num_elements, force_vector=force_vector, num_rhs=num_rhs) sub.add_subsystem('states_comp', comp) comp = MultiStressComp(num_elements=num_elements, E=E, num_rhs=num_rhs) sub.add_subsystem('stress_comp', comp) self.connect('local_stiffness_matrix_comp.K_local', 'parallel.%s.states_comp.K_local' % name) for k in range(num_rhs): sub.connect('states_comp.d_%d' % k, 'stress_comp.displacements_%d' % k, src_indices=np.arange(2 * num_nodes)) if parallel_derivs: color = 'red_%d' % k else: color = None comp = om.KSComp( width=num_elements, upper=max_bending, add_constraint=self.options['ks_add_constraint'], parallel_deriv_color=color) sub.add_subsystem('KS_%d' % k, comp) sub.connect('stress_comp.stress_%d' % k, 'KS_%d.g' % k) if not self.options['ks_add_constraint']: sub.add_constraint('KS_%d.KS' % k, upper=0.0, parallel_deriv_color=color) comp = VolumeComp(num_elements=num_elements, b=b, L=L) self.add_subsystem('volume_comp', comp) self.connect('inputs_comp.h_cp', 'interp.h_cp') self.connect('interp.h', 'I_comp.h') self.connect('I_comp.I', 'local_stiffness_matrix_comp.I') self.connect('interp.h', 'volume_comp.h') self.add_design_var('inputs_comp.h_cp', lower=1e-2, upper=10.) self.add_objective('volume_comp.volume')
def test_prob_getval_dist_disc(self): size = 14 p = om.Problem() top = p.model ivc = om.IndepVarComp() ivc.add_output('invec', np.ones(size)) ivc.add_discrete_output('disc_in', 'C1foo') top.add_subsystem('P', ivc) top.connect('P.invec', 'C1.invec') top.connect('P.disc_in', 'C1.disc_in') C1 = top.add_subsystem( "C1", DistribInputDistribOutputDiscreteComp(arr_size=size)) p.setup() # Conclude setup but don't run model. p.final_setup() rank = p.comm.rank p['P.invec'] = np.array([[4, 3, 2, 1, 8, 6, 4, 2, 9, 6, 3, 12, 8, 4.0]]) p['P.disc_in'] = 'boo' p.run_model() if rank == 0: ans = p.get_val('C1.invec', get_remote=False) np.testing.assert_allclose(ans, np.array([4, 3, 2, 1], dtype=float)) ans = p.get_val('C1.outvec', get_remote=False) np.testing.assert_allclose(ans, np.array([8, 6, 4, 2], dtype=float)) elif rank == 1: ans = p.get_val('C1.invec', get_remote=False) np.testing.assert_allclose(ans, np.array([8, 6, 4, 2], dtype=float)) ans = p.get_val('C1.outvec', get_remote=False) np.testing.assert_allclose(ans, np.array([16, 12, 8, 4], dtype=float)) elif rank == 2: ans = p.get_val('C1.invec', get_remote=False) np.testing.assert_allclose(ans, np.array([9, 6, 3], dtype=float)) ans = p.get_val('C1.outvec', get_remote=False) np.testing.assert_allclose(ans, np.array([18, 12, 6], dtype=float)) elif rank == 3: ans = p.get_val('C1.invec', get_remote=False) np.testing.assert_allclose(ans, np.array([12, 8, 4], dtype=float)) ans = p.get_val('C1.outvec', get_remote=False) np.testing.assert_allclose(ans, np.array([24, 16, 8], dtype=float)) ans = p.get_val('C1.invec', get_remote=True) np.testing.assert_allclose( ans, np.array([4, 3, 2, 1, 8, 6, 4, 2, 9, 6, 3, 12, 8, 4], dtype=float)) ans = p.get_val('C1.outvec', get_remote=True) np.testing.assert_allclose( ans, np.array([8, 6, 4, 2, 16, 12, 8, 4, 18, 12, 6, 24, 16, 8], dtype=float)) ans = p.get_val('C1.disc_in', get_remote=False) self.assertEqual(ans, 'boo') ans = p.get_val('C1.disc_in', get_remote=True) self.assertEqual(ans, 'boo') ans = p.get_val('C1.disc_out', get_remote=False) self.assertEqual(ans, 'boobar') ans = p.get_val('C1.disc_out', get_remote=True) self.assertEqual(ans, 'boobar')
def test(self): # Create a dictionary to store options about the surface mesh_dict = { 'num_y': 7, 'wing_type': 'CRM', 'symmetry': True, 'num_twist_cp': 5 } mesh, twist_cp = generate_mesh(mesh_dict) surf_dict = { # Wing definition 'name': 'wing', # name of the surface 'symmetry': True, # if true, model one half of wing # reflected across the plane y = 0 'fem_model_type': 'tube', 'mesh': mesh, # Structural values are based on aluminum 7075 'E': 70.e9, # [Pa] Young's modulus of the spar 'G': 30.e9, # [Pa] shear modulus of the spar 'yield': 500.e6 / 2.5, # [Pa] yield stress divided by 2.5 for limiting case 'mrho': 3.e3, # [kg/m^3] material density 'fem_origin': 0.35, # normalized chordwise location of the spar 't_over_c_cp': np.array([0.15]), # maximum airfoil thickness 'thickness_cp': np.ones((3)) * .1, 'wing_weight_ratio': 2., 'struct_weight_relief': False, # True to add the weight of the structure to the loads on the structure 'distributed_fuel_weight': False, 'exact_failure_constraint': False, } # Create the problem and assign the model group prob = om.Problem() ny = surf_dict['mesh'].shape[1] indep_var_comp = om.IndepVarComp() indep_var_comp.add_output('loads', val=np.ones((ny, 6)) * 2e5, units='N') indep_var_comp.add_output('load_factor', val=2.) struct_group = SpatialBeamAlone(surface=surf_dict) # Add indep_vars to the structural group struct_group.add_subsystem('indep_vars', indep_var_comp, promotes=['*']) prob.model.add_subsystem(surf_dict['name'], struct_group) # Set up the problem prob.setup() prob.run_model() assert_rel_error(self, prob['wing.structural_mass'][0], 124229.646011, 1e-4)
def test(self): # Create a dictionary to store options about the surface mesh_dict = { 'num_y': 5, 'num_x': 3, 'wing_type': 'CRM', 'symmetry': True, 'num_twist_cp': 6, 'chord_cos_spacing': 0, 'span_cos_spacing': 0, } mesh, twist_cp = generate_mesh(mesh_dict) surf_dict = { # Wing definition 'name': 'wing', # name of the surface 'symmetry': True, # if true, model one half of wing # reflected across the plane y = 0 'S_ref_type': 'wetted', # how we compute the wing area, # can be 'wetted' or 'projected' 'fem_model_type': 'wingbox', 'spar_thickness_cp': np.array([0.004, 0.005, 0.005, 0.008, 0.008, 0.01]), # [m] 'skin_thickness_cp': np.array([0.005, 0.01, 0.015, 0.020, 0.025, 0.026]), 'twist_cp': np.array([4., 5., 8., 8., 8., 9.]), 'mesh': mesh, 'data_x_upper': upper_x, 'data_x_lower': lower_x, 'data_y_upper': upper_y, 'data_y_lower': lower_y, 'strength_factor_for_upper_skin': 1., # Aerodynamic performance of the lifting surface at # an angle of attack of 0 (alpha=0). # These CL0 and CD0 values are added to the CL and CD # obtained from aerodynamic analysis of the surface to get # the total CL and CD. # These CL0 and CD0 values do not vary wrt alpha. 'CL0': 0.0, # CL of the surface at alpha=0 'CD0': 0.0078, # CD of the surface at alpha=0 # Airfoil properties for viscous drag calculation 'k_lam': 0.05, # percentage of chord with laminar # flow, used for viscous drag 't_over_c_cp': np.array([0.08, 0.08, 0.08, 0.10, 0.10, 0.08]), 'original_wingbox_airfoil_t_over_c': 0.12, 'c_max_t': .38, # chordwise location of maximum thickness 'with_viscous': True, 'with_wave': False, # if true, compute wave drag # Structural values are based on aluminum 7075 'E': 73.1e9, # [Pa] Young's modulus 'G': ( 73.1e9 / 2 / 1.33 ), # [Pa] shear modulus (calculated using E and the Poisson's ratio here) 'yield': (420.e6 / 1.5), # [Pa] allowable yield stress 'mrho': 2.78e3, # [kg/m^3] material density 'strength_factor_for_upper_skin': 1.0, # the yield stress is multiplied by this factor for the upper skin # 'fem_origin' : 0.35, # normalized chordwise location of the spar 'wing_weight_ratio': 1.25, 'struct_weight_relief': True, 'distributed_fuel_weight': False, # Constraints 'exact_failure_constraint': False, # if false, use KS function 'Wf_reserve': 15000., # [kg] reserve fuel mass 'span': 58. # [m] } surfaces = [surf_dict] # Create the problem and assign the model group prob = om.Problem() # Add problem information as an independent variables component indep_var_comp = om.IndepVarComp() indep_var_comp.add_output('v', val=.85 * 295.07, units='m/s') indep_var_comp.add_output('alpha', val=0., units='deg') indep_var_comp.add_output('Mach_number', val=0.85) indep_var_comp.add_output('re', val=0.348 * 295.07 * .85 * 1. / (1.43 * 1e-5), units='1/m') indep_var_comp.add_output('rho', val=0.348, units='kg/m**3') indep_var_comp.add_output('CT', val=0.53 / 3600, units='1/s') indep_var_comp.add_output('R', val=14.307e6, units='m') indep_var_comp.add_output('W0', val=148000 + surf_dict['Wf_reserve'], units='kg') indep_var_comp.add_output('speed_of_sound', val=295.07, units='m/s') indep_var_comp.add_output('load_factor', val=1.) indep_var_comp.add_output('empty_cg', val=np.zeros((3)), units='m') prob.model.add_subsystem('prob_vars', indep_var_comp, promotes=['*']) # Loop over each surface in the surfaces list for surface in surfaces: # Get the surface name and create a group to contain components # only for this surface name = surface['name'] aerostruct_group = AerostructGeometry(surface=surface) # Add tmp_group to the problem with the name of the surface. prob.model.add_subsystem(name, aerostruct_group) # Loop through and add a certain number of aero points for i in range(1): point_name = 'AS_point_{}'.format(i) # Connect the parameters within the model for each aero point # Create the aero point group and add it to the model AS_point = AerostructPoint(surfaces=surfaces) prob.model.add_subsystem(point_name, AS_point) # Connect flow properties to the analysis point prob.model.connect('v', point_name + '.v') prob.model.connect('alpha', point_name + '.alpha') prob.model.connect('Mach_number', point_name + '.Mach_number') prob.model.connect('re', point_name + '.re') prob.model.connect('rho', point_name + '.rho') prob.model.connect('CT', point_name + '.CT') prob.model.connect('R', point_name + '.R') prob.model.connect('W0', point_name + '.W0') prob.model.connect('speed_of_sound', point_name + '.speed_of_sound') prob.model.connect('empty_cg', point_name + '.empty_cg') prob.model.connect('load_factor', point_name + '.load_factor') for surface in surfaces: com_name = point_name + '.' + name + '_perf.' prob.model.connect( name + '.local_stiff_transformed', point_name + '.coupled.' + name + '.local_stiff_transformed') prob.model.connect(name + '.nodes', point_name + '.coupled.' + name + '.nodes') # Connect aerodyamic mesh to coupled group mesh prob.model.connect(name + '.mesh', point_name + '.coupled.' + name + '.mesh') prob.model.connect( name + '.element_mass', point_name + '.coupled.' + name + '.element_mass') # Connect performance calculation variables prob.model.connect(name + '.nodes', com_name + 'nodes') prob.model.connect( name + '.cg_location', point_name + '.' + 'total_perf.' + name + '_cg_location') prob.model.connect( name + '.structural_mass', point_name + '.' + 'total_perf.' + name + '_structural_mass') # Connect wingbox properties to von Mises stress calcs prob.model.connect(name + '.Qz', com_name + 'Qz') prob.model.connect(name + '.J', com_name + 'J') prob.model.connect(name + '.A_enc', com_name + 'A_enc') prob.model.connect(name + '.htop', com_name + 'htop') prob.model.connect(name + '.hbottom', com_name + 'hbottom') prob.model.connect(name + '.hfront', com_name + 'hfront') prob.model.connect(name + '.hrear', com_name + 'hrear') prob.model.connect(name + '.spar_thickness', com_name + 'spar_thickness') prob.model.connect(name + '.t_over_c', com_name + 't_over_c') prob.driver = om.ScipyOptimizeDriver() prob.driver.options['tol'] = 1e-9 # prob.driver = om.pyOptSparseDriver() # prob.driver.options['optimizer'] = "SNOPT" # prob.driver.opt_settings['Major optimality tolerance'] = 1e-6 # prob.driver.opt_settings['Major feasibility tolerance'] = 1e-8 # prob.driver.opt_settings['Major iterations limit'] = 200 # prob.driver.add_recorder(om.SqliteRecorder("wingbox.db")) # prob.driver.recording_options['record_derivatives'] = True # prob.driver.recording_options['includes'] = ['*'] prob.model.add_objective('AS_point_0.fuelburn', scaler=1e-5) # prob.model.add_design_var('alpha', lower=-15., upper=15.) prob.model.add_design_var('wing.twist_cp', lower=-15., upper=15., scaler=0.1) prob.model.add_design_var('wing.spar_thickness_cp', lower=0.003, upper=0.1, scaler=1e2) prob.model.add_design_var('wing.skin_thickness_cp', lower=0.003, upper=0.1, scaler=1e2) prob.model.add_design_var('wing.geometry.t_over_c_cp', lower=0.07, upper=0.2, scaler=10.) prob.model.add_design_var('wing.geometry.span', lower=55., upper=60., scaler=2e-2) prob.model.add_constraint('AS_point_0.CL', equals=0.5) # prob.model.add_constraint('AS_point_0.L_equals_W', equals=0.) prob.model.add_constraint('AS_point_0.wing_perf.failure', upper=0.) # prob.model.add_constraint('coupled.wing_loads.fuel_vol_delta', lower=0.) # Set up the problem prob.setup() # om.view_model(prob) prob.run_driver() # prob.check_partials(form='central', compact_print=True) # print(prob['AS_point_0.fuelburn'][0]) # print(prob['wing.structural_mass'][0]/1.25) # print(prob['wing.geometry.span']) assert_rel_error(self, prob['AS_point_0.fuelburn'][0], 84387.962001, 1e-5) assert_rel_error(self, prob['wing.structural_mass'][0] / 1.25, 13974.684240, 1e-5) assert_rel_error(self, prob['wing.geometry.span'][0], 60., 1e-5)
pde_problem.add_scalar_output('avg_density', avg_density_form, 'density') # Add output-compliance to the PDE problem: compliance_form = df.dot(f, displacements_function) * dss(6) pde_problem.add_scalar_output('compliance', compliance_form, 'displacements') # Add boundary conditions to the PDE problem: pde_problem.add_bc(df.DirichletBC(displacements_function_space, df.Constant((0.0, 0.0, 0.0)), '(abs(x[1]-30.) < DOLFIN_EPS)')) # Define the OpenMDAO problem and model prob = om.Problem() num_dof_density = pde_problem.inputs_dict['density']['function'].function_space().dim() # Add design variables---density on each element: comp = om.IndepVarComp() comp.add_output( 'density_unfiltered', shape=num_dof_density, val=np.random.random(num_dof_density) * 0.86, ) prob.model.add_subsystem('indep_var_comp', comp, promotes=['*']) # add the filter and specifying the filter radius--num_element_filtered=2 comp = GeneralFilterComp(density_function_space=density_function_space, num_element_filtered=2) prob.model.add_subsystem('general_filter_comp', comp, promotes=['*']) group = AtomicsGroup(pde_problem=pde_problem) prob.model.add_subsystem('atomics_group', group, promotes=['*']) prob.model.add_design_var('density_unfiltered',upper=1, lower=1e-4)
def test(self): # Create a dictionary to store options about the surface mesh_dict = { 'num_y': 5, 'num_x': 2, 'wing_type': 'CRM', 'symmetry': True, 'num_twist_cp': 5 } mesh, twist_cp = generate_mesh(mesh_dict) surf_dict = { # Wing definition 'name': 'wing', # name of the surface 'symmetry': True, # if true, model one half of wing # reflected across the plane y = 0 'S_ref_type': 'wetted', # how we compute the wing area, # can be 'wetted' or 'projected' 'fem_model_type': 'tube', 'thickness_cp': np.array([.1, .2, .3]), 'twist_cp': twist_cp, 'mesh': mesh, # Aerodynamic performance of the lifting surface at # an angle of attack of 0 (alpha=0). # These CL0 and CD0 values are added to the CL and CD # obtained from aerodynamic analysis of the surface to get # the total CL and CD. # These CL0 and CD0 values do not vary wrt alpha. 'CL0': 0.0, # CL of the surface at alpha=0 'CD0': 0.015, # CD of the surface at alpha=0 # Airfoil properties for viscous drag calculation 'k_lam': 0.05, # percentage of chord with laminar # flow, used for viscous drag 't_over_c_cp': np.array([0.15]), # thickness over chord ratio (NACA0015) 'c_max_t': .303, # chordwise location of maximum (NACA0015) # thickness 'with_viscous': True, 'with_wave': False, # if true, compute wave drag # Structural values are based on aluminum 7075 'E': 70.e9, # [Pa] Young's modulus of the spar 'G': 30.e9, # [Pa] shear modulus of the spar 'yield': 500.e6 / 2.5, # [Pa] yield stress divided by 2.5 for limiting case 'mrho': 3.e3, # [kg/m^3] material density 'fem_origin': 0.35, # normalized chordwise location of the spar 'wing_weight_ratio': 2., 'struct_weight_relief': False, # True to add the weight of the structure to the loads on the structure 'distributed_fuel_weight': False, # Constraints 'exact_failure_constraint': False, # if false, use KS function } surfaces = [surf_dict] # Create the problem and assign the model group prob = om.Problem() # Add problem information as an independent variables component indep_var_comp = om.IndepVarComp() indep_var_comp.add_output('v', val=248.136, units='m/s') indep_var_comp.add_output('alpha', val=5., units='deg') indep_var_comp.add_output('Mach_number', val=0.84) indep_var_comp.add_output('re', val=1.e6, units='1/m') indep_var_comp.add_output('rho', val=0.38, units='kg/m**3') indep_var_comp.add_output('CT', val=grav_constant * 17.e-6, units='1/s') indep_var_comp.add_output('R', val=11.165e6, units='m') indep_var_comp.add_output('W0', val=0.4 * 3e5, units='kg') indep_var_comp.add_output('speed_of_sound', val=295.4, units='m/s') indep_var_comp.add_output('load_factor', val=1.) indep_var_comp.add_output('empty_cg', val=np.zeros((3)), units='m') indep_var_comp.add_output('S_ref_total', val=150.0, units='m**2') prob.model.add_subsystem('prob_vars', indep_var_comp, promotes=['*']) # Loop over each surface in the surfaces list for surface in surfaces: # Get the surface name and create a group to contain components # only for this surface name = surface['name'] aerostruct_group = AerostructGeometry(surface=surface) # Add tmp_group to the problem with the name of the surface. prob.model.add_subsystem(name, aerostruct_group) # Loop through and add a certain number of aero points for i in range(1): point_name = 'AS_point_{}'.format(i) # Connect the parameters within the model for each aero point # Create the aero point group and add it to the model AS_point = AerostructPoint(surfaces=surfaces, user_specified_Sref=True) prob.model.add_subsystem(point_name, AS_point) # Connect flow properties to the analysis point prob.model.connect('v', point_name + '.v') prob.model.connect('alpha', point_name + '.alpha') prob.model.connect('Mach_number', point_name + '.Mach_number') prob.model.connect('re', point_name + '.re') prob.model.connect('rho', point_name + '.rho') prob.model.connect('CT', point_name + '.CT') prob.model.connect('R', point_name + '.R') prob.model.connect('W0', point_name + '.W0') prob.model.connect('speed_of_sound', point_name + '.speed_of_sound') prob.model.connect('empty_cg', point_name + '.empty_cg') prob.model.connect('load_factor', point_name + '.load_factor') prob.model.connect('S_ref_total', point_name + '.S_ref_total') for surface in surfaces: com_name = point_name + '.' + name + '_perf' prob.model.connect( name + '.local_stiff_transformed', point_name + '.coupled.' + name + '.local_stiff_transformed') prob.model.connect(name + '.nodes', point_name + '.coupled.' + name + '.nodes') # Connect aerodyamic mesh to coupled group mesh prob.model.connect(name + '.mesh', point_name + '.coupled.' + name + '.mesh') # Connect performance calculation variables prob.model.connect(name + '.radius', com_name + '.radius') prob.model.connect(name + '.thickness', com_name + '.thickness') prob.model.connect(name + '.nodes', com_name + '.nodes') prob.model.connect( name + '.cg_location', point_name + '.' + 'total_perf.' + name + '_cg_location') prob.model.connect( name + '.structural_mass', point_name + '.' + 'total_perf.' + name + '_structural_mass') prob.model.connect(name + '.t_over_c', com_name + '.t_over_c') # Set up the problem prob.setup() # om.view_model(prob) prob.run_model() assert_rel_error(self, prob['AS_point_0.CL'][0], 1.5775046966345903, 1e-6) assert_rel_error(self, prob['AS_point_0.CM'][1], -1.61358383281, 1e-5)
def test_sellar(self): # Basic sellar test. prob = om.Problem() model = prob.model model.add_subsystem('d1', SellarDis1withDerivatives(), promotes=['x', 'z', 'y1', 'y2']) model.add_subsystem('d2', SellarDis2withDerivatives(), promotes=['z', 'y1', 'y2']) model.add_subsystem('obj_cmp', om.ExecComp('obj = x**2 + z[1] + y1 + exp(-y2)', z=np.array([0.0, 0.0]), x=0.0), promotes=['obj', 'x', 'z', 'y1', 'y2']) model.add_subsystem('con_cmp1', om.ExecComp('con1 = 3.16 - y1'), promotes=['con1', 'y1']) model.add_subsystem('con_cmp2', om.ExecComp('con2 = y2 - 24.0'), promotes=['con2', 'y2']) nlbgs = model.nonlinear_solver = om.NonlinearBlockGS() prob.setup() prob.set_val('x', 1.) prob.set_val('z', np.array([5.0, 2.0])) prob.set_solver_print(level=0) prob.run_model() assert_near_equal(prob.get_val('y1'), 25.58830273, .00001) assert_near_equal(prob.get_val('y2'), 12.05848819, .00001) # Make sure we aren't iterating like crazy self.assertEqual(model.nonlinear_solver._iter_count, 8) # Only one extra execution self.assertEqual(model.d1.execution_count, 8) # With run_apply_linear, we execute the components more times. prob = om.Problem() model = prob.model model.add_subsystem('px', om.IndepVarComp('x', 1.0), promotes=['x']) model.add_subsystem('pz', om.IndepVarComp('z', np.array([5.0, 2.0])), promotes=['z']) model.add_subsystem('d1', SellarDis1withDerivatives(), promotes=['x', 'z', 'y1', 'y2']) model.add_subsystem('d2', SellarDis2withDerivatives(), promotes=['z', 'y1', 'y2']) model.add_subsystem('obj_cmp', om.ExecComp('obj = x**2 + z[1] + y1 + exp(-y2)', z=np.array([0.0, 0.0]), x=0.0), promotes=['obj', 'x', 'z', 'y1', 'y2']) model.add_subsystem('con_cmp1', om.ExecComp('con1 = 3.16 - y1'), promotes=['con1', 'y1']) model.add_subsystem('con_cmp2', om.ExecComp('con2 = y2 - 24.0'), promotes=['con2', 'y2']) nlbgs = model.nonlinear_solver = om.NonlinearBlockGS() nlbgs.options['use_apply_nonlinear'] = True prob.setup() prob.set_solver_print(level=0) prob.run_model() assert_near_equal(prob.get_val('y1'), 25.58830273, .00001) assert_near_equal(prob.get_val('y2'), 12.05848819, .00001) # Make sure we aren't iterating like crazy self.assertEqual(model.nonlinear_solver._iter_count, 7) # Nearly double the executions. self.assertEqual(model.d1.execution_count, 15)
def test_units_error_messages(self): prob = om.Problem() model = prob.model ivc = om.IndepVarComp() ivc.add_output('x', 35.0, units='degF') model.add_subsystem('p', ivc, promotes=['x']) model.add_subsystem('comp1', om.ExecComp('y1 = 2.0*x', x={'value': 2.0, 'units': 'degF'}, y1={'value': 2.0, 'units': 'degF'}), promotes=['x', 'y1']) model.add_design_var('x', units='ft', lower=0.0, upper=100.0, scaler=3.5, adder=77.0) prob.setup() with self.assertRaises(RuntimeError) as context: prob.final_setup() msg = "<model> <class Group>: Target for design variable x has 'degF' units, but 'ft' units were specified." self.assertEqual(str(context.exception), msg) prob = om.Problem() model = prob.model ivc = om.IndepVarComp() ivc.add_output('x', 35.0, units='degF') model.add_subsystem('p', ivc, promotes=['x']) model.add_subsystem('comp1', om.ExecComp('y1 = 2.0*x', x={'value': 2.0, 'units': 'degF'}, y1={'value': 2.0, 'units': 'degF'}), promotes=['x', 'y1']) model.add_constraint('x', units='ft', lower=0.0, upper=100.0) prob.setup() with self.assertRaises(RuntimeError) as context: prob.final_setup() msg = "<model> <class Group>: Target for constraint x has 'degF' units, but 'ft' units were specified." self.assertEqual(str(context.exception), msg) prob = om.Problem() model = prob.model ivc = om.IndepVarComp() ivc.add_output('x', 35.0, units=None) model.add_subsystem('p', ivc, promotes=['x']) model.add_subsystem('comp1', om.ExecComp('y1 = 2.0*x', x={'value': 2.0}, y1={'value': 2.0, 'units': 'degF'}), promotes=['x', 'y1']) model.add_design_var('x', units='ft', lower=0.0, upper=100.0, scaler=3.5, adder=77.0) prob.setup() with self.assertRaises(RuntimeError) as context: prob.final_setup() msg = "<model> <class Group>: Target for design variable x has no units, but 'ft' units were specified." self.assertEqual(str(context.exception), msg) prob = om.Problem() model = prob.model ivc = om.IndepVarComp() ivc.add_output('x', 35.0, units=None) model.add_subsystem('p', ivc, promotes=['x']) model.add_subsystem('comp1', om.ExecComp('y1 = 2.0*x', x={'value': 2.0}, y1={'value': 2.0, 'units': 'degF'}), promotes=['x', 'y1']) model.add_constraint('x', units='ft', lower=0.0, upper=100.0) prob.setup() with self.assertRaises(RuntimeError) as context: prob.final_setup() msg = "<model> <class Group>: Target for constraint x has no units, but 'ft' units were specified." self.assertEqual(str(context.exception), msg)
def test_ex_double_integrator_input_times_compressed(self): """ Tests that externally connected t_initial and t_duration function as expected. """ compressed = True p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.declare_coloring() times_ivc = p.model.add_subsystem('times_ivc', om.IndepVarComp(), promotes_outputs=['t0', 'tp']) times_ivc.add_output(name='t0', val=0.0, units='s') times_ivc.add_output(name='tp', val=1.0, units='s') transcription = dm.Radau(num_segments=20, order=3, compressed=compressed) phase = dm.Phase(ode_class=DoubleIntegratorODE, transcription=transcription) p.model.add_subsystem('phase0', phase) p.model.connect('t0', 'phase0.t_initial') p.model.connect('tp', 'phase0.t_duration') phase.set_time_options(input_initial=True, input_duration=True, units='s') phase.add_state('v', fix_initial=True, fix_final=True, rate_source='u', units='m/s') phase.add_state('x', fix_initial=True, rate_source='v', units='m') phase.add_control('u', units='m/s**2', scaler=0.01, continuity=False, rate_continuity=False, rate2_continuity=False, shape=(1, ), lower=-1.0, upper=1.0) # Maximize distance travelled in one second. phase.add_objective('x', loc='final', scaler=-1) p.model.linear_solver = om.DirectSolver() p.setup(check=True) p['t0'] = 0.0 p['tp'] = 1.0 p['phase0.states:x'] = phase.interpolate(ys=[0, 0.25], nodes='state_input') p['phase0.states:v'] = phase.interpolate(ys=[0, 0], nodes='state_input') p['phase0.controls:u'] = phase.interpolate(ys=[1, -1], nodes='control_input') p.run_driver()
def setup(self): self.add_subsystem('dv', om.IndepVarComp('x', 3.0)) self.add_subsystem('comp', om.ExecComp('y = (x-2)**2')) self.connect('dv.x', 'comp.x') self.add_design_var('dv.x', lower=-10, upper=10)
def test(self): # Create a dictionary to store options about the surface mesh_dict = {'num_y' : 5, 'num_x' : 3, 'wing_type' : 'rect', 'symmetry' : False, 'span' : 10., 'chord' : 1, 'span_cos_spacing' : 1.} mesh = generate_mesh(mesh_dict) surf_dict = { # Wing definition 'name' : 'wing', # name of the surface 'symmetry' : False, # if true, model one half of wing # reflected across the plane y = 0 'S_ref_type' : 'wetted', # how we compute the wing area, # can be 'wetted' or 'projected' 'fem_model_type' : 'tube', 'twist_cp' : np.zeros(5), 'mesh' : mesh, # Aerodynamic performance of the lifting surface at # an angle of attack of 0 (alpha=0). # These CL0 and CD0 values are added to the CL and CD # obtained from aerodynamic analysis of the surface to get # the total CL and CD. # These CL0 and CD0 values do not vary wrt alpha. 'CL0' : 0.0, # CL of the surface at alpha=0 'CD0' : 0.0, # CD of the surface at alpha=0 # Airfoil properties for viscous drag calculation 'k_lam' : 0.05, # percentage of chord with laminar # flow, used for viscous drag 't_over_c_cp' : np.array([0.12]), # thickness over chord ratio (NACA0015) 'c_max_t' : .303, # chordwise location of maximum (NACA0015) # thickness 'with_viscous' : True, # if true, compute viscous drag 'with_wave' : False, # if true, compute wave drag 'sweep' : 0., 'dihedral' : 0., } surfaces = [surf_dict] # Create the problem and the model group prob = om.Problem() indep_var_comp = om.IndepVarComp() indep_var_comp.add_output('v', val=248.136, units='m/s') indep_var_comp.add_output('alpha', val=5., units='deg') indep_var_comp.add_output('Mach_number', val=0.84) indep_var_comp.add_output('re', val=1.e6, units='1/m') indep_var_comp.add_output('rho', val=0.38, units='kg/m**3') indep_var_comp.add_output('cg', val=np.zeros((3)), units='m') prob.model.add_subsystem('prob_vars', indep_var_comp, promotes=['*']) # Loop over each surface in the surfaces list for surface in surfaces: geom_group = Geometry(surface=surface) # Add tmp_group to the problem as the name of the surface. # Note that is a group and performance group for each # individual surface. prob.model.add_subsystem(surface['name'], geom_group) # Loop through and add a certain number of aero points for i in range(1): # Create the aero point group and add it to the model aero_group = AeroPoint(surfaces=surfaces) point_name = 'aero_point_{}'.format(i) prob.model.add_subsystem(point_name, aero_group) # Connect flow properties to the analysis point prob.model.connect('v', point_name + '.v') prob.model.connect('alpha', point_name + '.alpha') prob.model.connect('Mach_number', point_name + '.Mach_number') prob.model.connect('re', point_name + '.re') prob.model.connect('rho', point_name + '.rho') prob.model.connect('cg', point_name + '.cg') # Connect the parameters within the model for each aero point for surface in surfaces: name = surface['name'] # Connect the mesh from the geometry component to the analysis point prob.model.connect(name + '.mesh', point_name + '.' + name + '.def_mesh') # Perform the connections with the modified names within the # 'aero_states' group. prob.model.connect(name + '.mesh', point_name + '.aero_states.' + name + '_def_mesh') prob.model.connect(name + '.t_over_c', point_name + '.' + name + '_perf.' + 't_over_c') prob.driver = om.ScipyOptimizeDriver() prob.driver.options['tol'] = 1e-5 # # Setup problem and add design variables, constraint, and objective prob.model.add_design_var('wing.twist_cp', lower=-10., upper=15.) prob.model.add_design_var('wing.sweep', lower=10., upper=30.) prob.model.add_design_var('wing.dihedral', lower=-10., upper=20.) prob.model.add_constraint(point_name + '.wing_perf.CL', equals=0.5) prob.model.add_objective(point_name + '.wing_perf.CD', scaler=1e4) # Set up the problem prob.setup() prob.run_driver() assert_rel_error(self, prob['aero_point_0.wing_perf.CL'][0], 0.5, 1e-5) assert_rel_error(self, prob['aero_point_0.wing_perf.CD'][0], 0.019234984422361764, 1e-3)
def setup(self): surface = self.options['surface'] connect_geom_DVs = self.options['connect_geom_DVs'] # Get the surface name and create a group to contain components # only for this surface ny = surface['mesh'].shape[1] # Check if any control points were added to the surface dict dv_keys = set([ 'twist_cp', 'chord_cp', 'xshear_cp', 'yshear_cp', 'zshear_cp', 'sweep', 'span', 'taper', 'dihedral', 't_over_c_cp' ]) active_dv_keys = dv_keys.intersection(set(surface.keys())) # Make sure that at least one of them is an independent variable make_ivc = False for key in active_dv_keys: if surface.get(key + '_dv', True): make_ivc = True break if make_ivc or self.options['DVGeo']: # Add independent variables that do not belong to a specific component indep_var_comp = om.IndepVarComp() # If connect_geom_DVs is true, then we promote all of the geometric # design variables to their appropriate manipulation functions. # If it's false, then we do not connect them, and the user can # choose to provide different values to those manipulation functions. # This is useful when you want to have morphing DVs, such as twist # or span, that are different at each point in a multipoint scheme. if connect_geom_DVs: self.add_subsystem('indep_vars', indep_var_comp, promotes=['*']) else: self.add_subsystem('indep_vars', indep_var_comp, promotes=[]) if self.options['DVGeo']: from openaerostruct.geometry.ffd_component import GeometryMesh indep_var_comp.add_output('shape', val=np.zeros( (surface['mx'], surface['my'])), units='m') if 't_over_c_cp' in surface.keys(): n_cp = len(surface['t_over_c_cp']) # Add bspline components for active bspline geometric variables. x_interp = np.linspace(0., 1., int(ny - 1)) comp = self.add_subsystem( 't_over_c_bsp', om.SplineComp(method='bsplines', x_interp_val=x_interp, num_cp=n_cp, interp_options={'order': min(n_cp, 4)}), promotes_inputs=['t_over_c_cp'], promotes_outputs=['t_over_c']) comp.add_spline(y_cp_name='t_over_c_cp', y_interp_name='t_over_c') if surface.get('t_over_c_cp_dv', True): indep_var_comp.add_output('t_over_c_cp', val=surface['t_over_c_cp']) self.add_subsystem('mesh', GeometryMesh(surface=surface, DVGeo=self.options['DVGeo']), promotes_inputs=['shape'], promotes_outputs=['mesh']) else: from openaerostruct.geometry.geometry_mesh import GeometryMesh bsp_inputs = [] if 'twist_cp' in surface.keys(): n_cp = len(surface['twist_cp']) # Add bspline components for active bspline geometric variables. x_interp = np.linspace(0., 1., int(ny)) comp = self.add_subsystem( 'twist_bsp', om.SplineComp(method='bsplines', x_interp_val=x_interp, num_cp=n_cp, interp_options={'order': min(n_cp, 4)}), promotes_inputs=['twist_cp'], promotes_outputs=['twist']) comp.add_spline(y_cp_name='twist_cp', y_interp_name='twist') bsp_inputs.append('twist') # Since default assumption is that we want tail rotation as a design variable, add this to allow for trimmed drag polar where the tail rotation should not be a design variable if surface.get('twist_cp_dv', True): indep_var_comp.add_output('twist_cp', val=surface['twist_cp'], units='deg') if 'chord_cp' in surface.keys(): n_cp = len(surface['chord_cp']) # Add bspline components for active bspline geometric variables. x_interp = np.linspace(0., 1., int(ny)) comp = self.add_subsystem( 'chord_bsp', om.SplineComp(method='bsplines', x_interp_val=x_interp, num_cp=n_cp, interp_options={'order': min(n_cp, 4)}), promotes_inputs=['chord_cp'], promotes_outputs=['chord']) comp.add_spline(y_cp_name='chord_cp', y_interp_name='chord') bsp_inputs.append('chord') if surface.get('chord_cp_dv', True): indep_var_comp.add_output('chord_cp', val=surface['chord_cp'], units='m') if 't_over_c_cp' in surface.keys(): n_cp = len(surface['t_over_c_cp']) # Add bspline components for active bspline geometric variables. x_interp = np.linspace(0., 1., int(ny - 1)) comp = self.add_subsystem( 't_over_c_bsp', om.SplineComp(method='bsplines', x_interp_val=x_interp, num_cp=n_cp, interp_options={'order': min(n_cp, 4)}), promotes_inputs=['t_over_c_cp'], promotes_outputs=['t_over_c']) comp.add_spline(y_cp_name='t_over_c_cp', y_interp_name='t_over_c') if surface.get('t_over_c_cp_dv', True): indep_var_comp.add_output('t_over_c_cp', val=surface['t_over_c_cp']) if 'xshear_cp' in surface.keys(): n_cp = len(surface['xshear_cp']) # Add bspline components for active bspline geometric variables. x_interp = np.linspace(0., 1., int(ny)) comp = self.add_subsystem( 'xshear_bsp', om.SplineComp(method='bsplines', x_interp_val=x_interp, num_cp=n_cp, interp_options={'order': min(n_cp, 4)}), promotes_inputs=['xshear_cp'], promotes_outputs=['xshear']) comp.add_spline(y_cp_name='xshear_cp', y_interp_name='xshear') bsp_inputs.append('xshear') if surface.get('xshear_cp_dv', True): indep_var_comp.add_output('xshear_cp', val=surface['xshear_cp'], units='m') if 'yshear_cp' in surface.keys(): n_cp = len(surface['yshear_cp']) # Add bspline components for active bspline geometric variables. x_interp = np.linspace(0., 1., int(ny)) comp = self.add_subsystem( 'yshear_bsp', om.SplineComp(method='bsplines', x_interp_val=x_interp, num_cp=n_cp, interp_options={'order': min(n_cp, 4)}), promotes_inputs=['yshear_cp'], promotes_outputs=['yshear']) comp.add_spline(y_cp_name='yshear_cp', y_interp_name='yshear') bsp_inputs.append('yshear') if surface.get('yshear_cp_dv', True): indep_var_comp.add_output('yshear_cp', val=surface['yshear_cp'], units='m') if 'zshear_cp' in surface.keys(): n_cp = len(surface['zshear_cp']) # Add bspline components for active bspline geometric variables. x_interp = np.linspace(0., 1., int(ny)) comp = self.add_subsystem( 'zshear_bsp', om.SplineComp(method='bsplines', x_interp_val=x_interp, num_cp=n_cp, interp_options={'order': min(n_cp, 4)}), promotes_inputs=['zshear_cp'], promotes_outputs=['zshear']) comp.add_spline(y_cp_name='zshear_cp', y_interp_name='zshear') bsp_inputs.append('zshear') if surface.get('zshear_cp_dv', True): indep_var_comp.add_output('zshear_cp', val=surface['zshear_cp'], units='m') if 'sweep' in surface.keys(): bsp_inputs.append('sweep') if surface.get('sweep_dv', True): indep_var_comp.add_output('sweep', val=surface['sweep'], units='deg') if 'span' in surface.keys(): bsp_inputs.append('span') if surface.get('span_dv', True): indep_var_comp.add_output('span', val=surface['span'], units='m') if 'dihedral' in surface.keys(): bsp_inputs.append('dihedral') if surface.get('dihedral_dv', True): indep_var_comp.add_output('dihedral', val=surface['dihedral'], units='deg') if 'taper' in surface.keys(): bsp_inputs.append('taper') if surface.get('taper_dv', True): indep_var_comp.add_output('taper', val=surface['taper']) self.add_subsystem('mesh', GeometryMesh(surface=surface), promotes_inputs=bsp_inputs, promotes_outputs=['mesh'])
def setUp(self): dm.options['include_check_partials'] = True self.p = om.Problem(model=om.Group()) ivp = self.p.model.add_subsystem('ivc', subsys=om.IndepVarComp(), promotes_outputs=['*']) ndn = 20 nn = 30 ivp.add_output('phase0:x', val=np.zeros((ndn, 1)), units='m') ivp.add_output('phase0:u', val=np.zeros((nn, 3)), units='deg') ivp.add_output('phase0:v', val=np.zeros((nn, 3, 3)), units='N') ivp.add_output('phase1:x', val=np.zeros((ndn, 1)), units='m') ivp.add_output('phase1:u', val=np.zeros((nn, 3)), units='deg') ivp.add_output('phase1:v', val=np.zeros((nn, 3, 3)), units='N') linkage_comp = PhaseLinkageComp() x_lnk = LinkageOptionsDictionary() x_lnk['phase_a'] = 'phase0' x_lnk['phase_b'] = 'phase1' x_lnk['var_a'] = 'x' x_lnk['var_b'] = 'x' x_lnk['loc_a'] = 'final' x_lnk['loc_b'] = 'initial' x_lnk['units'] = 'm' x_lnk['shape'] = (1, ) x_lnk['equals'] = 0.0 u_lnk = LinkageOptionsDictionary() u_lnk['phase_a'] = 'phase0' u_lnk['phase_b'] = 'phase1' u_lnk['var_a'] = 'u' u_lnk['var_b'] = 'u' u_lnk['loc_a'] = 'final' u_lnk['loc_b'] = 'initial' u_lnk['units'] = 'deg' u_lnk['shape'] = (3, ) u_lnk['equals'] = 0.0 v_lnk = LinkageOptionsDictionary() v_lnk['phase_a'] = 'phase0' v_lnk['phase_b'] = 'phase1' v_lnk['var_a'] = 'v' v_lnk['var_b'] = 'v' v_lnk['loc_a'] = 'final' v_lnk['loc_b'] = 'initial' v_lnk['units'] = 'N' v_lnk['shape'] = (3, 3) v_lnk['equals'] = 0.0 linkage_comp.add_linkage_configure(x_lnk) linkage_comp.add_linkage_configure(u_lnk) linkage_comp.add_linkage_configure(v_lnk) self.p.model.add_subsystem('linkage_comp', subsys=linkage_comp) self.p.model.connect('phase0:x', 'linkage_comp.phase0:x', src_indices=om.slicer[[0, -1], ...]) self.p.model.connect('phase1:x', 'linkage_comp.phase1:x', src_indices=om.slicer[[0, -1], ...]) self.p.model.connect('phase0:u', 'linkage_comp.phase0:u', src_indices=om.slicer[[0, -1], ...]) self.p.model.connect('phase1:u', 'linkage_comp.phase1:u', src_indices=om.slicer[[0, -1], ...]) self.p.model.connect('phase0:v', 'linkage_comp.phase0:v', src_indices=om.slicer[[0, -1], ...]) self.p.model.connect('phase1:v', 'linkage_comp.phase1:v', src_indices=om.slicer[[0, -1], ...]) self.p.setup() self.p['phase0:x'] = np.random.rand(*self.p['phase0:x'].shape) self.p['phase0:u'] = np.random.rand(*self.p['phase0:u'].shape) self.p['phase0:v'] = np.random.rand(*self.p['phase0:v'].shape) self.p['phase1:x'] = np.random.rand(*self.p['phase1:x'].shape) self.p['phase1:u'] = np.random.rand(*self.p['phase1:u'].shape) self.p['phase1:v'] = np.random.rand(*self.p['phase1:v'].shape) self.p.run_model()