IDAES / idaes-pse

The IDAES Process Systems Engineering Framework
https://idaes-pse.readthedocs.io/
Other
206 stars 228 forks source link

FlowsheetBlock TypeError #1422

Closed fahim831 closed 1 month ago

fahim831 commented 1 month ago

I installed WaterTAP, and IDAES was installed as part of it. I was using WaterTAP for a few weeks without issues. I tried to run an IDAES example today, specifically this small example. But I had an error in the line loading the FlowsheetBlock. I was confused because loading the same FlowsheetBlock line works in all my WaterTAP codes. So I tried installing the latest IDAES version in my environment, which then broke WaterTAP as well.

I tried making a new environment for IDAES and installed it by itself using conda in this environment. The example still isn't running and I'm getting an error, though slightly different error (did not keep a copy of the previous error unfortunately). Any assistance appreciated.

OS: macOS 14.5 Python version: 3.12.3 Pyomo version: 6.7.3 idaes-pse version: 2.4.0

Error message:

Traceback (most recent call last):
  File "/Users/$USER/water_tank_idaes_eg.py", line 39, in <module>
    m.fs = FlowsheetBlock(
           ^^^^^^^^^^^^^^^
  File "/Users/$USER/anaconda3/envs/my-idaes-env/lib/python3.12/site-packages/idaes/core/base/process_block.py", line 165, in __new__
    n = _ScalarProcessBlockMeta(bname, (cls._ComponentDataClass, cls), {})
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/$USER/anaconda3/envs/my-idaes-env/lib/python3.12/site-packages/idaes/core/base/process_block.py", line 133, in __new__
    return type.__new__(mcs, name, bases, dct)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
jsiirola commented 1 month ago

You need to downgrade Pyomo to 6.7.1. Pyomo 6.7.2 changed the name of a core class (_BlockData -> BlockData), and the backwards compatibility logic used in Pyomo turns out to not be compatible with IDAES's declare_process_block logic (resulting in the metaclass error you are seeing). IDAES/main has been updated to work with the new Pyomo release, and the next IDAES release (due out very soon) will work with / require Pyomo 6.7.3.

lbianchi-lbl commented 1 month ago

Hi @fahim831, this is a known issue due to an incompatibility between IDAES 2.4.0 and Pyomo 6.7.2+ (on the WaterTAP side, see watertap-org/watertap#1382 and watertap-org/watertap#1393). The issue has been resolved in this repository since #1402 was merged, and I'm literally now in the process of cutting a new release of IDAES that will have these changes.

You should be able to resolve this error by running either of these commands after activating your environment:

# option #1: install IDAES 2.5 release candidate
pip install idaes-pse==2.5.0rc0
# option #2: install IDAES from the main branch of IDAES/idaes-pse
pip install "git+https://github.com/IDAES/idaes-pse@main"
fahim831 commented 1 month ago

Thank you, @jsiirola and @lbianchi-lbl. I used option #1 and both examples run now.

By the way, I had initially tried to run the examples from here. However, they weren't working but I managed to make them work by changing the import lines slightly, specifically

from idaes.power_generation.unit_models.helm import HelmTurbineInletStage
from idaes.generic_models.properties import iapws95

to

from idaes.models_extra.power_generation.unit_models.helm import HelmTurbineInletStage
from idaes.models.properties import iapws95 

I guess that site isn't maintained and we should just use the ones in https://idaes-pse.readthedocs.io/en/2.4.0/reference_guides/model_libraries/power_generation/unit_models/turbine_inlet.html ?

lbianchi-lbl commented 1 month ago

Thank you, @jsiirola and @lbianchi-lbl. I used option #1 and both examples run now.

By the way, I had initially tried to run the examples from here. However, they weren't working but I managed to make them work by changing the import lines slightly, specifically

from idaes.power_generation.unit_models.helm import HelmTurbineInletStage
from idaes.generic_models.properties import iapws95

to

from idaes.models_extra.power_generation.unit_models.helm import HelmTurbineInletStage
from idaes.models.properties import iapws95 

I guess that site isn't maintained and we should just use the ones in https://idaes-pse.readthedocs.io/en/2.4.0/reference_guides/model_libraries/power_generation/unit_models/turbine_inlet.html ?

That's correct, the first link refers to IDAES 1.12 which is several years old at this point. Generally the ReadTheDocs page URL will contain the version (such as 2.4.0 in https://idaes-pse.readthedocs.io/en/2.4.0/reference_guides/model_libraries/power_generation/unit_models/turbine_inlet.html) that you can use to ensure it matches the version of the Python package you have installed.

fahim831 commented 1 month ago

Sorry to reopen the case. Both codes were working OK and now, after a few minutes (the most I might have done is reopen Terminal), suddenly it's back to the previous state where my WaterTAP codes run but IDAES ones don't, despite the former using FlowsheetBlock as well. I've copied the error I'm getting on the IDAES examples below. I think since it's still in the same function, it is best to keep it in the same thread but you can change it to a new thread if you think that is better.

2024-05-31 17:03:47 [ERROR] idaes.core.base.process_block: Failure in build: fs
Traceback (most recent call last):
  File "/Users/$USER/anaconda3/envs/watertap-dev/lib/python3.12/site-packages/idaes/core/base/process_block.py", line 41, in _rule_default
    b.build()
  File "/Users/$USER/anaconda3/envs/watertap-dev/lib/python3.12/site-packages/idaes/core/base/flowsheet_model.py", line 187, in build
    super(FlowsheetBlockData, self).build()
  File "/Users/$USER/anaconda3/envs/watertap-dev/lib/python3.12/site-packages/idaes/core/base/process_base.py", line 129, in build
    self._get_config_args()
  File "/Users/$USER/anaconda3/envs/watertap-dev/lib/python3.12/site-packages/idaes/core/base/process_base.py", line 250, in _get_config_args
    self.config = self.CONFIG(kwargs)
                  ^^^^^^^^^^^^^^^^^^^
  File "/Users/$USER/anaconda3/envs/watertap-dev/lib/python3.12/site-packages/pyomo/common/config.py", line 1789, in __call__
    ans.set_value(value)
  File "/Users/$USER/anaconda3/envs/watertap-dev/lib/python3.12/site-packages/pyomo/common/config.py", line 2722, in set_value
    raise ValueError(
ValueError: key 'default' not defined for ConfigDict '' and implicit (undefined) keys are not allowed
ERROR: Constructing component 'fs' from data=None failed:
        ValueError: key 'default' not defined for ConfigDict '' and implicit
        (undefined) keys are not allowed
Traceback (most recent call last):
  File "/Users/$USER/watertap/watertap/swro1d/water_tank_idaes_eg.py", line 36, in <module>
    m.fs = FlowsheetBlock(default={"dynamic": False})
    ^^^^
  File "/Users/$USER/anaconda3/envs/watertap-dev/lib/python3.12/site-packages/pyomo/core/base/block.py", line 571, in __setattr__
    self.add_component(name, val)
  File "/Users/$USER/anaconda3/envs/watertap-dev/lib/python3.12/site-packages/pyomo/core/base/block.py", line 1116, in add_component
    val.construct(data)
  File "/Users/$USER/anaconda3/envs/watertap-dev/lib/python3.12/site-packages/pyomo/core/base/block.py", line 2173, in construct
    self._getitem_when_not_present(_idx)
  File "/Users/$USER/anaconda3/envs/watertap-dev/lib/python3.12/site-packages/pyomo/core/base/block.py", line 2088, in _getitem_when_not_present
    obj = self._rule(_block, idx)
          ^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/$USER/anaconda3/envs/watertap-dev/lib/python3.12/site-packages/pyomo/core/base/initializer.py", line 316, in __call__
    return self._fcn(parent, idx)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/$USER/anaconda3/envs/watertap-dev/lib/python3.12/site-packages/idaes/core/base/process_block.py", line 41, in _rule_default
    b.build()
  File "/Users/$USER/anaconda3/envs/watertap-dev/lib/python3.12/site-packages/idaes/core/base/flowsheet_model.py", line 187, in build
    super(FlowsheetBlockData, self).build()
  File "/Users/$USER/anaconda3/envs/watertap-dev/lib/python3.12/site-packages/idaes/core/base/process_base.py", line 129, in build
    self._get_config_args()
  File "/Users/$USER/anaconda3/envs/watertap-dev/lib/python3.12/site-packages/idaes/core/base/process_base.py", line 250, in _get_config_args
    self.config = self.CONFIG(kwargs)
                  ^^^^^^^^^^^^^^^^^^^
  File "/Users/$USER/anaconda3/envs/watertap-dev/lib/python3.12/site-packages/pyomo/common/config.py", line 1789, in __call__
    ans.set_value(value)
  File "/Users/$USER/anaconda3/envs/watertap-dev/lib/python3.12/site-packages/pyomo/common/config.py", line 2722, in set_value
    raise ValueError(
ValueError: key 'default' not defined for ConfigDict '' and implicit (undefined) keys are not allowed
andrewlee94 commented 1 month ago

@fahim831 That is a separate issue caused by using code from IDAES v1.x. One of the changes we made when moving from IDAES v1 to v2 was to remove the need for the default argument - now you just pass the contents of the old default dict as keywords when constructing IDAES components.

fahim831 commented 1 month ago

I see. I did copy the code from the v1.x site and not removed the default argument. It works now. Thanks!