Skip to content

Params indexed by ContinuousSets are not initialized when the set is discretized. #4009

Description

@dallan-keylogic

Summary

When a Param is indexed by a ContinuousSet and that ContinuousSet is discretize, the Param is not initialized on the new indices created. If the Param is mutable and initialized at some value, I would expect the new ParamData to be initialized at the same value. If it's not mutable, then I'd expect either indexing it by a ContinuousSet or discretizing that ContinuousSet to fail.

Steps to reproduce the issue

import pyomo.environ as pyo
from pyomo.dae import DerivativeVar, ContinuousSet

m = pyo.ConcreteModel()
m.time = ContinuousSet(initialize=[0,1])
m.x = pyo.Var(m.time, initialize=0)
m.y = pyo.Param(m.time, mutable=True, initialize=0)

discretizer = pyo.TransformationFactory("dae.finite_difference")
discretizer.apply_to(m, nfe=4, wrt=m.time, scheme="BACKWARD")

print(f"x[0.25] = {m.x[0.25].value}")
print(f"y[0.25] = {m.y[0.25].value}")

Error Message

x[0.25] = 0
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[2], line 13
     10 discretizer.apply_to(m, nfe=4, wrt=m.time, scheme="BACKWARD")
     12 print(f"x[0.25] = {m.x[0.25].value}")
---> 13 print(f"y[0.25] = {m.y[0.25].value}")

File ~\miniforge3\envs\idaes-fresh\Lib\site-packages\pyomo\core\base\param.py:230, in ParamData.value(self)
    227 @property
    228 def value(self):
    229     """Return the value for this variable."""
--> 230     return self()

File ~\miniforge3\envs\idaes-fresh\Lib\site-packages\pyomo\core\base\param.py:217, in ParamData.__call__(self, exception)
    215 if self._value is Param.NoValue:
    216     if exception:
--> 217         raise ValueError(
    218             "Error evaluating Param value (%s):\n\tThe Param value is "
    219             "currently set to an invalid value.  This is\n\ttypically "
    220             "from a scalar Param or mutable Indexed Param without\n"
    221             "\tan initial or default value." % (self.name,)
    222         )
    223     else:
    224         return None

ValueError: Error evaluating Param value (y[0.25]):
        The Param value is currently set to an invalid value.  This is
        typically from a scalar Param or mutable Indexed Param without
        an initial or default value

Application and Workaround

As part of a larger IDAES model, I want a time-derivative term to exist regardless of whether the system is steady-state or dynamic. If it's steady-state, I want it to be a Param set to 0:

        if self.config.dynamic is True:
            self.dTdt = DerivativeVar(
                self.drum_wall_temperature, wrt=self.flowsheet().time
            )
        else:
            self.dTdt = Param(
                self.flowsheet().time,
                self.dimensionless_radial_domain,
                initialize=0,
                mutable=True
            )

A workaround is to use an Expression instead of a Param:

        if self.config.dynamic is True:
            self.dTdt = DerivativeVar(
                self.drum_wall_temperature, wrt=self.flowsheet().time
            )
        else:
            @self.Expression(self.flowsheet().time, self.dimensionless_radial_domain)
            def dTdt(b, t, r):
                return 0 

Information on your system

Pyomo version: 6.10.1
Python version: 3.13.14
Operating system: Windows 11
How Pyomo was installed (PyPI, conda, source): IDAES developer installation
Solver (if applicable): n/a

Additional information

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions