def test_run_apply(self): # This test makes sure that we correctly apply the "run_apply" flag # to all targets in the "broken" connection, even when they are # nested in Groups. prob = Problem() root = prob.root = Group() sub1 = root.add('sub1', Group()) sub2 = root.add('sub2', Group()) sub1.add('p1', Paraboloid()) sub1.add('p2', Paraboloid()) sub2.add('p1', Paraboloid()) sub2.add('p2', Paraboloid()) root.connect('sub1.p1.f_xy', 'sub2.p1.x') root.connect('sub1.p2.f_xy', 'sub2.p1.y') root.connect('sub1.p1.f_xy', 'sub2.p2.x') root.connect('sub1.p2.f_xy', 'sub2.p2.y') root.connect('sub2.p1.f_xy', 'sub1.p1.x') root.connect('sub2.p2.f_xy', 'sub1.p1.y') root.connect('sub2.p1.f_xy', 'sub1.p2.x') root.connect('sub2.p2.f_xy', 'sub1.p2.y') root.nl_solver = NLGaussSeidel() root.ln_solver = ScipyGMRES() prob.setup(check=False) # Will be True in one group and False in the other, depending on # where it cuts. self.assertTrue(root.sub1.p1._run_apply != root.sub2.p1._run_apply) self.assertTrue(root.sub1.p2._run_apply != root.sub2.p2._run_apply)
def __init__(self): super(SellarDerivatives, self).__init__() self.add('px', IndepVarComp('x1', 1.0), promotes=['x1']) self.add('pz', IndepVarComp('z', np.array([5.0, 2.0])), promotes=['z']) self.add('d1', SellarDisc1(), promotes=['z', 'x1', 'y1', 'y2']) self.add('d2', SellarDisc2(), promotes=['z', 'y1', 'y2']) self.add('obj_cmp', ExecComp('obj = x1**2 + z[1] + y1 + exp(-y2)', z=np.array([5.0, 2.0]), x1=1.0, y1=0.0, y2=0.0), promotes=['obj', 'x1', 'z', 'y1', 'y2']) self.add('con_cmp1', ExecComp('con1 = -y1 + 3.16', y1=0.0), promotes=['y1', 'con1']) self.add('con_cmp2', ExecComp('con2 = y2 - 24.0', y2=0.0), promotes=['y2', 'con2']) self.n1_solver = NLGaussSeidel() self.n1_solver.options['atol'] = 1.0e-12 self.ln_solver = ScipyGMRES()
def __init__(self): super(SellarDerivatives, self).__init__() # params will be provided by parent group self.add('px', IndepVarComp('x', 1.0), promotes=['x']) self.add('pz', IndepVarComp('z', np.array([5.0, 2.0])), promotes=['z']) self.add('d1', SellarDis1withDerivatives(), promotes=['x', 'z', 'y1', 'y2']) self.add('d2', SellarDis2withDerivatives(), promotes=['z', 'y1', 'y2']) self.add('obj_cmp', ExecComp('obj = x**2 + z[1] + y1 + exp(-y2)', z=np.array([0.0, 0.0]), x=0.0), promotes=['obj', 'x', 'z', 'y1', 'y2']) self.add('con_cmp1', ExecComp('con1 = 3.16 - y1'), promotes=['con1', 'y1']) self.add('con_cmp2', ExecComp('con2 = y2 - 24.0'), promotes=['con2', 'y2']) self.nl_solver = NLGaussSeidel() self.ln_solver = ScipyGMRES()
def __init__(self, nTurbines, direction_id=0, datasize=0, differentiable=True, use_rotor_components=False, nSamples=0, wake_model=floris_wrapper, wake_model_options=None): super(RotorSolveGroup, self).__init__() if wake_model_options is None: wake_model_options = { 'differentiable': differentiable, 'use_rotor_components': use_rotor_components, 'nSamples': nSamples } from openmdao.core.mpi_wrap import MPI # set up iterative solvers epsilon = 1E-6 if MPI: self.ln_solver = PetscKSP() else: self.ln_solver = ScipyGMRES() self.nl_solver = NLGaussSeidel() self.ln_solver.options['atol'] = epsilon self.add('CtCp', CPCT_Interpolate_Gradients_Smooth(nTurbines, direction_id=direction_id, datasize=datasize), promotes=[ 'gen_params:*', 'yaw%i' % direction_id, 'wtVelocity%i' % direction_id, 'Cp_out' ]) # TODO refactor the model component instance self.add('floris', wake_model(nTurbines, direction_id=direction_id, wake_model_options=wake_model_options), promotes=([ 'model_params:*', 'wind_speed', 'axialInduction', 'turbineXw', 'turbineYw', 'rotorDiameter', 'yaw%i' % direction_id, 'hubHeight', 'wtVelocity%i' % direction_id ] if (nSamples == 0) else [ 'model_params:*', 'wind_speed', 'axialInduction', 'turbineXw', 'turbineYw', 'rotorDiameter', 'yaw%i' % direction_id, 'hubHeight', 'wtVelocity%i' % direction_id, 'wsPositionX', 'wsPositionY', 'wsPositionZ', 'wsArray%i' % direction_id ])) self.connect('CtCp.Ct_out', 'floris.Ct')
def __init__(self, problem_id=0): super(SellarDerivativesSubGroup, self).__init__() self.add('d1', SellarDis1(problem_id=problem_id), promotes=['*']) self.add('d2', SellarDis2(problem_id=problem_id), promotes=['*']) self.nl_solver = NLGaussSeidel() self.nl_solver.options['atol'] = 1.0e-12 if impl is not None: self.ln_solver = PetscKSP()
def test_sellar(self): prob = Problem() prob.root = SellarNoDerivatives() prob.root.nl_solver = NLGaussSeidel() prob.setup(check=False) prob.run() assert_rel_error(self, prob['y1'], 25.58830273, .00001) assert_rel_error(self, prob['y2'], 12.05848819, .00001) # Make sure we aren't iterating like crazy self.assertLess(prob.root.nl_solver.iter_count, 8)
def test_indirect_errors_divide_subbed(self): # Make sure that two stacked solvers don't double append. top = Problem(debug=True) top.root = root = Group() sub = root.add('sub', Group()) sub.add('comp1', ErrorComp('xx')) sub.add('comp2', ErrorComp('indirect_divide')) root.connect('sub.comp1.out', 'sub.comp2.in') root.connect('sub.comp2.out', 'sub.comp1.in') root.nl_solver = NLGaussSeidel() root.ln_solver = ScipyGMRES() sub.nl_solver = NLGaussSeidel() sub.ln_solver = ScipyGMRES() top.setup(check=False) with self.assertRaises(FloatingPointError) as err: top.run() expected_msg = "invalid value encountered in subtract\nThe following unknowns are nonfinite: ['comp1.out', 'comp2.out']\nThe following resids are nonfinite: ['comp1.out']\nThe following params are nonfinite: ['comp1.in']" self.assertEqual(str(err.exception), expected_msg)
def setUp(self): root = ParallelGroup() root.nl_solver = NLGaussSeidel() root.add('C1', IndepVarComp('x', 5.)) root.add('C2', ExecComp('y=x*2.0')) root.add('C3', ExecComp('y=x*2.0')) root.add('C4', ExecComp('y=x*2.0')) root.connect("C1.x", "C2.x") root.connect("C2.y", "C4.x") root.connect("C4.y", "C3.x") self.root = root
def test_sellar_analysis_error(self): prob = Problem() prob.root = SellarNoDerivatives() prob.root.nl_solver = NLGaussSeidel() prob.root.nl_solver.options['maxiter'] = 2 prob.root.nl_solver.options['err_on_maxiter'] = True prob.setup(check=False) try: prob.run() except AnalysisError as err: self.assertEqual(str(err), "Solve in '': NLGaussSeidel FAILED to converge after 2 iterations") else: self.fail("expected AnalysisError")
def test_sellar_with_Aitken(self): # This test makes sure the Aitken acc. feature is working correctly prob = Problem() prob.root = SellarNoDerivatives() prob.root.nl_solver = NLGaussSeidel() prob.root.nl_solver.options['use_aitken'] = True prob.root.cycle.set_order(['d1', 'd2']) prob.setup(check=False) prob.run() # check the Aitken relaxation factor value assert_rel_error(self, prob.root.nl_solver.aitken_alpha, 0.980998467864, .00001) # check that the problem converges in 4 iters (1 less than w/o Aitken) self.assertTrue(prob.root.nl_solver.iter_count == 4)
def __init__(self): super(SellarDerivatives, self).__init__() self.add('px', IndepVarComp('x', 1.0), promotes=['*']) self.add('pz', IndepVarComp('z', np.array([5.0, 2.0])), promotes=['*']) self.add('d1', SellarDis1(), promotes=['*']) self.add('d2', SellarDis2(), promotes=['*']) self.add('obj_cmp', ExecComp('obj = x**2 + z[1] + y1 + exp(-y2)', z=np.array([0.0, 0.0])), promotes=['*']) self.add('con_cmp1', ExecComp('con1 = 3.16 - y1'), promotes=['*']) self.add('con_cmp2', ExecComp('con2 = y2 - 24.0'), promotes=['*']) self.nl_solver = NLGaussSeidel() self.nl_solver.options['atol'] = 1.0e-12
def test_sellar_group(self): prob = Problem() prob.root = SellarDerivativesGrouped() prob.root.nl_solver = NLGaussSeidel() prob.root.nl_solver.options['atol'] = 1e-9 prob.root.mda.nl_solver.options['atol'] = 1e-3 prob.root.nl_solver.options['iprint'] = 2 # so that print_norm is in coverage prob.setup(check=False) old_stdout = sys.stdout sys.stdout = cStringIO() # so we don't see the iprint output during testing try: prob.run() finally: sys.stdout = old_stdout assert_rel_error(self, prob['y1'], 25.58830273, .00001) assert_rel_error(self, prob['y2'], 12.05848819, .00001)
def test_sellar_utol(self): prob = Problem() prob.root = SellarNoDerivatives() prob.root.nl_solver = NLGaussSeidel() prob.setup(check=False) # make sure we trigger convergence from utol prob.root.nl_solver.options['rtol'] = 1e-99 prob.root.nl_solver.options['atol'] = 1e-99 prob.root.nl_solver.options['utol'] = 1e-6 prob.run() assert_rel_error(self, prob['y1'], 25.58830273, .00001) assert_rel_error(self, prob['y2'], 12.05848819, .00001) # Make sure we aren't iterating like crazy self.assertLess(prob.root.nl_solver.iter_count, 8)
def test_sellar(self): prob = Problem() prob.root = SellarNoDerivatives() prob.root.nl_solver = NLGaussSeidel() prob.setup(check=False) prob.run() assert_rel_error(self, prob['y1'], 25.58830273, .00001) assert_rel_error(self, prob['y2'], 12.05848819, .00001) # Make sure we aren't iterating like crazy self.assertLess(prob.root.nl_solver.iter_count, 8) # Make sure we only call apply_linear on 'heads' nd1 = prob.root.cycle.d1.execution_count nd2 = prob.root.cycle.d2.execution_count if prob.root.cycle.d1._run_apply == True: self.assertEqual(nd1, 2 * nd2) else: self.assertEqual(2 * nd1, nd2)
def __init__(self): super(Drivetrain, self).__init__() # self.add('InputVoltage', IndepVarComp('Voltage', 500.0)) self.add('Motor', ElectricMotor()) self.add('Inverter', Inverter()) self.add('Battery', Battery(), promotes=['des_time', 'time_of_flight']) # connect ElectricMotor outputs to Inverter inputs self.connect('Motor.frequency', 'Inverter.output_frequency') self.connect('Motor.phase_voltage', 'Inverter.output_voltage') self.connect('Motor.phase_current', 'Inverter.output_current') # connect Inverter outputs to Battery inputs self.connect('Inverter.input_current', 'Battery.des_current') self.connect('Inverter.input_power', 'Battery.des_power') # connect Battery outputs to Inverter inputs # self.connect('Battery.output_voltage', 'Inverter.input_voltage') self.nl_solver = NLGaussSeidel() self.nl_solver.options['atol'] = 1.0e-12 self.ln_solver = ScipyGMRES()
root.add('vlmfuncs', vlmfuncs_comp, promotes=['*']) # Add components to the coupled MDA here coupled = Group() coupled.add('mesh', mesh_comp, promotes=["*"]) ############################################################ # Problem 2b: # Try different nonlinear solvers on the coupled and root groups. # Nonlinear Gauss Seidel is included as an example. # Examine http://openmdao.readthedocs.io/en/latest/srcdocs/packages/openmdao.solvers.html # to see syntax for other options. ############################################################ ## Nonlinear Gauss Seidel on the coupled group coupled.nl_solver = NLGaussSeidel() coupled.nl_solver.options['iprint'] = 1 coupled.nl_solver.options['atol'] = 1e-5 coupled.nl_solver.options['rtol'] = 1e-12 ############################################################ # Problem 2c: # Try different linear solvers for the coupled group. # Again examine http://openmdao.readthedocs.io/en/latest/srcdocs/packages/openmdao.solvers.html # for linear solver options. ############################################################ ## Krylov Solver - LNGS preconditioning coupled.ln_solver = ScipyGMRES() coupled.ln_solver.options['iprint'] = 1 coupled.ln_solver.preconditioner = LinearGaussSeidel()
def setup_aerostruct(self): """ Specific method to add the necessary components to the problem for an aerostructural problem. """ # Set the problem name if the user doesn't if 'prob_name' not in self.prob_dict.keys(): self.prob_dict['prob_name'] = 'aerostruct' # Create the base root-level group root = Group() coupled = Group() # Create the problem and assign the root group self.prob = Problem() self.prob.root = root # Loop over each surface in the surfaces list for surface in self.surfaces: # Get the surface name and create a group to contain components # only for this surface name = surface['name'] tmp_group = Group() # Add independent variables that do not belong to a specific component indep_vars = [ (name + 'twist_cp', numpy.zeros(surface['num_twist'])), (name + 'thickness_cp', numpy.ones(surface['num_thickness']) * numpy.max(surface['t'])), (name + 'r', surface['r']), (name + 'dihedral', surface['dihedral']), (name + 'sweep', surface['sweep']), (name + 'span', surface['span']), (name + 'taper', surface['taper']) ] # Obtain the Jacobians to interpolate the data from the b-spline # control points jac_twist = get_bspline_mtx(surface['num_twist'], surface['num_y']) jac_thickness = get_bspline_mtx(surface['num_thickness'], surface['num_y'] - 1) # Add components to include in the '_pre_solve' group tmp_group.add('indep_vars', IndepVarComp(indep_vars), promotes=['*']) tmp_group.add('twist_bsp', Bspline(name + 'twist_cp', name + 'twist', jac_twist), promotes=['*']) tmp_group.add('thickness_bsp', Bspline(name + 'thickness_cp', name + 'thickness', jac_thickness), promotes=['*']) tmp_group.add('tube', MaterialsTube(surface), promotes=['*']) # Add tmp_group to the problem with the name of the surface and # '_pre_solve' appended. name_orig = name #.strip('_') name = name + 'pre_solve' exec(name + ' = tmp_group') exec('root.add("' + name + '", ' + name + ', promotes=["*"])') # Add components to the 'coupled' group for each surface tmp_group = Group() tmp_group.add('mesh', GeometryMesh(surface), promotes=['*']) tmp_group.add('def_mesh', TransferDisplacements(surface), promotes=['*']) tmp_group.add('vlmgeom', VLMGeometry(surface), promotes=['*']) tmp_group.add('spatialbeamstates', SpatialBeamStates(surface), promotes=['*']) tmp_group.spatialbeamstates.ln_solver = LinearGaussSeidel() name = name_orig + 'group' exec(name + ' = tmp_group') exec('coupled.add("' + name + '", ' + name + ', promotes=["*"])') # Add a loads component to the coupled group exec('coupled.add("' + name_orig + 'loads' + '", ' + 'TransferLoads(surface)' + ', promotes=["*"])') # Add a '_post_solve' group which evaluates the data after solving # the coupled system tmp_group = Group() tmp_group.add('spatialbeamfuncs', SpatialBeamFunctionals(surface), promotes=['*']) tmp_group.add('vlmfuncs', VLMFunctionals(surface), promotes=['*']) name = name_orig + 'post_solve' exec(name + ' = tmp_group') exec('root.add("' + name + '", ' + name + ', promotes=["*"])') # Add a single 'VLMStates' component for the whole system coupled.add('vlmstates', VLMStates(self.surfaces, self.prob_dict), promotes=['*']) # Set solver properties for the coupled group coupled.ln_solver = ScipyGMRES() coupled.ln_solver.options['iprint'] = 1 coupled.ln_solver.preconditioner = LinearGaussSeidel() coupled.vlmstates.ln_solver = LinearGaussSeidel() coupled.nl_solver = NLGaussSeidel() coupled.nl_solver.options['iprint'] = 1 # Ensure that the groups are ordered correctly within the coupled group order_list = [] for surface in self.surfaces: order_list.append(surface['name'] + 'group') order_list.append('vlmstates') for surface in self.surfaces: order_list.append(surface['name'] + 'loads') coupled.set_order(order_list) # Add the coupled group to the root problem root.add('coupled', coupled, promotes=['*']) # Add problem information as an independent variables component prob_vars = [('v', self.prob_dict['v']), ('alpha', self.prob_dict['alpha']), ('M', self.prob_dict['M']), ('Re', self.prob_dict['Re']), ('rho', self.prob_dict['rho'])] root.add('prob_vars', IndepVarComp(prob_vars), promotes=['*']) # Add functionals to evaluate performance of the system root.add('fuelburn', FunctionalBreguetRange(self.surfaces, self.prob_dict), promotes=['*']) root.add('eq_con', FunctionalEquilibrium(self.surfaces, self.prob_dict), promotes=['*']) self.setup_prob()
# driver.options['optimizer'] = 'SLSQP' params = (('fin_gap', 0.001, { 'units': 'm' }), ('fin_w', 0.0009, { 'units': 'm' })) root.add('input_vars', IndepVarComp(params)) root.connect('input_vars.fin_gap', 'inverter.fin_gap') root.connect('input_vars.fin_w', 'inverter.fin_w') #driver.add_desvar('input_vars.fin_gap', lower=.7, scaler=1.0) #driver.add_desvar('input_vars.fin_w', lower=.7, scaler=1.0) #driver.add_objective('inverter.R_hs') #top.driver.add_constraint('con1.c1', lower=0.0, scaler=1000.0) #top.driver.add_constraint('con2.c2', lower=0.0) root.ln_solver = ScipyGMRES() root.nl_solver = NLGaussSeidel() root.nl_solver.options['maxiter'] = 50 # root.nl_solver.options['iprint'] = 1 #p.print_all_convergence() p.root.set_order(['input_vars', 'inverter', 'balance']) p.setup() #root.list_connections() # view_tree(p) # exit() p.run() print('# of fins : %f' % p['inverter.n_fins']) print(p['inverter.h'], p['inverter.min_area'], p['inverter.Re']) print('R_hs : %f' % p['inverter.R_hs']) print('V_0, V_avg : %f, %f' % (p['inverter.V_0'], p['inverter.V_avg'])) # print('Min Area : %f m^2' %p['inverter.min_area'])
def setup_aerostruct(self): """ Specific method to add the necessary components to the problem for an aerostructural problem. """ # Set the problem name if the user doesn't if 'prob_name' not in self.prob_dict.keys(): self.prob_dict['prob_name'] = 'aerostruct' # Create the base root-level group root = Group() coupled = Group() # Create the problem and assign the root group self.prob = Problem() self.prob.root = root # Loop over each surface in the surfaces list for surface in self.surfaces: # Get the surface name and create a group to contain components # only for this surface name = surface['name'] tmp_group = Group() # Add independent variables that do not belong to a specific component indep_vars = [ ('twist_cp', numpy.zeros(surface['num_twist'])), ('thickness_cp', numpy.ones(surface['num_thickness']) * numpy.max(surface['t'])), ('r', surface['r']), ('dihedral', surface['dihedral']), ('sweep', surface['sweep']), ('span', surface['span']), ('taper', surface['taper']) ] # Obtain the Jacobians to interpolate the data from the b-spline # control points jac_twist = get_bspline_mtx(surface['num_twist'], surface['num_y']) jac_thickness = get_bspline_mtx(surface['num_thickness'], surface['num_y'] - 1) # Add components to include in the surface's group tmp_group.add('indep_vars', IndepVarComp(indep_vars), promotes=['*']) tmp_group.add('twist_bsp', Bspline('twist_cp', 'twist', jac_twist), promotes=['*']) tmp_group.add('thickness_bsp', Bspline('thickness_cp', 'thickness', jac_thickness), promotes=['*']) tmp_group.add('tube', MaterialsTube(surface), promotes=['*']) # Add tmp_group to the problem with the name of the surface. name_orig = name name = name[:-1] exec(name + ' = tmp_group') exec('root.add("' + name + '", ' + name + ', promotes=[])') # Add components to the 'coupled' group for each surface. # The 'coupled' group must contain all components and parameters # needed to converge the aerostructural system. tmp_group = Group() tmp_group.add('mesh', GeometryMesh(surface), promotes=['*']) tmp_group.add('def_mesh', TransferDisplacements(surface), promotes=['*']) tmp_group.add('aero_geom', VLMGeometry(surface), promotes=['*']) tmp_group.add('struct_states', SpatialBeamStates(surface), promotes=['*']) tmp_group.struct_states.ln_solver = LinearGaussSeidel() name = name_orig exec(name + ' = tmp_group') exec('coupled.add("' + name[:-1] + '", ' + name + ', promotes=[])') # Add a loads component to the coupled group exec('coupled.add("' + name_orig + 'loads' + '", ' + 'TransferLoads(surface)' + ', promotes=[])') # Add a performance group which evaluates the data after solving # the coupled system tmp_group = Group() tmp_group.add('struct_funcs', SpatialBeamFunctionals(surface), promotes=['*']) tmp_group.add('aero_funcs', VLMFunctionals(surface), promotes=['*']) name = name_orig + 'perf' exec(name + ' = tmp_group') exec('root.add("' + name + '", ' + name + ', promotes=["rho", "v", "alpha", "Re", "M"])') # Add a single 'aero_states' component for the whole system within the # coupled group. coupled.add('aero_states', VLMStates(self.surfaces, self.prob_dict), promotes=['v', 'alpha', 'rho']) # Explicitly connect parameters from each surface's group and the common # 'aero_states' group. for surface in self.surfaces: name = surface['name'] # Perform the connections with the modified names within the # 'aero_states' group. root.connect('coupled.' + name[:-1] + '.def_mesh', 'coupled.aero_states.' + name + 'def_mesh') root.connect('coupled.' + name[:-1] + '.b_pts', 'coupled.aero_states.' + name + 'b_pts') root.connect('coupled.' + name[:-1] + '.c_pts', 'coupled.aero_states.' + name + 'c_pts') root.connect('coupled.' + name[:-1] + '.normals', 'coupled.aero_states.' + name + 'normals') # Connect the results from 'aero_states' to the performance groups root.connect('coupled.aero_states.' + name + 'sec_forces', name + 'perf' + '.sec_forces') # Connect the results from 'coupled' to the performance groups root.connect('coupled.' + name[:-1] + '.def_mesh', 'coupled.' + name + 'loads.def_mesh') root.connect('coupled.aero_states.' + name + 'sec_forces', 'coupled.' + name + 'loads.sec_forces') root.connect('coupled.' + name + 'loads.loads', name + 'perf.loads') # Connect the output of the loads component with the FEM # displacement parameter. This links the coupling within the coupled # group that necessitates the subgroup solver. root.connect('coupled.' + name + 'loads.loads', 'coupled.' + name[:-1] + '.loads') # Connect aerodyamic design variables root.connect(name[:-1] + '.dihedral', 'coupled.' + name[:-1] + '.dihedral') root.connect(name[:-1] + '.span', 'coupled.' + name[:-1] + '.span') root.connect(name[:-1] + '.sweep', 'coupled.' + name[:-1] + '.sweep') root.connect(name[:-1] + '.taper', 'coupled.' + name[:-1] + '.taper') root.connect(name[:-1] + '.twist', 'coupled.' + name[:-1] + '.twist') # Connect structural design variables root.connect(name[:-1] + '.A', 'coupled.' + name[:-1] + '.A') root.connect(name[:-1] + '.Iy', 'coupled.' + name[:-1] + '.Iy') root.connect(name[:-1] + '.Iz', 'coupled.' + name[:-1] + '.Iz') root.connect(name[:-1] + '.J', 'coupled.' + name[:-1] + '.J') # Connect performance calculation variables root.connect(name[:-1] + '.r', name + 'perf.r') root.connect(name[:-1] + '.A', name + 'perf.A') # Connection performance functional variables root.connect(name + 'perf.weight', 'fuelburn.' + name + 'weight') root.connect(name + 'perf.weight', 'eq_con.' + name + 'weight') root.connect(name + 'perf.L', 'eq_con.' + name + 'L') root.connect(name + 'perf.CL', 'fuelburn.' + name + 'CL') root.connect(name + 'perf.CD', 'fuelburn.' + name + 'CD') # Connect paramters from the 'coupled' group to the performance # group. root.connect('coupled.' + name[:-1] + '.nodes', name + 'perf.nodes') root.connect('coupled.' + name[:-1] + '.disp', name + 'perf.disp') root.connect('coupled.' + name[:-1] + '.S_ref', name + 'perf.S_ref') # Set solver properties for the coupled group coupled.ln_solver = ScipyGMRES() coupled.ln_solver.options['iprint'] = 1 coupled.ln_solver.preconditioner = LinearGaussSeidel() coupled.aero_states.ln_solver = LinearGaussSeidel() coupled.nl_solver = NLGaussSeidel() coupled.nl_solver.options['iprint'] = 1 # Ensure that the groups are ordered correctly within the coupled group # so that a system with multiple surfaces is solved corretly. order_list = [] for surface in self.surfaces: order_list.append(surface['name'][:-1]) order_list.append('aero_states') for surface in self.surfaces: order_list.append(surface['name'] + 'loads') coupled.set_order(order_list) # Add the coupled group to the root problem root.add('coupled', coupled, promotes=['v', 'alpha', 'rho']) # Add problem information as an independent variables component prob_vars = [('v', self.prob_dict['v']), ('alpha', self.prob_dict['alpha']), ('M', self.prob_dict['M']), ('Re', self.prob_dict['Re']), ('rho', self.prob_dict['rho'])] root.add('prob_vars', IndepVarComp(prob_vars), promotes=['*']) # Add functionals to evaluate performance of the system. # Note that only the interesting results are promoted here; not all # of the parameters. root.add('fuelburn', FunctionalBreguetRange(self.surfaces, self.prob_dict), promotes=['fuelburn']) root.add('eq_con', FunctionalEquilibrium(self.surfaces, self.prob_dict), promotes=['eq_con', 'fuelburn']) # Actually set up the system self.setup_prob()
def __init__(self): """TODOs Params ------ tube_pressure : float Tube total pressure (Pa) pressure_initial : float initial Pressure before the pump down . Default value is 760.2. speed : float Pumping speed. Default value is 163333.3. pwr : float Motor rating. Default value is 18.5. electricity_price : float Cost of electricity per kilowatt hour. Default value is 0.13. time_down : float Desired pump down time. Default value is 300.0. gamma : float Operational percentage of the pump per day. Default value is 0.8. pump_weight : float Weight of one pump. Default value is 715.0. tube_thickness : float Thickness of tube in m. Default value is .05 tube_length : float Total length of tube from Mission (m) vf : float Top pod speed after boosting section. Default value is 335 m/s. Value will be taken from aero module vo : float Speed of pod when it enters boosting section. Default value is 324 m/s. num_thrust : float Number of propulsion thrusts required for trip (unitless) time_thrust : float Time required to accelerate pod to 1G (s) pod_mach : float Vehicle mach number (unitless) comp.map.PRdes : float Pressure ratio of compressor (unitless) nozzle.Ps_exhaust : float Exit pressure of nozzle (psi) comp_inlet_area : float Inlet area of compressor. (m**2) des_time : float time until design power point (h) time_of_flight : float total mission time (h) motor_max_current : float max motor phase current (A) motor_LD_ratio : float length to diameter ratio of motor (unitless) motor_oversize_factor : float scales peak motor power by this figure inverter_efficiency : float power out / power in (W) battery_cross_section_area : float cross_sectional area of battery used to compute length (cm^2) n_passengers : float Number of passengers per pod. Default value is 28 A_payload : float Cross sectional area of passenger compartment. Default value is 2.72 Returns ------- S : float Platform area of the pod total_pod_mass : float Pod Mass (kg) References ---------- .. [1] Friend, Paul. Magnetic Levitation Train Technology 1. Thesis. Bradley University, 2004. N.p.: n.p., n.d. Print. """ super(TubeAndPod, self).__init__() self.add('tube', TubeGroup(), promotes=[ 'pressure_initial', 'pwr', 'num_pods', 'Cd', 'speed', 'time_down', 'gamma', 'pump_weight', 'electricity_price', 'tube_thickness', 'r_pylon', 'tube_length', 'h', 'vf', 'v0', 'num_thrust', 'time_thrust', 'fl_start.W', 'depth', 'pod_period' ]) self.add('pod', PodGroup(), promotes=[ 'pod_mach', 'tube_pressure', 'comp.map.PRdes', 'nozzle.Ps_exhaust', 'comp_inlet_area', 'des_time', 'time_of_flight', 'motor_max_current', 'motor_LD_ratio', 'motor_oversize_factor', 'inverter_efficiency', 'battery_cross_section_area', 'n_passengers', 'A_payload', 'S', 'total_pod_mass', 'vel_b', 'h_lev', 'vel', 'mag_drag', 'L_pod' ]) self.add('cost', TicketCost(), promotes=['land_length', 'water_length', 'track_length']) self.add('mission', SampleMission()) # Connects promoted group level params self.connect('tube_pressure', ['tube.p_tunnel', 'cost.p_tunnel', 'mission.p_tunnel']) # Connects tube group outputs to pod self.connect('tube.temp_boundary', 'pod.tube_temp') # Connects pod group outputs to tube self.connect('pod.nozzle.Fg', ['tube.nozzle_thrust', 'mission.nozzle_thrust']) self.connect('pod.inlet.F_ram', ['tube.ram_drag', 'mission.ram_drag']) self.connect('pod.nozzle.Fl_O:tot:T', 'tube.nozzle_air_Tt') self.connect('pod.nozzle.Fl_O:stat:W', 'tube.nozzle_air_W') self.connect('pod.A_tube', 'tube.tube_area') self.connect('S', ['tube.S', 'cost.S', 'mission.S']) self.connect('L_pod', 'tube.L_pod') self.connect('mag_drag', ['tube.D_mag', 'cost.D_mag', 'mission.D_mag']) self.connect('total_pod_mass', ['tube.m_pod', 'cost.m_pod', 'mission.m_pod']) self.connect('vf', 'cost.vf') self.connect('pod_period', 'cost.pod_period') self.connect('tube.Struct.total_material_cost', 'cost.land_cost') self.connect('tube.Vacuum.pwr_tot', 'cost.vac_power') self.connect('tube.PropMech.pwr_req', 'cost.prop_power') self.connect('pod.cycle.comp.power', 'cost.pod_power') self.connect('tube.comp.power', 'cost.steady_vac_power') self.connect('tube.SubmergedTube.material_cost', 'cost.water_cost') self.connect('pod_mach', 'mission.M_pod') self.connect('track_length', 'mission.track_length') self.nl_solver = NLGaussSeidel() self.nl_solver.options['maxiter'] = 20 self.nl_solver.options['atol'] = 0.0001 # self.nl_solver.options['iprint'] = 2 self.ln_solver = ScipyGMRES() self.ln_solver.options['maxiter'] = 20