diff --git a/idaes/core/util/model_statistics.py b/idaes/core/util/model_statistics.py index 7aacfd2b70..99cb7b315e 100644 --- a/idaes/core/util/model_statistics.py +++ b/idaes/core/util/model_statistics.py @@ -403,6 +403,7 @@ def number_grey_box_equalities(block) -> int: block, ctype=ExternalGreyBoxBlock, active=True, descend_into=True ): equalities += len(grey_box.outputs) + equalities += grey_box.get_external_model().n_equality_constraints() return equalities @@ -555,7 +556,7 @@ def deactivated_inequalities_generator(block): block : model to be studied Returns: - A generator which returns all in deactivated equality Constraint + A generator which returns all deactivated equality Constraint components block """ for c in total_inequalities_generator(block): @@ -1060,22 +1061,78 @@ def unfixed_variables_in_activated_equalities_set(block): for v in variables_in_activated_equalities_set(block): if not v.fixed: var_set.add(v) - # Checks for greyboxes, and if they exist will add - # input and output vars to var_set if they are free - # inputs and outputs are defined names for greybox class and should always exist + for v in unfixed_greybox_variables(block): + var_set.add(v) + return var_set + + +def unfixed_greybox_variables(block): + """ + Function to return a ComponentSet of all unfixed Var in GreyBoxModels + + Args: + block : model to be studied + + Returns: + A ComponentSet including all unfixed Var components which appear within + activated equality Constraints in block + """ + var_set = ComponentSet() + for var in greybox_variables(block): + if not var.fixed: + var_set.add(var) + return var_set + + +def greybox_variables(block): + """ + Function to return a ComponentSet of all Var in GreyBoxModels + + Args: + block : model to be studied + + Returns: + A ComponentSet including all unfixed Var components which appear within + activated equality Constraints in block + """ + var_set = ComponentSet() for grey_box in _iter_indexed_block_data_objects( block, ctype=ExternalGreyBoxBlock, active=True, descend_into=True ): for in_var in grey_box.inputs: - if not grey_box.inputs[in_var].fixed: - var_set.add(grey_box.inputs[in_var]) + var_set.add(grey_box.inputs[in_var]) for out_var in grey_box.outputs: - if not grey_box.outputs[out_var].fixed: - var_set.add(grey_box.outputs[out_var]) + var_set.add(grey_box.outputs[out_var]) return var_set +def number_of_unfixed_greybox_variables(block): + """ + Function to return a number of unfixed variables in grey box + Args: + block : model to be studied + + Returns: + number of unfixed greybox variables + """ + + return len(unfixed_greybox_variables(block)) + + +def number_of_greybox_variables(block): + """ + Function to return a number of variables in grey box + Args: + block : model to be studied + + Returns: + number of greybox variables + """ + + return len(greybox_variables(block)) + + def number_unfixed_variables_in_activated_equalities(block): """ Method to return the number of unfixed Var components which appear within diff --git a/idaes/core/util/tests/test_model_statistics.py b/idaes/core/util/tests/test_model_statistics.py index 48bce9683c..7085323ea7 100644 --- a/idaes/core/util/tests/test_model_statistics.py +++ b/idaes/core/util/tests/test_model_statistics.py @@ -693,7 +693,8 @@ def test_degrees_of_freedom(m): def test_degrees_of_freedom_with_graybox(): """non functional graybox model added to m fixture, to test DOFs - GreyBoxModel has 3 inputs and 2 outputs calculated an unknown function""" + GreyBoxModel has 3 inputs and 2 outputs calculated an unknown function, + input a1 and a2 are bound by equality constraint through internal graybox model""" class BasicGrayBox(ExternalGreyBoxModel): def input_names(self): @@ -702,12 +703,26 @@ def input_names(self): def output_names(self): return ["o1", "o2"] + def equality_constraint_names(self): + return ["a_sum"] + + def evaluate_equality_constraints(self): + a1 = self._input_values[0] + a2 = self._input_values[1] + return [a1 * 0.5 + a2] + m = ConcreteModel() m.gb = ExternalGreyBoxBlock(external_model=BasicGrayBox()) + # test counting functions + assert number_of_greybox_variables(m) == 5 + assert number_of_unfixed_greybox_variables(m) == 5 + assert number_grey_box_equalities(m) == 3 # verify DOFS works on stand alone greybox - assert degrees_of_freedom(m) == 3 + assert degrees_of_freedom(m) == 2 m.gb.inputs.fix() + m.gb.inputs["a1"].unfix() + assert number_of_unfixed_greybox_variables(m) == 3 assert degrees_of_freedom(m) == 0 m.gb.outputs.fix() assert degrees_of_freedom(m) == -2 @@ -716,7 +731,7 @@ def output_names(self): # verify DOFs works on greybox connected to other vars on a model via constraints m.a1 = Var(initialize=1) m.a1.fix() - m.gb.inputs["a1"].unfix() + m.gb.inputs["a2"].unfix() m.a1_eq = Constraint(expr=m.a1 == m.gb.inputs["a1"]) assert degrees_of_freedom(m) == 0 m.o1 = Var(initialize=1)