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

Costing Unification: move from factor_total_investment to TIC #1175

Merged
merged 10 commits into from
Dec 7, 2023

Conversation

bknueven
Copy link
Contributor

Fixes/Resolves: Part 1 of 3 for #1134

Summary/Motivation:

The two costing packages have different ways of accounting for indirect capital costs. The ZO Costing Package allows the indirect capital cost to be specified per unit model. The WT Costing Package has a global-level indirect capital cost.

This PR would resolve the conflict in favor of the ZO costing package. This requires modifying WaterTAP's existing detailed model's costing methods, and a few related changes to our detailed flowsheets.

Changes proposed in this PR:

  • Move TIC / TPEC factor calculation to the costing base class
  • Add TIC factor to all unit models which do not already have a factor
  • Specify a default o 2 for TIC when used in the WT Costing Package
  • Make factor_total_investment have a default value of 1 in the WT Costing Package
  • Various changes to detailed flowsheets to reproduce existing results.
  • Set automatic scaling factors on unit model costing aggregates to resolve some resulting detailed flowsheet instability (in particular, NF and LSRRO).

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.

@codecov
Copy link

codecov bot commented Oct 19, 2023

Codecov Report

Attention: 2 lines in your changes are missing coverage. Please review.

Comparison is base (a88cf2f) 94.78% compared to head (8b34ef1) 94.77%.

Files Patch % Lines
watertap/costing/costing_base.py 90.47% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1175      +/-   ##
==========================================
- Coverage   94.78%   94.77%   -0.02%     
==========================================
  Files         356      356              
  Lines       35526    35553      +27     
==========================================
+ Hits        33675    33696      +21     
- Misses       1851     1857       +6     

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

@ksbeattie ksbeattie added the Priority:Normal Normal Priority Issue or PR label Oct 19, 2023
Copy link
Contributor

@avdudchenko avdudchenko left a comment

Choose a reason for hiding this comment

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

This looks good to me.

@bknueven bknueven force-pushed the factor_total_investment_to_TIC branch 2 times, most recently from d8e8656 to 73878be Compare October 27, 2023 15:53
blk.capital_cost_constraint = pyo.Constraint(
expr=blk.capital_cost
== pyo.units.convert(
== blk.cost_factor
Copy link
Contributor

Choose a reason for hiding this comment

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

There is currently a total_installed_cost_factor with value of 1.65 used in capital costs for IX that I had included before there was a global TIC. That should be removed entirely and use the global variable to not be double counting.

Copy link
Contributor

Choose a reason for hiding this comment

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

Of course whatever you decide to do it will cause the IX test to fail.

@@ -336,9 +336,11 @@ def cost_ion_exchange(blk):
to_units=blk.costing_package.base_currency,
)
)
blk.costing_package.add_cost_factor(blk, "TIC")
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
blk.costing_package.add_cost_factor(blk, "TIC")
blk.costing_package.add_cost_factor(blk, None)

I suppose we could also just use the local IX total_installed_cost_factor doing something like this? I am fine with the system TIC also and would let you make the decision.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay, thanks for catching this. I will use the system TIC and modify IX costing model appropriately.

Copy link
Contributor

@kurbansitterley kurbansitterley left a comment

Choose a reason for hiding this comment

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

There is a change needed for the ion_exchange costing model to not double count indirect costs with the use of TIC. As far as I know, that is the only unit model that had a local factor to account or indirect costs.

blk.capital_cost_constraint = pyo.Constraint(
expr=blk.capital_cost
== pyo.units.convert(
== blk.cost_factor
Copy link
Contributor

Choose a reason for hiding this comment

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

Of course whatever you decide to do it will cause the IX test to fail.

@@ -407,7 +407,7 @@ def test_costing(self, adm):
assert_optimal_termination(results)

# Check solutions
assert pytest.approx(1083290.8, rel=1e-5) == value(
assert pytest.approx(2.0 * 1083290.8, rel=1e-5) == value(
Copy link
Contributor

Choose a reason for hiding this comment

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

How does doubling the capital costs via this factor not affect LCOW? I don't see any LCOW tests changed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The factor is now part of the unit model's capital_cost variable, as opposed to being applied at the global level.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok I see.

Explanation for myself and anyone else: factor_capital_cost was set to 1 so mooted the influence of having TIC applied at the unit model level. So the value of aggregate_capital_cost, which is the sum of unit model capital_cost, didn't change; aggregate_capital_cost is used in total_capital_cost, which is used in LCOW.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For others, this change is being made to create uniformity around "where" the indirect capital cost is applied.

Right now the ZOCostingPackage does things at the unit-level, and the WaterTAPCosting package at the global-level. The PR modifies all the existing detailed models to put it at the unit-level.

@bknueven bknueven force-pushed the factor_total_investment_to_TIC branch from 73878be to 8264aae Compare November 10, 2023 23:00
@bknueven
Copy link
Contributor Author

@kurbansitterley I believe I have addressed your concerns around the ion exchange model in 8264aae.

Copy link
Contributor

@kurbansitterley kurbansitterley left a comment

Choose a reason for hiding this comment

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

LGTM

@bknueven
Copy link
Contributor Author

There are two costing PRs open, #1186 and #1196. Should this wait on those?

@adam-a-a
Copy link
Contributor

There are two costing PRs open, #1186 and #1196. Should this wait on those?

Not necessarily.

B_max=None,
number_of_RO_finite_elements=10
)
except ValueError:
Copy link
Contributor

Choose a reason for hiding this comment

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

Why was this needed? To sidestep the occasional fail related to this test or something else?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If Ipopt terminates with a weird termination condition, then Pyomo will raise a ValueError trying to load the results back into the model.

This simply catches this mode of failure. Note that if the solve fails (or succeeds) and we didn't expect it to the test will still fail.

@bknueven bknueven force-pushed the factor_total_investment_to_TIC branch 2 times, most recently from 51d6b60 to 55e1754 Compare November 13, 2023 16:55
@bknueven
Copy link
Contributor Author

@kurbansitterley could you have a look at 55e1754? I left a few things out on the previous commit...

@bknueven bknueven force-pushed the factor_total_investment_to_TIC branch from 46748f7 to 4cc952e Compare November 14, 2023 16:18
@kurbansitterley
Copy link
Contributor

@kurbansitterley could you have a look at 55e1754? I left a few things out on the previous commit...

Yes, see that. Most important change was addressed (not double counting indirect costs) and is now reflected in the tests, it appears. So my approval remains!

@bknueven bknueven force-pushed the factor_total_investment_to_TIC branch 4 times, most recently from 060d40e to 6dca9cb Compare November 20, 2023 21:24
@bknueven
Copy link
Contributor Author

bknueven commented Dec 6, 2023

This is currently held up by the failing notebook test tutorials/nawi_spring_meeting2023.ipynb.

@adam-a-a @avdudchenko any thoughts?

@bknueven bknueven force-pushed the factor_total_investment_to_TIC branch from a7f7c11 to 1c50315 Compare December 7, 2023 18:28
@bknueven bknueven force-pushed the factor_total_investment_to_TIC branch from 1c50315 to 2825670 Compare December 7, 2023 19:19
Comment on lines 460 to 471
m.fs.costing.initialize()
m.objective = Objective(expr=m.fs.costing.LCOW)
assert_units_consistent(m)
results = solver.solve(m)
results = solver.solve(m, tee=True)

assert_optimal_termination(results)

# Check solutions
assert pytest.approx(526.45 * 2, rel=1e-5) == value(
m.fs.unit.costing.capital_cost
)
assert pytest.approx(1.07948e-5, rel=1e-5) == value(m.fs.costing.LCOW)
assert pytest.approx(8.94365e-07, rel=1e-5) == value(m.fs.costing.LCOW)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@MarcusHolly can you have a look at this? It seems like this flowsheet had degrees of freedom but no objective, and therefore the LCOW could converge to an arbitrary value.

I've fixed it here to what I got out of the optimization.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sure, I can take a look at it soon, just not right now...

@bknueven bknueven force-pushed the factor_total_investment_to_TIC branch from 2825670 to 8b34ef1 Compare December 7, 2023 19:39
@bknueven
Copy link
Contributor Author

bknueven commented Dec 7, 2023

@adam-a-a should this wait on #1213? 7d33365 might be of help with that, so we might want to merge this anyways.

@adam-a-a
Copy link
Contributor

adam-a-a commented Dec 7, 2023

This is currently held up by the failing notebook test tutorials/nawi_spring_meeting2023.ipynb.

@adam-a-a @avdudchenko any thoughts?

Is this still an issue or have your latest commits resolved this?

@adam-a-a
Copy link
Contributor

adam-a-a commented Dec 7, 2023

@adam-a-a should this wait on #1213? 7d33365 might be of help with that, so we might want to merge this anyways.

I suppose this doesn't need to wait on #1213 , assuming it won't break the BSM2 flowsheet.

@bknueven
Copy link
Contributor Author

bknueven commented Dec 7, 2023

This is currently held up by the failing notebook test tutorials/nawi_spring_meeting2023.ipynb.
@adam-a-a @avdudchenko any thoughts?

Is this still an issue or have your latest commits resolved this?

No, that was fixed by 7d33365 (making LCOW an Expression)

@bknueven
Copy link
Contributor Author

bknueven commented Dec 7, 2023

@adam-a-a should this wait on #1213? 7d33365 might be of help with that, so we might want to merge this anyways.

I suppose this doesn't need to wait on #1213 , assuming it won't break the BSM2 flowsheet.

Sounds like we should wait ... I mean, it shouldn't, but I am not extraordinarily confident either.

@bknueven bknueven marked this pull request as draft December 7, 2023 20:20
@bknueven
Copy link
Contributor Author

bknueven commented Dec 7, 2023

Going to wait on #1213.

@ksbeattie ksbeattie marked this pull request as ready for review December 7, 2023 21:29
@ksbeattie ksbeattie merged commit 094da03 into watertap-org:main Dec 7, 2023
24 checks passed
hunterbarber added a commit to hunterbarber/watertap that referenced this pull request Dec 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
costing Priority:Normal Normal Priority Issue or PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants