def setUp(self): self.prob = Problem() self.prob.root = SellarDerivatives() self.prob.driver = KonaOptimizer() self.driver = driver = self.prob.driver # need to give driver a pointer to problem since I'm not always going to run it # which is where it would normally get that pointer self.driver.problem = self.prob driver.add_desvar('z', lower=np.array([-10.0, 0.0]), upper=np.array([10.0, 10.0])) driver.add_desvar('x', lower=0.0, upper=10.0) driver.add_objective('obj') driver.add_constraint('con1', upper=0.0) driver.add_constraint('con2', upper=0.0) # not part of sellar, but just need to have some of these for the tests self.prob.root.add('con_cmp3', ExecComp('con3 = 2*x - y1'), promotes=['*']) driver.add_constraint('con3', equals=0) self.prob.root.add('con_cmp4', ExecComp('con4 = 2*x - y1'), promotes=['*']) driver.add_constraint('con4', lower=0) self.prob.setup(check=False) # allocate memory like a kona-memory would do self.memory_allocator = Allocator(3,2,1,1,2,3,3) self.primals = self.memory_allocator.alloc_primal(3) self.states = self.memory_allocator.alloc_state(3) self.duals = self.memory_allocator.alloc_dual(3)
class TestKonaSolver(unittest.TestCase): def setUp(self): self.prob = Problem() self.prob.root = SellarDerivatives() self.prob.driver = KonaOptimizer() self.driver = driver = self.prob.driver # need to give driver a pointer to problem since I'm not always going to run it # which is where it would normally get that pointer self.driver.problem = self.prob driver.add_desvar('z', lower=np.array([-10.0, 0.0]), upper=np.array([10.0, 10.0])) driver.add_desvar('x', lower=0.0, upper=10.0) driver.add_objective('obj') driver.add_constraint('con1', upper=0.0) driver.add_constraint('con2', upper=0.0) # not part of sellar, but just need to have some of these for the tests self.prob.root.add('con_cmp3', ExecComp('con3 = 2*x - y1'), promotes=['*']) driver.add_constraint('con3', equals=0) self.prob.root.add('con_cmp4', ExecComp('con4 = 2*x - y1'), promotes=['*']) driver.add_constraint('con4', lower=0) self.prob.setup(check=False) # allocate memory like a kona-memory would do self.memory_allocator = Allocator(3,2,1,1,2,3,3) self.primals = self.memory_allocator.alloc_primal(3) self.states = self.memory_allocator.alloc_state(3) self.duals = self.memory_allocator.alloc_dual(3) def test_solver_init_design(self): init_vec = self.primals[0] # pull a vector out of kona memory self.driver.init_design(init_vec) for name, idx in self.driver.primal_vars: assert_rel_error(self, init_vec.data[idx[0]:idx[1]], self.prob[name], 1e-10) def test_solver_eval_obj(self): at_des = self.primals[0] at_state = self.states[0] at_des.data = np.array([1.111, 12.111, 13.111]) at_state.data = np.array([2.511, 3.11]) obj = self.driver.eval_obj(at_des, at_state) # make sure that the state variables in the u-vec didn't get changed assert_rel_error(self, self.prob['y1'], 2.511, 1e-10) assert_rel_error(self, self.prob['y2'], 3.11, 1e-10) assert_rel_error(self, obj, 1.111**2 + 13.111 + 2.511 + np.exp(-3.11), 1e-5) def test_solver_eval_constraints(self): at_des = self.primals[0] at_state = self.states[0] store_here = self.duals[0] at_des.data = np.array([1.111, 12.111, 13.111]) at_state.data = np.array([2.511, 3.11]) self.driver.eval_constraints(at_des, at_state, store_here) # make sure that the state variables in the u-vec didn't get changed assert_rel_error(self, self.prob['y1'], 2.511, 1e-10) assert_rel_error(self, self.prob['y2'], 3.11, 1e-10) # KONA Wants positive-valid constraints, so have to negate openmdao! c1 = 3.16 - self.prob['y1'] # y1 > 3.16 -- violated, so negative! c2 = self.prob['y2'] - 24.0 # y2 < 24 -- met, so positive! # print(store_here.ieq_ub_data, np.array([-c1,-c2])) assert_rel_error(self, store_here.ieq_ub_data, np.array([-c1,-c2]), 1e-5) assert_rel_error(self, store_here.eq_data, np.array([-.289]), 1e-5) assert_rel_error(self, store_here.ieq_lb_data, np.array([-.289]), 1e-5) assert_rel_error(self, store_here.primal_lb_data, np.array([1.111, 22.111, 13.111]), 1e-5) assert_rel_error(self, store_here.primal_ub_data, np.array([8.889, -2.111, -3.111]), 1e-5) def test_solver_eval_residual(self): at_des = self.primals[0] at_state = self.states[0] store_here = self.states[1] at_des.data = np.array([1.111, 12.111, 13.111]) at_state.data = np.array([2.511, 3.11]) self.driver.eval_residual(at_des, at_state, store_here) # Note: Some implementation details in OpenMDAO currently have an inconsistency between residual sign and residual derivative sign! for name, idx in self.driver.state_vars: # print(name, store_here.data[idx[0]:idx[1]], self.prob.root.resids[name]) assert_rel_error(self, store_here.data[idx[0]:idx[1]],-self.prob.root.resids[name],1e-10) def test_solver_solve_nonlinear(self): at_des = self.primals[0] store_here = self.states[1] at_des.data = np.array([1.111, 12.111, 13.111]) self.driver.solve_nonlinear(at_des, store_here) for name, idx in self.driver.state_vars: # print(name, store_here.data[idx[0]:idx[1]], self.prob[name]) assert_rel_error(self, store_here.data[idx[0]:idx[1]],self.prob[name],1e-10) def test_solver_multiply_dRdx(self): at_des = self.primals[0] at_state = self.states[0] at_des.data = np.array([1,1,1]) at_state.data = np.array([1,1]) in_vec = self.primals[1] out_vec = self.states[1] in_vec.data = np.array([2,2,2]) self.driver.multiply_dRdX(at_des, at_state, in_vec, out_vec) assert_rel_error(self, out_vec.data[0], -8., 1e-10) assert_rel_error(self, out_vec.data[1], -4., 1e-10) in_vec = self.states[2] out_vec = self.primals[2] in_vec.data = np.array([2,2]) self.driver.multiply_dRdX_T(at_des, at_state, in_vec, out_vec) assert_rel_error(self, out_vec.data[0], -2., 1e-10) assert_rel_error(self, out_vec.data[1], -6., 1e-10) assert_rel_error(self, out_vec.data[2], -4., 1e-10) def test_solver_multiply_dRdU(self): at_des = self.primals[0] at_state = self.states[0] at_des.data = np.array([1,1,1]) at_state.data = np.array([1,1]) in_vec = self.states[1] out_vec = self.states[2] in_vec.data = np.array([2,2]) self.driver.multiply_dRdU(at_des, at_state, in_vec, out_vec) assert_rel_error(self, out_vec.data[0], 2.4, 1e-10) assert_rel_error(self, out_vec.data[1], 1., 1e-10) in_vec = self.states[1] out_vec = self.states[2] in_vec.data = np.array([2,2]) self.driver.multiply_dRdU_T(at_des, at_state, in_vec, out_vec) assert_rel_error(self, out_vec.data[0], 1., 1e-10) assert_rel_error(self, out_vec.data[1], 2.4, 1e-10) def test_solver_multiply_dCdU(self): at_des = self.primals[0] at_state = self.states[0] at_des.data = np.array([1,1,1]) at_state.data = np.array([1,1]) in_vec = self.states[1] out_vec = self.duals[2] in_vec.data = np.array([2,2]) out_vec.ieq_ub_data = np.array([-5,-5]) # con1, con2 self.driver.multiply_dCdU(at_des, at_state, in_vec, out_vec) assert_rel_error(self, out_vec.ieq_ub_data[0], 2., 1e-10) assert_rel_error(self, out_vec.ieq_ub_data[1], -2., 1e-10) assert_rel_error(self, out_vec.eq_data[0], -2., 1e-10) assert_rel_error(self, out_vec.ieq_lb_data[0], -2., 1e-10) in_vec = self.duals[1] out_vec = self.states[2] in_vec.ieq_ub_data = np.array([2,2]) in_vec.ieq_lb_data = np.array([2]) in_vec.eq_data = np.array([2]) self.driver.multiply_dCdU_T(at_des, at_state, in_vec, out_vec) assert_rel_error(self, out_vec.data[0], -2, 1e-10) assert_rel_error(self, out_vec.data[1], -2, 1e-10) def test_solver_multiply_dCdX(self): at_des = self.primals[0] at_state = self.states[0] at_des.data = np.array([1,1,1]) at_state.data = np.array([1,1]) in_vec = self.primals[1] out_vec = self.duals[2] in_vec.data = np.array([2,2,2]) out_vec.ieq_ub_data = np.array([-5,-5]) out_vec.eq_data = np.array([-5,-5]) self.driver.multiply_dCdX(at_des, at_state, in_vec, out_vec) assert_rel_error(self, out_vec.ieq_ub_data[0], 0., 1e-10) assert_rel_error(self, out_vec.ieq_ub_data[1], 0., 1e-10) assert_rel_error(self, out_vec.eq_data[0], 4., 1e-10) assert_rel_error(self, out_vec.ieq_lb_data[0], 4., 1e-10) assert_rel_error(self, out_vec.primal_lb_data, 2*np.ones(3), 1e-10) assert_rel_error(self, out_vec.primal_ub_data, -2*np.ones(3), 1e-10) in_vec = self.duals[1] out_vec = self.primals[2] in_vec.ieq_ub_data = np.array([2, 2]) in_vec.ieq_lb_data = np.array([2]) in_vec.eq_data = np.array([2]) in_vec.primal_lb_data = np.ones(3) in_vec.primal_ub_data = -np.ones(3) self.driver.multiply_dCdX_T(at_des, at_state, in_vec, out_vec) assert_rel_error(self, out_vec.data[0], 10, 1e-10) assert_rel_error(self, out_vec.data[1], 2., 1e-10) assert_rel_error(self, out_vec.data[2], 2., 1e-10) def test_solver_eval_dFdX(self): at_des = self.primals[0] at_state = self.states[0] at_des.data = np.array([1,1,1]) at_state.data = np.array([1,1]) store_here = self.primals[1] self.driver.eval_dFdX(at_des, at_state, store_here) assert_rel_error(self, store_here.data[0], 2., 1e-10) assert_rel_error(self, store_here.data[1], 0., 1e-10) assert_rel_error(self, store_here.data[2], 1., 1e-10) def test_solver_eval_dFdU(self): at_des = self.primals[0] at_state = self.states[0] at_des.data = np.array([1,1,1]) at_state.data = np.array([1,1]) store_here = self.states[1] self.driver.eval_dFdU(at_des, at_state, store_here) assert_rel_error(self, store_here.data[0], 1., 1e-10) assert_rel_error(self, store_here.data[1], -np.exp(-1), 1e-10) def test_solver_solve_dRdU(self): at_des = self.primals[0] at_state = self.states[0] at_des.data = np.array([1,1,1]) at_state.data = np.array([1,1]) tol = 1e-10 in_vec = self.states[1] out_vec = self.states[2] in_vec.data = np.array([-3, 7]) self.driver.solve_linear(at_des, at_state, in_vec, tol, out_vec) assert_rel_error(self, out_vec.data[0], -4., 1e-10) assert_rel_error(self, out_vec.data[1], 5., 1e-10) in_vec = self.states[1] out_vec = self.states[2] in_vec.data = np.array([9,4]) self.driver.solve_adjoint(at_des, at_state, in_vec, tol, out_vec) assert_rel_error(self, out_vec.data[0], 10., 1e-10) assert_rel_error(self, out_vec.data[1], 2., 1e-10)