diff --git a/idaes/core/base/flowsheet_model.py b/idaes/core/base/flowsheet_model.py index b9ff3a63ca..d5a3b82acf 100644 --- a/idaes/core/base/flowsheet_model.py +++ b/idaes/core/base/flowsheet_model.py @@ -139,7 +139,7 @@ class FlowsheetBlockData(ProcessBlockData): CONFIG.declare( "time_set", ConfigValue( - default=[0], + default=None, domain=ListOf(float), description="Set of points for initializing time domain", doc="""Set of points for initializing time domain. This should be a @@ -287,6 +287,31 @@ def _get_stream_table_contents(self, time_point=0): return self.stream_table(time_point) def _setup_dynamics(self): + def _create_time_domain(): + if self.config.dynamic: + # Check if time_set has at least two points + if len(self.config.time_set) < 2: + # Check if time_set is at default value + if self.config.time_set == [0.0]: + # If default, set default end point to be 1.0 + self.config.time_set = [0.0, 1.0] + else: + # Invalid user input, raise Exception + raise DynamicError( + "Flowsheet provided with invalid " + "time_set attribute - must have at " + "least two values (start and end)." + ) + # For dynamics, need a ContinuousSet + self._time = ContinuousSet(initialize=self.config.time_set) + else: + # For steady-state, use an ordered Set + self._time = pe.Set(initialize=self.config.time_set, ordered=True) + self._time_units = self.config.time_units + + # Set time config argument as reference to time domain + self.config.time = self._time + # Look for parent flowsheet fs = self.flowsheet() @@ -342,35 +367,21 @@ def _setup_dynamics(self): "{} was set as a dynamic flowsheet, but time domain " "provided was not a ContinuousSet.".format(self.name) ) + add_object_reference(self, "_time", self.config.time) self._time_units = self.config.time_units else: # If no parent flowsheet, set up time domain if fs is None: + # Set default time_set to [0] if not provided + if self.config.time_set is None: + self.config.time_set = [0] # Create time domain - if self.config.dynamic: - # Check if time_set has at least two points - if len(self.config.time_set) < 2: - # Check if time_set is at default value - if self.config.time_set == [0.0]: - # If default, set default end point to be 1.0 - self.config.time_set = [0.0, 1.0] - else: - # Invalid user input, raise Exception - raise DynamicError( - "Flowsheet provided with invalid " - "time_set attribute - must have at " - "least two values (start and end)." - ) - # For dynamics, need a ContinuousSet - self._time = ContinuousSet(initialize=self.config.time_set) - else: - # For steady-state, use an ordered Set - self._time = pe.Set(initialize=self.config.time_set, ordered=True) - self._time_units = self.config.time_units - - # Set time config argument as reference to time domain - self.config.time = self._time + _create_time_domain() + # Creates a new time domain for a sub-flowsheet with user provided time domain + elif self.config.time_set is not None: + # Create time domain from config.time_set + _create_time_domain() else: # Set time config argument to parent time self.config.time = fs.time diff --git a/idaes/core/base/tests/test_flowsheet_model.py b/idaes/core/base/tests/test_flowsheet_model.py index dfbb581375..87299ee5f1 100644 --- a/idaes/core/base/tests/test_flowsheet_model.py +++ b/idaes/core/base/tests/test_flowsheet_model.py @@ -55,7 +55,7 @@ def test_config(self, model): assert len(model.fs.config) == 5 assert model.fs.config.dynamic is useDefault assert model.fs.config.time is None - assert model.fs.config.time_set == [0] + assert model.fs.config.time_set == None assert model.fs.config.default_property_package is None assert model.fs.config.time_units is None @@ -400,6 +400,40 @@ def test_dynamic_external_time(self): assert m.fs.sub.config.time is m.s assert m.fs.sub.time_units == units.minute + @pytest.mark.unit + def test_dynamic_nested_time(self): + m = ConcreteModel() + m.s1 = ContinuousSet(initialize=[4, 5]) + m.s2 = ContinuousSet(initialize=[1, 2, 3]) + m.fs = FlowsheetBlock(dynamic=True, time=m.s1, time_units=units.minute) + m.fs.sub = FlowsheetBlock(dynamic=True, time=m.s2, time_units=units.s) + + assert m.fs.sub.config.dynamic is True + assert m.fs.sub.time is m.s2 + assert m.fs.sub.time_units == units.s + + @pytest.mark.unit + def test_dynamic_nested_time_from_time_set(self): + m = ConcreteModel() + m.fs = FlowsheetBlock(dynamic=True, time_set=[1, 2, 3], time_units=units.s) + m.fs.sub = FlowsheetBlock(dynamic=True, time_set=[1, 2], time_units=units.s) + + assert m.fs.sub.config.dynamic is True + assert isinstance(m.fs.sub.time, ContinuousSet) + assert list(m.fs.sub.time) == [1, 2] + assert m.fs.sub.time_units is units.s + + @pytest.mark.unit + def test_dynamic_parent_time_indexed_ss_child(self): + m = ConcreteModel() + m.fs = FlowsheetBlock(dynamic=True, time_set=[1, 2, 3], time_units=units.s) + m.fs.sub = FlowsheetBlock(dynamic=False, time_set=[0, 1], time_units=units.min) + + assert m.fs.sub.config.dynamic is False + assert isinstance(m.fs.sub.time, Set) + assert list(m.fs.sub.time) == [0, 1] + assert m.fs.sub.time_units == units.min + @pytest.mark.unit def test_dynamic_external_time_invalid(self): m = ConcreteModel()