def test_converge_diverge_groups(self): # Test derivatives for converge-diverge-groups topology. prob = om.Problem() model = prob.model = ConvergeDivergeGroups() model.linear_solver = om.LinearRunOnce() model.g1.linear_solver = om.LinearRunOnce() model.g1.g2.linear_solver = om.LinearRunOnce() model.g3.linear_solver = om.LinearRunOnce() prob.set_solver_print(level=0) prob.setup(check=False, mode='fwd') prob.run_model() wrt = ['iv.x'] of = ['c7.y1'] # Make sure value is fine. assert_rel_error(self, prob['c7.y1'], -102.7, 1e-6) J = prob.compute_totals(of=of, wrt=wrt, return_format='flat_dict') assert_rel_error(self, J['c7.y1', 'iv.x'][0][0], -40.75, 1e-6) prob.setup(check=False, mode='rev') prob.run_model() J = prob.compute_totals(of=of, wrt=wrt, return_format='flat_dict') assert_rel_error(self, J['c7.y1', 'iv.x'][0][0], -40.75, 1e-6)
def test_par_dup(self, mode): # duplicated output, parallel input prob = om.Problem() model = prob.model par = model.add_subsystem('par', om.ParallelGroup()) par.add_subsystem('indep1', om.IndepVarComp('x', 1.0)) par.add_subsystem('indep2', om.IndepVarComp('x', 1.0)) model.add_subsystem('C1', om.ExecComp('y = 2.5 * x1 + 3.5 * x2')) model.connect('par.indep1.x', 'C1.x1') model.connect('par.indep2.x', 'C1.x2') of = ['C1.y'] wrt = ['par.indep1.x', 'par.indep2.x'] prob.model.linear_solver = om.LinearRunOnce() # import wingdbstub prob.setup(check=False, mode=mode) prob.set_solver_print(level=0) prob.run_model() assert_rel_error(self, prob['C1.y'], 6., 1e-6) J = prob.compute_totals(of=of, wrt=wrt) assert_rel_error(self, J['C1.y', 'par.indep1.x'][0][0], 2.5, 1e-6) assert_rel_error(self, J['C1.y', 'par.indep2.x'][0][0], 3.5, 1e-6) assert_rel_error(self, prob['C1.y'], 6., 1e-6)
def test_dup_dist(self, mode): # duplicated output, parallel input prob = om.Problem() model = prob.model size = 3 sizes = [2, 1] rank = prob.comm.rank model.add_subsystem('indep', om.IndepVarComp('x', np.ones(size))) model.add_subsystem( 'C1', DistribExecComp(['y=2.5*x', 'y=3.5*x'], arr_size=size)) model.connect('indep.x', 'C1.x') of = ['C1.y'] wrt = ['indep.x'] prob.model.linear_solver = om.LinearRunOnce() prob.setup(check=False, mode=mode) prob.set_solver_print(level=0) prob.run_model() assert_rel_error(self, prob.get_val('C1.y', get_remote=True), np.array([2.5, 2.5, 3.5], dtype=float), 1e-6) J = prob.compute_totals(of=of, wrt=wrt) expected = np.array([[2.5, 0, 0], [0, 2.5, 0], [0, 0, 3.5]], dtype=float) assert_rel_error(self, J['C1.y', 'indep.x'], expected, 1e-6) assert_rel_error(self, prob.get_val('C1.y', get_remote=True), np.array([2.5, 2.5, 3.5], dtype=float), 1e-6)
def setup_model(self, size): class DelayComp(om.ExplicitComponent): def initialize(self): self.counter = 0 self.options.declare('time', default=3.0) self.options.declare('size', default=1) def setup(self): size = self.options['size'] self.add_input('x', shape=size) self.add_output('y', shape=size) self.add_output('y2', shape=size) self.declare_partials('y', 'x') self.declare_partials('y2', 'x') def compute(self, inputs, outputs): waittime = self.options['time'] size = self.options['size'] outputs['y'] = np.linspace(3, 10, size) * inputs['x'] outputs['y2'] = np.linspace(2, 4, size) * inputs['x'] def compute_jacvec_product(self, inputs, d_inputs, d_outputs, mode): waittime = self.options['time'] size = self.options['size'] if mode == 'fwd': time.sleep(waittime) if 'x' in d_inputs: self.counter += 1 if 'y' in d_outputs: d_outputs['y'] += np.linspace(3, 10, size) * d_inputs['x'] if 'y2' in d_outputs: d_outputs['y2'] += np.linspace( 2, 4, size) * d_inputs['x'] elif mode == 'rev': if 'x' in d_inputs: self.counter += 1 time.sleep(waittime) if 'y' in d_outputs: d_inputs['x'] += np.linspace(3, 10, size) * d_outputs['y'] if 'y2' in d_outputs: d_inputs['x'] += np.linspace( 2, 4, size) * d_outputs['y2'] model = om.Group() iv = om.IndepVarComp() mysize = size iv.add_output('x', val=3.0 * np.ones((mysize, ))) model.add_subsystem('iv', iv) pg = model.add_subsystem('pg', om.ParallelGroup(), promotes=['*']) pg.add_subsystem('dc1', DelayComp(size=mysize, time=0.0)) pg.add_subsystem('dc2', DelayComp(size=mysize, time=0.0)) pg.add_subsystem('dc3', DelayComp(size=mysize, time=0.0)) model.connect('iv.x', ['dc1.x', 'dc2.x', 'dc3.x']) model.linear_solver = om.LinearRunOnce() model.add_design_var('iv.x', lower=-1.0, upper=1.0) return model
def test_dup_dup(self, mode, auto): # non-distributed vars on both ends prob = om.Problem() model = prob.model if not auto: model.add_subsystem('indep', om.IndepVarComp('x', 1.0)) model.add_subsystem('C1', om.ExecComp('y = 2.5 * x')) if auto: wrt = ['C1.x'] else: model.connect('indep.x', 'C1.x') wrt = ['indep.x'] of = ['C1.y'] prob.model.linear_solver = om.LinearRunOnce() prob.setup(check=False, mode=mode) prob.set_solver_print(level=0) prob.run_model() J = prob.compute_totals(of=of, wrt=wrt) assert_near_equal(J['C1.y', wrt[0]][0][0], 2.5, 1e-6) assert_near_equal(prob['C1.y'], 2.5, 1e-6)
def test_circuit_voltage_source(self): import openmdao.api as om from openmdao.test_suite.scripts.circuit_analysis import Circuit p = om.Problem() model = p.model model.add_subsystem('ground', om.IndepVarComp('V', 0., units='V')) # replacing the fixed current source with a BalanceComp to represent a fixed Voltage source # model.add_subsystem('source', om.IndepVarComp('I', 0.1, units='A')) model.add_subsystem('batt', om.IndepVarComp('V', 1.5, units='V')) bal = model.add_subsystem('batt_balance', om.BalanceComp()) bal.add_balance('I', units='A', eq_units='V') model.add_subsystem('circuit', Circuit()) model.add_subsystem('batt_deltaV', om.ExecComp('dV = V1 - V2', V1={'units':'V'}, V2={'units':'V'}, dV={'units':'V'})) # current into the circuit is now the output state from the batt_balance comp model.connect('batt_balance.I', 'circuit.I_in') model.connect('ground.V', ['circuit.Vg','batt_deltaV.V2']) model.connect('circuit.n1.V', 'batt_deltaV.V1') # set the lhs and rhs for the battery residual model.connect('batt.V', 'batt_balance.rhs:I') model.connect('batt_deltaV.dV', 'batt_balance.lhs:I') p.setup() ################### # Solver Setup ################### # change the circuit solver to RunOnce because we're # going to converge at the top level of the model with newton instead p.model.circuit.nonlinear_solver = om.NonlinearRunOnce() p.model.circuit.linear_solver = om.LinearRunOnce() # Put Newton at the top so it can also converge the new BalanceComp residual newton = p.model.nonlinear_solver = om.NewtonSolver() p.model.linear_solver = om.DirectSolver() newton.options['iprint'] = 2 newton.options['maxiter'] = 20 newton.options['solve_subsystems'] = True newton.linesearch = om.ArmijoGoldsteinLS() newton.linesearch.options['maxiter'] = 10 newton.linesearch.options['iprint'] = 2 # set initial guesses from the current source problem p['circuit.n1.V'] = 9.8 p['circuit.n2.V'] = .7 p.run_model() assert_near_equal(p['circuit.n1.V'], 1.5, 1e-5) assert_near_equal(p['circuit.n2.V'], 0.65113362, 1e-5) assert_near_equal(p['circuit.R1.I'], 0.015, 1e-5) assert_near_equal(p['circuit.R2.I'], 8.48866375e-05, 1e-5) assert_near_equal(p['circuit.D1.I'], 8.48866375e-05, 1e-5)
def test_dup_par(self, mode): # duplicated output, parallel input prob = om.Problem() model = prob.model model.add_subsystem('indep', om.IndepVarComp('x', 1.0)) par = model.add_subsystem('par', om.ParallelGroup()) par.add_subsystem('C1', om.ExecComp('y = 2.5 * x')) par.add_subsystem('C2', om.ExecComp('y = 7 * x')) model.connect('indep.x', 'par.C1.x') model.connect('indep.x', 'par.C2.x') of = ['par.C1.y', 'par.C2.y'] wrt = ['indep.x'] prob.model.linear_solver = om.LinearRunOnce() prob.setup(check=False, mode=mode) prob.set_solver_print(level=0) prob.run_model() assert_rel_error(self, prob.get_val('par.C1.y', get_remote=True), 2.5, 1e-6) assert_rel_error(self, prob.get_val('par.C2.y', get_remote=True), 7., 1e-6) J = prob.compute_totals(of=of, wrt=wrt) assert_rel_error(self, J['par.C1.y', 'indep.x'][0][0], 2.5, 1e-6) assert_rel_error(self, prob.get_val('par.C1.y', get_remote=True), 2.5, 1e-6) assert_rel_error(self, J['par.C2.y', 'indep.x'][0][0], 7., 1e-6) assert_rel_error(self, prob.get_val('par.C2.y', get_remote=True), 7., 1e-6)
def test_dup_par(self, mode, auto): # non-distributed output, parallel input prob = om.Problem() model = prob.model if not auto: model.add_subsystem('indep', om.IndepVarComp('x', 1.0), promotes=['x']) par = model.add_subsystem('par', om.ParallelGroup(), promotes=['x']) par.add_subsystem('C1', om.ExecComp('y = 2.5 * x'), promotes=['x']) par.add_subsystem('C2', om.ExecComp('y = 7 * x'), promotes=['x']) wrt = ['x'] of = ['par.C1.y', 'par.C2.y'] prob.model.linear_solver = om.LinearRunOnce() prob.setup(check=False, mode=mode) prob.set_solver_print(level=0) prob.run_model() assert_near_equal(prob.get_val('par.C1.y', get_remote=True), 2.5, 1e-6) assert_near_equal(prob.get_val('par.C2.y', get_remote=True), 7., 1e-6) J = prob.compute_totals(of=of, wrt=wrt) assert_near_equal(J['par.C1.y', 'x'][0][0], 2.5, 1e-6) assert_near_equal(J['par.C2.y', 'x'][0][0], 7., 1e-6) assert_near_equal(prob.get_val('par.C1.y', get_remote=True), 2.5, 1e-6) assert_near_equal(prob.get_val('par.C2.y', get_remote=True), 7., 1e-6)
def test_undeclared_options(self): # Test that using options that should not exist in class cause an error solver = om.LinearRunOnce() msg = "\"LinearRunOnce: Option '%s' cannot be set because it has not been declared.\"" for option in ['atol', 'rtol', 'maxiter', 'err_on_maxiter']: with self.assertRaises(KeyError) as context: solver.options[option] = 1 self.assertEqual(str(context.exception), msg % option)
def test_error_need_direct_solver(self): # Test top level Sellar (i.e., not grouped). prob = om.Problem() model = prob.model = SellarStateConnection(nonlinear_solver=om.BroydenSolver(), linear_solver=om.LinearRunOnce()) prob.setup() with self.assertRaises(ValueError) as context: prob.run_model() msg = "BroydenSolver in SellarStateConnection (<model>): Linear solver must be DirectSolver when solving the full model." self.assertEqual(str(context.exception), msg)
def test_linsearch_3_deprecation(self): prob = om.Problem() model = prob.model = SellarStateConnection( nonlinear_solver=om.BroydenSolver(), linear_solver=om.LinearRunOnce()) prob.setup() model.nonlinear_solver.options['state_vars'] = ['state_eq.y2_command'] model.nonlinear_solver.options['compute_jacobian'] = False msg = 'Deprecation warning: In V 3.0, the default Broyden solver setup will change ' + \ 'to use the BoundsEnforceLS line search.' with assert_warning(DeprecationWarning, msg): prob.final_setup()
def test_error_badname(self): # Test top level Sellar (i.e., not grouped). prob = om.Problem() model = prob.model = SellarStateConnection(nonlinear_solver=om.BroydenSolver(), linear_solver=om.LinearRunOnce()) prob.setup() model.nonlinear_solver.options['state_vars'] = ['junk'] with self.assertRaises(ValueError) as context: prob.run_model() msg = "BroydenSolver in SellarStateConnection (<model>): The following variable names were not found: junk" self.assertEqual(str(context.exception), msg)
def test_simple_sellar(self): # Test top level Sellar (i.e., not grouped). prob = om.Problem() model = prob.model = SellarStateConnection(nonlinear_solver=om.BroydenSolver(), linear_solver=om.LinearRunOnce()) prob.setup() model.nonlinear_solver.options['state_vars'] = ['state_eq.y2_command'] model.nonlinear_solver.options['compute_jacobian'] = False prob.run_model() assert_near_equal(prob['y1'], 25.58830273, .00001) assert_near_equal(prob['state_eq.y2_command'], 12.05848819, .00001)
def setup(self): surface = self.options['surface'] promotes = [] if surface['struct_weight_relief']: promotes = promotes + list( set(['nodes', 'element_mass', 'load_factor'])) if surface['distributed_fuel_weight']: promotes = promotes + list(set(['nodes', 'load_factor'])) if 'n_point_masses' in surface.keys(): promotes = promotes + list( set([ 'point_mass_locations', 'point_masses', 'nodes', 'load_factor', 'engine_thrusts' ])) self.add_subsystem( 'struct_states', SpatialBeamStates(surface=surface), promotes_inputs=['local_stiff_transformed', 'forces', 'loads'] + promotes, promotes_outputs=['disp']) self.add_subsystem('def_mesh', DisplacementTransferGroup(surface=surface), promotes_inputs=['nodes', 'mesh', 'disp'], promotes_outputs=['def_mesh']) self.add_subsystem('aero_geom', VLMGeometry(surface=surface), promotes_inputs=['def_mesh'], promotes_outputs=[ 'b_pts', 'widths', 'cos_sweep', 'lengths', 'chords', 'S_ref' ]) # Add control surfaces if 'control_surfaces' in surface: self.add_subsystem( 'control_surfaces', ControlSurfacesGroup( control_surfaces=surface['control_surfaces'], mesh=surface['mesh']), promotes_inputs=['def_mesh']) self.linear_solver = om.LinearRunOnce()
def test_method(self): p = om.Problem() p.model.add_subsystem('des_vars', om.IndepVarComp('a', val=10., units='m'), promotes=['*']) p.model.add_subsystem('icomp', DistribStateImplicit(), promotes=['*']) model = p.model model.linear_solver = om.PETScKrylov() model.linear_solver.precon = om.LinearRunOnce() p.setup(mode='rev', check=False) p.run_model() jac = p.compute_totals(of=['out_var'], wrt=['a'], return_format='dict') assert_near_equal(15.0, jac['out_var']['a'][0][0])
def test_simple_sellar_cycle(self): # Test top level Sellar (i.e., not grouped). prob = om.Problem() model = prob.model = SellarDerivatives(nonlinear_solver=om.BroydenSolver(), linear_solver=om.LinearRunOnce()) prob.setup() model.nonlinear_solver.options['state_vars'] = ['y1'] model.nonlinear_solver.options['compute_jacobian'] = True prob.set_solver_print(level=2) prob.run_model() assert_near_equal(prob['y1'], 25.58830273, .00001) assert_near_equal(prob['y2'], 12.05848819, .00001)
def test_sellar(self): import openmdao.api as om from openmdao.test_suite.components.sellar import SellarStateConnection prob = om.Problem() model = prob.model = SellarStateConnection(nonlinear_solver=om.BroydenSolver(), linear_solver=om.LinearRunOnce()) prob.setup() model.nonlinear_solver.options['state_vars'] = ['state_eq.y2_command'] model.nonlinear_solver.options['compute_jacobian'] = False prob.set_solver_print(level=2) prob.run_model() assert_near_equal(prob['y1'], 25.58830273, .00001) assert_near_equal(prob['state_eq.y2_command'], 12.05848819, .00001)
def test_par_dist(self, mode, auto): # non-distributed output, parallel input prob = om.Problem() model = prob.model size = 3 sizes = [2, 1] rank = prob.comm.rank model.add_subsystem('indep', om.IndepVarComp('x', np.ones(size))) par = model.add_subsystem('par', om.ParallelGroup()) par.add_subsystem( 'C1', om.ExecComp('y = 3 * x', x=np.zeros(size), y=np.zeros(size))) par.add_subsystem( 'C2', om.ExecComp('y = 5 * x', x=np.zeros(size), y=np.zeros(size))) model.add_subsystem( 'C3', DistribExecComp(['y=1.5*x1+2.5*x2', 'y=2.5*x1-.5*x2'], arr_size=size)) model.connect('indep.x', 'par.C1.x') model.connect('indep.x', 'par.C2.x') model.connect('par.C1.y', 'C3.x1') model.connect('par.C2.y', 'C3.x2') of = ['C3.y'] wrt = ['indep.x'] prob.model.linear_solver = om.LinearRunOnce() prob.setup(check=False, mode=mode) prob.set_solver_print(level=0) prob.run_model() assert_near_equal(prob.get_val('C3.y', get_remote=True), np.array([17, 17, 5], dtype=float), 1e-6) J = prob.compute_totals(of=of, wrt=wrt) expected = np.array([[17, 0, 0], [0, 17, 0], [0, 0, 5]], dtype=float) assert_near_equal(J['C3.y', 'indep.x'], expected, 1e-6) assert_near_equal(prob.get_val('C3.y', get_remote=True), np.array([17, 17, 5], dtype=float), 1e-6)
def test_simple_sellar_full_jacobian(self): # Test top level Sellar (i.e., not grouped). prob = om.Problem() model = prob.model = SellarStateConnection(nonlinear_solver=om.BroydenSolver(), linear_solver=om.LinearRunOnce()) prob.setup() model.nonlinear_solver.linear_solver = om.DirectSolver() prob.run_model() assert_near_equal(prob['y1'], 25.58830273, .00001) assert_near_equal(prob['state_eq.y2_command'], 12.05848819, .00001) # Normally takes about 5 iters, but takes around 4 if you calculate an initial # Jacobian. self.assertTrue(model.nonlinear_solver._iter_count < 5)
def test_dist_dup(self, mode, auto): # non-distributed output, parallel input # Note: Auto-ivc not supported for distributed inputs. prob = om.Problem() model = prob.model size = 3 rank = prob.comm.rank if not auto: model.add_subsystem('indep', om.IndepVarComp('x', np.ones(size)), promotes=['x']) model.add_subsystem('C1', DistribExecComp(['y=2.5*x', 'y=3.5*x'], arr_size=size), promotes=['x']) model.add_subsystem( 'sink', om.ExecComp('y=-1.5 * x', x=np.zeros(size), y=np.zeros(size))) model.connect('C1.y', 'sink.x', src_indices=om.slicer[:]) of = ['sink.y'] wrt = ['x'] prob.model.linear_solver = om.LinearRunOnce() prob.setup(check=False, mode=mode) prob.set_solver_print(level=0) prob.run_model() assert_near_equal(prob.get_val('sink.y', get_remote=True), np.array([-3.75, -3.75, -5.25], dtype=float), 1e-6) J = prob.compute_totals(of=of, wrt=wrt) expected = np.array([[-3.75, 0, 0], [0, -3.75, 0], [0, 0, -5.25]], dtype=float) assert_near_equal(J['sink.y', 'x'], expected, 1e-6) assert_near_equal(prob.get_val('sink.y', get_remote=True), np.array([-3.75, -3.75, -5.25], dtype=float), 1e-6)
def test_sellar_state_connection_fd_system(self): # Sellar model closes loop with state connection instead of a cycle. # This test is just fd. prob = om.Problem() model = prob.model = SellarStateConnection(nonlinear_solver=om.BroydenSolver(), linear_solver=om.LinearRunOnce()) prob.model.approx_totals(method='fd') prob.setup() model.nonlinear_solver.options['state_vars'] = ['state_eq.y2_command'] model.nonlinear_solver.options['compute_jacobian'] = False prob.run_model() assert_near_equal(prob['y1'], 25.58830273, .00001) assert_near_equal(prob['state_eq.y2_command'], 12.05848819, .00001) # Make sure we aren't iterating like crazy self.assertLess(prob.model.nonlinear_solver._iter_count, 6)
def test_simple_sellar_jacobian_assembled_dense(self): # Test top level Sellar (i.e., not grouped). prob = om.Problem() model = prob.model = SellarStateConnection(nonlinear_solver=om.BroydenSolver(), linear_solver=om.LinearRunOnce()) prob.setup() model.options['assembled_jac_type'] = 'dense' model.nonlinear_solver.linear_solver = om.DirectSolver(assemble_jac=True) prob.run_model() assert_rel_error(self, prob['y1'], 25.58830273, .00001) assert_rel_error(self, prob['state_eq.y2_command'], 12.05848819, .00001) # Normally takes about 4 iters, but takes around 3 if you calculate an initial # Jacobian. self.assertTrue(model.nonlinear_solver._iter_count < 4)
def test_dup_dist(self, mode, auto): # Note: Auto-ivc not supported for distributed inputs. # non-distributed output, parallel input prob = om.Problem() model = prob.model size = 3 sizes = [2, 1] rank = prob.comm.rank if not auto: model.add_subsystem('indep', om.IndepVarComp('x', np.ones(size)), promotes=['x']) model.add_subsystem('C1', DistribExecComp(['y=2.5*x', 'y=3.5*x'], arr_size=size), promotes=['x']) of = ['C1.y'] wrt = ['x'] prob.model.linear_solver = om.LinearRunOnce() prob.setup(check=False, mode=mode) prob.set_solver_print(level=0) prob.run_model() assert_near_equal(prob.get_val('C1.y', get_remote=True), np.array([2.5, 2.5, 3.5], dtype=float), 1e-6) J = prob.compute_totals(of=of, wrt=wrt) expected = np.array([[2.5, 0, 0], [0, 2.5, 0], [0, 0, 3.5]], dtype=float) assert_near_equal(J['C1.y', 'x'], expected, 1e-6) assert_near_equal(prob.get_val('C1.y', get_remote=True), np.array([2.5, 2.5, 3.5], dtype=float), 1e-6)
def test_feature_solver(self): prob = om.Problem() model = prob.model model.add_subsystem('comp', Paraboloid(), promotes=['x', 'y', 'f_xy']) model.linear_solver = om.LinearRunOnce() prob.setup(check=False, mode='fwd') prob.set_val('x', 0.0) prob.set_val('y', 0.0) prob.run_model() of = ['f_xy'] wrt = ['x', 'y'] derivs = prob.compute_totals(of=of, wrt=wrt, return_format='dict') assert_near_equal(derivs['f_xy']['x'], [[-6.0]], 1e-6) assert_near_equal(derivs['f_xy']['y'], [[8.0]], 1e-6)
def test_dist_dup(self, mode): # duplicated output, parallel input prob = om.Problem() model = prob.model size = 3 rank = prob.comm.rank model.add_subsystem('indep', om.IndepVarComp('x', np.ones(size))) model.add_subsystem( 'C1', DistribExecComp(['y=2.5*x', 'y=3.5*x'], arr_size=size)) model.add_subsystem( 'sink', om.ExecComp('y=-1.5 * x', x=np.zeros(size), y=np.zeros(size))) model.connect('indep.x', 'C1.x') model.connect('C1.y', 'sink.x') of = ['sink.y'] wrt = ['indep.x'] prob.model.linear_solver = om.LinearRunOnce() #import wingdbstub prob.setup(check=False, mode=mode) prob.set_solver_print(level=0) prob.run_model() assert_near_equal(prob.get_val('sink.y', get_remote=True), np.array([-3.75, -3.75, -5.25], dtype=float), 1e-6) J = prob.compute_totals(of=of, wrt=wrt) expected = np.array([[-3.75, 0, 0], [0, -3.75, 0], [0, 0, -5.25]], dtype=float) assert_near_equal(J['sink.y', 'indep.x'], expected, 1e-6) assert_near_equal(prob.get_val('sink.y', get_remote=True), np.array([-3.75, -3.75, -5.25], dtype=float), 1e-6)
def test_feature_solver(self): import openmdao.api as om from openmdao.test_suite.components.paraboloid import Paraboloid prob = om.Problem() model = prob.model model.add_subsystem('p1', om.IndepVarComp('x', 0.0), promotes=['x']) model.add_subsystem('p2', om.IndepVarComp('y', 0.0), promotes=['y']) model.add_subsystem('comp', Paraboloid(), promotes=['x', 'y', 'f_xy']) model.linear_solver = om.LinearRunOnce() prob.setup(check=False, mode='fwd') prob.run_model() of = ['f_xy'] wrt = ['x', 'y'] derivs = prob.compute_totals(of=of, wrt=wrt, return_format='dict') assert_rel_error(self, derivs['f_xy']['x'], [[-6.0]], 1e-6) assert_rel_error(self, derivs['f_xy']['y'], [[8.0]], 1e-6)
def test_dup_dup(self, mode): # duplicated vars on both ends prob = om.Problem() model = prob.model model.add_subsystem('indep', om.IndepVarComp('x', 1.0)) model.add_subsystem('C1', om.ExecComp('y = 2.5 * x')) model.connect('indep.x', 'C1.x') of = ['C1.y'] wrt = ['indep.x'] prob.model.linear_solver = om.LinearRunOnce() prob.setup(check=False, mode=mode) prob.set_solver_print(level=0) prob.run_model() J = prob.compute_totals(of=of, wrt=wrt) print(model.comm.rank, "val:", J['C1.y', 'indep.x'][0][0]) assert_rel_error(self, J['C1.y', 'indep.x'][0][0], 2.5, 1e-6) assert_rel_error(self, prob['C1.y'], 2.5, 1e-6)
def vanderpol(transcription='gauss-lobatto', num_segments=8, transcription_order=3, compressed=True, optimizer='SLSQP', use_pyoptsparse=False, delay=None): """Dymos problem definition for optimal control of a Van der Pol oscillator""" # define the OpenMDAO problem p = om.Problem(model=om.Group()) if not use_pyoptsparse: p.driver = om.ScipyOptimizeDriver() else: p.driver = om.pyOptSparseDriver() p.driver.options['optimizer'] = optimizer if use_pyoptsparse and optimizer == 'SNOPT': p.driver.opt_settings['iSumm'] = 6 # show detailed SNOPT output p.driver.declare_coloring() # define a Trajectory object and add to model traj = dm.Trajectory() p.model.add_subsystem('traj', subsys=traj) # define a Transcription if transcription == 'gauss-lobatto': t = dm.GaussLobatto(num_segments=num_segments, order=transcription_order, compressed=compressed) elif transcription == 'radau-ps': t = dm.Radau(num_segments=num_segments, order=transcription_order, compressed=compressed) elif transcription == 'runge-kutta': t = dm.RungeKutta(num_segments=num_segments, order=transcription_order, compressed=compressed) # define a Phase as specified above and add to Phase if not delay: phase = dm.Phase(ode_class=vanderpol_ode, transcription=t) else: phase = dm.Phase(ode_class=vanderpol_ode_group, transcription=t) # distributed component group traj.add_phase(name='phase0', phase=phase) t_final = 15.0 phase.set_time_options(fix_initial=True, fix_duration=True, duration_val=t_final, units='s') # set the State time options phase.add_state('x0', fix_initial=False, fix_final=False, rate_source='x0dot', units='V/s', targets='x0') # target required because x0 is an input phase.add_state('x1', fix_initial=False, fix_final=False, rate_source='x1dot', units='V', targets='x1') # target required because x1 is an input phase.add_state('J', fix_initial=False, fix_final=False, rate_source='Jdot', units=None) # define the control phase.add_control(name='u', units=None, lower=-0.75, upper=1.0, continuity=True, rate_continuity=True, targets='u') # target required because u is an input # add constraints phase.add_boundary_constraint('x0', loc='initial', equals=1.0) phase.add_boundary_constraint('x1', loc='initial', equals=1.0) phase.add_boundary_constraint('J', loc='initial', equals=0.0) phase.add_boundary_constraint('x0', loc='final', equals=0.0) phase.add_boundary_constraint('x1', loc='final', equals=0.0) # define objective to minimize phase.add_objective('J', loc='final') # setup the problem p.setup(check=True) # TODO - Dymos API will soon provide a way to specify this. # the linear solver used to compute derivatives is not working on MPI, so switch to LinearRunOnce for phase in traj._phases.values(): phase.linear_solver = om.LinearRunOnce() p['traj.phase0.t_initial'] = 0.0 p['traj.phase0.t_duration'] = t_final # add a linearly interpolated initial guess for the state and control curves p['traj.phase0.states:x0'] = phase.interpolate(ys=[1, 0], nodes='state_input') p['traj.phase0.states:x1'] = phase.interpolate(ys=[1, 0], nodes='state_input') p['traj.phase0.states:J'] = phase.interpolate(ys=[0, 1], nodes='state_input') p['traj.phase0.controls:u'] = phase.interpolate(ys=[-0.75, -0.75], nodes='control_input') p.final_setup() # debugging helpers: # om.n2(p) # show n2 diagram # # with np.printoptions(linewidth=1024): # display partials for manual checking # p.check_partials(compact_print=True) return p
def test_feature(self): class CustomSolveImplicit(om.ImplicitComponent): def setup(self): self.add_input('a', val=10., units='m') rank = self.comm.rank GLOBAL_SIZE = 15 sizes, offsets = evenly_distrib_idxs(self.comm.size, GLOBAL_SIZE) self.add_output('states', shape=int(sizes[rank])) self.add_output('out_var', shape=1) self.local_size = sizes[rank] self.linear_solver = om.PETScKrylov() self.linear_solver.precon = om.LinearUserDefined(solve_function=self.mysolve) def solve_nonlinear(self, i, o): o['states'] = i['a'] local_sum = np.zeros(1) local_sum[0] = np.sum(o['states']) tmp = np.zeros(1) o['out_var'] = tmp[0] def apply_nonlinear(self, i, o, r): r['states'] = o['states'] - i['a'] local_sum = np.zeros(1) local_sum[0] = np.sum(o['states']) global_sum = np.zeros(1) r['out_var'] = o['out_var'] - tmp[0] def apply_linear(self, i, o, d_i, d_o, d_r, mode): if mode == 'fwd': if 'states' in d_o: d_r['states'] += d_o['states'] local_sum = np.array([np.sum(d_o['states'])]) global_sum = np.zeros(1) self.comm.Allreduce(local_sum, global_sum, op=MPI.SUM) d_r['out_var'] -= global_sum if 'out_var' in d_o: d_r['out_var'] += d_o['out_var'] if 'a' in d_i: d_r['states'] -= d_i['a'] elif mode == 'rev': if 'states' in d_o: d_o['states'] += d_r['states'] tmp = np.zeros(1) if self.comm.rank == 0: tmp[0] = d_r['out_var'].copy() self.comm.Bcast(tmp, root=0) d_o['states'] -= tmp if 'out_var' in d_o: d_o['out_var'] += d_r['out_var'] if 'a' in d_i: d_i['a'] -= np.sum(d_r['states']) def mysolve(self, d_outputs, d_residuals, mode): r""" Apply inverse jac product. The model is assumed to be in an unscaled state. If mode is: 'fwd': d_residuals \|-> d_outputs 'rev': d_outputs \|-> d_residuals Parameters ---------- d_outputs: Vector Unscaled, dimensional quantities read via d_outputs[key]. d_residuals: Vector Unscaled, dimensional quantities read via d_residuals[key]. mode: str either 'fwd' or 'rev' """ # Note: we are just preconditioning with Identity as a proof of concept. if mode == 'fwd': d_outputs.set_vec(d_residuals) elif mode == 'rev': d_residuals.set_vec(d_outputs) prob = om.Problem() prob.model.add_subsystem('icomp', CustomSolveImplicit(), promotes=['*']) prob.model.set_input_defaults('a', 10., units='m') model = prob.model model.linear_solver = om.PETScKrylov() model.linear_solver.precon = om.LinearRunOnce() prob.setup(mode='rev', check=False) prob.run_model() jac = prob.compute_totals(of=['out_var'], wrt=['a'], return_format='dict') assert_near_equal(15.0, jac['out_var']['a'][0][0])
model.connect('circuit.n1.V', 'batt_deltaV.V1') # set the lhs and rhs for the battery residual model.connect('batt.V', 'batt_balance.rhs:I') model.connect('batt_deltaV.dV', 'batt_balance.lhs:I') p.setup() ################### # Solver Setup ################### # change the circuit solver to RunOnce because we're # going to converge at the top level of the model with newton instead p.model.circuit.nonlinear_solver = om.NonlinearRunOnce() p.model.circuit.linear_solver = om.LinearRunOnce() # Put Newton at the top so it can also converge the new BalanceComp residual newton = p.model.nonlinear_solver = om.NewtonSolver() p.model.linear_solver = om.DirectSolver() newton.options['iprint'] = 2 newton.options['maxiter'] = 20 newton.options['solve_subsystems'] = True newton.linesearch = om.ArmijoGoldsteinLS() newton.linesearch.options['maxiter'] = 10 newton.linesearch.options['iprint'] = 2 # set initial guesses from the current source problem p['circuit.n1.V'] = 9.8 p['circuit.n2.V'] = .7