def test_speed(self): from openmdao.api import Problem, Group, IndepVarComp, ExecComp from openmdao.core.tests.test_units import SpeedComp comp = IndepVarComp() comp.add_output('distance', val=1., units='m') comp.add_output('time', val=1., units='s') prob = Problem(model=Group()) prob.model.add_subsystem('c1', comp) prob.model.add_subsystem('c2', SpeedComp()) prob.model.add_subsystem('c3', ExecComp('f=speed',speed={'units': 'm/s'})) prob.model.connect('c1.distance', 'c2.distance') prob.model.connect('c1.time', 'c2.time') prob.model.connect('c2.speed', 'c3.speed') prob.setup() prob.run_model() assert_rel_error(self, prob['c1.distance'], 1.) # units: m assert_rel_error(self, prob['c2.distance'], 1.e-3) # units: km assert_rel_error(self, prob['c1.time'], 1.) # units: s assert_rel_error(self, prob['c2.time'], 1./3600.) # units: h assert_rel_error(self, prob['c2.speed'], 3.6) # units: km/h assert_rel_error(self, prob['c3.f'], 1.0) # units: km/h
def setUp(self): self.nn = 100 self.p = Problem(model=Group()) ivc = IndepVarComp() ivc.add_output(name='a', shape=(self.nn, 4)) ivc.add_output(name='b', shape=(self.nn, 4)) self.p.model.add_subsystem(name='ivc', subsys=ivc, promotes_outputs=['a', 'b']) self.p.model.add_subsystem(name='dot_prod_comp', subsys=DotProductComp(vec_size=self.nn, length=4)) self.p.model.connect('a', 'dot_prod_comp.a') self.p.model.connect('b', 'dot_prod_comp.b') self.p.setup() self.p['a'] = np.random.rand(self.nn, 4) self.p['b'] = np.random.rand(self.nn, 4) self.p.run_model()
def setUp(self): self.nn = 5 self.p = Problem(model=Group()) ivc = IndepVarComp() ivc.add_output(name='a', shape=(self.nn, 3)) ivc.add_output(name='b', shape=(self.nn, 3)) self.p.model.add_subsystem(name='ivc', subsys=ivc, promotes_outputs=['a', 'b']) adder=self.p.model.add_subsystem(name='add_subtract_comp', subsys=AddSubtractComp()) adder.add_equation('adder_output',['input_a','input_b'],vec_size=self.nn,length=3) self.p.model.connect('a', 'add_subtract_comp.input_a') self.p.model.connect('b', 'add_subtract_comp.input_b') self.p.setup() self.p['a'] = np.random.rand(self.nn, 3) self.p['b'] = np.random.rand(self.nn, 3) self.p.run_model()
def setUp(self): self.nn = 10 self.p = Problem(model=Group()) ivc = IndepVarComp() ivc.add_output(name='a', shape=(self.nn,)) ivc.add_output(name='b', shape=(self.nn,)) self.p.model.add_subsystem(name='ivc', subsys=ivc, promotes_outputs=['a', 'b']) demux_comp = self.p.model.add_subsystem(name='demux_comp', subsys=DemuxComp(vec_size=self.nn)) demux_comp.add_var('a', shape=(self.nn,)) demux_comp.add_var('b', shape=(self.nn,)) self.p.model.connect('a', 'demux_comp.a') self.p.model.connect('b', 'demux_comp.b') self.p.setup(force_alloc_complex=True) self.p['a'] = np.random.rand(self.nn) self.p['b'] = np.random.rand(self.nn) self.p.run_model()
def setUp(self): self.nn = 5 self.p = Problem(model=Group()) ivc = IndepVarComp() ivc.add_output(name='a', shape=(self.nn, 3, 1)) ivc.add_output(name='b', shape=(self.nn, 3, 1)) self.p.model.add_subsystem(name='ivc', subsys=ivc, promotes_outputs=['a', 'b']) self.p.model.add_subsystem(name='cross_prod_comp', subsys=CrossProductComp(vec_size=self.nn)) self.p.model.connect('a', 'cross_prod_comp.a') self.p.model.connect('b', 'cross_prod_comp.b') self.p.setup(force_alloc_complex=True) self.p['a'] = np.random.rand(self.nn, 3, 1) self.p['b'] = np.random.rand(self.nn, 3, 1) self.p['a'][:, 0, 0] = 2.0 self.p['a'][:, 1, 0] = 3.0 self.p['a'][:, 2, 0] = 4.0 self.p['b'][:, 0, 0] = 5.0 self.p['b'][:, 1, 0] = 6.0 self.p['b'][:, 2, 0] = 7.0 self.p.run_model()
def test_iimplicit(self): # Testing that our scale/unscale contexts leave the output vector in the correct state when # linearize is called on implicit components. prob = Problem() model = prob.model inputs_comp = IndepVarComp() inputs_comp.add_output('x1_u', val=1.0) model.add_subsystem('p', inputs_comp) mycomp = model.add_subsystem('comp', MyImplicitComp()) model.connect('p.x1_u', 'comp.x2_u') model.linear_solver = DirectSolver() model.nonlinear_solver = NewtonSolver() model.nonlinear_solver.options['atol'] = 1e-12 model.nonlinear_solver.options['rtol'] = 1e-12 model.add_design_var('p.x1_u', lower=-11, upper=11) model.add_constraint('p.x1_u', upper=3.3) model.add_objective('comp.x3_u') model.add_objective('comp.x3_s') prob.setup() prob.run_model() totals = prob.check_totals(compact_print=True, out_stream=None) for (of, wrt) in totals: assert_rel_error(self, totals[of, wrt]['abs error'][0], 0.0, 1e-7)
def setUp(self): self.nn = 5 self.p = Problem(model=Group()) ivc = IndepVarComp() ivc.add_output(name='a', shape=(self.nn, 3), units='lbf') ivc.add_output(name='b', shape=(self.nn, 3), units='ft/s') self.p.model.add_subsystem(name='ivc', subsys=ivc, promotes_outputs=['a', 'b']) self.p.model.add_subsystem(name='dot_prod_comp', subsys=DotProductComp(vec_size=self.nn, a_units='N', b_units='m/s', c_units='W')) self.p.model.connect('a', 'dot_prod_comp.a') self.p.model.connect('b', 'dot_prod_comp.b') self.p.setup() self.p['a'] = np.random.rand(self.nn, 3) self.p['b'] = np.random.rand(self.nn, 3) self.p.run_model()
def test_structural_weight_loads(self): surface = get_default_surfaces()[0] comp = StructureWeightLoads(surface=surface) group = Group() indep_var_comp = IndepVarComp() ny = surface['mesh'].shape[1] #carefully chosen "random" values that give non-uniform derivatives outputs that are good for testing nodesval = np.array([[1., 2., 4.], [20., 22., 7.], [8., 17., 14.], [13., 14., 16.]],dtype=complex) element_weights_val = np.arange(ny-1)+1 indep_var_comp.add_output('nodes', val=nodesval,units='m') indep_var_comp.add_output('element_weights', val=element_weights_val,units='N') group.add_subsystem('indep_var_comp', indep_var_comp, promotes=['*']) group.add_subsystem('load', comp, promotes=['*']) p = run_test(self, group, complex_flag=True, compact_print=True)
def test_raise_no_error_on_singular(self): prob = Problem() model = prob.model comp = 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=Group()) teg.add_subsystem('dynamics', ExecComp('z = 2.0*thrust'), promotes=['*']) thrust_bal = 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 = DirectSolver(assemble_jac=False) teg.nonlinear_solver = 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(check=False) prob.set_solver_print(level=0) teg.linear_solver.options['err_on_singular'] = False prob.run_model()
def setup(self): surface = self.options['surface'] mesh = surface['mesh'] nx = mesh.shape[0] ny = mesh.shape[1] # Add independent variables that do not belong to a specific component indep_var_comp = IndepVarComp() # Add structural components to the surface-specific group self.add_subsystem('indep_vars', indep_var_comp, promotes=['*']) if 'struct' in surface['type']: self.add_subsystem('radius_comp', RadiusComp(surface=surface), promotes_inputs=['mesh', 't_over_c'], promotes_outputs=['radius']) if 'thickness_cp' in surface.keys(): n_cp = len(surface['thickness_cp']) # Add bspline components for active bspline geometric variables. self.add_subsystem('thickness_bsp', BsplinesComp( in_name='thickness_cp', out_name='thickness', units='m', num_control_points=n_cp, num_points=int(ny-1), bspline_order=min(n_cp, 4), distribution='uniform'), promotes_inputs=['thickness_cp'], promotes_outputs=['thickness']) indep_var_comp.add_output('thickness_cp', val=surface['thickness_cp'], units='m') self.add_subsystem('tube', SectionPropertiesTube(surface=surface), promotes_inputs=['thickness', 'radius'], promotes_outputs=['A', 'Iy', 'Iz', 'J'])
def setUp(self): self.nn = 5 self.p = Problem(model=Group()) ivc = IndepVarComp() ivc.add_output(name='A', shape=(self.nn, 6, 4)) ivc.add_output(name='x', shape=(self.nn, 4)) self.p.model.add_subsystem(name='ivc', subsys=ivc, promotes_outputs=['A', 'x']) self.p.model.add_subsystem(name='mat_vec_product_comp', subsys=MatrixVectorProductComp(vec_size=self.nn, A_shape=(6, 4))) self.p.model.connect('A', 'mat_vec_product_comp.A') self.p.model.connect('x', 'mat_vec_product_comp.x') self.p.setup(force_alloc_complex=True) self.p['A'] = np.random.rand(self.nn, 6, 4) self.p['x'] = np.random.rand(self.nn, 4) self.p.run_model()
def test_const_jacobian(self): import numpy as np from openmdao.api import Problem, Group, IndepVarComp, DirectSolver, DenseJacobian from openmdao.jacobians.tests.test_jacobian_features import SimpleCompConst model = Group() comp = IndepVarComp() for name, val in (('x', 1.), ('y1', np.ones(2)), ('y2', np.ones(2)), ('y3', np.ones(2)), ('z', np.ones((2, 2)))): comp.add_output(name, val) model.add_subsystem('input_comp', comp, promotes=['x', 'y1', 'y2', 'y3', 'z']) problem = Problem(model=model) model.suppress_solver_output = True model.linear_solver = DirectSolver() model.jacobian = DenseJacobian() model.add_subsystem('simple', SimpleCompConst(), promotes=['x', 'y1', 'y2', 'y3', 'z', 'f', 'g']) problem.setup(check=False) problem.run_model() totals = problem.compute_totals(['f', 'g'], ['x', 'y1', 'y2', 'y3', 'z']) assert_rel_error(self, totals['f', 'x'], [[1.]]) assert_rel_error(self, totals['f', 'z'], np.ones((1, 4))) assert_rel_error(self, totals['f', 'y1'], np.zeros((1, 2))) assert_rel_error(self, totals['f', 'y2'], np.zeros((1, 2))) assert_rel_error(self, totals['f', 'y3'], np.zeros((1, 2))) assert_rel_error(self, totals['g', 'x'], [[1], [0], [0], [1]]) assert_rel_error(self, totals['g', 'z'], np.zeros((4, 4))) assert_rel_error(self, totals['g', 'y1'], [[1, 0], [1, 0], [0, 1], [0, 1]]) assert_rel_error(self, totals['g', 'y2'], [[1, 0], [0, 1], [1, 0], [0, 1]]) assert_rel_error(self, totals['g', 'y3'], [[1, 0], [1, 0], [0, 1], [0, 1]])
def test_const_jacobian(self): model = Group() comp = IndepVarComp() for name, val in (('x', 1.), ('y1', np.ones(2)), ('y2', np.ones(2)), ('y3', np.ones(2)), ('z', np.ones((2, 2)))): comp.add_output(name, val) model.add_subsystem('input_comp', comp, promotes=['x', 'y1', 'y2', 'y3', 'z']) problem = Problem(model=model) problem.set_solver_print(level=0) model.linear_solver = ScipyKrylov() model.jacobian = COOJacobian() model.add_subsystem('simple', SimpleCompConst(), promotes=['x', 'y1', 'y2', 'y3', 'z', 'f', 'g']) problem.setup(check=False) problem.run_model() totals = problem.compute_totals(['f', 'g'], ['x', 'y1', 'y2', 'y3', 'z']) jacobian = {} jacobian['f', 'x'] = [[1.]] jacobian['f', 'z'] = np.ones((1, 4)) jacobian['f', 'y1'] = np.zeros((1, 2)) jacobian['f', 'y2'] = np.zeros((1, 2)) jacobian['f', 'y3'] = np.zeros((1, 2)) jacobian['g', 'y1'] = [[1, 0], [1, 0], [0, 1], [0, 1]] jacobian['g', 'y2'] = [[1, 0], [0, 1], [1, 0], [0, 1]] jacobian['g', 'y3'] = [[1, 0], [1, 0], [0, 1], [0, 1]] jacobian['g', 'x'] = [[1], [0], [0], [1]] jacobian['g', 'z'] = np.zeros((4, 4)) assert_rel_error(self, totals, jacobian)
def test_sparse_jacobian(self): import numpy as np from openmdao.api import Problem, Group, IndepVarComp, ExplicitComponent class SparsePartialComp(ExplicitComponent): def setup(self): self.add_input('x', shape=(4,)) self.add_output('f', shape=(2,)) self.declare_partials(of='f', wrt='x', rows=[0, 1, 1, 1], cols=[0, 1, 2, 3]) def compute_partials(self, inputs, partials): # Corresponds to the [(0,0), (1,1), (1,2), (1,3)] entries. partials['f', 'x'] = [1., 2., 3., 4.] model = Group() comp = IndepVarComp() comp.add_output('x', np.ones(4)) model.add_subsystem('input', comp) model.add_subsystem('example', SparsePartialComp()) model.connect('input.x', 'example.x') problem = Problem(model=model) problem.setup(check=False) problem.run_model() totals = problem.compute_totals(['example.f'], ['input.x']) assert_rel_error(self, totals['example.f', 'input.x'], [[1., 0., 0., 0.], [0., 2., 3., 4.]])
def setup(self, compname, inputs, state0): # create instance of component type try: comp = eval('%s(NTIME)' % compname) except TypeError: try: comp = eval('%s()' % compname) except TypeError: comp = eval('%s(NTIME, 300)' % compname) # collect metadata for component inputs prob = Problem(comp) prob.setup() prob.final_setup() self.inputs_dict = {} for name, meta in prob.model.list_inputs(units=True, out_stream=None): self.inputs_dict[name.split('.')[-1]] = meta # create independent vars for each input, initialized with random values indep = IndepVarComp() for item in inputs + state0: shape = self.inputs_dict[item]['value'].shape units = self.inputs_dict[item]['units'] indep.add_output(item, np.random.random(shape), units=units) # setup problem for test self.prob = Problem() self.prob.model.add_subsystem('indep', indep, promotes=['*']) self.prob.model.add_subsystem('comp', comp, promotes=['*']) self.prob.setup()
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, 'radius_cp' : np.ones((5)) * 0.5, # 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 = Problem() ny = surf_dict['mesh'].shape[1] indep_var_comp = 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) # Set up the problem prob.setup() prob.run_model() assert_rel_error(self, prob['wing.structural_mass'][0], 117819.798089, 1e-4)
def setup(self): E = self.metadata['E'] L = self.metadata['L'] b = self.metadata['b'] volume = self.metadata['volume'] num_elements = self.metadata['num_elements'] num_nodes = num_elements + 1 force_vector = np.zeros(2 * num_nodes) force_vector[-2] = -1. inputs_comp = IndepVarComp() inputs_comp.add_output('h', shape=num_elements) self.add_subsystem('inputs_comp', inputs_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) comp = GlobalStiffnessMatrixComp(num_elements=num_elements) self.add_subsystem('global_stiffness_matrix_comp', comp) comp = StatesComp(num_elements=num_elements, force_vector=force_vector) self.add_subsystem('states_comp', comp) comp = DisplacementsComp(num_elements=num_elements) self.add_subsystem('displacements_comp', comp) comp = ComplianceComp(num_elements=num_elements, force_vector=force_vector) self.add_subsystem('compliance_comp', comp) comp = VolumeComp(num_elements=num_elements, b=b, L=L) self.add_subsystem('volume_comp', comp) self.connect('inputs_comp.h', 'I_comp.h') self.connect('I_comp.I', 'local_stiffness_matrix_comp.I') self.connect( 'local_stiffness_matrix_comp.K_local', 'global_stiffness_matrix_comp.K_local') self.connect( 'global_stiffness_matrix_comp.K', 'states_comp.K') self.connect( 'states_comp.d', 'displacements_comp.d') self.connect( 'displacements_comp.displacements', 'compliance_comp.displacements') self.connect( 'inputs_comp.h', 'volume_comp.h') self.add_design_var('inputs_comp.h', lower=1e-2, upper=10.) self.add_objective('compliance_comp.compliance') self.add_constraint('volume_comp.volume', equals=volume)
def test_add_output(self): """Define two independent variables using the add_output method.""" from openmdao.api import Problem, IndepVarComp comp = IndepVarComp() comp.add_output('indep_var_1', val=1.0, lower=0, upper=10) comp.add_output('indep_var_2', val=2.0, lower=1, upper=20) prob = Problem(comp).setup(check=False) assert_rel_error(self, prob['indep_var_1'], 1.0) assert_rel_error(self, prob['indep_var_2'], 2.0)
def test_scalar_with_guess_func_additional_input(self): model = Group(assembled_jac_type='dense') bal = BalanceComp() bal.add_balance('x') bal.add_input('guess_x', val=0.0) ivc = IndepVarComp() ivc.add_output(name='y_tgt', val=4) ivc.add_output(name='guess_x', val=2.5) exec_comp = ExecComp('y=x**2', x={'value': 1}, y={'value': 1}) model.add_subsystem(name='ivc', subsys=ivc, promotes_outputs=['y_tgt', 'guess_x']) model.add_subsystem(name='exec', subsys=exec_comp) model.add_subsystem(name='balance', subsys=bal) model.connect('guess_x', 'balance.guess_x') model.connect('y_tgt', 'balance.rhs:x') model.connect('balance.x', 'exec.x') model.connect('exec.y', 'balance.lhs:x') model.linear_solver = DirectSolver(assemble_jac=True) model.nonlinear_solver = NewtonSolver(maxiter=100, iprint=0) prob = Problem(model) prob.setup() # run problem without a guess function prob['balance.x'] = .5 prob.run_model() assert_almost_equal(prob['balance.x'], 2.0, decimal=7) iters_no_guess = model.nonlinear_solver._iter_count # run problem with same initial value and a guess function def guess_function(inputs, outputs, resids): outputs['x'] = inputs['guess_x'] bal.options['guess_func'] = guess_function prob['balance.x'] = .5 prob.run_model() assert_almost_equal(prob['balance.x'], 2.0, decimal=7) iters_with_guess = model.nonlinear_solver._iter_count # verify it converges faster with the guess function self.assertTrue(iters_with_guess < iters_no_guess)
def test_keys(self): p = Problem() comp = IndepVarComp() comp.add_output('v1', val=1.0) comp.add_output('v2', val=2.0) p.model.add_subsystem('des_vars', comp, promotes=['*']) p.setup() p.final_setup() keys = sorted(p.model._outputs.keys()) expected = ['des_vars.v1', 'des_vars.v2'] self.assertListEqual(keys, expected, msg='keys() is not returning the expected names')
def test_iter(self): p = Problem() comp = IndepVarComp() comp.add_output('v1', val=1.0) comp.add_output('v2', val=2.0) p.model.add_subsystem('des_vars', comp, promotes=['*']) p.setup() p.final_setup() outputs = [n for n in p.model._outputs] expected = ['des_vars.v1', 'des_vars.v2'] self.assertListEqual(outputs, expected, msg='Iter is not returning the expected names')
def test_dot(self): p = Problem() comp = IndepVarComp() comp.add_output('v1', val=1.0) comp.add_output('v2', val=2.0) p.model.add_subsystem('des_vars', comp, promotes=['*']) p.setup() p.final_setup() new_vec = p.model._outputs._clone() new_vec.set_const(3.) self.assertEqual(new_vec.dot(p.model._outputs), 9.)
def test_scalar_with_guess_func_additional_input(self): n = 1 prob = Problem(model=Group()) bal = BalanceComp() bal.add_balance('x', guess_func=lambda inputs, resids: inputs['guess_x']) bal.add_input('guess_x', val=0.0) ivc = IndepVarComp() ivc.add_output(name='y_tgt', val=4) ivc.add_output(name='guess_x', val=2.5) exec_comp = ExecComp('y=x**2', x={'value': 1}, y={'value': 1}) prob.model.add_subsystem(name='ivc', subsys=ivc, promotes_outputs=['y_tgt', 'guess_x']) prob.model.add_subsystem(name='exec', subsys=exec_comp) prob.model.add_subsystem(name='balance', subsys=bal) prob.model.connect('guess_x', 'balance.guess_x') 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 = DirectSolver() prob.model.nonlinear_solver = NewtonSolver() prob.model.nonlinear_solver.options['maxiter'] = 100 prob.model.nonlinear_solver.options['iprint'] = 0 prob.model.jacobian = DenseJacobian() prob.setup() prob['balance.x'] = np.random.rand(n) prob.run_model() assert_almost_equal(prob['balance.x'], 2.0, decimal=7) np.set_printoptions(linewidth=1024) cpd = prob.check_partials() for (of, wrt) in cpd['balance']: assert_almost_equal(cpd['balance'][of, wrt]['abs error'], 0.0, decimal=5)
def test(self): surface = get_default_surfaces()[0] ny = surface['mesh'].shape[1] group = Group() ivc = IndepVarComp() ivc.add_output('nodes', val=np.random.random_sample((ny, 3))) comp = Weight(surface=surface) group.add_subsystem('ivc', ivc, promotes=['*']) group.add_subsystem('comp', comp, promotes=['*']) run_test(self, group, compact_print=False, complex_flag=True)
def test_add_output_type_bug(self): prob = Problem() model = prob.model ivc = IndepVarComp() ivc.add_output('x1', val=[1, 2, 3], lower=0, upper=10) model.add_subsystem('p', ivc) prob.setup() prob['p.x1'][0] = 0.5 prob.run_model() assert_rel_error(self, prob['p.x1'][0], 0.5)
def test(self): """ An example demonstrating a trivial use case of DemuxComp """ import numpy as np from openmdao.api import Problem, Group, IndepVarComp, DemuxComp, ExecComp from openmdao.utils.assert_utils import assert_rel_error # The number of elements to be demuxed n = 3 # The size of each element to be demuxed m = 100 p = Problem(model=Group()) ivc = IndepVarComp() ivc.add_output(name='pos_ecef', shape=(m, 3), units='km') p.model.add_subsystem(name='ivc', subsys=ivc, promotes_outputs=['pos_ecef']) mux_comp = p.model.add_subsystem(name='demux', subsys=DemuxComp(vec_size=n)) mux_comp.add_var('pos', shape=(m, n), axis=1, units='km') p.model.add_subsystem(name='longitude_comp', subsys=ExecComp('long = atan(y/x)', x={'value': np.ones(m), 'units': 'km'}, y={'value': np.ones(m), 'units': 'km'}, long={'value': np.ones(m), 'units': 'rad'})) p.model.connect('demux.pos_0', 'longitude_comp.x') p.model.connect('demux.pos_1', 'longitude_comp.y') p.model.connect('pos_ecef', 'demux.pos') p.setup() p['pos_ecef'][:, 0] = 6378 * np.cos(np.linspace(0, 2*np.pi, m)) p['pos_ecef'][:, 1] = 6378 * np.sin(np.linspace(0, 2*np.pi, m)) p['pos_ecef'][:, 2] = 0.0 p.run_model() expected = np.arctan(p['pos_ecef'][:, 1] / p['pos_ecef'][:, 0]) assert_rel_error(self, p.get_val('longitude_comp.long'), expected)
def test_dot_petsc(self): if not PETScVector: raise unittest.SkipTest("PETSc is not installed") p = Problem() comp = IndepVarComp() comp.add_output('v1', val=1.0) comp.add_output('v2', val=2.0) p.model.add_subsystem('des_vars', comp, promotes=['*']) p.setup() p.final_setup() new_vec = p.model._outputs._clone() new_vec.set_const(3.) self.assertEqual(new_vec.dot(p.model._outputs), 9.)
def test_debug_after_raised_error(self): prob = Problem() model = prob.model comp = 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=Group()) teg.add_subsystem('dynamics', ExecComp('z = 2.0*thrust'), promotes=['*']) thrust_bal = 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 = DirectSolver() teg.nonlinear_solver = NewtonSolver() teg.nonlinear_solver.options['solve_subsystems'] = True teg.nonlinear_solver.options['max_sub_solves'] = 1 teg.nonlinear_solver.options['atol'] = 1e-4 teg.nonlinear_solver.options['debug_print'] = True prob.setup(check=False) prob.set_solver_print(level=0) stdout = sys.stdout strout = StringIO() sys.stdout = strout with self.assertRaises(RuntimeError) as cm: prob.run_model() sys.stdout = stdout output = strout.getvalue() target = "'thrust_equilibrium_group.thrust_bal.thrust'" self.assertTrue(target in output, msg=target + "NOT FOUND IN" + output) # Make sure exception is unchanged. expected_msg = "Singular entry found in 'thrust_equilibrium_group' for row associated with state/residual 'thrust'." self.assertEqual(expected_msg, str(cm.exception))
def test2(self): surfaces = get_default_surfaces() group = Group() comp = MomentCoefficient(surfaces=surfaces) indep_var_comp = IndepVarComp() indep_var_comp.add_output('S_ref_total', val=1e4, units='m**2') group.add_subsystem('moment_calc', comp) group.add_subsystem('indep_var_comp', indep_var_comp) group.connect('indep_var_comp.S_ref_total', 'moment_calc.S_ref_total') run_test(self, group)
def test(self): surfaces = get_default_surfaces() group = Group() comp = VLMGeometry(surface=surfaces[0]) indep_var_comp = IndepVarComp() indep_var_comp.add_output('def_mesh', val=surfaces[0]['mesh'], units='m') group.add_subsystem('geom', comp) group.add_subsystem('indep_var_comp', indep_var_comp) group.connect('indep_var_comp.def_mesh', 'geom.def_mesh') run_test(self, group)
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 'type': 'aero', '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, 'num_x': mesh.shape[0], 'num_y': mesh.shape[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.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': 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 'sweep': 0., 'dihedral': 0., } surfaces = [surf_dict] # Create the problem and the model group prob = Problem() indep_var_comp = IndepVarComp() indep_var_comp.add_output('v', val=248.136, units='m/s') indep_var_comp.add_output('alpha', val=5.) indep_var_comp.add_output('M', 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('M', point_name + '.M') 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') from openmdao.api import ScipyOptimizeDriver prob.driver = 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)
TestPoint_x = trajectory_x[59] TestPoint_y = trajectory_y[59] outputs['life_dist'] = np.linalg.norm( [x - TestPoint_x, y - TestPoint_y]) if __name__ == '__main__': from openmdao.api import Problem, Group, IndepVarComp group = Group() comp = IndepVarComp() comp.add_output('l1') comp.add_output('l2') group.add_subsystem('i_comp', comp, promotes=['*']) comp = FkComp() group.add_subsystem('fk_comp', comp, promotes=['*']) comp = LiftPointCon() group.add_subsystem('lift_con', comp, promotes=['*']) prob = Problem() prob.model = group prob.setup() prob.run_model() prob.model.list_outputs()
def setup(self): RefBlade = self.options['RefBlade'] npts_coarse_power_curve = self.options['npts_coarse_power_curve'] npts_spline_power_curve = self.options['npts_spline_power_curve'] regulation_reg_II5 = self.options['regulation_reg_II5'] regulation_reg_III = self.options['regulation_reg_III'] flag_Cp_Ct_Cq_Tables = self.options['flag_Cp_Ct_Cq_Tables'] Analysis_Level = self.options['Analysis_Level'] FASTpref = self.options['FASTpref'] topLevelFlag = self.options['topLevelFlag'] rc_verbosity = self.options['rc_verbosity'] rc_tex_table = self.options['rc_tex_table'] rc_generate_plots = self.options['rc_generate_plots'] rc_show_plots = self.options['rc_show_plots'] rc_show_warnings = self.options['rc_show_warnings'] rc_discrete = self.options['rc_discrete'] NPTS = len(RefBlade['pf']['s']) rotorIndeps = IndepVarComp() rotorIndeps.add_discrete_output('tiploss', True) rotorIndeps.add_discrete_output('hubloss', True) rotorIndeps.add_discrete_output('wakerotation', True) rotorIndeps.add_discrete_output('usecd', True) rotorIndeps.add_discrete_output( 'nSector', val=4, desc= 'number of sectors to divide rotor face into in computing thrust and power' ) self.add_subsystem('rotorIndeps', rotorIndeps, promotes=['*']) if topLevelFlag: sharedIndeps = IndepVarComp() sharedIndeps.add_output( 'lifetime', val=20.0, units='year', desc='project lifetime for fatigue analysis') sharedIndeps.add_output('hub_height', val=0.0, units='m') sharedIndeps.add_output('rho', val=1.225, units='kg/m**3') sharedIndeps.add_output('mu', val=1.81e-5, units='kg/(m*s)') sharedIndeps.add_output('shearExp', val=0.2) self.add_subsystem('sharedIndeps', sharedIndeps, promotes=['*']) # --- Rotor Aero & Power --- self.add_subsystem('rg', RotorGeometry(RefBlade=RefBlade, topLevelFlag=True, verbosity=rc_verbosity, tex_table=rc_tex_table, generate_plots=rc_generate_plots, show_plots=rc_show_plots, show_warnings=rc_show_warnings, discrete=rc_discrete), promotes=['*']) self.add_subsystem('ra', RotorAeroPower( RefBlade=RefBlade, npts_coarse_power_curve=npts_coarse_power_curve, npts_spline_power_curve=npts_spline_power_curve, regulation_reg_II5=regulation_reg_II5, regulation_reg_III=regulation_reg_III, flag_Cp_Ct_Cq_Tables=flag_Cp_Ct_Cq_Tables, topLevelFlag=False), promotes=['*']) self.add_subsystem( 'rs', RotorStructure(RefBlade=RefBlade, topLevelFlag=False, Analysis_Level=Analysis_Level), promotes=[ 'fst_vt_in', 'VfactorPC', 'turbulence_class', 'gust_stddev', 'pitch_extreme', 'azimuth_extreme', 'rstar_damage', 'Mxb_damage', 'Myb_damage', 'strain_ult_spar', 'strain_ult_te', 'm_damage', 'gamma_fatigue', 'gamma_freq', 'gamma_f', 'gamma_m', 'dynamic_amplification', 'azimuth_load180', 'azimuth_load0', 'azimuth_load120', 'azimuth_load240', 'nSector', 'rho', 'mu', 'shearExp', 'tiploss', 'hubloss', 'wakerotation', 'usecd', 'bladeLength', 'R', 'V_mean', 'chord', 'theta', 'precurve', 'presweep', 'Rhub', 'Rtip', 'r', 'r_in', 'airfoils_cl', 'airfoils_cd', 'airfoils_cm', 'airfoils_aoa', 'airfoils_Re', 'z', 'EA', 'EIxx', 'EIyy', 'EIxy', 'GJ', 'rhoA', 'rhoJ', 'x_ec', 'y_ec', 'Tw_iner', 'flap_iner', 'edge_iner', 'eps_crit_spar', 'eps_crit_te', 'xu_strain_spar', 'xl_strain_spar', 'yu_strain_spar', 'yl_strain_spar', 'xu_strain_te', 'xl_strain_te', 'yu_strain_te', 'yl_strain_te', 'precurveTip', 'presweepTip', 'precone', 'tilt', 'yaw', 'nBlades', 'downwind', 'control_tsr', 'control_pitch', 'lifetime', 'hub_height', 'mass_one_blade', 'mass_all_blades', 'I_all_blades', 'freq_pbeam', 'freq_curvefem', 'modes_coef_curvefem', 'tip_deflection', 'tip_position', 'ground_clearance', 'strainU_spar', 'strainL_spar', 'strainU_te', 'strainL_te', #'eps_crit_spar','eps_crit_te', 'root_bending_moment', 'Mxyz', 'damageU_spar', 'damageL_spar', 'damageU_te', 'damageL_te', 'delta_bladeLength_out', 'delta_precurve_sub_out', 'Fxyz_1', 'Fxyz_2', 'Fxyz_3', 'Fxyz_4', 'Fxyz_5', 'Fxyz_6', 'Mxyz_1', 'Mxyz_2', 'Mxyz_3', 'Mxyz_4', 'Mxyz_5', 'Mxyz_6', 'Fxyz_total', 'Mxyz_total', 'TotalCone', 'Pitch' ]) # self.add_subsystem('rc', RotorCost(RefBlade=RefBlade, verbosity=rc_verbosity), # promotes=['bladeLength','total_blade_cost','Rtip','Rhub','r','chord','le_location','materials','upperCS','lowerCS','websCS','profile']) self.add_subsystem('obj_cmp', ExecComp('obj = -AEP', AEP={ 'units': 'kW*h', 'value': 1000000.0 }, obj={'units': 'kW*h'}), promotes=['*']) # Connections between rotor_aero and rotor_structure self.connect('V_mean', 'wind.Uref') self.connect('wind_zvec', 'wind.z') self.connect('rated_V', ['rs.V_hub', 'rs.setuppc.Vrated']) self.connect('rated_Omega', [ 'rs.Omega', 'rs.aero_rated.Omega_load', 'rs.aero_rated_0.Omega_load', 'rs.aero_rated_120.Omega_load', 'rs.aero_rated_240.Omega_load' ]) self.connect('rated_pitch', 'rs.aero_rated.pitch_load') self.connect('V_extreme50', 'rs.aero_extrm.V_load') self.connect('V_extreme_full', 'rs.aero_extrm_forces.Uhub') self.connect('theta', 'rs.tip.theta', src_indices=[NPTS - 1]) # Connections to AeroelasticSE if Analysis_Level >= 1: self.add_subsystem( 'aeroelastic', FASTLoadCases(RefBlade=RefBlade, npts_coarse_power_curve=npts_coarse_power_curve, npts_spline_power_curve=npts_spline_power_curve, FASTpref=FASTpref), promotes=[ 'fst_vt_in', 'fst_vt_out', 'FASTpref_updated', 'r', 'le_location', 'chord', 'theta', 'precurve', 'shearExp', 'presweep', 'Rhub', 'Rtip', 'turbulence_class', 'turbine_class', 'V_R25', 'rho', 'mu', 'control_maxTS', 'control_maxOmega', 'hub_height', 'airfoils_cl', 'airfoils_cd', 'airfoils_cm', 'airfoils_aoa', 'airfoils_Re', 'airfoils_coord_x', 'airfoils_coord_y', 'rthick' ]) self.connect('rhoA', 'aeroelastic.beam:rhoA') self.connect('EIxx', 'aeroelastic.beam:EIxx') self.connect('EIyy', 'aeroelastic.beam:EIyy') self.connect('Tw_iner', 'aeroelastic.beam:Tw_iner') self.connect('modes_coef_curvefem', 'aeroelastic.modes_coef_curvefem') self.connect('rs.z_az', 'aeroelastic.z_az') self.connect('V', 'aeroelastic.U_init') self.connect('Omega', 'aeroelastic.Omega_init') self.connect('pitch', 'aeroelastic.pitch_init') self.connect('rated_V', 'aeroelastic.Vrated') self.connect('rs.gust.V_gust', 'aeroelastic.Vgust') self.connect('V_mean', 'aeroelastic.V_mean_iec') self.connect('machine_rating', 'aeroelastic.control_ratedPower') if Analysis_Level > 1: self.connect('aeroelastic.dx_defl', 'rs.tip.dx') self.connect('aeroelastic.dy_defl', 'rs.tip.dy') self.connect('aeroelastic.dz_defl', 'rs.tip.dz') self.connect('aeroelastic.loads_Px', 'rs.loads_strain.aeroloads_Px') self.connect('aeroelastic.loads_Py', 'rs.loads_strain.aeroloads_Py') self.connect('aeroelastic.loads_Pz', 'rs.loads_strain.aeroloads_Pz') self.connect('aeroelastic.loads_Omega', 'rs.loads_strain.aeroloads_Omega') self.connect('aeroelastic.loads_azimuth', 'rs.loads_strain.aeroloads_azimuth') self.connect('aeroelastic.loads_pitch', 'rs.loads_strain.aeroloads_pitch') self.connect('aeroelastic.root_bending_moment', 'rs.root_bending_moment_in') self.connect('aeroelastic.Mxyz', 'rs.Mxyz_in')
def setup(self): debug = self.options['debug'] ''' HubSE class The HubSE class is used to represent the hub system of a wind turbine. HubSE integrates the hub, pitch system and spinner / nose cone components for the hub system. ''' self.add_subsystem('hub', Hub_OM(debug=debug), promotes=['*']) self.add_subsystem('pitchSystem', PitchSystem_OM(debug=debug), promotes=['*']) self.add_subsystem('spinner', Spinner_OM(debug=debug), promotes=['*']) if self.options['mass_only']: self.add_subsystem('adder', Hub_Mass_Adder_OM(debug=debug), promotes=['*']) else: self.add_subsystem('adder', Hub_System_Adder_OM(debug=debug), promotes=['*']) if self.options['topLevelFlag']: sharedIndeps = IndepVarComp() sharedIndeps.add_output('rotor_diameter', 0.0, units='m') sharedIndeps.add_discrete_output('number_of_blades', 0) sharedIndeps.add_output('blade_root_diameter', 0.0, units='m') sharedIndeps.add_output('blade_mass', 0.0, units='kg') sharedIndeps.add_output('machine_rating', 0.0, units='kW') sharedIndeps.add_output('shaft_angle', 0.0, units='rad') sharedIndeps.add_output('rotor_rpm', 0.0, units='rpm') self.add_subsystem('sharedIndeps', sharedIndeps, promotes=['*'])
def setup(self): shape = self.options['shape'] module = self.options['options_dictionary'] comp = IndepVarComp() comp.add_output('mass_scalar') comp.add_output('normalized_power', shape=shape) self.add_subsystem('inputs_comp', comp, promotes=['*']) comp = ScalarExpansionComp( shape=shape, out_name='mass', in_name='mass_scalar', ) self.add_subsystem('mass_comp', comp, promotes=['*']) comp = PowerCombinationComp( shape=shape, out_name='weight', coeff=constants.g, powers_dict=dict( mass=1., ), ) self.add_subsystem('weight_comp', comp, promotes=['*']) comp = PowerCombinationComp( shape=shape, out_name='usable_energy', coeff=module['specific_energy'] * (1 - module['reserve']), powers_dict=dict( mass=1., ), ) self.add_subsystem('usable_energy_comp', comp, promotes=['*']) comp = PowerCombinationComp( shape=shape, out_name='maximum_power', coeff=module['specific_power'], powers_dict=dict( mass=1., ), ) self.add_subsystem('maximum_power_comp', comp, promotes=['*']) comp = PowerCombinationComp( shape=shape, out_name='power', powers_dict=dict( normalized_power=1., maximum_power=1., ), ) self.add_subsystem('power_comp', comp, promotes=['*']) comp = PowerCombinationComp( shape=shape, out_name='energy', powers_dict=dict( power=1., time=1., ), ) self.add_subsystem('energy_comp', comp, promotes=['*']) comp = LinearCombinationComp( shape=shape, out_name='energy_constraint', coeffs_dict=dict( energy=1., usable_energy=-1., ), ) self.add_subsystem('energy_constraint_comp', comp, promotes=['*'])
def add_prob_vars(case_settings, surfaces): # Create the problem and assign the model group prob = Problem() # Add problem information as an independent variables component indep_var_comp = IndepVarComp() indep_var_comp.add_output('v', val=np.array([102.9, .75 * 102.9]), units='m/s') indep_var_comp.add_output('alpha', val=0., units='deg') indep_var_comp.add_output('alpha_maneuver', val=0., units='deg') indep_var_comp.add_output('Mach_number', val=np.array([0.305, 0.75 * 0.305])) indep_var_comp.add_output('re',val=np.array([6.03e6, 0.75 * 6.03e6]), units='1/m') indep_var_comp.add_output('rho', val=np.array([1.05549, 1.225]), units='kg/m**3') indep_var_comp.add_output('CT', val=0.45/3600, units='1/s') indep_var_comp.add_output('R', val=0.74e6, units='m') indep_var_comp.add_output('speed_of_sound', val= np.array([334.4, 342.]), units='m/s') indep_var_comp.add_output('load_factor', val=np.array([1., 2.5])) indep_var_comp.add_output('empty_cg', val=np.zeros((3)), units='m') indep_var_comp.add_output('fuel_mass', val=800., units='kg') if case_settings['engine_mass'] or case_settings['engine_thrust']: point_mass_locations = np.array([[-0.85, -3., 0.15], [-0.55, -6., 0.15]]) indep_var_comp.add_output('point_mass_locations', val=point_mass_locations, units='m') if case_settings['engine_thrust']: engine_thrusts = np.array([[250., 250.]]) indep_var_comp.add_output('engine_thrusts', val=engine_thrusts, units='N') # TODO : need to fix this one too if case_settings['engine_mass']: indep_var_comp.add_output('W0_without_point_masses', val=6000. + surfaces[0]['Wf_reserve'] - 350., units='kg') prob.model.add_subsystem('W0_comp', ExecComp('W0 = W0_without_point_masses + sum(point_masses)', units='kg', point_masses=np.zeros((2))), promotes=['*']) point_masses = np.array([[175., 175.]]) indep_var_comp.add_output('point_masses', val=point_masses, units='kg') else: indep_var_comp.add_output('W0', val=6000 + surfaces[0]['Wf_reserve'], units='kg') prob.model.add_subsystem('prob_vars', indep_var_comp, promotes=['*']) return prob
def setup(self): E = self.metadata['E'] L = self.metadata['L'] b = self.metadata['b'] volume = self.metadata['volume'] num_elements = self.metadata['num_elements'] num_nodes = num_elements + 1 num_cp = self.metadata['num_cp'] num_load_cases = self.metadata['num_load_cases'] inputs_comp = IndepVarComp() inputs_comp.add_output('h_cp', shape=num_cp) self.add_subsystem('inputs_comp', inputs_comp) comp = 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) comp = GlobalStiffnessMatrixComp(num_elements=num_elements) self.add_subsystem('global_stiffness_matrix_comp', comp) # Parallel Subsystem for load cases. par = self.add_subsystem('parallel', 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, 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('global_stiffness_matrix_comp.K', 'parallel.%s.states_comp.K' % 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 = 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('local_stiffness_matrix_comp.K_local', 'global_stiffness_matrix_comp.K_local') 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 test(self): # Create a dictionary to store options about the surface mesh_dict = {'num_y' : 7, 'num_x' : 2, 'wing_type' : 'rect', 'symmetry' : True} mesh = generate_mesh(mesh_dict) surf_dict = { # Wing definition 'name' : 'wing', # name of the surface 'type' : 'aero', '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', 'mesh' : mesh, 'num_x' : mesh.shape[0], 'num_y' : mesh.shape[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.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' : 0.15, # thickness over chord ratio (NACA0015) 'c_max_t' : .303, # chordwise location of maximum (NACA0015) # thickness 'with_viscous' : True, # if true, compute viscous drag } # Create a dictionary to store options about the surface mesh_dict = {'num_y' : 5, 'num_x' : 3, 'wing_type' : 'rect', 'symmetry' : True, 'offset' : np.array([50, 0., 0.])} mesh = generate_mesh(mesh_dict) surf_dict2 = { # Wing definition 'name' : 'tail', # name of the surface 'type' : 'aero', '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' 'mesh' : mesh, 'num_x' : mesh.shape[0], 'num_y' : mesh.shape[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.0, # CD of the surface at alpha=0 'fem_origin' : 0.35, # Airfoil properties for viscous drag calculation 'k_lam' : 0.05, # percentage of chord with laminar # flow, used for viscous drag 't_over_c' : 0.15, # thickness over chord ratio (NACA0015) 'c_max_t' : .303, # chordwise location of maximum (NACA0015) # thickness 'with_viscous' : True, # if true, compute viscous drag } surfaces = [surf_dict, surf_dict2] # Create the problem and the model group prob = Problem() indep_var_comp = IndepVarComp() indep_var_comp.add_output('v', val=248.136, units='m/s') indep_var_comp.add_output('alpha', val=5.) indep_var_comp.add_output('M', 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('M', point_name + '.M') 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') # Set up the problem prob.setup() prob.run_model() assert_rel_error(self, prob['aero_point_0.wing_perf.CD'][0], 0.035076501750605345, 1e-6) assert_rel_error(self, prob['aero_point_0.wing_perf.CL'][0], 0.4523608754613204, 1e-6) assert_rel_error(self, prob['aero_point_0.CM'][1], -10.59426779178033, 1e-6)
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, 'n_point_masses': 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.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 = Problem() # Add problem information as an independent variables component indep_var_comp = 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') point_masses = np.array([[8000.]]) engine_thrusts = np.array([[80.e3]]) point_mass_locations = np.array([[25, -10., -1.]]) indep_var_comp.add_output('point_masses', val=point_masses, units='kg') indep_var_comp.add_output('engine_thrusts', val=engine_thrusts, units='N') indep_var_comp.add_output('point_mass_locations', val=point_mass_locations, 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') prob.model.connect('load_factor', point_name + '.coupled.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') # 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') coupled_name = point_name + '.coupled.' + name prob.model.connect('point_masses', coupled_name + '.point_masses') prob.model.connect('engine_thrusts', coupled_name + '.engine_thrusts') prob.model.connect('point_mass_locations', coupled_name + '.point_mass_locations') # Set up the problem prob.setup() prob.run_model() print(prob['AS_point_0.fuelburn'][0]) print(prob['AS_point_0.CM'][1]) assert_rel_error(self, prob['AS_point_0.fuelburn'][0], 277112.600118, 1e-4) assert_rel_error(self, prob['AS_point_0.CM'][1], -0.565647440276, 1e-5)
def test(self): # Create a dictionary to store options about the surface mesh_dict = { 'num_y': 7, 'num_x': 2, 'wing_type': 'CRM', 'symmetry': False, 'num_twist_cp': 2, 'span_cos_spacing': 1. } mesh, twist_cp = generate_mesh(mesh_dict) surf_dict = { # Wing definition 'name': 'wing', # name of the surface 'type': 'aerostruct', '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', 'thickness_cp': np.ones(2) * 0.06836728, 'twist_cp': twist_cp, 'mesh': mesh, 'num_x': mesh.shape[0], 'num_y': mesh.shape[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.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.12]), # 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': 1., # Constraints 'exact_failure_constraint': False, # if false, use KS function } surfaces = [surf_dict] # Create the problem and assign the model group prob = Problem() # Add problem information as an independent variables component indep_var_comp = 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('M', 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=9.80665 * 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('a', 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') 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 = Aerostruct(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('M', point_name + '.M') 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('a', point_name + '.a') 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', name + '.load_factor') com_name = point_name + '.' + name + '_perf' prob.model.connect(name + '.K', point_name + '.coupled.' + name + '.K') # Connect aerodyamic mesh to coupled group mesh prob.model.connect(name + '.mesh', point_name + '.coupled.' + name + '.mesh') prob.model.connect( name + '.element_weights', point_name + '.coupled.' + name + '.element_weights') # 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_weight', point_name + '.' + 'total_perf.' + name + '_structural_weight') prob.model.connect(name + '.t_over_c', com_name + '.t_over_c') from openmdao.api import ScipyOptimizeDriver prob.driver = ScipyOptimizeDriver() prob.driver.options['tol'] = 1e-9 # Setup problem and add design variables, constraint, and objective prob.model.add_design_var('wing.twist_cp', lower=-15., upper=15.) prob.model.add_design_var('wing.thickness_cp', lower=0.01, upper=0.5, scaler=1e2) prob.model.add_constraint('AS_point_0.wing_perf.failure', upper=0.) prob.model.add_constraint('AS_point_0.wing_perf.thickness_intersects', upper=0.) # Add design variables, constraisnt, and objective on the problem prob.model.add_design_var('alpha', lower=-10., upper=10.) prob.model.add_constraint('AS_point_0.L_equals_W', equals=0.) prob.model.add_objective('AS_point_0.fuelburn', scaler=1e-5) # Set up the problem prob.setup() # from openmdao.api import view_model # view_model(prob) prob.run_driver() assert_rel_error(self, prob['AS_point_0.wing_perf.CL'][0], 0.469152412337, 1e-6) assert_rel_error(self, prob['AS_point_0.fuelburn'][0], 95396.2868311, 1e-6) assert_rel_error(self, prob['AS_point_0.wing_perf.failure'][0], 0., 1e-6) assert_rel_error(self, prob['AS_point_0.CM'][1], -0.13357819566, 1e-4)
result = self.options['deriv']( *[inputs[in_name].flatten() for in_name in in_names]) for ind, in_name in enumerate(in_names): partials[out_name, in_name] = result[ind] if __name__ == '__main__': from openmdao.api import Problem, IndepVarComp shape = (2, 3, 4) prob = Problem() comp = IndepVarComp() comp.add_output('x', np.random.rand(*shape)) comp.add_output('y', np.random.rand(*shape)) comp.add_output('z', np.random.rand(*shape)) prob.model.add_subsystem('inputs_comp', comp, promotes=['*']) def func(x, y, z): return x * y * z def deriv(x, y, z): return ( y * z, x * z, x * y, ) comp = GeneralOperationComp(
def setup(self): lsm_solver = self.options['lsm_solver'] num_bpts = self.options['num_bpts'] upperbound = self.options['ub'] lowerbound = self.options['lb'] Sf = self.options['Sf'] Sg = self.options['Sg'] constraintDistance = self.options['constraintDistance'] num_dvs = 2 # number of lambdas # inputs (IndepVarComp: component) comp = IndepVarComp() comp.add_output('lambdas', val = 0.0, shape = num_dvs) comp.add_output('Sf', val=Sf) comp.add_output('Sg', val=Sg) comp.add_output('constraintDistance', val=constraintDistance) self.add_subsystem('inputs_comp', comp) self.add_design_var('inputs_comp.lambdas', lower = np.array([lowerbound[0], lowerbound[1]]), upper = np.array([upperbound[0], upperbound[1]])) # scalings setup # verified (10/24) comp = ScalingComp(nBpts= num_bpts, lsm_solver=lsm_solver) self.add_subsystem('scaling_f_comp',comp) self.connect('inputs_comp.Sf', 'scaling_f_comp.x') comp = ScalingComp(nBpts= num_bpts, lsm_solver=lsm_solver) self.add_subsystem('scaling_g_comp',comp) self.connect('inputs_comp.Sg', 'scaling_g_comp.x') # displacements setup comp = DisplacementComp(lsm_solver = lsm_solver, nBpts = num_bpts, ndvs = num_dvs) self.add_subsystem('displacement_comp', comp) self.connect('inputs_comp.lambdas', 'displacement_comp.lambdas') self.connect('inputs_comp.Sf', 'displacement_comp.Sf') self.connect('inputs_comp.Sg', 'displacement_comp.Sg') self.connect('scaling_f_comp.y', 'displacement_comp.Scale_f') self.connect('scaling_g_comp.y', 'displacement_comp.Scale_g') # integration setup comp = IntegralComp(lsm_solver=lsm_solver, nBpts=num_bpts) self.add_subsystem('integral_f_comp', comp) self.connect('inputs_comp.Sf', 'integral_f_comp.x') comp = IntegralComp(lsm_solver=lsm_solver, nBpts=num_bpts) self.add_subsystem('integral_g_comp', comp) self.connect('inputs_comp.Sg', 'integral_g_comp.x') # objective setup comp = ObjectiveComp(lsm_solver = lsm_solver, nBpts = num_bpts) comp.add_objective('delF') self.add_subsystem('objective_comp', comp) self.connect('displacement_comp.displacements', 'objective_comp.displacements') self.connect('integral_f_comp.y', 'objective_comp.Cf') self.connect('scaling_f_comp.y', 'objective_comp.scale_f') # constraint setup comp = ConstraintComp(lsm_solver = lsm_solver, nBpts = num_bpts) comp.add_constraint('delG', upper = 0.0 ) self.add_subsystem('constraint_comp', comp) self.connect('displacement_comp.displacements', 'constraint_comp.displacements') self.connect('integral_g_comp.y', 'constraint_comp.Cg') self.connect('scaling_g_comp.y', 'constraint_comp.scale_g') self.connect('inputs_comp.constraintDistance', 'constraint_comp.constraintDistance')
'blade_drag_coeff', 'glauert_factor', ] self.options['get_res_func'] = get_res_func self.options['get_derivs_func'] = get_derivs_func if __name__ == '__main__': import numpy as np from openmdao.api import Problem, IndepVarComp blade_solidity = 0.2 shape = (2, 3) prob = Problem() comp = IndepVarComp() comp.add_output('eta2', np.random.random(shape)) comp.add_output('eta3', np.random.random(shape)) comp.add_output('power_coeff', np.random.random(shape)) comp.add_output('advance_ratio', np.random.random(shape)) prob.model.add_subsystem('input_comp', comp, promotes=['*']) comp = Eta1Comp(shape=shape, blade_solidity=blade_solidity) prob.model.add_subsystem('comp', comp, promotes=['*']) prob.setup(check=True) prob.run_model() prob.check_partials(compact_print=True)
def test(self): from openaerostruct.geometry.utils import generate_mesh, write_FFD_file from openaerostruct.integration.aerostruct_groups import AerostructGeometry, AerostructPoint from openmdao.api import IndepVarComp, Problem, Group, SqliteRecorder from pygeo import DVGeometry # 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]), 'mesh': mesh, 'geom_manipulator': 'FFD', 'mx': 2, 'my': 3, # 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 = Problem() # Add problem information as an independent variables component indep_var_comp = 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=9.80665 * 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') 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'] filename = write_FFD_file(surface, surface['mx'], surface['my']) DVGeo = DVGeometry(filename) aerostruct_group = AerostructGeometry(surface=surface, DVGeo=DVGeo) # 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', name + '.load_factor') com_name = point_name + '.' + name + '_perf' prob.model.connect(name + '.K', point_name + '.coupled.' + name + '.K') 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_weight', point_name + '.' + 'total_perf.' + name + '_structural_weight') prob.model.connect(name + '.t_over_c', com_name + '.t_over_c') # Import the Scipy Optimizer and set the driver of the problem to use # it, which defaults to an SLSQP optimization method from openmdao.api import ScipyOptimizeDriver prob.driver = ScipyOptimizeDriver() recorder = SqliteRecorder("aerostruct_ffd.db") prob.driver.add_recorder(recorder) prob.driver.recording_options['record_derivatives'] = True prob.driver.recording_options['includes'] = ['*'] # Setup problem and add design variables, constraint, and objective prob.model.add_design_var('wing.shape', lower=-3, upper=2) prob.model.add_design_var('wing.thickness_cp', lower=0.01, upper=0.5, scaler=1e2) prob.model.add_constraint('AS_point_0.wing_perf.failure', upper=0.) prob.model.add_constraint('AS_point_0.wing_perf.thickness_intersects', upper=0.) # Add design variables, constraisnt, and objective on the problem prob.model.add_design_var('alpha', lower=-10., upper=10.) prob.model.add_constraint('AS_point_0.L_equals_W', equals=0.) prob.model.add_objective('AS_point_0.fuelburn', scaler=1e-5) # iprofile.setup() # iprofile.start() # Set up the problem prob.setup() # from openmdao.api import view_model # view_model(prob, outfile='aerostruct_ffd', show_browser=False) # prob.run_model() prob.run_driver() # prob.check_partials(compact_print=True) # print("\nWing CL:", prob['aero_point_0.wing_perf.CL']) # print("Wing CD:", prob['aero_point_0.wing_perf.CD']) # from helper import plot_3d_points # # mesh = prob['aero_point_0.wing.def_mesh'] # plot_3d_points(mesh) # # filename = mesh_dict['wing_type'] + '_' + str(mesh_dict['num_x']) + '_' + str(mesh_dict['num_y']) # filename += '_' + str(surf_dict['mx']) + '_' + str(surf_dict['my']) + '.mesh' # np.save(filename, mesh) assert_rel_error(self, prob['AS_point_0.fuelburn'][0], 104675.0989232741, 1e-3)
def compute_partials(self, inputs, partials): in_name = self.options['in_name'] out_name = self.options['out_name'] partials[out_name, in_name] = 1.0 - ( (1.0 / np.tanh(inputs[in_name]))**2).flatten() if __name__ == "__main__": from openmdao.api import Problem, IndepVarComp, Group n = 100 val = np.random.rand(n) indeps = IndepVarComp() indeps.add_output( 'x', val=val, shape=(n, ), ) prob = Problem() prob.model = Group() prob.model.add_subsystem( 'indeps', indeps, promotes=['*'], ) prob.model.add_subsystem( 'coth', CotanhComp(in_name='x', out_name='y', shape=(n, )), promotes=['*'], ) prob.setup()
tmps[ind] = array partials[out_name, in2_name] = (tmps[0] + tmps[1] + tmps[2]).flatten() if __name__ == '__main__': from openmdao.api import Problem, IndepVarComp shape = (2, 4, 3, 5) axis = 2 prob = Problem() comp = IndepVarComp() comp.add_output('in1', val=np.random.random(shape)) comp.add_output('in2', val=np.random.random(shape)) prob.model.add_subsystem('ivc', comp, promotes=['*']) comp = CrossProductComp( shape=shape, axis=axis, out_name='out', in1_name='in1', in2_name='in2', ) prob.model.add_subsystem('comp', comp, promotes=['*']) prob.setup(check=True) prob.run_model() prob.check_partials(compact_print=True)
def setup(self): map_data = self.options['map_data'] design = self.options['design'] method = self.options['interp_method'] extrap = self.options['extrap'] params = map_data.param_data outputs = map_data.output_data # Define map which will be used readmap = MetaModelStructuredComp(method=method, extrapolate=extrap) for p in params: readmap.add_input(p['name'], val=p['default'], units=p['units'], training_data=p['values']) for o in outputs: readmap.add_output(o['name'], val=o['default'], units=o['units'], training_data=o['values']) # Create instance of map for evaluating actual operating point if design: # In design mode, operating point specified by default values for RlineMap, NcMap and alphaMap mapDesPt = IndepVarComp() mapDesPt.add_output('NcMap', val=map_data.defaults['NcMap'], units='rpm') mapDesPt.add_output('RlineMap', val=map_data.defaults['RlineMap'], units=None) self.add_subsystem('mapDesPt', subsys=mapDesPt, promotes=['*']) # Evaluate map using design point values self.add_subsystem( 'map', readmap, promotes_inputs=['RlineMap', 'NcMap', 'alphaMap'], promotes_outputs=['effMap', 'PRmap', 'WcMap']) # Compute map scalars based on input PR, eff, Nc and Wc as well as unscaled map values self.add_subsystem( 'scalars', MapScalars(), promotes_inputs=[ 'PR', 'eff', 'Nc', 'Wc', 'NcMap', 'effMap', 'PRmap', 'WcMap' ], promotes_outputs=['s_Nc', 's_PR', 's_eff', 's_Wc']) else: # In off-design mode, RlineMap, NcMap and alphaMap are input to map self.add_subsystem( 'map', readmap, promotes_inputs=['RlineMap', 'NcMap', 'alphaMap'], promotes_outputs=['effMap', 'PRmap', 'WcMap']) # Compute scaled map outputs base on input scalars and unscaled map values self.add_subsystem('scaledOutput', ScaledMapValues(), promotes_inputs=[ 's_PR', 's_eff', 's_Wc', 's_Nc', 'NcMap', 'effMap', 'PRmap', 'WcMap' ], promotes_outputs=['PR', 'eff']) # Use balance component to vary NcMap and RlineMap to match incoming corrected flow and speed map_bal = BalanceComp() map_bal.add_balance('NcMap', val=map_data.defaults['NcMap'], units='rpm', eq_units='rpm') map_bal.add_balance('RlineMap', val=map_data.defaults['RlineMap'], units=None, eq_units='lbm/s', lower=map_data.RlineStall) self.add_subsystem(name='map_bal', subsys=map_bal, promotes_inputs=[('lhs:NcMap', 'Nc'), ('lhs:RlineMap', 'Wc')], promotes_outputs=['NcMap', 'RlineMap']) self.connect('scaledOutput.Nc', 'map_bal.rhs:NcMap') self.connect('scaledOutput.Wc', 'map_bal.rhs:RlineMap') # Define the Rline corresponding to stall RlineStall = IndepVarComp() RlineStall.add_output('RlineStall', val=map_data.RlineStall, units=None) self.add_subsystem('stall_R', subsys=RlineStall) # Evaluate map for the constant speed stall margin (SMN) SMN_map = MetaModelStructuredComp(method=method, extrapolate=extrap) for p in params: SMN_map.add_input(p['name'], val=p['default'], units=p['units'], training_data=p['values']) for o in outputs: SMN_map.add_output(o['name'], val=o['default'], units=o['units'], training_data=o['values']) self.add_subsystem('SMN_map', SMN_map, promotes_inputs=['NcMap', 'alphaMap']) self.connect('stall_R.RlineStall', 'SMN_map.RlineMap') # Evaluate map for the constant speed stall margin (SMN) SMW_map = MetaModelStructuredComp(method=method, extrapolate=extrap) for p in params: SMW_map.add_input(p['name'], val=p['default'], units=p['units'], training_data=p['values']) for o in outputs: SMW_map.add_output(o['name'], val=o['default'], units=o['units'], training_data=o['values']) self.add_subsystem('SMW_map', SMW_map, promotes_inputs=['alphaMap']) self.connect('stall_R.RlineStall', 'SMW_map.RlineMap') # Use balance to vary NcMap on SMW map to hold corrected flow constant SMW_bal = BalanceComp() SMW_bal.add_balance('NcMap', val=map_data.defaults['NcMap'], units='rpm', eq_units='lbm/s') self.add_subsystem(name='SMW_bal', subsys=SMW_bal) self.connect('SMW_bal.NcMap', 'SMW_map.NcMap') self.connect('WcMap', 'SMW_bal.lhs:NcMap') self.connect('SMW_map.WcMap', 'SMW_bal.rhs:NcMap') # Compute the stall margins self.add_subsystem('stall_margins', StallCalcs(), promotes_inputs=[('PR_actual', 'PRmap'), ('Wc_actual', 'WcMap')], promotes_outputs=['SMN', 'SMW']) self.connect('SMN_map.PRmap', 'stall_margins.PR_SMN') self.connect('SMW_map.PRmap', 'stall_margins.PR_SMW') self.connect('SMN_map.WcMap', 'stall_margins.Wc_SMN')
def fctOptim(mrhoi, skin, spar, span, toverc): # Starting time starttime = time.time() # Materials #sandw1=material(66.35,4.25e9,1.63e9,58.7e6/1.5,34.7,"sandw1") #sandw2=material(174.5,14.15e9,5.44e9,195.6e6/1.5,43.4,"sandw2") #sandw3=material(483,42.5e9,16.3e9,586e6/1.5,46.8,"sandw3") sandw4 = material(504.5, 42.5e9, 16.3e9, 586e6 / 1.5, 44.9, "sandw4") #sandw5=material(574.5,42.5e9,16.3e9,586e6/1.5,39.3,"sandw5") sandw5 = material(560.5, 42.5e9, 16.3e9, 586e6 / 1.5, 40.3, "sandw5") sandw6 = material(529, 42.5e9, 16.3e9, 237e6 / 1.5, 42.75, "sandw6") al7075 = material(2.80e3, 72.5e9, 27e9, 444.5e6 / 1.5, 13.15 * (1 - 0.426) + 2.61 * 0.426, "al7075") #from EDUPACK #al7075oas=material(2.78e3,73.1e9,73.1e9/2/1.33,444.5e6/1.5,13.15*(1-0.426)+2.61*0.426,"al7075") #from OAS example qiCFRP = material(1565, 54.9e9, 21e9, 670e6 / 1.5, 48.1, "qiCFRP") steel = material(7750, 200e9, 78.5e9, 562e6 / 1.5, 4.55 * (1 - 0.374) + 1.15 * 0.374, "steel") gfrp = material(1860, 21.4e9, 8.14e9, 255e6, 6.18, "gfrp") #epoxy-Eglass,woven,QI #nomat=material(1370,0.01,0.01,0.01,60,"noMaterial") nomat = material(50, 1e8, 1e4, 1e5, 6000, "noMaterial") #nomat=material(50,1e8,1e4,1e5,60,"noMaterial") fakemat = material((2.80e3 + 7750) / 2, (72.5e9 + 200e9) / 2, (27e9 + 78.5e9) / 2, (444.5e6 / 1.5 + 562e6 / 1.5) / 2, (13.15 * (1 - 0.426) + 2.61 * 0.426 + 4.55 * (1 - 0.374) + 1.15 * 0.374) / 2, "fakemat") nomatEnd = material(10000, 5e9, 2e9, 20e6 / 1.5, 60, "nomatEnd") materials = [ al7075, qiCFRP, steel, gfrp, nomat, fakemat, nomatEnd, sandw4, sandw5, sandw6 ] # materials=[al7075, qiCFRP, steel, gfrp, nomat, fakemat, nomatEnd, sandw3, sandw4, sandw5, sandw6] # materials=[al7075, qiCFRP, steel, gfrp, nomat, fakemat, nomatEnd,sandw1,sandw2,sandw3] # materials=[sandw4, sandw5, nomat, nomatEnd] # Provide coordinates for a portion of an airfoil for the wingbox cross-section as an nparray with dtype=complex (to work with the complex-step approximation for derivatives). # These should be for an airfoil with the chord scaled to 1. # We use the 10% to 60% portion of the NACA 63412 airfoil for this case # We use the coordinates available from airfoiltools.com. Using such a large number of coordinates is not necessary. # The first and last x-coordinates of the upper and lower surfaces must be the same upper_x = np.array([ 0.1, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.3, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6 ], dtype='complex128') lower_x = np.array([ 0.1, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.3, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6 ], dtype='complex128') upper_y = np.array([ 0.0513, 0.0537, 0.0559, 0.0580, 0.0600, 0.0619, 0.0636, 0.0652, 0.0668, 0.0682, 0.0696, 0.0709, 0.0721, 0.0732, 0.0742, 0.0752, 0.0761, 0.0769, 0.0776, 0.0782, 0.0788, 0.0793, 0.0797, 0.0801, 0.0804, 0.0806, 0.0808, 0.0808, 0.0808, 0.0807, 0.0806, 0.0804, 0.0801, 0.0798, 0.0794, 0.0789, 0.0784, 0.0778, 0.0771, 0.0764, 0.0757, 0.0749, 0.0740, 0.0732, 0.0723, 0.0713, 0.0703, 0.0692, 0.0681, 0.0669, 0.0657 ], dtype='complex128') lower_y = np.array([ -0.0296, -0.0307, -0.0317, -0.0326, -0.0335, -0.0343, -0.0350, -0.0357, -0.0363, -0.0368, -0.0373, -0.0378, -0.0382, -0.0386, -0.0389, -0.0391, -0.0394, -0.0395, -0.0397, -0.0398, -0.0398, -0.0398, -0.0398, -0.0397, -0.0396, -0.0394, -0.0392, -0.0389, -0.0386, -0.0382, -0.0378, -0.0374, -0.0369, -0.0363, -0.0358, -0.0352, -0.0345, -0.0338, -0.0331, -0.0324, -0.0316, -0.0308, -0.0300, -0.0292, -0.0283, -0.0274, -0.0265, -0.0256, -0.0246, -0.0237, -0.0227 ], dtype='complex128') Rcurv = RadiusCurvature(upper_x, lower_x, upper_y, lower_y) # Create a dictionary to store options about the surface mesh_dict = { 'num_y': 15, 'num_x': 3, 'wing_type': 'rect', 'symmetry': True, 'chord_cos_spacing': 0, 'span_cos_spacing': 0, 'num_twist_cp': 4 } mesh = generate_mesh(mesh_dict) # Batteries and solar panels densityPV = 0.23 #kg/m^2 energeticDensityBattery = 435 * 0.995 * 0.95 * 0.875 * 0.97 #Wh/kg 0.995=battery controller efficiency, 0.95=end of life capacity loss of 5%, 0.97=min battery SOC of 3%, 0.875=packaging efficiency emissionBat = 0.104 / 0.995 / 0.95 / 0.875 / 0.97 #[kgCO2/Wh] night_hours = 13 #h productivityPV = 350.0 * 0.97 * 0.95 #[W/m^2] 350 from Zephyr power figure, 0.97=MPPT efficiency, 0.95=battery round trip efficiency emissionPV = 0.05 / 0.97 / 0.95 #[kgCO2/W] emissions of the needed PV surface to produce 1W emissionsPerW = emissionPV + emissionBat * night_hours #[kgCO2/W] # Dictionary for the lifting surface surf_dict = { # Wing definition 'name': 'wing', # give the surface some name 'symmetry': True, # if True, model only one half of the lifting surface 'S_ref_type': 'projected', # how we compute the wing area, # can be 'wetted' or 'projected' 'mesh': mesh, 'fem_model_type': 'wingbox', # 'wingbox' or 'tube' 'data_x_upper': upper_x, 'data_x_lower': lower_x, 'data_y_upper': upper_y, 'data_y_lower': lower_y, 'airfoil_radius_curvature': Rcurv, 'twist_cp': np.array([10., 20., 20., 20.]), # [deg] 'chord_cp': [1.5], # [m] 'span': span, #[m] 'taper': 0.3, 'spar_thickness_cp': np.array([spar, spar, spar, spar]), # [m] 'skin_thickness_cp': np.array([skin / 2, skin, skin * 1.5, 2 * skin]), # [m] 't_over_c_cp': np.array([0.75 * toverc, toverc, toverc, 1.25 * toverc]), #TODELETE 'original_wingbox_airfoil_t_over_c': 0.12, # Aerodynamic deltas. # 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. # They can be used to account for things that are not included, such as contributions from the fuselage, camber, etc. 'CL0': 0.0, # CL delta 'CD0': 0.0078, # CD delta 'with_viscous': True, # if true, compute viscous drag 'with_wave': True, # if true, compute wave drag # Airfoil properties for viscous drag calculation 'k_lam': 0.80, #'k_lam' : 0.05, # fraction of chord with laminar # flow, used for viscous drag 'c_max_t': .349, # chordwise location of maximum thickness # Materials 'materlist': materials, 'puissanceMM': 1, #power used in muli-material function # Structural values 'strength_factor_for_upper_skin': 1.0, # the yield stress is multiplied by this factor for the upper skin 'wing_weight_ratio': 1., 'exact_failure_constraint': False, # if false, use KS function 'struct_weight_relief': True, # Engines 'n_point_masses': 1, # number of point masses in the system; in this case, the engine (omit option if no point masses) # Power 'productivityPV': productivityPV, #[W/m^2] 'densityPV': densityPV + productivityPV / energeticDensityBattery * night_hours, #[kg/m^2] the weight of the batteries is counted here 'payload_power': 125.5, #[W] payload=150 + avionics=211 'motor_propeller_efficiency': 0.84, #thrusting power/electrical power used by propulsion 'co2PV': emissionsPerW * productivityPV / (densityPV + productivityPV / energeticDensityBattery * night_hours), #[kgCO2/kg] #co2 burden of PV cells and battery 'prop_density': 0.0058, #[kg/W] 'mppt_density': 0.00045, #[kg/W] } surfaces = [surf_dict] # Create the problem and assign the model group prob = Problem() # Add problem information as an independent variables component data for altitude=23240 m and 0 m speed = 15.56 #m/s speed_dive = 1.4 * speed #m/s gust_speed = 3.4 #m/s rho_air = 0.089 #kg/m**3 speed_sound = 295.1 #m/s #n_gust = 1 + 0.5*rho_air*speed_dive*gust_speed*2*pi/3000 indep_var_comp = IndepVarComp() indep_var_comp.add_output('Mach_number', val=np.array([ speed / speed_sound, (speed_dive**2 + gust_speed**2)**0.5 / speed_sound, 0 ])) indep_var_comp.add_output( 'v', val=np.array([speed, (speed_dive**2 + gust_speed**2)**0.5, 0]), units='m/s') indep_var_comp.add_output('re',val=np.array([rho_air*speed*1./(1.4*1e-5), \ rho_air*speed_dive*1./(1.4*1e-5), 0]), units='1/m') #L=10m, indep_var_comp.add_output('rho', val=np.array([rho_air, rho_air, 1.225]), units='kg/m**3') indep_var_comp.add_output('speed_of_sound', val=np.array([speed_sound, speed_sound, 340]), units='m/s') indep_var_comp.add_output('W0_without_point_masses', val=8, units='kg') indep_var_comp.add_output('load_factor', val=np.array([1., 1.1, 0.])) indep_var_comp.add_output('alpha', val=0., units='deg') indep_var_comp.add_output('alpha_gust', val=atan(gust_speed / speed_dive) * 180 / pi, units='deg') indep_var_comp.add_output('empty_cg', val=np.zeros((3)), units='m') indep_var_comp.add_output('mrho', val=np.array([mrhoi, mrhoi]), units='kg/m**3') indep_var_comp.add_output('engine_location', val=-0.3) #VMGM 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 groups to the problem with the name of the surface. prob.model.add_subsystem(name, aerostruct_group) prob.model.add_subsystem('YoungMM', YoungMM(surface=surface), promotes_inputs=['mrho'], promotes_outputs=['young']) #VMGM prob.model.add_subsystem('ShearMM', ShearMM(surface=surface), promotes_inputs=['mrho'], promotes_outputs=['shear']) #VMGM prob.model.add_subsystem('YieldMM', YieldMM(surface=surface), promotes_inputs=['mrho'], promotes_outputs=['yield']) #VMGM prob.model.add_subsystem('CO2MM', CO2MM(surface=surface), promotes_inputs=['mrho'], promotes_outputs=['co2']) #VMGM prob.model.add_subsystem( 'PointMassLocations', PointMassLocations(surface=surface), promotes_inputs=['engine_location', 'span', 'nodes'], promotes_outputs=['point_mass_locations']) #VMGM prob.model.add_subsystem('PointMasses', PointMasses(surface=surface), promotes_inputs=['PV_surface'], promotes_outputs=['point_masses']) #VMGM prob.model.add_subsystem( 'W0_comp', ExecComp('W0 = W0_without_point_masses + 2*sum(point_masses)', units='kg'), promotes=['*']) prob.model.connect('mrho', name + '.struct_setup.structural_mass.mrho') #ED prob.model.connect('young', name + '.struct_setup.assembly.local_stiff.young') #VMGM prob.model.connect('shear', name + '.struct_setup.assembly.local_stiff.shear') #VMGM prob.model.connect('wing.span', 'span') #VMGM prob.model.connect('AS_point_0.total_perf.PV_surface', 'PV_surface') #VMGM prob.model.connect(name + '.nodes', 'nodes') #VMGM # Loop through and add a certain number of aerostruct points for i in range(3): # for i in range(1): point_name = 'AS_point_{}'.format(i) # Connect the parameters within the model for each aero point # Create the aerostruct 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', src_indices=[i]) prob.model.connect('Mach_number', point_name + '.Mach_number', src_indices=[i]) prob.model.connect('re', point_name + '.re', src_indices=[i]) prob.model.connect('rho', point_name + '.rho', src_indices=[i]) prob.model.connect('W0', point_name + '.W0') prob.model.connect('speed_of_sound', point_name + '.speed_of_sound', src_indices=[i]) prob.model.connect('empty_cg', point_name + '.empty_cg') prob.model.connect('load_factor', point_name + '.load_factor', src_indices=[i]) for surface in surfaces: name = surface['name'] prob.model.connect('load_factor', point_name + '.coupled.load_factor', src_indices=[i]) #for PV distributed weight 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') prob.model.connect('young', com_name + 'struct_funcs.vonmises.young') prob.model.connect('shear', com_name + 'struct_funcs.vonmises.shear') prob.model.connect('yield', com_name + 'struct_funcs.failure.yield') #VMGM prob.model.connect('young', com_name + 'struct_funcs.buckling.young') #VMGM prob.model.connect('shear', com_name + 'struct_funcs.buckling.shear') #VMGM prob.model.connect(name + '.t_over_c', com_name + 'struct_funcs.buckling.t_over_c') #VMGM # Connect aerodyamic mesh to coupled group mesh prob.model.connect(name + '.mesh', point_name + '.coupled.' + name + '.mesh') if surf_dict['struct_weight_relief']: 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 + '.Qx', com_name + 'Qx') prob.model.connect(name + '.spar_thickness', com_name + 'spar_thickness') prob.model.connect(name + '.skin_thickness', com_name + 'skin_thickness') prob.model.connect(name + '.t_over_c', com_name + 't_over_c') coupled_name = point_name + '.coupled.' + name prob.model.connect('point_masses', coupled_name + '.point_masses') prob.model.connect('point_mass_locations', coupled_name + '.point_mass_locations') prob.model.connect('alpha', 'AS_point_0' + '.alpha') prob.model.connect('alpha_gust', 'AS_point_1' + '.alpha') prob.model.connect('alpha', 'AS_point_2' + '.alpha') #VMGM # Here we add the co2 objective componenet to the model prob.model.add_subsystem('emittedco2', structureCO2(surfaces=surfaces), promotes_inputs=['co2'], promotes_outputs=['emitted_co2']) #VMGM prob.model.connect('wing.structural_mass', 'emittedco2.mass') prob.model.connect('AS_point_0.total_perf.PV_mass', 'emittedco2.PV_mass') prob.model.connect('wing.spars_mass', 'emittedco2.spars_mass') #VMGM #Here we add the thickness constraint to the model prob.model.add_subsystem('acceptableThickness', checkThickness(surface=surface), promotes_outputs=['acceptableThickness']) prob.model.connect('wing.geometry.t_over_c_cp', 'acceptableThickness.t_over_c') prob.model.connect('wing.chord_cp', 'acceptableThickness.chordroot') prob.model.connect('wing.skin_thickness_cp', 'acceptableThickness.skinThickness') prob.model.connect('wing.taper', 'acceptableThickness.taper') prob.model.connect('wing.struct_setup.PV_areas', 'AS_point_0.coupled.wing.struct_states.PV_areas') prob.model.connect('AS_point_0.total_perf.PV_mass', 'AS_point_0.coupled.wing.struct_states.PV_mass') prob.model.connect('wing.struct_setup.PV_areas', 'AS_point_1.coupled.wing.struct_states.PV_areas') prob.model.connect('AS_point_0.total_perf.PV_mass', 'AS_point_1.coupled.wing.struct_states.PV_mass') prob.model.connect('wing.chord_cp', 'AS_point_1.wing_perf.struct_funcs.chord') prob.model.connect('wing.taper', 'AS_point_1.wing_perf.struct_funcs.taper') prob.model.connect('wing.struct_setup.PV_areas', 'AS_point_2.coupled.wing.struct_states.PV_areas') #VMGM prob.model.connect('AS_point_0.total_perf.PV_mass', 'AS_point_2.coupled.wing.struct_states.PV_mass') #VMGM prob.model.connect('wing.chord_cp', 'AS_point_2.wing_perf.struct_funcs.chord') #VMGM prob.model.connect('wing.taper', 'AS_point_2.wing_perf.struct_funcs.taper') #VMGM # Objective function prob.model.add_objective('emitted_co2', scaler=1e-4) # Design variables prob.model.add_design_var('wing.twist_cp', lower=-20., upper=20., scaler=0.1) #VMGM prob.model.add_design_var('wing.spar_thickness_cp', lower=0.0001, upper=0.1, scaler=1e4) prob.model.add_design_var('wing.skin_thickness_cp', lower=0.0001, upper=0.1, scaler=1e3) prob.model.add_design_var('wing.span', lower=1., upper=1000., scaler=0.1) prob.model.add_design_var('wing.chord_cp', lower=1.4, upper=500., scaler=1) ##prob.model.add_design_var('wing.span', lower=1., upper=50., scaler=0.1) ##prob.model.add_design_var('wing.chord_cp', lower=1., upper=500., scaler=1) prob.model.add_design_var('wing.taper', lower=0.3, upper=0.99, scaler=10) prob.model.add_design_var('wing.geometry.t_over_c_cp', lower=0.01, upper=0.4, scaler=10.) prob.model.add_design_var('mrho', lower=504.5, upper=504.5, scaler=0.001) #ED #prob.model.add_design_var('mrho', lower=500, upper=8000, scaler=0.001) #ED prob.model.add_design_var('engine_location', lower=-1, upper=0, scaler=10.) #VMGM # Constraints prob.model.add_constraint('AS_point_0.L_equals_W', equals=0.) prob.model.add_constraint( 'AS_point_0.enough_power', upper=0. ) #Make sure needed power stays below the solar power producible by the wing prob.model.add_constraint( 'acceptableThickness', upper=0. ) #Make sure skin thickness fits in the wing (to avoid negative spar mass) #prob.model.add_constraint('AS_point_0.wing_perf.failure', upper=0.) #VMGM #prob.model.add_constraint('AS_point_0.wing_perf.buckling', upper=0.) #VMGM prob.model.add_constraint('AS_point_1.wing_perf.failure', upper=0.) prob.model.add_constraint('AS_point_1.wing_perf.buckling', upper=0.) prob.model.add_constraint('AS_point_2.wing_perf.failure', upper=0.) #VMGM prob.model.add_constraint('AS_point_2.wing_perf.buckling', upper=0.) #VMGM prob.model.add_constraint( 'AS_point_0.coupled.wing.S_ref', upper=200.) # Surface constarint to avoid snowball effect #prob.model.approx_totals(method='fd', step=5e-7, form='forward', step_calc='rel') #prob.model.nonlinear_solver = newton = NewtonSolver() prob.driver = ScipyOptimizeDriver() prob.driver.options['optimizer'] = 'SLSQP' prob.driver.options['tol'] = 1e-6 prob.driver.options['maxiter'] = 250 #prob.driver.options['debug_print'] = ['desvars','ln_cons','nl_cons','totals'] recorder = SqliteRecorder("aerostructMrhoi" + str(mrhoi) + "sk" + str(skin) + "sr" + str(spar) + "sn" + str(span) + "tc" + str(toverc) + ".db") prob.driver.add_recorder(recorder) # We could also just use prob.driver.recording_options['includes']=['*'] here, but for large meshes the database file becomes extremely large. So we just select the variables we need. prob.driver.recording_options['includes'] = [ 'alpha', 'rho', 'v', 'cg', 'alpha_gust', # 'AS_point_1.cg', 'AS_point_0.cg', # 'AS_point_0.cg', #ED 'AS_point_0.coupled.wing_loads.loads', 'AS_point_1.coupled.wing_loads.loads', # 'AS_point_2.coupled.wing_loads.loads', # 'AS_point_0.coupled.wing.normals', 'AS_point_1.coupled.wing.normals', # 'AS_point_0.coupled.wing.widths', 'AS_point_1.coupled.wing.widths', # 'AS_point_0.coupled.aero_states.wing_sec_forces', 'AS_point_1.coupled.aero_states.wing_sec_forces', # 'AS_point_2.coupled.aero_states.wing_sec_forces', # 'AS_point_0.wing_perf.CL1', 'AS_point_1.wing_perf.CL1', # 'AS_point_0.coupled.wing.S_ref', 'AS_point_1.coupled.wing.S_ref', # 'wing.geometry.twist', 'wing.geometry.mesh.taper.taper', 'wing.geometry.mesh.stretch.span', 'wing.geometry.mesh.scale_x.chord', 'wing.mesh', 'wing.skin_thickness', 'wing.spar_thickness', 'wing.t_over_c', 'wing.structural_mass', 'AS_point_0.wing_perf.vonmises', 'AS_point_1.wing_perf.vonmises', # 'AS_point_0.coupled.wing.def_mesh', 'AS_point_1.coupled.wing.def_mesh', # 'AS_point_0.total_perf.PV_mass', 'AS_point_0.total_perf.total_weight', 'AS_point_0.CL', 'AS_point_0.CD', 'yield', 'point_masses', #VMGM 'point_mass_locations', #VMGM 'engine_location', #VMGM ] prob.driver.recording_options['record_objectives'] = True prob.driver.recording_options['record_constraints'] = True prob.driver.recording_options['record_desvars'] = True prob.driver.recording_options['record_inputs'] = True # Set up the problem prob.setup() ##prob.run_model() #ED2 ##data = prob.check_partials(out_stream=None, compact_print=True, method='cs') #ED2 ##print(data) #ED2 prob.run_driver() ##print (prob.model.list_outputs(values=False, implicit=False)) #VMGM print('The wingbox mass (including the wing_weight_ratio) is', prob['wing.structural_mass'][0], '[kg]') endtime = time.time() totaltime = endtime - starttime print('computing time is', totaltime) print('co2 emissions are', prob['emitted_co2'][0]) print('The wing surface is', prob['AS_point_0.coupled.wing.S_ref'][0], '[m2]') #VMGM return prob['wing.structural_mass'][0], totaltime, prob['mrho'][0], prob[ 'emitted_co2'][0]
def test_multiple_masses(self): # Create a dictionary to store options about the surface mesh_dict = { 'num_y': 31, 'wing_type': 'rect', 'span': 10, 'symmetry': True } mesh = generate_mesh(mesh_dict) surface = { # 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.5, # 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 = Problem() ny = surface['mesh'].shape[1] surface['n_point_masses'] = 2 indep_var_comp = IndepVarComp() indep_var_comp.add_output('loads', val=np.zeros((ny, 6)), units='N') indep_var_comp.add_output('load_factor', val=1.) point_masses = np.array([[10., 20.]]) point_mass_locations = np.array([[1., -1., 0.], [1., -2., 0.]]) indep_var_comp.add_output('point_masses', val=point_masses, units='kg') indep_var_comp.add_output('point_mass_locations', val=point_mass_locations, units='m') struct_group = SpatialBeamAlone(surface=surface) # Add indep_vars to the structural group struct_group.add_subsystem('indep_vars', indep_var_comp, promotes=['*']) prob.model.add_subsystem(surface['name'], struct_group, promotes=['*']) # Set up the problem prob.setup() prob.run_model() assert_rel_error(self, prob['vonmises'][-1, 0], 1557126.5793494075, 1e-4)
'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 } # Create the problem and assign the model group prob = Problem() # Add problem information as an independent variables component indep_var_comp = 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('delta_aileron', val=0.) prob.model.add_subsystem('prob_vars', indep_var_comp, promotes=['*'])
if __name__ == '__main__': from openmdao.api import Problem, Group, IndepVarComp from numpy import sqrt class RSSMerge(AbstractWakeMerging): def compute(self, inputs, outputs): all_du = inputs['all_du'] add = 0.0 for du in all_du: add += du**2.0 root = sqrt(add) outputs['u'] = root model = Group() ivc = IndepVarComp() ivc.add_output('deficits', [0.16, 0.14, 0.15, 0.18]) model.add_subsystem('indep', ivc) model.add_subsystem('rms', RSSMerge(4)) model.connect('indep.deficits', 'rms.all_du') prob = Problem(model) prob.setup() prob.run_model() print(prob['rms.u'])
out_name = self.options['out_name'] partials[out_name, in_names[0]] = np.tile(inputs[in_names[1]], in_shapes[0]) partials[out_name, in_names[1]] = np.repeat(inputs[in_names[0]], in_shapes[1]) if __name__ == '__main__': from openmdao.api import Problem, IndepVarComp import time prob = Problem() comp = IndepVarComp() comp.add_output('x', np.arange(7)) comp.add_output('y', np.arange(3, 6)) prob.model.add_subsystem('input_comp', comp, promotes=['*']) comp = VectorOuterProductComp( in_names=['x', 'y'], in_shapes=[7, 3], out_name='f', ) prob.model.add_subsystem('comp', comp, promotes=['*']) start = time.time() prob.setup(check=True)
J['K_q', 'k'] = [[q_1 + E_k - q_2], [q_2 - q_1 - E_k]] J['K_q', 'E_k'] = [[k], [-k]] J['K_q', 'q_1'] = [[k], [-k]] J['K_q', 'q_2'] = [[-k], [k]] J['F', 'tor'] = [[1], [0]] if __name__ == '__main__': from openmdao.api import Problem, IndepVarComp num = 20 prob = Problem() comp = IndepVarComp() comp.add_output('k', val=14.1543) comp.add_output('E_k', val=0) comp.add_output('tor', 0.5) comp.add_output('q', val=np.random.random((num, 2))) comp.add_output('w', val=np.random.random((num, 2))) comp.add_output('p_1', 0.311658) comp.add_output('p_2', 0.155) comp.add_output('p_3', 0.10024) comp.add_output('p_4', 9.39299) comp.add_output('p_5', 3.278) prob.model.add_subsystem('ivc', comp, promotes=['*']) comp = elements(num=num) prob.model.add_subsystem('elements', comp, promotes=['*']) prob.setup()
from engine_hours_comp import EngineHoursComp from tooling_hours_comp import ToolingHoursComp from mfg_hours_comp import MfgHoursComp from quality_hours_comp import QualityHoursComp from devel_support_comp import DevelSupportComp from flight_test_cost_comp import FlightTestCostComp from mfg_material_cost_comp import MfgMaterialCostComp from rdte_fly_cost_comp import RdteFlyCostComp prob = Problem() group = Group() # Adding all of the Explicit components to the main group comp = IndepVarComp() comp.add_output('We', val=4.) comp.add_output('V', val=83.) comp.add_output('Q', val=500.) comp.add_output('FTA', val=2.) comp.add_output('Re', val=86.0 * 1.530) comp.add_output('Rt', val=88.0 * 1.530) comp.add_output('Rq', val=81.0 * 1.530) comp.add_output('Rm', val=73.0 * 1.530) comp.add_output('Ceng', val=19.99) comp.add_output('Neng', val=2.0) comp.add_output('Cav', val=113.08) group.add_subsystem('ivc', comp, promotes=['*', '*']) group.add_subsystem('ehc', EngineHoursComp(), promotes=['*', '*']) group.add_subsystem('thc', ToolingHoursComp(), promotes=['*', '*']) group.add_subsystem('mhc', MfgHoursComp(), promotes=['*', '*'])
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, # 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 'Wf_reserve': 15000., # [kg] reserve fuel mass } surfaces = [surf_dict] # Create the problem and assign the model group prob = Problem() # Add problem information as an independent variables component indep_var_comp = 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') prob.model.connect( 'load_factor', point_name + '.coupled.' + name + '.load_factor') # 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') from openmdao.api import ScipyOptimizeDriver prob.driver = ScipyOptimizeDriver() prob.driver.options['tol'] = 1e-9 prob.driver.options['disp'] = True # Set up the problem prob.setup() AS_point.nonlinear_solver.options['iprint'] = 2 # # from openmdao.api import view_model # view_model(prob) prob.run_model() # prob.model.list_outputs(values=True, # implicit=False, # units=True, # shape=True, # bounds=True, # residuals=True, # scaling=True, # hierarchical=False, # print_arrays=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], 112469.567077, 1e-5) assert_rel_error(self, prob['wing.structural_mass'][0] / 1.25, 24009.5230566, 1e-5)
def setup(self): shape = self.options['shape'] part = self.options['part'] comp = IndepVarComp() comp.add_output('sweep_30', val=30. * np.pi / 180., shape=shape) self.add_subsystem('sweep_30_comp', comp, promotes=['*']) comp = ElementwiseMinComp( shape=shape, out_name='sweep_capped_30', in_names=['sweep', 'sweep_30'], rho=10., ) self.add_subsystem('sweep_capped_30_comp', comp, promotes=['*']) comp = LinearPowerCombinationComp( shape=shape, out_name='oswald_efficiency_unswept', constant=1.14, terms_list=[ (-1.78 * 0.045, dict( aspect_ratio=0.68, )), ], ) self.add_subsystem('oswald_efficiency_unswept_comp', comp, promotes=['*']) comp = LinearPowerCombinationComp( shape=shape, out_name='oswald_efficiency_swept', constant=-3.1, terms_list=[ (4.61, dict( cos_sweep=0.15, )), (-4.61 * 0.045, dict( aspect_ratio=0.68, cos_sweep=0.15, )), ], ) self.add_subsystem('oswald_efficiency_swept_comp', comp, promotes=['*']) comp = LinearPowerCombinationComp( shape=shape, out_name='oswald_efficiency', terms_list=[ (1. / (30. * np.pi / 180.), dict( oswald_efficiency_unswept=1., )), (-1. / (30. * np.pi / 180.), dict( oswald_efficiency_unswept=1., sweep_capped_30=1., )), (1. / (30. * np.pi / 180.), dict( oswald_efficiency_swept=1., sweep_capped_30=1., )), ], ) self.add_subsystem('oswald_efficiency_comp', comp, promotes=['*']) comp = PowerCombinationComp( shape=shape, out_name='induced_drag_coeff', coeff=1. / np.pi, powers_dict=dict( lift_coeff=2., oswald_efficiency=-1., aspect_ratio=-1., ), ) self.add_subsystem('induced_drag_coeff_comp', comp, promotes=['*'])
from drag_models.reynolds_comp import Reynolds from drag_models.form_factors_comp import FormFactors from drag_models.c_f_comp import Cf from drag_models.drag_coefficient_zero_comp import Cd0 from drag_models.drag_coefficient_comp import Cd from drag_models.k_comp import K from drag_models.drag_m_comp import DragModelComp from drag_models.lift_drag_comp import LD prob = Problem() group = Group() comp = IndepVarComp() comp.add_output('rho', val=1.225) comp.add_output('V', val=23.) comp.add_output('mu', val=2.008 * 10**(-5)) comp.add_output('sweep', val=30.) comp.add_output('tc1', val=0.12) comp.add_output('xc1', val=0.3) comp.add_output('C_bar', val=0.30) comp.add_output('S', val=.57) comp.add_output('Dq', val=0.0278709) comp.add_output('Cd0_23', val=0.007380519) comp.add_output('b', val=2) # total spa comp.add_output('Cl', val=.7) # group.add_subsystem('ivc', comp, promotes=['*']) group.add_subsystem('re', Reynolds(), promotes=['*'])
def setup(self): num_times = self.options['num_times'] num_cp = self.options['num_cp'] step_size = self.options['step_size'] cubesat = self.options['cubesat'] mtx = self.options['mtx'] shape = (3, num_times) thrust_unit_vec = np.outer( np.array([1., 0., 0.]), np.ones(num_times), ) comp = IndepVarComp() comp.add_output('thrust_unit_vec_b_3xn', val=thrust_unit_vec) comp.add_output('thrust_scalar_mN_cp', val=1.e-3 * np.ones(num_cp)) comp.add_output('initial_propellant_mass', 0.17) comp.add_design_var('thrust_scalar_mN_cp', lower=0., upper=20000) self.add_subsystem('inputs_comp', comp, promotes=['*']) comp = MtxVecComp( num_times=num_times, mtx_name='rot_mtx_i_b_3x3xn', vec_name='thrust_unit_vec_b_3xn', out_name='thrust_unit_vec_3xn', ) self.add_subsystem('thrust_unit_vec_3xn_comp', comp, promotes=['*']) comp = LinearCombinationComp( shape=(num_cp, ), out_name='thrust_scalar_cp', coeffs_dict=dict(thrust_scalar_mN_cp=1.e-3), ) self.add_subsystem('thrust_scalar_cp_comp', comp, promotes=['*']) comp = BsplineComp( num_pt=num_times, num_cp=num_cp, jac=mtx, in_name='thrust_scalar_cp', out_name='thrust_scalar', ) self.add_subsystem('thrust_scalar_comp', comp, promotes=['*']) comp = ArrayExpansionComp( shape=shape, expand_indices=[0], in_name='thrust_scalar', out_name='thrust_scalar_3xn', ) self.add_subsystem('thrust_scalar_3xn_comp', comp, promotes=['*']) comp = PowerCombinationComp( shape=shape, out_name='thrust_3xn', powers_dict=dict( thrust_unit_vec_3xn=1., thrust_scalar_3xn=1., ), ) self.add_subsystem('thrust_3xn_comp', comp, promotes=['*']) comp = LinearCombinationComp( shape=(num_times, ), out_name='mass_flow_rate', coeffs_dict=dict(thrust_scalar=-1. / (cubesat['acceleration_due_to_gravity'] * cubesat['specific_impulse']))) self.add_subsystem('mass_flow_rate_comp', comp, promotes=['*']) comp = PropellantMassRK4Comp( num_times=num_times, step_size=step_size, ) self.add_subsystem('propellant_mass_rk4_comp', comp, promotes=['*']) comp = ExecComp( 'total_propellant_used=propellant_mass[0] - propellant_mass[-1]', propellant_mass=np.empty(num_times), ) self.add_subsystem('total_propellant_used_comp', comp, promotes=['*'])
if surface['sweep'] == 0: surfname = 'str' ailList = ailList_straight else: surfname = 'swp' ailList = ailList_swept for aileron in ailList: surface['control_surfaces'] = [aileron] print(surfname+'_'+aileron['name']+'\n') # Create the problem and assign the model group prob = Problem() # Add problem information as an independent variables component indep_var_comp = IndepVarComp() indep_var_comp.add_output('v', val=25., units='m/s') indep_var_comp.add_output('alpha', val=alpha, units='deg') indep_var_comp.add_output('re', val=5e5, units='1/m') indep_var_comp.add_output('rho', val=rho, units='kg/m**3') indep_var_comp.add_output('cg', val=cg_loc, units='m') indep_var_comp.add_output('delta_aileron', val=12.5,units='deg') indep_var_comp.add_output('omega', val=np.array([1.,0.,0.]),units='rad/s') prob.model.add_subsystem('prob_vars', indep_var_comp, promotes=['*']) aerostruct_group = AerostructGeometry(surface=surface) name = 'wing'
def test(self): import numpy as np from openmdao.api import IndepVarComp, Problem, Group, NewtonSolver, \ ScipyIterativeSolver, LinearBlockGS, NonlinearBlockGS, \ DirectSolver, LinearBlockGS, PetscKSP, SqliteRecorder from openaerostruct.geometry.utils import generate_mesh from openaerostruct.geometry.geometry_group import Geometry from openaerostruct.aerodynamics.aero_groups import AeroPoint # Create a dictionary to store options about the mesh mesh_dict = { 'num_y': 7, 'num_x': 2, 'wing_type': 'CRM', 'symmetry': False, 'num_twist_cp': 5 } # Generate the aerodynamic mesh based on the previous dictionary mesh, twist_cp = generate_mesh(mesh_dict) # Create a dictionary with info and options about the aerodynamic # lifting surface surface = { # 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': 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, # if true, compute viscous drag 'with_wave': False, # if true, compute wave drag } # Create the OpenMDAO problem prob = Problem() # Create an independent variable component that will supply the flow # conditions to the problem. indep_var_comp = 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') # Add this IndepVarComp to the problem model prob.model.add_subsystem('prob_vars', indep_var_comp, promotes=['*']) # Create and add a group that handles the geometry for the # aerodynamic lifting surface geom_group = Geometry(surface=surface) prob.model.add_subsystem(surface['name'], geom_group) # Create the aero point group, which contains the actual aerodynamic # analyses aero_group = AeroPoint(surfaces=[surface]) point_name = 'aero_point_0' prob.model.add_subsystem( point_name, aero_group, promotes_inputs=['v', 'alpha', 'Mach_number', 're', 'rho', 'cg']) 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') # Import the Scipy Optimizer and set the driver of the problem to use # it, which defaults to an SLSQP optimization method from openmdao.api import ScipyOptimizeDriver prob.driver = ScipyOptimizeDriver() prob.driver.options['tol'] = 1e-9 # Setup problem and add design variables, constraint, and objective prob.model.add_design_var('wing.twist_cp', lower=-10., upper=15.) 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 and run the optimization problem prob.setup() prob.run_model() # prob.check_partials() # exit() prob.run_driver() assert_rel_error(self, prob['aero_point_0.wing_perf.CD'][0], 0.03339013029042684, 1e-5) assert_rel_error(self, prob['aero_point_0.wing_perf.CL'][0], 0.5, 1e-6) assert_rel_error(self, prob['aero_point_0.CM'][1], -1.7886135541410009, 1e-4)