Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1D Membrane Model for CO2 Capture and Utilization #1378

Open
wants to merge 42 commits into
base: main
Choose a base branch
from

Conversation

Morgan88888888
Copy link
Member

Summary/Motivation:

There is a new project ongoing to support NETL's reactive capture technology. The goal of this work is to integrate CO2-selective polymer membranes with electrochemical conversion to efficiently transform captured CO2 into formic acid. The unit and flowsheet models developed in the field of capturing and utilizing CO2 during this project will be maintained in this repository. These models will benefit other ongoing work, such as membrane design and process configuration optimization.

Changes proposed in this PR:

  • Created the workspace for ongoing CO2 Capture and Utilization modeling efforts to support NETL's reactive capture technology.
  • Developed a one-dimensional membrane model for CO2 capture.
  • Developed the model testing for 1D membrane model

Legal Acknowledgement

By contributing to this software project, I agree to the following terms and conditions for my contribution:

  1. I agree my contributions are submitted under the license terms described in the LICENSE.txt file at the top level of this directory.
  2. I represent I am authorized to make the contributions and grant the license. If my employer has rights to intellectual property that includes these contributions, I represent that I have received permission to make contributions and grant the required license on behalf of that employer.

@Morgan88888888 Morgan88888888 added models_extra Issues related to models in models_extra folder. CCU ongoing CO2 capture and utilization project labels Mar 19, 2024
@Morgan88888888 Morgan88888888 self-assigned this Mar 19, 2024
Copy link
Member

@andrewlee94 andrewlee94 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is a first batch of comments. Most are minor things and ways to do things better, and otherwise what I have seen so far looks good.

Some general comments are:

  1. Fix all the pylint issues (either by running pylint yourself or looking throguh the notifications here on GitHub).
  2. Fix the tests so that they run.
  3. We will also need some basic documentation to merge this PR.

@ksbeattie ksbeattie added the Priority:Normal Normal Priority Issue or PR label Mar 21, 2024
Copy link

codecov bot commented Mar 29, 2024

Codecov Report

Attention: Patch coverage is 82.75862% with 15 lines in your changes are missing coverage. Please review.

Project coverage is 77.63%. Comparing base (c09433b) to head (f6dc03b).
Report is 2 commits behind head on main.

Files Patch % Lines
...capture_and_utilization/unit_models/membrane_1d.py 82.55% 7 Missing and 8 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1378      +/-   ##
==========================================
+ Coverage   77.60%   77.63%   +0.02%     
==========================================
  Files         391      393       +2     
  Lines       64333    64462     +129     
  Branches    14245    14272      +27     
==========================================
+ Hits        49926    50042     +116     
- Misses      11831    11841      +10     
- Partials     2576     2579       +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Member

@andrewlee94 andrewlee94 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A number of comments. A few other things:

  1. There are a lot of lines of code that are not covered by tests (mostly things like different combinations of configurations). Whilst not required for models_extra, I would strongly encourage you to do at least minimal testing of the different configurations to ensure they at least build successfully.
  2. You do not have the methods required to support the report and stream table functionality (and thus the visualizer). Whilst again not critical, they would be a good thing to include for usability.
  3. You need to include some basic documentation. At a minimum of explaining what these models are for, the key equations and what degrees of freedom the user should set (this is especially important given my comment about selectivity).

One-dimensional membrane class for CO2 gas separation
"""

# pylint: disable=unused-import
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this being disabled? Enum is being used, so there should not be a warning issued by this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, why is this disabled? This implies you have an unused import which should be removed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is disabled to pass the pylint test.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You miss my point. I am asking why you are disabling the test, as you generally should not turn off pytest checks.

self.selectivity = Var(
self.flowsheet().time,
self.mscontactor.elements,
self.mscontactor.feed_side.component_list,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need the full factorial combination of these? I suspect you do not need the combination where both components are the same, and that S[i, j] == 1/S[j, i]. Looking below, I think this is confirmed by the following constraint.

Thus, my question becomes how do you intend for a user to use these? If a user were to naively fix all the selectivity, then the problem would be over-specified.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are you handling the possible over-specification here?

@andrewlee94
Copy link
Member

Also, Sphinx is complaining about a doc string in you model. I think you need to add a line break at the end of line 57 in you model.

@ksbeattie
Copy link
Member

@Morgan88888888 any update on this?

@Morgan88888888
Copy link
Member Author

Based on the feedback, several major improvements have been made:

Documentation has been added to provide better model explanations.
Improved support for multi-property package applications.
Enhanced testing to cover various configurations.
Added functions to report stream tables.

@Morgan88888888 Morgan88888888 reopened this Nov 5, 2024
@Morgan88888888
Copy link
Member Author

Also, Sphinx is complaining about a doc string in you model. I think you need to add a line break at the end of line 57 in you model.

A line break has been added, and more documentation has been included.

Copy link
Member

@andrewlee94 andrewlee94 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A number of comments on some edge cases and a few outstanding issues.

One-dimensional membrane class for CO2 gas separation
"""

# pylint: disable=unused-import
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, why is this disabled? This implies you have an unused import which should be removed.


self.permeance = Var(
self.flowsheet().time,
self.mscontactor.elements,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens here if the two property packages have different components? Should this instead use the intersection of the two component lists (which is easy to do)?

self.mscontactor.elements,
self.mscontactor.feed_side.component_list,
initialize=1,
doc="Values in Gas Permeance Unit(GPU)",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing space "Unit (GPU)"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

doc=" This is a coefficient that will convert the unit of permeability from GPU to SI units for further calculation",
)

"""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pylint complains about this - general practice is to do this as single line comments (i.e. use #).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed by using #

self.selectivity = Var(
self.flowsheet().time,
self.mscontactor.elements,
self.mscontactor.feed_side.component_list,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are you handling the possible over-specification here?

return (
self.permeance[t, e, a] * self.selectivity[t, e, a, b]
== self.permeance[t, e, b]
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like it results in an over-specified problem. You write a constraint for a, b and b, a which are reflections of each other. If the user specifies all the selectivities they will have a degree of freedom issue.

I think you really need to only cover the unique pairs (and exclude a=b).


p_units = feed_side_units.PRESSURE

crossover_component_list = list(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you needed this earlier. It might also be a good idea to attach this ot the model to save Pyomo replicating this every time you use it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved and used for permeance as well

self.mscontactor.elements,
doc="Energy balance",
)
def energy_transfer(self, t, s):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For clarity, I would call this an isothermal constraint. It is not an energy balance.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also suggest changing the name of the constraint (i.e. the name of the rule/function).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

{
"Feed Inlet": self.feed_side_inlet,
"Feed Outlet": self.feed_side_outlet,
"Permeate Inlet": self.sweep_side_inlet,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need logic here to handle cases where the sweep stream is not present.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

@andrewlee94
Copy link
Member

@Morgan88888888 Please of not mark issues as resolved unless they are minor typo corrections. Reviewers need to be able to look over the issues and ensure that they have been addressed.

@andrewlee94
Copy link
Member

@Morgan88888888 Also, this PR still needs to have at least basic documentation before it can be merged.

@Morgan88888888
Copy link
Member Author

@andrewlee94 I have addressed your comments. I changed the model input to require permeance for all components across the membrane, and basic documentation has been added.

Copy link
Member

@andrewlee94 andrewlee94 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few more minor things.

self.mscontactor.elements,
doc="Energy balance",
)
def energy_transfer(self, t, s):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also suggest changing the name of the constraint (i.e. the name of the rule/function).

)

# Check unit config arguments
print("=====================================================")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should remove these print statements for the tests.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

can be connected for this application. The two sides of the membrane are called the feed side
and sweep side. The sweep stream inlet is optional. The driving force across the membrane is the
partial pressure difference in this gas separation application. Additionally, the energy balance
assumes that temperature remains constant on each side of the membrane.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments here:

  1. Reference guides should be entirely autogenerated using Sphinx. Any thing that is hand written really should be an explanation (they go else where in the docs structure).
  2. It would be good to have a short code example here, or a discussion of what the inputs/degrees of freedom are. This will help users understand what information they should be supplying.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks and more info about model inputs/degrees of freedom are added.

Copy link
Member

@andrewlee94 andrewlee94 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more minor comment for now. Otherwise I am just waiting to see that the tests all pass (so I suggest you not push any changes until they finish).

* Feed flowrate - :math:`F_fr`
* Feed compositions - :math:`x`
* Feed pressure - :math:`P`
* Feed temperature - :math:`T`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should selectivity be here, or is that calculated from permeances?

Also, should there be mention of sweep conditions here too?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! The selectivity could be calculated and sweep condition is mentioned in the beginning.

Copy link
Member

@andrewlee94 andrewlee94 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pending fixing the final test failure, I think this is OK.

@codecov-commenter
Copy link

codecov-commenter commented Nov 6, 2024

Codecov Report

Attention: Patch coverage is 83.75000% with 13 lines in your changes missing coverage. Please review.

Project coverage is 77.05%. Comparing base (7eac461) to head (d44f95e).

Files with missing lines Patch % Lines
...capture_and_utilization/unit_models/membrane_1d.py 83.54% 9 Missing and 4 partials ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1378   +/-   ##
=======================================
  Coverage   77.05%   77.05%           
=======================================
  Files         384      386    +2     
  Lines       62335    62415   +80     
  Branches    10222    10230    +8     
=======================================
+ Hits        48031    48095   +64     
- Misses      11875    11888   +13     
- Partials     2429     2432    +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@lbianchi-lbl lbianchi-lbl added the CI:run-integration triggers_workflow: Integration label Nov 14, 2024
@idaes-build idaes-build removed the CI:run-integration triggers_workflow: Integration label Nov 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CCU ongoing CO2 capture and utilization project models_extra Issues related to models in models_extra folder. Priority:Normal Normal Priority Issue or PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants