Ejemplo n.º 1
0
def test_categorize_error():
    model = make_model(horizon=1, ntfe=5, ntcp=2)
    time = model.fs.time

    scalar_vars, dae_vars = flatten_dae_components(model, time, ctype=Var)

    # Add a dummy var to treat as an input.
    # This var is not in `dae_vars`, so it will not be located during
    # categorization, which should fail.
    model.dummy_var = Var(time)

    init_input_list = [
        model.fs.mixer.S_inlet.flow_vol[0],
        model.fs.mixer.E_inlet.flow_vol[0],
        model.dummy_var[0],
    ]

    with pytest.raises(RuntimeError, match=r'Not all inputs could be found'):
        category_dict = categorize_dae_variables(
            dae_vars,
            time,
            init_input_list,
        )

    # Re-run flattener. Now `dummy_var` should be included in `dae_vars`.
    scalar_vars, dae_vars = flatten_dae_components(model, time, ctype=Var)
    category_dict = categorize_dae_variables(
        dae_vars,
        time,
        init_input_list,
    )
Ejemplo n.º 2
0
 def make_block(self, sample_time=0.5, horizon=1, nfe=2):
     model = make_model(horizon=horizon, nfe=nfe)
     time = model.time
     t0 = time.first()
     inputs = [model.flow_in[t0]]
     measurements = [model.conc[t0, 'A'], model.conc[t0, 'B']]
     scalar_vars, dae_vars = flatten_dae_components(
         model,
         time,
         pyo.Var,
     )
     category_dict = categorize_dae_variables(dae_vars,
                                              time,
                                              inputs,
                                              measurements=measurements)
     dyn_block = DynamicBlock(
         model=model,
         time=time,
         category_dict={None: category_dict},
         #inputs=inputs,
         #measurements=measurements,
     )
     dyn_block.construct()
     dyn_block.set_sample_time(sample_time)
     return dyn_block
Ejemplo n.º 3
0
    def _construct(self):
        """ Generates time-indexed references and categorizes them. """
        model = self.mod
        time = self.time
        inputs = self._inputs
        try:
            measurements = self._measurements
        except AttributeError:
            measurements = self._measurements = None

        # TODO: Give the user the option to provide their own
        # category_dict (they know the structure of their model
        # better than I do...)
        scalar_vars, dae_vars = flatten_dae_components(
            model,
            time,
            ctype=Var,
        )
        self.scalar_vars = scalar_vars
        self.dae_vars = dae_vars
        category_dict = categorize_dae_variables(
            dae_vars,
            time,
            inputs,
            measurements=measurements,
        )
        self.category_dict = category_dict

        self._add_category_blocks()
        self._add_category_references()

        self.differential_vars = category_dict[VC.DIFFERENTIAL]
        self.algebraic_vars = category_dict[VC.ALGEBRAIC]
        self.derivative_vars = category_dict[VC.DERIVATIVE]
        self.input_vars = category_dict[VC.INPUT]
        self.fixed_vars = category_dict[VC.FIXED]

        self.measurement_vars = category_dict.pop(VC.MEASUREMENT)
        # The categories in category_dict now form a partition of the
        # time-indexed variables. This is necessary to have a well-defined
        # vardata map, which maps each vardata to a unique component indexed
        # only by time.

        # Maps each vardata (of a time-indexed var) to the NmpcVar
        # that contains it.
        self.vardata_map = ComponentMap((var[t], var)
                                        for varlist in category_dict.values()
                                        for var in varlist for t in time)
        # NOTE: looking up var[t] instead of iterating over values()
        # appears to be ~ 5x faster

        # These should be overridden by a call to `set_sample_time`
        # The defaults assume that the entire model is one sample.
        self.sample_points = [time.first(), time.last()]
        self.sample_point_indices = [1, len(time)]
Ejemplo n.º 4
0
def test_categorize_4():
    """
    This tests categorization when a psuedo-steady state
    approximation is used. Energy accumulation and accumulation of E
    are fixed, the corresponding initial conditions unfixed, and
    the corresponding discretization equations deactivated.
    """
    model = make_model(horizon=1, ntfe=5, ntcp=2)
    time = model.fs.time

    CV = model.fs.cstr.control_volume
    CV.energy_accumulation[:, 'aq'].fix(0.)
    CV.material_accumulation[:, 'aq', 'E'].fix(0.)
    CV.energy_holdup[0, 'aq'].unfix()
    CV.material_holdup[0, 'aq', 'E'].unfix()
    CV.energy_accumulation_disc_eq.deactivate()
    CV.material_accumulation_disc_eq.deactivate()

    init_input_list = [
        model.fs.mixer.S_inlet.flow_vol[0],
        model.fs.mixer.E_inlet.flow_vol[0],
    ]
    init_input_set = ComponentSet(init_input_list)

    init_deriv_list = [
        CV.material_accumulation[0, 'aq', 'C'],
        CV.material_accumulation[0, 'aq', 'S'],
        CV.material_accumulation[0, 'aq', 'P'],
        CV.material_accumulation[0, 'aq', 'Solvent'],
    ]
    init_deriv_set = ComponentSet(init_deriv_list)

    init_diff_list = [
        CV.material_holdup[0, 'aq', 'C'],
        CV.material_holdup[0, 'aq', 'S'],
        CV.material_holdup[0, 'aq', 'P'],
        CV.material_holdup[0, 'aq', 'Solvent'],
    ]
    init_diff_set = ComponentSet(init_diff_list)

    init_fixed_list = [
        model.fs.cstr.control_volume.energy_accumulation[0, 'aq'],
        CV.material_accumulation[0, 'aq', 'E'],
        model.fs.mixer.E_inlet.temperature[0],
        model.fs.mixer.S_inlet.temperature[0],
        *list(model.fs.mixer.E_inlet.conc_mol[0, :]),
        *list(model.fs.mixer.S_inlet.conc_mol[0, :]),
        model.fs.cstr.outlet.conc_mol[0, 'Solvent'],
        model.fs.mixer.outlet.conc_mol[0, 'Solvent'],
    ]
    init_fixed_set = ComponentSet(init_fixed_list)

    init_meas_list = [
        model.fs.cstr.control_volume.volume[0],
        CV.material_holdup[0, 'aq', 'P'],
        CV.material_holdup[0, 'aq', 'C'],
        CV.material_holdup[0, 'aq', 'S'],
    ]
    init_meas_set = ComponentSet(init_meas_list)

    init_alg_list = [
        model.fs.cstr.control_volume.energy_holdup[0, 'aq'],
        CV.material_holdup[0, 'aq', 'E'],
        model.fs.cstr.outlet.flow_vol[0],
        model.fs.cstr.outlet.temperature[0],
        model.fs.cstr.inlet.flow_vol[0],
        model.fs.cstr.inlet.temperature[0],
        model.fs.mixer.outlet.flow_vol[0],
        model.fs.mixer.outlet.temperature[0],
        model.fs.cstr.control_volume.volume[0],
        *list(model.fs.cstr.control_volume.properties_out[0].flow_mol_comp[:]),
        *list(model.fs.cstr.inlet.conc_mol[0, :]),
        *list(model.fs.cstr.control_volume.properties_in[0].flow_mol_comp[:]),
        *list(model.fs.cstr.control_volume.rate_reaction_generation[0,
                                                                    'aq', :]),
        *list(model.fs.mixer.mixed_state[0].flow_mol_comp[:]),
        *list(model.fs.mixer.E_inlet_state[0].flow_mol_comp[:]),
        *list(model.fs.mixer.S_inlet_state[0].flow_mol_comp[:]),
        *list(model.fs.cstr.outlet.conc_mol[0, :]),
        *list(model.fs.mixer.outlet.conc_mol[0, :]),
        *list(model.fs.cstr.control_volume.reactions[0].reaction_coef[:]),
        *list(model.fs.cstr.control_volume.reactions[0].reaction_rate[:]),
        *list(model.fs.cstr.control_volume.rate_reaction_extent[0, :]),
    ]
    init_alg_set = ComponentSet(init_alg_list)
    # solvent outlet concentrations are not algebraic variables as
    # it is fixed.
    init_alg_set.remove(model.fs.cstr.outlet.conc_mol[0, 'Solvent'])
    init_alg_set.remove(model.fs.mixer.outlet.conc_mol[0, 'Solvent'])

    scalar_vars, dae_vars = flatten_dae_components(model, time, ctype=Var)
    category_dict = categorize_dae_variables(dae_vars, time, init_input_list)

    input_vars = category_dict[VC.INPUT]
    diff_vars = category_dict[VC.DIFFERENTIAL]
    deriv_vars = category_dict[VC.DERIVATIVE]
    fixed_vars = category_dict[VC.FIXED]
    alg_vars = category_dict[VC.ALGEBRAIC]
    meas_vars = category_dict[VC.MEASUREMENT]

    assert len(input_vars) == len(init_input_set)
    for v in input_vars:
        assert v[0] in init_input_set

    assert len(deriv_vars) == len(init_deriv_set)
    for v in deriv_vars:
        assert v[0] in init_deriv_set

    assert len(diff_vars) == len(init_deriv_set)
    for v in diff_vars:
        assert v[0] in init_diff_set

    assert len(fixed_vars) == len(init_fixed_set)
    for v in fixed_vars:
        assert v[0] in init_fixed_set

    assert len(alg_vars) == len(init_alg_set)
    for v in alg_vars:
        assert v[0] in init_alg_set

    assert len(meas_vars) == len(init_meas_set)
    for v in meas_vars:
        assert v[0] in init_meas_set

    assert len(scalar_vars) == 0
Ejemplo n.º 5
0
def test_categorize_1():
    """
    This test categorizes the enzyme cstr "as intended."
    Volume is used as a measurement, and solvent flow rates are
    fixed, but otherwise equations are as expected.
    """
    model = make_model(horizon=1, ntfe=5, ntcp=2)
    time = model.fs.time

    init_input_list = [
        model.fs.mixer.S_inlet.flow_vol[0],
        model.fs.mixer.E_inlet.flow_vol[0],
    ]
    init_input_set = ComponentSet(init_input_list)

    init_deriv_list = [
        model.fs.cstr.control_volume.energy_accumulation[0, 'aq'],
        *list(model.fs.cstr.control_volume.material_accumulation[0, 'aq', :]),
    ]
    init_deriv_set = ComponentSet(init_deriv_list)

    init_diff_list = [
        model.fs.cstr.control_volume.energy_holdup[0, 'aq'],
        *list(model.fs.cstr.control_volume.material_holdup[0, 'aq', :]),
    ]
    init_diff_set = ComponentSet(init_diff_list)

    init_fixed_list = [
        model.fs.mixer.E_inlet.temperature[0],
        model.fs.mixer.S_inlet.temperature[0],
        *list(model.fs.mixer.E_inlet.conc_mol[0, :]),
        *list(model.fs.mixer.S_inlet.conc_mol[0, :]),
        model.fs.cstr.outlet.conc_mol[0, 'Solvent'],
        model.fs.mixer.outlet.conc_mol[0, 'Solvent'],
    ]
    init_fixed_set = ComponentSet(init_fixed_list)

    init_meas_list = [
        model.fs.cstr.control_volume.energy_holdup[0, 'aq'],
        model.fs.cstr.control_volume.volume[0],
        *list(model.fs.cstr.control_volume.material_holdup[0, 'aq', :]),
    ]
    init_meas_set = ComponentSet(init_meas_list)
    # Solvent holdup is not a measurement; we measure volume instead
    init_meas_set.remove(
        model.fs.cstr.control_volume.material_holdup[0, 'aq', 'Solvent'])

    init_alg_list = [
        model.fs.cstr.outlet.flow_vol[0],
        model.fs.cstr.outlet.temperature[0],
        model.fs.cstr.inlet.flow_vol[0],
        model.fs.cstr.inlet.temperature[0],
        model.fs.mixer.outlet.flow_vol[0],
        model.fs.mixer.outlet.temperature[0],
        model.fs.cstr.control_volume.volume[0],
        *list(model.fs.cstr.control_volume.properties_out[0].flow_mol_comp[:]),
        *list(model.fs.cstr.inlet.conc_mol[0, :]),
        *list(model.fs.cstr.control_volume.properties_in[0].flow_mol_comp[:]),
        *list(model.fs.cstr.control_volume.rate_reaction_generation[0,
                                                                    'aq', :]),
        *list(model.fs.mixer.mixed_state[0].flow_mol_comp[:]),
        *list(model.fs.mixer.E_inlet_state[0].flow_mol_comp[:]),
        *list(model.fs.mixer.S_inlet_state[0].flow_mol_comp[:]),
        *list(model.fs.cstr.outlet.conc_mol[0, :]),
        *list(model.fs.mixer.outlet.conc_mol[0, :]),
        *list(model.fs.cstr.control_volume.reactions[0].reaction_coef[:]),
        *list(model.fs.cstr.control_volume.reactions[0].reaction_rate[:]),
        *list(model.fs.cstr.control_volume.rate_reaction_extent[0, :]),
    ]
    init_alg_set = ComponentSet(init_alg_list)
    # solvent outlet concentrations are not algebraic variables as
    # it is fixed.
    init_alg_set.remove(model.fs.cstr.outlet.conc_mol[0, 'Solvent'])
    init_alg_set.remove(model.fs.mixer.outlet.conc_mol[0, 'Solvent'])

    scalar_vars, dae_vars = flatten_dae_components(model, time, ctype=Var)
    category_dict = categorize_dae_variables(dae_vars, time, init_input_list)

    input_vars = category_dict[VC.INPUT]
    diff_vars = category_dict[VC.DIFFERENTIAL]
    deriv_vars = category_dict[VC.DERIVATIVE]
    fixed_vars = category_dict[VC.FIXED]
    alg_vars = category_dict[VC.ALGEBRAIC]
    meas_vars = category_dict[VC.MEASUREMENT]

    assert len(input_vars) == len(init_input_set)
    for v in input_vars:
        assert v[0] in init_input_set

    assert len(deriv_vars) == len(init_deriv_set)
    for v in deriv_vars:
        assert v[0] in init_deriv_set

    assert len(diff_vars) == len(init_deriv_set)
    for v in diff_vars:
        assert v[0] in init_diff_set

    assert len(fixed_vars) == len(init_fixed_set)
    for v in fixed_vars:
        assert v[0] in init_fixed_set

    assert len(alg_vars) == len(init_alg_set)
    for v in alg_vars:
        assert v[0] in init_alg_set

    assert len(meas_vars) == len(init_meas_set)
    for v in meas_vars:
        assert v[0] in init_meas_set

    assert len(scalar_vars) == 0
Ejemplo n.º 6
0
def test_categorize_3():
    """
    In this test we fix one of the differential variables.
    This is the case where somebody wants to run an isothermal
    CSTR.
    """
    model = make_model(horizon=1, ntfe=5, ntcp=2)
    time = model.fs.time

    CV = model.fs.cstr.control_volume
    CV.energy_holdup.fix(300)
    CV.energy_accumulation_disc_eq.deactivate()

    init_input_list = [
        model.fs.mixer.S_inlet.flow_vol[0],
        model.fs.mixer.E_inlet.flow_vol[0],
    ]
    init_input_set = ComponentSet(init_input_list)

    init_deriv_list = [
        *list(model.fs.cstr.control_volume.material_accumulation[0, 'aq', :]),
    ]
    init_deriv_set = ComponentSet(init_deriv_list)

    init_diff_list = [
        *list(model.fs.cstr.control_volume.material_holdup[0, 'aq', :]),
    ]
    init_diff_set = ComponentSet(init_diff_list)

    init_fixed_list = [
        # Energy holdup has been fixed
        model.fs.cstr.control_volume.energy_holdup[0, 'aq'],
        model.fs.mixer.E_inlet.temperature[0],
        model.fs.mixer.S_inlet.temperature[0],
        *list(model.fs.mixer.E_inlet.conc_mol[0, :]),
        *list(model.fs.mixer.S_inlet.conc_mol[0, :]),
        model.fs.cstr.outlet.conc_mol[0, 'Solvent'],
        model.fs.mixer.outlet.conc_mol[0, 'Solvent'],
    ]
    init_fixed_set = ComponentSet(init_fixed_list)

    init_meas_list = [
        model.fs.cstr.control_volume.volume[0],
        *list(model.fs.cstr.control_volume.material_holdup[0, 'aq', :]),
    ]
    init_meas_set = ComponentSet(init_meas_list)
    # Solvent holdup is not a measurement; we measure volume instead
    init_meas_set.remove(
        model.fs.cstr.control_volume.material_holdup[0, 'aq', 'Solvent'])

    init_alg_list = [
        # Since energy_holdup is fixed, energy_accumulation is not
        # considered a derivative. Instead it is algebraic.
        model.fs.cstr.control_volume.energy_accumulation[0, 'aq'],
        model.fs.cstr.outlet.flow_vol[0],
        model.fs.cstr.outlet.temperature[0],
        model.fs.cstr.inlet.flow_vol[0],
        model.fs.cstr.inlet.temperature[0],
        model.fs.mixer.outlet.flow_vol[0],
        model.fs.mixer.outlet.temperature[0],
        model.fs.cstr.control_volume.volume[0],
        *list(model.fs.cstr.control_volume.properties_out[0].flow_mol_comp[:]),
        *list(model.fs.cstr.inlet.conc_mol[0, :]),
        *list(model.fs.cstr.control_volume.properties_in[0].flow_mol_comp[:]),
        *list(model.fs.cstr.control_volume.rate_reaction_generation[0,
                                                                    'aq', :]),
        *list(model.fs.mixer.mixed_state[0].flow_mol_comp[:]),
        *list(model.fs.mixer.E_inlet_state[0].flow_mol_comp[:]),
        *list(model.fs.mixer.S_inlet_state[0].flow_mol_comp[:]),
        *list(model.fs.cstr.outlet.conc_mol[0, :]),
        *list(model.fs.mixer.outlet.conc_mol[0, :]),
        *list(model.fs.cstr.control_volume.reactions[0].reaction_coef[:]),
        *list(model.fs.cstr.control_volume.reactions[0].reaction_rate[:]),
        *list(model.fs.cstr.control_volume.rate_reaction_extent[0, :]),
    ]
    init_alg_set = ComponentSet(init_alg_list)
    # solvent outlet concentrations are not algebraic variables as
    # it is fixed.
    init_alg_set.remove(model.fs.cstr.outlet.conc_mol[0, 'Solvent'])
    init_alg_set.remove(model.fs.mixer.outlet.conc_mol[0, 'Solvent'])

    scalar_vars, dae_vars = flatten_dae_components(model, time, ctype=Var)
    category_dict = categorize_dae_variables(dae_vars, time, init_input_list)

    input_vars = category_dict[VC.INPUT]
    diff_vars = category_dict[VC.DIFFERENTIAL]
    deriv_vars = category_dict[VC.DERIVATIVE]
    fixed_vars = category_dict[VC.FIXED]
    alg_vars = category_dict[VC.ALGEBRAIC]
    meas_vars = category_dict[VC.MEASUREMENT]

    assert len(input_vars) == len(init_input_set)
    for v in input_vars:
        assert v[0] in init_input_set

    assert len(deriv_vars) == len(init_deriv_set)
    for v in deriv_vars:
        assert v[0] in init_deriv_set

    assert len(diff_vars) == len(init_deriv_set)
    for v in diff_vars:
        assert v[0] in init_diff_set

    assert len(fixed_vars) == len(init_fixed_set)
    for v in fixed_vars:
        assert v[0] in init_fixed_set

    assert len(alg_vars) == len(init_alg_set)
    for v in alg_vars:
        assert v[0] in init_alg_set

    assert len(meas_vars) == len(init_meas_set)
    for v in meas_vars:
        assert v[0] in init_meas_set

    assert len(scalar_vars) == 0
Ejemplo n.º 7
0
def test_categorize_2():
    """
    In this instance, temperature is "measured" (used as an initial condition)
    instead of energy_holdup, conc[P] is measured instead of holdup[P],
    and accumulation[C] is measured instead of holdup[C].
    """
    model = make_model(horizon=1, ntfe=5, ntcp=2)
    time = model.fs.time
    t0 = time.first()

    material_holdup = model.fs.cstr.control_volume.material_holdup
    material_accumulation = model.fs.cstr.control_volume.material_accumulation
    energy_holdup = model.fs.cstr.control_volume.energy_holdup
    energy_accumulation = model.fs.cstr.control_volume.energy_accumulation
    conc_mol = model.fs.cstr.outlet.conc_mol

    # Specify temperature instead of energy holdup
    energy_holdup[t0, 'aq'].unfix()
    model.fs.cstr.outlet.temperature[t0].fix(300)

    # Specify C_P instead of holdup
    material_holdup[t0, 'aq', 'P'].unfix()
    conc_mol[t0, 'P'].fix(0.)

    # Specify accumulation of C instead of holdup
    # You might want to do this if you want to start at steady state,
    # but don't know the value of every variable at the steady state
    # you want to start at...
    material_holdup[t0, 'aq', 'C'].unfix()
    material_accumulation[t0, 'aq', 'C'].fix(0.)

    init_input_list = [
        model.fs.mixer.S_inlet.flow_vol[0],
        model.fs.mixer.E_inlet.flow_vol[0],
    ]
    init_input_set = ComponentSet(init_input_list)

    init_deriv_list = [
        model.fs.cstr.control_volume.energy_accumulation[0, 'aq'],
        *list(model.fs.cstr.control_volume.material_accumulation[0, 'aq', :]),
    ]
    init_deriv_set = ComponentSet(init_deriv_list)

    init_diff_list = [
        model.fs.cstr.control_volume.energy_holdup[0, 'aq'],
        *list(model.fs.cstr.control_volume.material_holdup[0, 'aq', :]),
    ]
    init_diff_set = ComponentSet(init_diff_list)

    init_fixed_list = [
        model.fs.mixer.E_inlet.temperature[0],
        model.fs.mixer.S_inlet.temperature[0],
        *list(model.fs.mixer.E_inlet.conc_mol[0, :]),
        *list(model.fs.mixer.S_inlet.conc_mol[0, :]),
        model.fs.cstr.outlet.conc_mol[0, 'Solvent'],
        model.fs.mixer.outlet.conc_mol[0, 'Solvent'],
    ]
    init_fixed_set = ComponentSet(init_fixed_list)

    init_meas_list = [
        model.fs.cstr.outlet.temperature[0],
        model.fs.cstr.control_volume.volume[0],
        model.fs.cstr.control_volume.material_holdup[0, 'aq', 'S'],
        model.fs.cstr.control_volume.material_holdup[0, 'aq', 'E'],
        model.fs.cstr.control_volume.material_holdup[0, 'aq', 'S'],
        model.fs.cstr.control_volume.material_accumulation[0, 'aq', 'C'],
        model.fs.cstr.outlet.conc_mol[0, 'P'],
    ]
    init_meas_set = ComponentSet(init_meas_list)
    # No need to remove solvent holdup here as it was not added to this list.

    init_alg_list = [
        model.fs.cstr.outlet.flow_vol[0],
        model.fs.cstr.outlet.temperature[0],
        model.fs.cstr.inlet.flow_vol[0],
        model.fs.cstr.inlet.temperature[0],
        model.fs.mixer.outlet.flow_vol[0],
        model.fs.mixer.outlet.temperature[0],
        model.fs.cstr.control_volume.volume[0],
        *list(model.fs.cstr.control_volume.properties_out[0].flow_mol_comp[:]),
        *list(model.fs.cstr.inlet.conc_mol[0, :]),
        *list(model.fs.cstr.control_volume.properties_in[0].flow_mol_comp[:]),
        *list(model.fs.cstr.control_volume.rate_reaction_generation[0,
                                                                    'aq', :]),
        *list(model.fs.mixer.mixed_state[0].flow_mol_comp[:]),
        *list(model.fs.mixer.E_inlet_state[0].flow_mol_comp[:]),
        *list(model.fs.mixer.S_inlet_state[0].flow_mol_comp[:]),
        *list(model.fs.cstr.outlet.conc_mol[0, :]),
        *list(model.fs.mixer.outlet.conc_mol[0, :]),
        *list(model.fs.cstr.control_volume.reactions[0].reaction_coef[:]),
        *list(model.fs.cstr.control_volume.reactions[0].reaction_rate[:]),
        *list(model.fs.cstr.control_volume.rate_reaction_extent[0, :]),
    ]
    init_alg_set = ComponentSet(init_alg_list)
    # solvent outlet concentrations are not algebraic variables as
    # it is fixed.
    init_alg_set.remove(model.fs.cstr.outlet.conc_mol[0, 'Solvent'])
    init_alg_set.remove(model.fs.mixer.outlet.conc_mol[0, 'Solvent'])

    scalar_vars, dae_vars = flatten_dae_components(model, time, ctype=Var)
    category_dict = categorize_dae_variables(dae_vars, time, init_input_list)

    input_vars = category_dict[VC.INPUT]
    diff_vars = category_dict[VC.DIFFERENTIAL]
    deriv_vars = category_dict[VC.DERIVATIVE]
    fixed_vars = category_dict[VC.FIXED]
    alg_vars = category_dict[VC.ALGEBRAIC]
    meas_vars = category_dict[VC.MEASUREMENT]

    assert len(input_vars) == len(init_input_set)
    for v in input_vars:
        assert v[0] in init_input_set

    assert len(deriv_vars) == len(init_deriv_set)
    for v in deriv_vars:
        assert v[0] in init_deriv_set

    assert len(diff_vars) == len(init_deriv_set)
    for v in diff_vars:
        assert v[0] in init_diff_set

    assert len(fixed_vars) == len(init_fixed_set)
    for v in fixed_vars:
        assert v[0] in init_fixed_set

    assert len(alg_vars) == len(init_alg_set)
    for v in alg_vars:
        assert v[0] in init_alg_set

    assert len(meas_vars) == len(init_meas_set)
    for v in meas_vars:
        assert v[0] in init_meas_set

    assert len(scalar_vars) == 0
Ejemplo n.º 8
0
    def _construct(self):
        """ Generates time-indexed references and categorizes them. """
        model = self.mod
        time = self.time
        try:
            inputs = self._inputs
        except AttributeError:
            inputs = self._inputs = None
        try:
            measurements = self._measurements
        except AttributeError:
            measurements = self._measurements = None

        # TODO: Give the user the option to provide their own
        # category_dict (they know the structure of their model
        # better than I do...)
        if self._category_dict is not None:
            category_dict = self.category_dict = self._category_dict
            if (VC.INPUT not in category_dict and inputs is not None):
                self.category_dict[VC.INPUT] = inputs
            if (VC.MEASUREMENT not in category_dict
                    and measurements is not None):
                self.category_dict[VC.MEASUREMENT] = measurements
            self.dae_vars = []
            for categ, varlist in category_dict.items():
                if categ is not VC.MEASUREMENT:
                    # Assume that measurements are duplicates
                    self.dae_vars.extend(varlist)

        else:
            scalar_vars, dae_vars = flatten_dae_components(
                model,
                time,
                ctype=Var,
            )
            self.scalar_vars = scalar_vars
            self.dae_vars = dae_vars
            category_dict = categorize_dae_variables(
                dae_vars,
                time,
                inputs,
                measurements=measurements,
            )
            self.category_dict = category_dict

        keys = list(category_dict)
        for categ in keys:
            if not category_dict[categ]:
                # Empty categories cause problems for us down the road
                # due empty (unknown dimension) slices.
                category_dict.pop(categ)

        self._add_category_blocks()
        self._add_category_references()

        self.categories = set(category_dict)

        # Now that we don't rely on knowing what the categories
        # will be, we do not need these attributes. They are, however,
        # used in the tests, so for now, we add them if possible.
        if VC.DIFFERENTIAL in category_dict:
            self.differential_vars = category_dict[VC.DIFFERENTIAL]
        if VC.ALGEBRAIC in category_dict:
            self.algebraic_vars = category_dict[VC.ALGEBRAIC]
        if VC.DERIVATIVE in category_dict:
            self.derivative_vars = category_dict[VC.DERIVATIVE]
        if VC.INPUT in category_dict:
            self.input_vars = category_dict[VC.INPUT]
        if VC.FIXED in category_dict:
            self.fixed_vars = category_dict[VC.FIXED]
        if VC.MEASUREMENT in category_dict:
            self.measurement_vars = category_dict.pop(VC.MEASUREMENT)

        # The categories in category_dict now form a partition of the
        # time-indexed variables. This is necessary to have a well-defined
        # vardata map, which maps each vardata to a unique component indexed
        # only by time.

        # Maps each vardata (of a time-indexed var) to the NmpcVar
        # that contains it.
        self.vardata_map = ComponentMap(
            (var[t], var)
            for var in self.component_objects(SubclassOf(NmpcVar))
            #for varlist in category_dict.values()
            #for var in varlist
            for t in time if var.ctype is not MeasuredVar)
        # NOTE: looking up var[t] instead of iterating over values()
        # appears to be ~ 5x faster

        # These should be overridden by a call to `set_sample_time`
        # The defaults assume that the entire model is one sample.
        self.sample_points = [time.first(), time.last()]
        self.sample_point_indices = [1, len(time)]