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

enhancement: energy_loss update #11

Merged
merged 24 commits into from
Dec 20, 2024
Merged

Conversation

dmulash
Copy link
Collaborator

@dmulash dmulash commented Sep 9, 2024

No description provided.

@dmulash dmulash marked this pull request as ready for review September 9, 2024 16:54
@RHammond2 RHammond2 added bug Something isn't working enhancement New feature or request labels Sep 9, 2024
@RHammond2
Copy link
Collaborator

Resolves #10

@RHammond2 RHammond2 linked an issue Sep 9, 2024 that may be closed by this pull request
11 tasks
Copy link
Collaborator

@RHammond2 RHammond2 left a comment

Choose a reason for hiding this comment

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

This is an excellent start @dmulash, thanks for updating all the impacted methods!

I left a lot of comments, but they're mostly relating to the use of an electrical losses method, rather than an input. I have a couple of questions in there as well that'd be great to get your input on, especially while we're modifying the code. I also made a handful of smaller changes myself just to reduce some of the back and forth.

waves/project.py Show resolved Hide resolved
waves/project.py Show resolved Hide resolved
waves/project.py Show resolved Hide resolved
waves/project.py Show resolved Hide resolved
waves/project.py Show resolved Hide resolved
waves/project.py Outdated Show resolved Hide resolved
waves/project.py Show resolved Hide resolved
waves/project.py Show resolved Hide resolved
waves/project.py Outdated Show resolved Hide resolved
waves/project.py Outdated Show resolved Hide resolved
waves/project.py Outdated Show resolved Hide resolved
@dmulash
Copy link
Collaborator Author

dmulash commented Sep 11, 2024

Hi @RHammond2,

Apart from your suggested changes (eliminate with_losses everywhere, substitute loss_ratio with environmental_loss_ratio, and keep the logic from energy_potential() for wake_losses()), I have also updated the config files for floating and fixed to include a line specifying the turbine_type. Additionally, I modified the example notebook to correct instances where it was calling with_losses for breakdowns.

Feel free to adjust as needed!

@@ -1424,14 +1445,12 @@ def energy_production(
by: str = "windfarm",
units: str = "gw",
per_capacity: str | None = None,
with_losses: bool = False,
loss_ratio: float | None = None,
environmental_loss_ratio: float | None = None,
Copy link
Collaborator

Choose a reason for hiding this comment

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

It looks like the energy losses weren't applied in this method, which should be done just before the AEP conditional.

Copy link
Collaborator

@RHammond2 RHammond2 Sep 17, 2024

Choose a reason for hiding this comment

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

Basically the section you removed should be replaced with something like:

losses = self.energy_losses(...)  # pass the parameters that were used for the energy potential basis 
production = potential - losses

waves/project.py Outdated Show resolved Hide resolved
waves/project.py Outdated Show resolved Hide resolved
@@ -1624,6 +1631,228 @@ def energy_losses(

return losses / self.capacity(per_capacity)

def wake_losses(
Copy link
Collaborator

Choose a reason for hiding this comment

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

I realized there was an error in how this was done, which was mostly my fault, so I fixed that. I would double check the remaining losses calculations, and replicate the process in this method to ensure that both the control flow and the calculations are correct.

waves/project.py Outdated Show resolved Hide resolved
@@ -1592,19 +1610,25 @@ def energy_losses(
by="turbine",
units="kw",
)

Copy link
Collaborator

@RHammond2 RHammond2 Sep 17, 2024

Choose a reason for hiding this comment

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

This section should be roughly in the form of:

if not losses_breakdown:
    production = ... # the code that's there already
    losses = potentail.copy()
    losses["total_losses"] = potential.values - production.values  # can use a different column name
else:
    # raise an error for if by == "turbine" because detailed breakdowns are only for the wind farm
    environmental_lr = self.environmental_loss_ratio()
    availability_lr = self.availability(which="energy", by="windfarm", frequency="month-year")
    ... # the remaining loss ratios

    losses = potential.copy
    losses = losses.assign(
        environmental_losses=environmental_lr,
        availability_losses=availability_lr,
        ... # the remaining lossses
    ).rename(columns={}) # final step if you think we should have them displayed more nicely

# convert to desired units

# aggregate to apporpriate time scale ("annual", "project")

# apply aep

# apply per_capacity

Copy link
Collaborator

Choose a reason for hiding this comment

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

From our conversation: only calculate the loss ratio, not the actual losses. (removed from the example above)

waves/project.py Outdated

return total_loss_ratio

def losses_breakdown(
Copy link
Collaborator

@RHammond2 RHammond2 Sep 17, 2024

Choose a reason for hiding this comment

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

This should really be incorporated into the energy_losses method using a new keyword argument called breakdown because the loss amounts may need to be broken down across time as well.

waves/project.py Outdated
if self.floris_results_type == "wind_rose":
power = pd.DataFrame(0.0, dtype=float, index=availability.index, columns=["drop"])
power = power.merge(
energy_gwh = pd.DataFrame(0.0, dtype=float, index=availability.index, columns=["drop"])
Copy link
Collaborator

Choose a reason for hiding this comment

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

@RHammond2 fix this to get potential as the base energy, so losses can be subtracted.

…loss_ratio and descriptive note for total_loss_ratio method
@dmulash
Copy link
Collaborator Author

dmulash commented Dec 2, 2024

Summary of where we left this enhancement:

The main objective of this enhancement is to be able to output a loss breakdown with the following losses. (please keep in mind that the total losses are calculated as a product of efficiencies as in the following table, so it will not be possible to output the losses in MWh for each category).

Parameter Value Units Note for Rob
Gross Capacity Factor 55.48 % From FLORIS = gross_aep / (project_capacity * 8760)
Wake Losses 5.78 % From FLORIS = (wake_losses/gross_aep)
Availability Losses 5.02 % From WOMBAT = (1-availability)
Electrical Losses 3.21 % From ORCA (method from aep.py)
Environmental Losses 1.67 % Input from user or default value from ORCA
Technical Losses 1.00 % Default value from ORCA
Total System Losses 15.68 % L_total  = 1 - [(1 - L_1) * (1 - L_2) … * (1 - L_n)]
Net Capacity Factor 46.78 % NCF = GCF * (1 – L_total)

The branch today can output a losses breakdown.
image

The problem is that the net energy production does not match when we use that loss ratio, compared to when we calculate it by turbine and by month. See screenshots below to see that numbers do not match.
image
image

Rob and Daniel explored potential reasons for the mismatch on values and concluded that it might stem from the accumulation of shortened decimal values by month and by turbine. Rob recommended an update to WOMBAT to address this.

@dmulash dmulash requested a review from RHammond2 December 10, 2024 22:08
@dmulash
Copy link
Collaborator Author

dmulash commented Dec 10, 2024

This looks good to me, but please note the following caveat:

The total loss ratio cannot be applied with greater granularity than the "project" level (e.g., "month-year" or "annual") or the "windfarm" level (e.g., "turbine"). This is because the availability loss ratio calculation relies on the base potential energy production from WOMBAT, rather than the energy_potential used in WAVES for the wake loss ratio and net AEP calculations.

@RHammond2 RHammond2 merged commit 641d4aa into NREL:develop Dec 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Update Energy Losses to Represent ORCA's Losses Method
2 participants