def test_has_consistent_initial_conditions(self): nmpc = self.make_nmpc() with pytest.raises(ValueError): # Model has not been properly initialized nmpc.has_consistent_initial_conditions(nmpc.plant) t0 = nmpc.plant_time.first() nmpc.plant.rate[t0, :].set_value(0.0) nmpc.plant.flow_out[t0].set_value(nmpc.plant.flow_in[t0].value) for j in nmpc.plant.components: calculate_variable_from_constraint( nmpc.plant.dcdt[t0, j], nmpc.plant.material_balance[t0, j], ) assert nmpc.has_consistent_initial_conditions(nmpc.plant) nmpc.plant.flow_out[t0].set_value(0.0) assert not nmpc.has_consistent_initial_conditions(nmpc.plant)
def test_solve_consistent_initial_conditions(self): # solve, assert has_consistent..., assert same dof nmpc = self.make_nmpc() dof_prior = degrees_of_freedom(nmpc.plant) # Just going to assume this model needs no additional # initialization before solving for initial conditions. nmpc.solve_consistent_initial_conditions(nmpc.plant) assert nmpc.has_consistent_initial_conditions(nmpc.plant) dof_post = degrees_of_freedom(nmpc.plant) assert dof_prior == dof_post nmpc.controller.flow_in.setlb(0.0) nmpc.controller.flow_out.setlb(0.0) nmpc.controller.flow_in.setub(10.0) nmpc.controller.flow_out.setub(10.0) nmpc.solve_consistent_initial_conditions(nmpc.controller, strip_bounds=False) assert nmpc.has_consistent_initial_conditions(nmpc.controller)
def test_initialize_by_element_in_range(nmpc): plant = nmpc.plant controller = nmpc.controller time = plant.time sample_time = nmpc.sample_time nmpc.solve_consistent_initial_conditions(plant) assert nmpc.has_consistent_initial_conditions(plant, tolerance=1e-6) assert degrees_of_freedom(plant) == 0 initialize_by_element_in_range(plant, time, 0, 3, dae_vars=plant._NMPC_NAMESPACE.dae_vars, time_linking_vars=plant._NMPC_NAMESPACE.diff_vars.varlist) assert degrees_of_freedom(plant) == 0 for con in activated_equalities_generator(plant): if 'disc_eq' in con.local_name or 'balance' in con.local_name: # (know disc. and balance equations will be directly indexed # by time) index = con.index() if not type(index) is tuple: index = (index,) t_index = index[0] if t_index <= 3: # Equalities in simulated range should not be violated assert abs(value(con.body)-value(con.upper)) < 1e-6 nmpc.simulate_plant(0) # Check that plant simulation matches controller simulation. # Only valid because there is no noise or plant-model-mismatch # and plant/controller have the same time discretizations p_varlist = (plant._NMPC_NAMESPACE.diff_vars.varlist + plant._NMPC_NAMESPACE.alg_vars.varlist + plant._NMPC_NAMESPACE.deriv_vars.varlist) c_varlist = (controller._NMPC_NAMESPACE.diff_vars.varlist + controller._NMPC_NAMESPACE.alg_vars.varlist + controller._NMPC_NAMESPACE.deriv_vars.varlist) for i, pvar in enumerate(p_varlist): for t in time: if t > sample_time or t == 0: continue cvar = c_varlist[i] assert pvar[t].value == approx(cvar[t].value, abs=1e-5)
def test_calculate_full_state_setpoint(nmpc): controller = nmpc.controller controller.mixer.E_inlet.flow_vol[0].fix(0.1) controller.mixer.S_inlet.flow_vol[0].fix(2.0) nmpc.solve_consistent_initial_conditions(controller) assert nmpc.has_consistent_initial_conditions(controller, tolerance=1e-6) # Deactivate tracking objective from previous tests #controller._NMPC_NAMESPACE.tracking_objective.deactivate() set_point = [(controller.cstr.outlet.conc_mol[0, 'P'], 0.4), # (controller.cstr.outlet.conc_mol[0, 'S'], 0.0), # (controller.cstr.control_volume.energy_holdup[0, 'aq'], 300), (controller.mixer.E_inlet.flow_vol[0], 0.2), (controller.mixer.S_inlet.flow_vol[0], 2.5)] weight_tolerance = 5e-7 weight_override = [ (controller.mixer.E_inlet.flow_vol[0.], 20.), (controller.mixer.S_inlet.flow_vol[0.], 2.), (controller.cstr.control_volume.energy_holdup[0., 'aq'], 0.1), (controller.cstr.outlet.conc_mol[0., 'P'], 1.), (controller.cstr.outlet.conc_mol[0., 'S'], 1.), ] # FIXME: This steady state setpoint solve is more sensitive than I # would like. nmpc.calculate_full_state_setpoint(set_point, objective_weight_tolerance=weight_tolerance, objective_weight_override=weight_override) assert hasattr(controller._NMPC_NAMESPACE, 'user_setpoint') user_setpoint = controller._NMPC_NAMESPACE.user_setpoint assert hasattr(controller._NMPC_NAMESPACE, 'user_setpoint_weights') user_setpoint_weights = controller._NMPC_NAMESPACE.user_setpoint_weights assert hasattr(controller._NMPC_NAMESPACE, 'user_setpoint_vars') user_setpoint_vars = controller._NMPC_NAMESPACE.user_setpoint_vars for i, var in enumerate(user_setpoint_vars): # if var.local_name.startswith('conc'): # assert user_setpoint_weights[i] == 1. # elif var.local_name.startswith('energy'): # assert user_setpoint_weights[i] == 0.1 if var.local_name.startswith('E_'): assert user_setpoint_weights[i] == 20. elif var.local_name.startswith('S_'): assert user_setpoint_weights[i] == 2. alg_vars = controller._NMPC_NAMESPACE.alg_vars diff_vars = controller._NMPC_NAMESPACE.diff_vars input_vars = controller._NMPC_NAMESPACE.input_vars categories = [ VariableCategory.DIFFERENTIAL, VariableCategory.ALGEBRAIC, VariableCategory.DERIVATIVE, VariableCategory.INPUT, ] category_dict = controller._NMPC_NAMESPACE.category_dict for categ in categories: group = category_dict[categ] # Assert that setpoint has been populated with non-None values assert not any([sp is None for sp in group.setpoint]) # Assert that setpoint (target) and reference (initial) values are # different in some way assert not all([sp == ref for sp, ref in zip(group.setpoint, group.reference)]) # Assert that initial and reference values are the same assert all([ref == var[0].value for ref, var in zip(group.reference, group.varlist)])