def setup(self): super(IntegratorTestValLimits, self).setup() nn = self.options['num_nodes'] ec2 = self.add_subsystem( 'ec2', om.ExecComp( ['df2 = 5.1*x**2 +0.5*x-7.2'], df2={ 'val': 1.0 * np.ones((nn, )), 'units': 'W', 'tags': [ 'integrate', 'state_name:f2', 'state_units:J', 'state_upper:1e20', 'state_lower:-1e20', 'state_val:np.linspace(0,5,' + str(nn) + ')' ] }, x={ 'val': 1.0 * np.ones((nn, )), 'units': 's' })) self.connect('iv.x', 'ec2.x') self.set_order(['iv', 'ec', 'ec2', 'ode_integ'])
def test_driver_options(self): """Tests if F and Pc options can be set.""" prob = om.Problem() indeps = prob.model.add_subsystem('indeps', om.IndepVarComp(), promotes=['*']) indeps.add_output('x', 1.) prob.model.add_subsystem('model', om.ExecComp('y=x**2'), promotes=['*']) prob.driver = GenericDriver( algorithm=DifferentialEvolution(F=.123, Pc=.0123, max_gen=5)) # prob.driver.options['F'] = 0.123 # prob.driver.options['Pc'] = 0.0123 # prob.driver.options['max_gen'] = 5 prob.model.add_design_var('x', lower=-10., upper=10.) prob.model.add_objective('y') prob.setup() prob.run_driver()
def test_feature_scalar_with_default_mult(self): from numpy.testing import assert_almost_equal import openmdao.api as om prob = om.Problem() bal = om.BalanceComp() bal.add_balance('x', use_mult=True, mult_val=2.0) tgt = om.IndepVarComp(name='y_tgt', val=4) exec_comp = om.ExecComp('y=x**2', x={'value': 1}, y={'value': 1}) prob.model.add_subsystem(name='target', subsys=tgt, promotes_outputs=['y_tgt']) prob.model.add_subsystem(name='exec', subsys=exec_comp) prob.model.add_subsystem(name='balance', subsys=bal) prob.model.connect('y_tgt', 'balance.rhs:x') prob.model.connect('balance.x', 'exec.x') prob.model.connect('exec.y', 'balance.lhs:x') prob.model.linear_solver = om.DirectSolver(assemble_jac=True) prob.model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False, maxiter=100, iprint=0) prob.setup() # A reasonable initial guess to find the positive root. prob['balance.x'] = 1.0 prob.run_model() assert_almost_equal(prob['balance.x'], np.sqrt(2), decimal=7)
def test_lower_flag(self): import numpy as np import openmdao.api as om prob = om.Problem() model = prob.model model.add_subsystem('comp', om.ExecComp('y = 3.0*x', x=np.zeros((2, )), y=np.zeros((2, ))), promotes_inputs=['x']) model.add_subsystem('ks', om.KSComp(width=2)) model.connect('comp.y', 'ks.g') model.ks.options['lower_flag'] = True prob.setup() prob.set_val('x', np.array([5.0, 4.0])) prob.run_model() assert_near_equal(prob.get_val('ks.KS'), [[-12.0]])
def test_remote_distrib(self): # this test has remote distributed components (distributed comps under parallel groups) p = om.Problem() indep = p.model.add_subsystem('indep', om.IndepVarComp()) indep.add_output('x1', shape_by_conn=True) par = p.model.add_subsystem('par', om.ParallelGroup()) G1 = par.add_subsystem('G1', DynShapeGroupSeries(2, 1, DistribDynShapeComp)) G2 = par.add_subsystem('G2', DynShapeGroupSeries(2, 1, DistribDynShapeComp)) # 'sink' has a defined shape and dyn shapes propagate in reverse from there. p.model.add_subsystem('sink', om.ExecComp(['y1=x1+x2'], shape=(8, ))) p.model.connect('indep.x1', ['par.G1.C1.x1', 'par.G2.C1.x1']) p.model.connect('par.G1.C2.y1', 'sink.x1', src_indices=om.slicer[:]) p.model.connect('par.G2.C2.y1', 'sink.x2', src_indices=om.slicer[:]) with self.assertRaises(RuntimeError) as cm: p.setup() cname = 'G1' if p.model.comm.rank <= 1 else 'G2' msg = f"'par.{cname}.C1' <class DistribDynShapeComp>: Can't determine src_indices automatically for input 'par.{cname}.C1.x1'. They must be supplied manually." self.assertEqual(str(cm.exception), msg)
def test_feature_vector(self): import numpy as np from numpy.testing import assert_almost_equal import openmdao.api as om n = 100 prob = om.Problem() exec_comp = om.ExecComp('y=b*x+c', b={'value': np.random.uniform(0.01, 100, size=n)}, c={'value': np.random.rand(n)}, x={'value': np.zeros(n)}, y={'value': np.ones(n)}) prob.model.add_subsystem(name='exec', subsys=exec_comp) prob.model.add_subsystem(name='balance', subsys=om.BalanceComp('x', val=np.ones(n))) prob.model.connect('balance.x', 'exec.x') prob.model.connect('exec.y', 'balance.lhs:x') prob.model.linear_solver = om.DirectSolver(assemble_jac=True) prob.model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False, maxiter=100, iprint=0) prob.setup() prob.set_val('balance.x', np.random.rand(n)) prob.run_model() b = prob.get_val('exec.b') c = prob.get_val('exec.c') assert_almost_equal(prob.get_val('balance.x'), -c/b, decimal=6) assert_almost_equal(-c/b, prob.get_val('balance.x'), decimal=6) # expected
def test_units_compute_totals(self): p = om.Problem() p.model.add_subsystem('stuff', om.ExecComp(['y = x', 'cy = x'], x={'units': 'inch'}, y={'units': 'kg'}, cy={'units': 'kg'}), promotes=['*']) p.model.add_design_var('x', units='ft') p.model.add_objective('y', units='lbm') p.model.add_constraint('cy', units='lbm', lower=0) p.setup() p['x'] = 1.0 p.run_model() J_driver = p.driver._compute_totals() fact = convert_units(1.0, 'kg/inch', 'lbm/ft') assert_near_equal(J_driver['stuff.y', 'x'][0, 0], fact, 1e-5) assert_near_equal(J_driver['stuff.cy', 'x'][0, 0], fact, 1e-5)
def test_auto_ivc(self): """ Tests a model with automatically added IndepVarComp. """ filename = 'xdsm_auto_ivc' p = om.Problem() p.model.add_subsystem('paraboloid', om.ExecComp('f = (x-3)**2 + x*y + (y+4)**2 - 3'), promotes_inputs=['x', 'y']) # setup the optimization p.driver = om.ScipyOptimizeDriver() p.driver.options['optimizer'] = 'SLSQP' p.model.add_design_var('x', lower=-50, upper=50) p.model.add_design_var('y', lower=-50, upper=50) p.model.add_objective('paraboloid.f') p.setup() p.final_setup() # Write output write_xdsm(p, filename=filename, out_format=PYXDSM_OUT, show_browser=SHOW, quiet=QUIET, include_indepvarcomps=False) # Not showing the Auto IVC # Check if file was created self.assertTrue(os.path.isfile(filename + '.tex')) write_xdsm(p, filename=filename + '2', out_format=PYXDSM_OUT, show_browser=SHOW, quiet=QUIET, include_indepvarcomps=True) # Showing the Auto IVC # Check if file was created self.assertTrue(os.path.isfile(filename + '2.tex'))
def test_execcomp(self): filename = 'pyxdsm_execcomp' out_format = PYXDSM_OUT p = om.Problem() indeps = p.model.add_subsystem('indeps', om.IndepVarComp(), promotes=['*']) indeps.add_output('x') p.model.add_subsystem('C1', om.ExecComp(['y=2.0*x+1.'], x=2.0), promotes=['*']) p.driver = om.ScipyOptimizeDriver() p.model.add_design_var('x', lower=0.0, upper=10.0) p.model.add_objective('y') p.setup() # Conclude setup but don't run model. p.final_setup() write_xdsm(p, filename=filename, out_format=out_format, quiet=QUIET, show_browser=SHOW, show_parallel=True) # Check if file was created self.assertTrue(os.path.isfile(filename + '.' + out_format)) # Including the expression from the ExecComp formatted in LaTeX write_xdsm(p, filename=filename + "2", out_format=out_format, quiet=QUIET, show_browser=SHOW, show_parallel=True, equations=True) # Check if file was created self.assertTrue(os.path.isfile(filename + '.' + out_format))
def test_vectorized(self): import numpy as np import openmdao.api as om prob = om.Problem() model = prob.model model.add_subsystem( 'px', om.IndepVarComp('x', val=np.array([[5.0, 4.0], [10.0, 8.0]]))) model.add_subsystem( 'comp', om.ExecComp('y = 3.0*x', x=np.zeros((2, 2)), y=np.zeros((2, 2)))) model.add_subsystem('ks', om.KSComp(width=2, vec_size=2)) model.connect('px.x', 'comp.x') model.connect('comp.y', 'ks.g') prob.setup() prob.run_model() assert_rel_error(self, prob['ks.KS'][0], 15.0) assert_rel_error(self, prob['ks.KS'][1], 30.0)
def test_reraise_analylsis_error(self): prob = om.Problem() model = prob.model model.add_subsystem('p1', om.IndepVarComp('x', 0.5)) model.add_subsystem('p2', om.IndepVarComp('x', 3.0)) sub = model.add_subsystem('sub', om.ParallelGroup()) sub.add_subsystem('c1', AEComp()) sub.add_subsystem('c2', AEComp()) model.add_subsystem('obj', om.ExecComp(['val = x1 + x2'])) model.connect('p1.x', 'sub.c1.x') model.connect('p2.x', 'sub.c2.x') model.connect('sub.c1.y', 'obj.x1') model.connect('sub.c2.y', 'obj.x2') prob.driver = AEDriver() prob.setup() handled = prob.run_driver() self.assertTrue(handled)
def test_broadcast_scalar_connection(self): """ OpenMDAO should allow promotion to an input that appears to have a certain shape. Users should be allowed to connect an arbitrary variable with compatible src_indices to that input. """ p = om.Problem() # c1 contains scalar calculations ivc = p.model.add_subsystem('ivc', om.IndepVarComp()) ivc.add_output('y', val=5.0*np.ones(4,)) ivc.add_output('x', val=np.arange(4, dtype=float) + 1) g1 = p.model.add_subsystem('g1', om.Group()) # c2 is vectorized calculations c2 = g1.add_subsystem('c2', om.ExecComp('z = a * y', shape=(4,))) # The ultimate source of a and y may be scalar, or have some other arbitrary shape g1.promotes('c2', inputs=['a'], src_indices=[0, 0, 0, 0], src_shape=(1,)) g1.promotes('c2', inputs=['y'], src_indices=[0, 0, 0, 0], src_shape=(4,)) p.model.connect('ivc.y', 'g1.y') # Now connect only a portion of some other output to a, which appears as a scalar input p.model.connect('ivc.x', 'g1.a', src_indices=[-1]) p.setup() p.run_model() assert_near_equal(p['g1.a'], 4.) assert_near_equal(p.model.g1.get_val('a'), 4.) assert_near_equal(p['g1.y'], [5., 5., 5., 5.]) assert_near_equal(p.model.g1.get_val('y'), [5., 5., 5., 5.]) assert_near_equal(p['g1.c2.y'], [5., 5., 5., 5.]) assert_near_equal(p['g1.c2.a'], [4., 4., 4., 4.]) assert_near_equal(p['g1.c2.z'], [20., 20., 20., 20.])
def test_cycle_rev(self): # now put the DynShapeGroupSeries in a cycle (sink.y2 feeds back into Gdyn.C1.x2), but here, # only the sink outputs are known and inputs are coming from auto_ivcs. p = om.Problem() p.model.add_subsystem('Gdyn', DynShapeGroupSeries(3, 2, DynShapeComp)) p.model.add_subsystem( 'sink', om.ExecComp('y1, y2 = x1*2, x2*2', x1=np.ones((2, 3)), x2=np.ones((4, 2)), y1=np.ones((2, 3)), y2=np.ones((4, 2)))) p.model.connect('Gdyn.C3.y1', 'sink.x1') p.model.connect('Gdyn.C3.y2', 'sink.x2') p.model.connect('sink.y2', 'Gdyn.C1.x2') p.setup() p.run_model() np.testing.assert_allclose(p['sink.y1'], np.ones((2, 3)) * 16) np.testing.assert_allclose(p['sink.y2'], np.ones((4, 2)) * 16) p.run_model() np.testing.assert_allclose(p['sink.y1'], np.ones((2, 3)) * 16) # each time we run_model, the value of sink.y2 will be multiplied by 16 # because of the feedback np.testing.assert_allclose(p['sink.y2'], np.ones((4, 2)) * 256)
def test_rhs_val(self): """ Test solution with a default RHS value and no connected RHS variable. """ n = 1 prob = om.Problem(model=om.Group(assembled_jac_type='dense')) bal = om.BalanceComp('x', rhs_val=4.0) exec_comp = om.ExecComp('y=x**2', x={'value': 1}, y={'value': 1}) prob.model.add_subsystem(name='exec', subsys=exec_comp) prob.model.add_subsystem(name='balance', subsys=bal) prob.model.connect('balance.x', 'exec.x') prob.model.connect('exec.y', 'balance.lhs:x') prob.model.linear_solver = om.DirectSolver(assemble_jac=True) prob.model.nonlinear_solver = om.NewtonSolver(maxiter=100, iprint=0) prob.setup() prob['balance.x'] = np.random.rand(n) prob.run_model() assert_almost_equal(prob['balance.x'], 2.0, decimal=7) cpd = prob.check_partials(out_stream=None) for (of, wrt) in cpd['balance']: assert_almost_equal(cpd['balance'][of, wrt]['abs error'], 0.0, decimal=5)
def test_feature_has_diag_partials(self): import numpy as np import openmdao.api as om p = om.Problem() model = p.model model.add_subsystem('indep', om.IndepVarComp('x', val=np.ones(5))) model.add_subsystem( 'comp', om.ExecComp('y=3.0*x + 2.5', has_diag_partials=True, x=np.ones(5), y=np.ones(5))) model.connect('indep.x', 'comp.x') p.setup() p.run_model() J = p.compute_totals(of=['comp.y'], wrt=['indep.x'], return_format='array') assert_almost_equal(J, np.eye(5) * 3., decimal=6)
def test_multi_dim_src_indices(self): prob = om.Problem() model = prob.model size = 5 model.add_subsystem( 'indeps', om.IndepVarComp('x', np.arange(5).reshape((1, size, 1)))) model.add_subsystem( 'comp', om.ExecComp('y = x * 2.', x=np.zeros((size, )), y=np.zeros((size, )))) src_indices = [[0, i, 0] for i in range(size)] model.connect('indeps.x', 'comp.x', src_indices=src_indices) model.linear_solver = om.DirectSolver() prob.setup() prob.run_model() J = prob.compute_totals(wrt=['indeps.x'], of=['comp.y'], return_format='array') np.testing.assert_almost_equal(J, np.eye(size) * 2.)
def test_abs_array_complex_step(self): prob = om.Problem() C1 = prob.model.add_subsystem( 'C1', om.ExecComp('y=2.0*abs(x)', x=np.ones(3) * -2.0, y=np.zeros(3))) prob.setup() prob.set_solver_print(level=0) prob.run_model() assert_rel_error(self, C1._outputs['y'], np.ones(3) * 4.0, 0.00001) # any positive C1.x should give a 2.0 derivative for dy/dx C1._inputs['x'] = np.ones(3) * 1.0e-10 C1._linearize() assert_rel_error(self, C1._jacobian['y', 'x'], np.eye(3) * 2.0, 0.00001) C1._inputs['x'] = np.ones(3) * -3.0 C1._linearize() assert_rel_error(self, C1._jacobian['y', 'x'], np.eye(3) * -2.0, 0.00001) C1._inputs['x'] = np.zeros(3) C1._linearize() assert_rel_error(self, C1._jacobian['y', 'x'], np.eye(3) * 2.0, 0.00001) C1._inputs['x'] = np.array([1.5, -0.6, 2.4]) C1._linearize() expect = np.zeros((3, 3)) expect[0, 0] = 2.0 expect[1, 1] = -2.0 expect[2, 2] = 2.0 assert_rel_error(self, C1._jacobian['y', 'x'], expect, 0.00001)
def test_nonlinear_solver_stall_detection(self): prob = om.Problem() prob.model.add_subsystem('comp', om.ExecComp('y=3*x+1'), promotes=['*']) balance = prob.model.add_subsystem('balance', om.BalanceComp(), promotes=['*']) balance.add_balance('x', lower=-.1, upper=10, rhs_val=0, lhs_name='y') newton = prob.model.nonlinear_solver = om.NewtonSolver() newton.options['solve_subsystems'] = True newton.options['stall_limit'] = 3 newton.options['stall_tol'] = 1e-8 newton.options['maxiter'] = 100 newton.options['err_on_non_converge'] = True prob.model.linear_solver = om.DirectSolver() prob.setup() with self.assertRaises(om.AnalysisError) as context: prob.run_model() msg = "Solver 'NL: Newton' on system '' stalled after 4 iterations." self.assertEqual(str(context.exception), msg)
def test_cycle_fwd_rev(self): # now put the DynShapeGroupSeries in a cycle (sink.y2 feeds back into Gdyn.C1.x2). Sizes are known # at both ends of the model (the IVC and at the sink) p = om.Problem() indep = p.model.add_subsystem('indep', om.IndepVarComp('x1', val=np.ones((2,3)))) p.model.add_subsystem('Gdyn', DynShapeGroupSeries(3,2, DynShapeComp)) p.model.add_subsystem('sink', om.ExecComp('y1, y2 = x1*2, x2*2', x1=np.ones((2,3)), x2=np.ones((4,2)), y1=np.ones((2,3)), y2=np.ones((4,2)))) p.model.connect('Gdyn.C3.y1', 'sink.x1') p.model.connect('Gdyn.C3.y2', 'sink.x2') p.model.connect('sink.y2', 'Gdyn.C1.x2') p.model.connect('indep.x1', 'Gdyn.C1.x1') p.setup() p.run_model() np.testing.assert_allclose(p['sink.y1'], np.ones((2,3))*16) np.testing.assert_allclose(p['sink.y2'], np.ones((4,2))*16) p.run_model() np.testing.assert_allclose(p['sink.y1'], np.ones((2,3))*16) # each time we run_model, the value of sink.y2 will be multiplied by 16 # because of the feedback np.testing.assert_allclose(p['sink.y2'], np.ones((4,2))*256)
def test_raise_error_on_singular_with_sparsejac(self): prob = om.Problem() model = prob.model comp = om.IndepVarComp() comp.add_output('dXdt:TAS', val=1.0) comp.add_output('accel_target', val=2.0) model.add_subsystem('des_vars', comp, promotes=['*']) teg = model.add_subsystem('thrust_equilibrium_group', subsys=om.Group()) teg.add_subsystem('dynamics', om.ExecComp('z = 2.0*thrust'), promotes=['*']) thrust_bal = om.BalanceComp() thrust_bal.add_balance(name='thrust', val=1207.1, lhs_name='dXdt:TAS', rhs_name='accel_target', eq_units='m/s**2', lower=-10.0, upper=10000.0) teg.add_subsystem(name='thrust_bal', subsys=thrust_bal, promotes_inputs=['dXdt:TAS', 'accel_target'], promotes_outputs=['thrust']) teg.linear_solver = om.DirectSolver(assemble_jac=True) teg.nonlinear_solver = om.NewtonSolver() teg.nonlinear_solver.options['solve_subsystems'] = True teg.nonlinear_solver.options['max_sub_solves'] = 1 teg.nonlinear_solver.options['atol'] = 1e-4 prob.setup() prob.set_solver_print(level=0) with self.assertRaises(RuntimeError) as cm: prob.run_model() expected_msg = "Singular entry found in 'thrust_equilibrium_group' <class Group> for row associated with state/residual 'thrust' ('thrust_equilibrium_group.thrust_bal.thrust') index 0." self.assertEqual(expected_msg, str(cm.exception))
def __init__(self): super(ConvergeDivergeGroups, self).__init__() self.add_subsystem('iv', om.IndepVarComp('x', 2.0)) g1 = self.add_subsystem('g1', om.ParallelGroup()) g1.add_subsystem('c1', om.ExecComp(['y1 = 2.0*x1**2', 'y2 = 3.0*x1' ])) g2 = g1.add_subsystem('g2', om.ParallelGroup()) g2.add_subsystem('c2', om.ExecComp('y1 = 0.5*x1')) g2.add_subsystem('c3', om.ExecComp('y1 = 3.5*x1')) g1.add_subsystem('c4', om.ExecComp(['y1 = x1 + 2.0*x2', 'y2 = 3.0*x1 - 5.0*x2' ])) g3 = self.add_subsystem('g3', om.ParallelGroup()) g3.add_subsystem('c5', om.ExecComp('y1 = 0.8*x1')) g3.add_subsystem('c6', om.ExecComp('y1 = 0.5*x1')) self.add_subsystem('c7', om.ExecComp('y1 = x1 + 3.0*x2')) # make connections self.connect('iv.x', 'g1.c1.x1') g1.connect('c1.y1', 'g2.c2.x1') g1.connect('c1.y2', 'g2.c3.x1') self.connect('g1.g2.c2.y1', 'g1.c4.x1') self.connect('g1.g2.c3.y1', 'g1.c4.x2') self.connect('g1.c4.y1', 'g3.c5.x1') self.connect('g1.c4.y2', 'g3.c6.x1') self.connect('g3.c5.y1', 'c7.x1') self.connect('g3.c6.y1', 'c7.x2')
def test_parallel_group_order(self): prob = om.Problem() model = prob.model model.add_subsystem('p1', om.IndepVarComp('x', 1.0)) model.add_subsystem('p2', om.IndepVarComp('x', 1.0)) parallel = model.add_subsystem('parallel', om.ParallelGroup()) parallel.add_subsystem('c1', om.ExecComp(['y=-2.0*x'])) parallel.add_subsystem('c2', om.ExecComp(['y=5.0*x'])) parallel.connect('c1.y', 'c2.x') parallel = model.add_subsystem('parallel_copy', om.ParallelGroup()) parallel.add_subsystem('comp1', om.ExecComp(['y=-2.0*x'])) parallel.add_subsystem('comp2', om.ExecComp(['y=5.0*x'])) parallel.connect('comp1.y', 'comp2.x') model.add_subsystem('c3', om.ExecComp(['y=3.0*x1+7.0*x2'])) model.add_subsystem('c4', om.ExecComp(['y=3.0*x_copy_1+7.0*x_copy_2'])) model.connect("parallel.c1.y", "c3.x1") model.connect("parallel.c2.y", "c3.x2") model.connect("parallel_copy.comp1.y", "c4.x_copy_1") model.connect("parallel_copy.comp2.y", "c4.x_copy_2") model.connect("p1.x", "parallel.c1.x") model.connect("p1.x", "parallel_copy.comp1.x") testlogger = TestLogger() prob.setup(check=True, mode='fwd', logger=testlogger) msg = "Need to attach NonlinearBlockJac, NewtonSolver, or BroydenSolver to 'parallel' when " \ "connecting components inside parallel groups" with assert_warning(UserWarning, msg): prob.run_model() expected_warning = ("The following systems are executed out-of-order:\n" " System 'parallel.c2' executes out-of-order with respect to its source systems ['parallel.c1']\n" " System 'parallel_copy.comp2' executes out-of-order with respect to its source systems ['parallel_copy.comp1']\n") testlogger.find_in('warning', expected_warning)
def setup(self): E = self.options['E'] L = self.options['L'] b = self.options['b'] volume = self.options['volume'] 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'] inputs_comp = om.IndepVarComp() inputs_comp.add_output('h_cp', shape=num_cp) self.add_subsystem('inputs_comp', inputs_comp) comp = om.BsplinesComp(num_control_points=num_cp, num_points=num_elements, in_name='h_cp', out_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) obj_srcs = [] 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 = MultiDisplacementsComp(num_elements=num_elements, num_rhs=num_rhs) sub.add_subsystem('displacements_comp', comp) comp = MultiComplianceComp(num_elements=num_elements, force_vector=force_vector, num_rhs=num_rhs) sub.add_subsystem('compliance_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, 'displacements_comp.d_%d' % k) sub.connect('displacements_comp.displacements_%d' % k, 'compliance_comp.displacements_%d' % k) obj_srcs.append('parallel.%s.compliance_comp.compliance_%d' % (name, k)) comp = VolumeComp(num_elements=num_elements, b=b, L=L) self.add_subsystem('volume_comp', comp) comp = om.ExecComp([ 'obj = ' + ' + '.join(['compliance_%d' % i for i in range(num_load_cases)]) ]) self.add_subsystem('obj_sum', comp) for j, src in enumerate(obj_srcs): self.connect(src, 'obj_sum.compliance_%d' % j) 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_constraint('volume_comp.volume', equals=volume) self.add_objective('obj_sum.obj')
def setup(self): design = self.options['design'] thermo_data = self.options['thermo_data'] flow1_elements = self.options['Fl_I1_elements'] flow1_thermo = Thermo(thermo_data, init_reacts=flow1_elements) n_flow1_prods = len(flow1_thermo.products) in_flow = FlowIn(fl_name='Fl_I1', num_prods=n_flow1_prods) self.add_subsystem('in_flow1', in_flow, promotes=['Fl_I1:*']) flow2_elements = self.options['Fl_I2_elements'] flow2_thermo = Thermo(thermo_data, init_reacts=flow2_elements) n_flow2_prods = len(flow2_thermo.products) in_flow = FlowIn(fl_name='Fl_I2', num_prods=n_flow2_prods) self.add_subsystem('in_flow2', in_flow, promotes=['Fl_I2:*']) if design: # internal flow station to compute the area that is needed to match the static pressures if self.options['designed_stream'] == 1: Fl1_stat = SetStatic(mode="Ps", thermo_data=thermo_data, init_reacts=flow1_elements, fl_name="Fl_I1_calc:stat") self.add_subsystem('Fl_I1_stat_calc', Fl1_stat, promotes_inputs=[('init_prod_amounts', 'Fl_I1:stat:n'), ('S', 'Fl_I1:tot:S'), ('ht', 'Fl_I1:tot:h'), ('W', 'Fl_I1:stat:W'), ('Ps', 'Fl_I2:stat:P')], promotes_outputs=['Fl_I1_calc:stat*']) self.add_subsystem('area_calc', AreaSum(), promotes_inputs=['Fl_I2:stat:area'], promotes_outputs=[('area_sum', 'area')]) self.connect('Fl_I1_calc:stat:area', 'area_calc.Fl_I1:stat:area') else: Fl2_stat = SetStatic(mode="Ps", thermo_data=thermo_data, init_reacts=flow2_elements, fl_name="Fl_I2_calc:stat") self.add_subsystem('Fl_I2_stat_calc', Fl2_stat, promotes_inputs=[('init_prod_amounts', 'Fl_I2:tot:n'), ('S', 'Fl_I2:tot:S'), ('ht', 'Fl_I2:tot:h'), ('W', 'Fl_I2:stat:W'), ('Ps', 'Fl_I1:stat:P')], promotes_outputs=['Fl_I2_calc:stat:*']) self.add_subsystem('area_calc', AreaSum(), promotes_inputs=['Fl_I1:stat:area'], promotes_outputs=[('area_sum', 'area')]) self.connect('Fl_I2_calc:stat:area', 'area_calc.Fl_I2:stat:area') else: if self.options['designed_stream'] == 1: Fl1_stat = SetStatic(mode="area", thermo_data=thermo_data, init_reacts=flow1_elements, fl_name="Fl_I1_calc:stat") self.add_subsystem('Fl_I1_stat_calc', Fl1_stat, promotes_inputs=[('init_prod_amounts', 'Fl_I1:tot:n'), ('S', 'Fl_I1:tot:S'), ('ht', 'Fl_I1:tot:h'), ('W', 'Fl_I1:stat:W'), ('guess:Pt', 'Fl_I1:tot:P'), ('guess:gamt', 'Fl_I1:tot:gamma')], promotes_outputs=['Fl_I1_calc:stat*']) else: Fl2_stat = SetStatic(mode="area", thermo_data=thermo_data, init_reacts=flow2_elements, fl_name="Fl_I2_calc:stat") self.add_subsystem('Fl_I2_stat_calc', Fl2_stat, promotes_inputs=[('init_prod_amounts', 'Fl_I2:tot:n'), ('S', 'Fl_I2:tot:S'), ('ht', 'Fl_I2:tot:h'), ('W', 'Fl_I2:stat:W'), ('guess:Pt', 'Fl_I2:tot:P'), ('guess:gamt', 'Fl_I2:tot:gamma')], promotes_outputs=['Fl_I2_calc:stat*']) self.add_subsystem('extraction_ratio', om.ExecComp('ER=Pt1/Pt2', Pt1={'units':'Pa'}, Pt2={'units':'Pa'}), promotes_inputs=[('Pt1', 'Fl_I1:tot:P'), ('Pt2', 'Fl_I2:tot:P')], promotes_outputs=['ER']) mix_flow = MixFlow(thermo_data=thermo_data, Fl_I1_elements=self.options['Fl_I1_elements'], Fl_I2_elements=self.options['Fl_I2_elements']) if self.options['designed_stream'] == 1: self.add_subsystem('mix_flow', mix_flow, promotes_inputs=['Fl_I1:tot:h', 'Fl_I1:tot:n', ('Fl_I1:stat:W','Fl_I1_calc:stat:W'), ('Fl_I1:stat:P','Fl_I1_calc:stat:P'), ('Fl_I1:stat:V','Fl_I1_calc:stat:V'), ('Fl_I1:stat:area','Fl_I1_calc:stat:area'), 'Fl_I2:tot:h', 'Fl_I2:tot:n', 'Fl_I2:stat:W', 'Fl_I2:stat:P', 'Fl_I2:stat:V', 'Fl_I2:stat:area']) else: self.add_subsystem('mix_flow', mix_flow, promotes_inputs=['Fl_I1:tot:h', 'Fl_I1:tot:n', 'Fl_I1:stat:W', 'Fl_I1:stat:P', 'Fl_I1:stat:V', 'Fl_I1:stat:area', 'Fl_I2:tot:h', 'Fl_I2:tot:n', ('Fl_I2:stat:W','Fl_I2_calc:stat:W'), ('Fl_I2:stat:P','Fl_I2_calc:stat:P'), ('Fl_I2:stat:V','Fl_I2_calc:stat:V'), ('Fl_I2:stat:area','Fl_I2_calc:stat:area')]) # group to converge for the impulse balance conv = self.add_subsystem('impulse_converge', om.Group(), promotes=['*']) if self.options['internal_solver']: newton = conv.nonlinear_solver = om.NewtonSolver() newton.options['maxiter'] = 30 newton.options['atol'] = 1e-2 newton.options['solve_subsystems'] = True newton.options['max_sub_solves'] = 20 newton.options['reraise_child_analysiserror'] = False newton.linesearch = om.BoundsEnforceLS() newton.linesearch.options['bound_enforcement'] = 'scalar' newton.linesearch.options['iprint'] = -1 conv.linear_solver = om.DirectSolver(assemble_jac=True) out_tot = SetTotal(thermo_data=thermo_data, mode='h', init_reacts=self.options['Fl_I1_elements'], fl_name="Fl_O:tot") conv.add_subsystem('out_tot', out_tot, promotes_outputs=['Fl_O:tot:*']) self.connect('mix_flow.n_mix', 'out_tot.init_prod_amounts') self.connect('mix_flow.ht_mix', 'out_tot.h') # note: gets Pt from the balance comp out_stat = SetStatic(mode="area", thermo_data=thermo_data, init_reacts=self.options['Fl_I1_elements'], fl_name="Fl_O:stat") conv.add_subsystem('out_stat', out_stat, promotes_outputs=['Fl_O:stat:*'], promotes_inputs=['area', ]) self.connect('mix_flow.n_mix', 'out_stat.init_prod_amounts') self.connect('mix_flow.W_mix','out_stat.W') conv.connect('Fl_O:tot:S', 'out_stat.S') self.connect('mix_flow.ht_mix', 'out_stat.ht') conv.connect('Fl_O:tot:P', 'out_stat.guess:Pt') conv.connect('Fl_O:tot:gamma', 'out_stat.guess:gamt') conv.add_subsystem('imp_out', Impulse()) conv.connect('Fl_O:stat:P', 'imp_out.P') conv.connect('Fl_O:stat:area', 'imp_out.area') conv.connect('Fl_O:stat:V', 'imp_out.V') conv.connect('Fl_O:stat:W', 'imp_out.W') balance = conv.add_subsystem('balance', om.BalanceComp()) balance.add_balance('P_tot', val=100, units='psi', eq_units='N', lower=1e-3, upper=10000) conv.connect('balance.P_tot', 'out_tot.P') conv.connect('imp_out.impulse', 'balance.lhs:P_tot') self.connect('mix_flow.impulse_mix', 'balance.rhs:P_tot') #note that this connection comes from outside the convergence group
def _make_tree_model(): p = om.Problem() model = p.model units1 = units2 = 'ft' val = 1.0 g1 = model.add_subsystem("G1", om.Group(), promotes_inputs=['x']) g2 = g1.add_subsystem("G2", om.Group(), promotes_inputs=['x']) g2.add_subsystem("C1", om.ExecComp("y = 2. * x", x={ 'val': val, 'units': units2 }, y={ 'val': 1.0, 'units': units2 }), promotes_inputs=['x']) g2.add_subsystem("C2", om.ExecComp("y = 3. * x", x={ 'val': val, 'units': units1 }, y={ 'val': 1.0, 'units': units1 }), promotes_inputs=['x']) g3 = model.add_subsystem("G3", om.Group(), promotes_inputs=['x']) g3.add_subsystem("C3", om.ExecComp("y = 4. * x", x={ 'val': val, 'units': units1 }, y={ 'val': 1.0, 'units': units1 }), promotes_inputs=['x']) g3.add_subsystem("C4", om.ExecComp("y = 5. * x", x={ 'val': val, 'units': units2 }, y={ 'val': 1.0, 'units': units2 }), promotes_inputs=['x']) par = model.add_subsystem("par", om.ParallelGroup(), promotes_inputs=['x']) g4 = par.add_subsystem("G4", om.Group(), promotes_inputs=['x']) g4.add_subsystem("C5", om.ExecComp("y = 6. * x", x={ 'val': val, 'units': units2 }, y={ 'val': 1.0, 'units': units2 }), promotes_inputs=['x']) g4.add_subsystem("C6", om.ExecComp("y = 7. * x", x={ 'val': val, 'units': units1 }, y={ 'val': 1.0, 'units': units1 }), promotes_inputs=['x']) g5 = par.add_subsystem("G5", om.Group(), promotes_inputs=['x']) g5.add_subsystem("C7", om.ExecComp("y = 8. * x", x={ 'val': val, 'units': units1 }, y={ 'val': 1.0, 'units': units1 }), promotes_inputs=['x']) g5.add_subsystem("C8", om.ExecComp("y = 9. * x", x={ 'val': val, 'units': units2 }, y={ 'val': 1.0, 'units': units2 }), promotes_inputs=['x']) model.add_subsystem("C9", om.ExecComp("y = 10. * x", x={ 'val': val, 'units': units2 }, y={ 'val': 1.0, 'units': units2 }), promotes_inputs=['x']) return p
def test(self): """ This is an opt problem that tests the wingbox model with wave drag and the fuel vol constraint """ # Create a dictionary to store options about the surface mesh_dict = { 'num_y': 7, 'num_x': 2, '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': True, # 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': True, # Constraints 'exact_failure_constraint': False, # if false, use KS function 'fuel_density': 803., # [kg/m^3] fuel density (only needed if the fuel-in-wing volume constraint is used) 'Wf_reserve': 15000., # [kg] reserve fuel mass } 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') indep_var_comp.add_output('fuel_mass', val=10000., units='kg') 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: prob.model.connect('load_factor', point_name + '.coupled.load_factor') com_name = point_name + '.' + name + '_perf.' prob.model.connect( name + '.local_stiff_transformed', point_name + '.coupled.' + name + '.local_stiff_transformed') # 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') prob.model.connect(name + '.nodes', point_name + '.coupled.' + name + '.nodes') # 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') #======================================================================================= # Here we add the fuel volume constraint componenet to the model #======================================================================================= prob.model.add_subsystem('fuel_vol_delta', WingboxFuelVolDelta(surface=surface)) prob.model.connect('AS_point_0.fuelburn', 'fuel_vol_delta.fuelburn') prob.model.connect('wing.struct_setup.fuel_vols', 'fuel_vol_delta.fuel_vols') prob.model.connect( 'wing.struct_setup.fuel_vols', 'AS_point_0.coupled.wing.struct_states.fuel_vols') prob.model.connect( 'fuel_mass', 'AS_point_0.coupled.wing.struct_states.fuel_mass') comp = om.ExecComp('fuel_diff = (fuel_mass - fuelburn) / fuelburn', units='kg') prob.model.add_subsystem('fuel_diff', comp, promotes_inputs=['fuel_mass'], promotes_outputs=['fuel_diff']) prob.model.connect('AS_point_0.fuelburn', 'fuel_diff.fuelburn') #======================================================================================= #======================================================================================= prob.driver = om.ScipyOptimizeDriver() prob.driver.options['tol'] = 1e-9 # prob.driver = om.pyOptSparseDriver() # prob.driver.add_recorder(om.SqliteRecorder("cases.sql")) # 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.model.add_objective('AS_point_0.fuelburn', scaler=1e-5) 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('fuel_mass', lower=0., upper=2e5, scaler=1e-5) prob.model.add_constraint('AS_point_0.CL', equals=0.5) prob.model.add_constraint('AS_point_0.wing_perf.failure', upper=0.) #======================================================================================= # Here we add the fuel volume constraint #======================================================================================= prob.model.add_constraint('fuel_vol_delta.fuel_vol_delta', lower=0.) prob.model.add_constraint('fuel_diff', equals=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) assert_rel_error(self, prob['AS_point_0.fuelburn'][0], 80758.28839215, 1e-5) assert_rel_error(self, prob['wing.structural_mass'][0] / 1.25, 12330.193521430, 1e-5)
def setup(self): num_nodes = self.options['num_nodes'] num_radial = self.options['num_radial'] num_blades = self.options['num_blades'] af_filename = self.options['af_filename'] turbine = self.options['turbine'] installed_thrust_loss = self.options['installed_thrust_loss'] comp = om.ExecComp([ 'hub_radius = 0.5*hub_diameter', 'prop_radius = 0.5*prop_diameter' ], shape=num_nodes, has_diag_partials=True, hub_radius={'units': 'm'}, hub_diameter={'units': 'm'}, prop_radius={'units': 'm'}, prop_diameter={'units': 'm'}) self.add_subsystem('hub_prop_radius_comp', comp, promotes=['*']) # Stole this from John Hwang's OpenBEMT code. this_dir = os.path.split(__file__)[0] file_path = os.path.join(this_dir, 'airfoils', af_filename) af = af_from_files([file_path]) comp = make_component( CCBladeResidualComp(num_nodes=num_nodes, num_radial=num_radial, af=af, B=num_blades, turbine=turbine)) comp.linear_solver = om.DirectSolver(assemble_jac=True) self.add_subsystem('ccblade_comp', comp, promotes_inputs=[("r", "radii"), "chord", "theta", "Vx", "Vy", "rho", "mu", "asound", ("Rhub", "hub_radius"), ("Rtip", "prop_radius"), "precone", "pitch"], promotes_outputs=['Np', 'Tp']) comp = FunctionalsComp(num_nodes=num_nodes, num_radial=num_radial, num_blades=num_blades) if installed_thrust_loss: promotes_outputs = [('thrust', 'uninstalled_thrust'), 'torque', 'power', 'efficiency'] else: promotes_outputs = ['thrust', 'torque', 'power', 'efficiency'] self.add_subsystem('ccblade_torquethrust_comp', comp, promotes_inputs=[ 'hub_radius', 'prop_radius', 'radii', 'Np', 'Tp', 'v', 'omega' ], promotes_outputs=promotes_outputs) if installed_thrust_loss: comp = BertonInstalledThrustLossInputComp(num_nodes=num_nodes) self.add_subsystem('installed_thrust_loss_inputs_comp', comp, promotes_inputs=['omega', 'v', 'prop_diameter'], promotes_outputs=['sqa', 'zje']) comp = om.MetaModelStructuredComp(vec_size=num_nodes) comp.add_input('sqa', val=0.0, training_data=sqa_training, units=None) comp.add_input('zje', val=0.0, training_data=zje_training, units=None) comp.add_output('fb', val=1.0, training_data=fb_training, units=None) self.add_subsystem('installed_thrust_loss_mm_comp', comp, promotes_inputs=['sqa', 'zje'], promotes_outputs=['fb']) comp = om.ExecComp('thrust = fb*uninstalled_thrust', has_diag_partials=True, uninstalled_thrust={ 'units': 'N', 'shape': num_nodes }, fb={ 'units': None, 'shape': num_nodes }, thrust={ 'units': 'N', 'shape': num_nodes }) self.add_subsystem('installed_thrust_loss_comp', comp, promotes_inputs=['fb', 'uninstalled_thrust'], promotes_outputs=['thrust'])
comp = om.MetaModelStructuredComp(vec_size=nn) comp.add_input('sqa', val=0.0, training_data=sqa_training, units=None) comp.add_input('zje', val=0.0, training_data=zje_training, units=None) comp.add_output('fb', val=1.0, training_data=fb_training, units=None) prob.model.add_subsystem('installed_thrust_loss_mm_comp', comp, promotes_inputs=['sqa', 'zje'], promotes_outputs=['fb']) comp = om.ExecComp('installed_thrust = fb*bemt_thrust', has_diag_partials=True, bemt_thrust={ 'units': 'N', 'shape': nn }, fb={ 'units': None, 'shape': nn }, installed_thrust={ 'units': 'N', 'shape': nn }) prob.model.add_subsystem('installed_thrust_loss_comp', comp, promotes_inputs=['fb', 'bemt_thrust'], promotes_outputs=['installed_thrust']) prob.setup() prob.run_model() print(f"sqa = {prob.get_val('sqa')}") print(f"zje = {prob.get_val('zje')}")
def test_dangling_input_w_units(self): prob = om.Problem() prob.model.add_subsystem( 'C1', om.ExecComp('y=x', x={'units': 'ft'}, y={'units': 'm'})) prob.setup() prob.run_model()
def test_pyxdsm_pdf(self): """ Makes an XDSM of the Sphere test case. It also adds a design variable, constraint and objective. """ class Rosenbrock(om.ExplicitComponent): def __init__(self, problem): super(Rosenbrock, self).__init__() self.problem = problem self.counter = 0 def setup(self): self.add_input('x', np.array([1.5, 1.5])) self.add_output('f', 0.0) self.declare_partials('f', 'x', method='fd', form='central', step=1e-4) def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): x = inputs['x'] outputs['f'] = sum(x**2) x0 = np.array([1.2, 1.5]) filename = 'xdsm2' prob = om.Problem() indeps = prob.model.add_subsystem('indeps', om.IndepVarComp(problem=prob), promotes=['*']) indeps.add_output('x', list(x0)) prob.model.add_subsystem('sphere', Rosenbrock(problem=prob), promotes=['*']) prob.model.add_subsystem('con', om.ExecComp('c=sum(x)', x=np.ones(2)), promotes=['*']) prob.driver = om.ScipyOptimizeDriver() prob.model.add_design_var('x') prob.model.add_objective('f') prob.model.add_constraint('c', lower=1.0) prob.setup() prob.final_setup() # requesting 'pdf', but if 'pdflatex' is not found we will only get 'tex' pdflatex = find_executable('pdflatex') # Write output om.write_xdsm(prob, filename=filename, out_format='pdf', show_browser=SHOW, quiet=QUIET) # Check if file was created self.assertTrue(os.path.isfile('.'.join([filename, 'tex']))) # Check if PDF was created (only if pdflatex is installed) self.assertTrue(not pdflatex or os.path.isfile('.'.join([filename, 'pdf'])))