From 418d6d0a70cc29478d99ceb8123c1c9844159248 Mon Sep 17 00:00:00 2001 From: Kurt Rhee <33131958+kurt-rhee@users.noreply.github.com> Date: Wed, 19 Jun 2024 14:00:50 -0700 Subject: [PATCH] Add a simple transformer effficiency model to pvlib (#2053) * wrote a simple transformer efficiency model * edited documentation to include latex, unsure if it will compile correctly in docs. * removed "if __main__" * removed "if __main__" * changed whatsnew rst * updated to be in compliance with Flake8 * Update pvlib/transformer.py Co-authored-by: Cliff Hansen * Update pvlib/transformer.py Co-authored-by: Cliff Hansen * Update pvlib/transformer.py Co-authored-by: Cliff Hansen * + added transformer to index.rst + added transformer.rst to pvlib/docs/source/sphinx/reference * Update docs/sphinx/source/reference/transformer.rst Co-authored-by: Cliff Hansen * Update pvlib/transformer.py Co-authored-by: Cliff Hansen * updated names of loss values and changed to [unitless] * Update pvlib/transformer.py Co-authored-by: Cliff Hansen * Update pvlib/transformer.py Co-authored-by: Cliff Hansen * Update pvlib/transformer.py Co-authored-by: Cliff Hansen * Update pvlib/transformer.py Co-authored-by: Cliff Hansen * Update pvlib/transformer.py Co-authored-by: Cliff Hansen * Update pvlib/transformer.py Co-authored-by: Cliff Hansen * Update pvlib/transformer.py Co-authored-by: Cliff Hansen * Update pvlib/transformer.py Co-authored-by: Cliff Hansen * forgot to update arguments in test function * updated formatting of docstring * Update pvlib/transformer.py Co-authored-by: Cliff Hansen * Update pvlib/transformer.py Co-authored-by: Cliff Hansen * Update pvlib/transformer.py Co-authored-by: Cliff Hansen * Update pvlib/transformer.py Co-authored-by: Cliff Hansen * Update pvlib/transformer.py Co-authored-by: Cliff Hansen * adding space between equations in docstring * fixing flake8 linting * removing whitespace * Update docs/sphinx/source/reference/transformer.rst Co-authored-by: Echedey Luis <80125792+echedey-ls@users.noreply.github.com> * Update pvlib/transformer.py Co-authored-by: Echedey Luis <80125792+echedey-ls@users.noreply.github.com> * Update pvlib/transformer.py Co-authored-by: Cliff Hansen * Update pvlib/transformer.py Co-authored-by: Echedey Luis <80125792+echedey-ls@users.noreply.github.com> * Update pvlib/transformer.py Co-authored-by: Echedey Luis <80125792+echedey-ls@users.noreply.github.com> * Update pvlib/transformer.py Co-authored-by: Echedey Luis <80125792+echedey-ls@users.noreply.github.com> * Update docs/sphinx/source/whatsnew/v0.11.0.rst Co-authored-by: Echedey Luis <80125792+echedey-ls@users.noreply.github.com> * Update pvlib/transformer.py Co-authored-by: Echedey Luis <80125792+echedey-ls@users.noreply.github.com> * Update pvlib/tests/test_transformer.py Co-authored-by: Echedey Luis <80125792+echedey-ls@users.noreply.github.com> * Update pvlib/transformer.py Co-authored-by: Echedey Luis <80125792+echedey-ls@users.noreply.github.com> * Update pvlib/transformer.py Co-authored-by: Kevin Anderson * Update pvlib/transformer.py Co-authored-by: Kevin Anderson * Update docs/sphinx/source/whatsnew/v0.11.0.rst Co-authored-by: Adam R. Jensen <39184289+AdamRJensen@users.noreply.github.com> * Update pvlib/transformer.py Co-authored-by: Echedey Luis <80125792+echedey-ls@users.noreply.github.com> * Update pvlib/transformer.py Co-authored-by: Echedey Luis <80125792+echedey-ls@users.noreply.github.com> * clean up derivation and docstring * change code calculations to match docstring * test recovery of no-load and full-load values * bit more cleanup * typo * Apply suggestions from code review Co-authored-by: Cliff Hansen * Apply suggestions from code review --------- Co-authored-by: Cliff Hansen Co-authored-by: Echedey Luis <80125792+echedey-ls@users.noreply.github.com> Co-authored-by: Kevin Anderson Co-authored-by: Adam R. Jensen <39184289+AdamRJensen@users.noreply.github.com> --- docs/sphinx/source/reference/index.rst | 1 + docs/sphinx/source/reference/transformer.rst | 11 ++ docs/sphinx/source/whatsnew/v0.11.0.rst | 3 + pvlib/tests/test_transformer.py | 60 ++++++++++ pvlib/transformer.py | 117 +++++++++++++++++++ 5 files changed, 192 insertions(+) create mode 100644 docs/sphinx/source/reference/transformer.rst create mode 100644 pvlib/tests/test_transformer.py create mode 100644 pvlib/transformer.py diff --git a/docs/sphinx/source/reference/index.rst b/docs/sphinx/source/reference/index.rst index 9083f85bdd..8a990ac923 100644 --- a/docs/sphinx/source/reference/index.rst +++ b/docs/sphinx/source/reference/index.rst @@ -20,3 +20,4 @@ API reference bifacial scaling location + transformer diff --git a/docs/sphinx/source/reference/transformer.rst b/docs/sphinx/source/reference/transformer.rst new file mode 100644 index 0000000000..293f301296 --- /dev/null +++ b/docs/sphinx/source/reference/transformer.rst @@ -0,0 +1,11 @@ +.. currentmodule:: pvlib + +Transformer losses +================== + +Methods to account for losses in transformers + +.. autosummary:: + :toctree: generated/ + + transformer.simple_efficiency diff --git a/docs/sphinx/source/whatsnew/v0.11.0.rst b/docs/sphinx/source/whatsnew/v0.11.0.rst index 2fdcd1c444..5806df2cf2 100644 --- a/docs/sphinx/source/whatsnew/v0.11.0.rst +++ b/docs/sphinx/source/whatsnew/v0.11.0.rst @@ -33,6 +33,8 @@ Deprecations Enhancements ~~~~~~~~~~~~ +* Add a simple transformer efficiency model :py:func:`pvlib.transformer.simple_efficiency`. + (:issue:`1269`, :pull:`2053`) * Add function :py:func:`pvlib.shading.shaded_fraction1d`, to calculate the shade perpendicular to ``axis_azimuth``. The function is applicable to both fixed-tilt and one-axis tracking systems. @@ -70,6 +72,7 @@ Requirements Contributors ~~~~~~~~~~~~ * Cliff Hansen (:ghuser:`cwhanse`) +* Kurt Rhee (:ghuser:`kurt-rhee`) * Mark Mikofski (:ghuser:`mikofski`) * Siddharth Kaul (:ghuser:`k10blogger`) * Ioannis Sifnaios (:ghuser:`IoannisSifnaios`) diff --git a/pvlib/tests/test_transformer.py b/pvlib/tests/test_transformer.py new file mode 100644 index 0000000000..0739a9e95a --- /dev/null +++ b/pvlib/tests/test_transformer.py @@ -0,0 +1,60 @@ +import pandas as pd + +from numpy.testing import assert_allclose + +from pvlib import transformer + + +def test_simple_efficiency(): + + # define test inputs + input_power = pd.Series([ + -800.0, + 436016.609823837, + 1511820.16603752, + 1580687.44677249, + 1616441.79660171 + ]) + no_load_loss = 0.002 + load_loss = 0.007 + transformer_rating = 2750000 + + # define expected test results + expected_output_power = pd.Series([ + -6300.10103234071, + 430045.854892526, + 1500588.39919874, + 1568921.77089526, + 1604389.62839879 + ]) + + # run test function with test inputs + calculated_output_power = transformer.simple_efficiency( + input_power=input_power, + no_load_loss=no_load_loss, + load_loss=load_loss, + transformer_rating=transformer_rating + ) + + # determine if expected results are obtained + assert_allclose(calculated_output_power, expected_output_power) + + +def test_simple_efficiency_known_values(): + no_load_loss = 0.005 + load_loss = 0.01 + rating = 1000 + args = (no_load_loss, load_loss, rating) + + # verify correct behavior at no-load condition + assert_allclose( + transformer.simple_efficiency(no_load_loss*rating, *args), + 0.0 + ) + + # verify correct behavior at rated condition + assert_allclose( + transformer.simple_efficiency(rating*(1 + no_load_loss + load_loss), + *args), + rating, + ) diff --git a/pvlib/transformer.py b/pvlib/transformer.py new file mode 100644 index 0000000000..3b66b0beb3 --- /dev/null +++ b/pvlib/transformer.py @@ -0,0 +1,117 @@ +""" +This module contains functions for transformer modeling. + +Transformer models calculate AC power output and losses at a given input power. +""" + + +def simple_efficiency( + input_power, no_load_loss, load_loss, transformer_rating +): + r''' + Calculate the power at the output terminal of the transformer + after taking into account efficiency using a simple calculation. + + The equation used in this function can be derived from [1]_. + + For a zero input power, the output power will be negative. + This means the transformer will consume energy from the grid at night if + it stays connected (due to the parallel impedance in the equivalent + circuit). + If the input power is negative, the output power will be even more + negative; so the model can be used bidirectionally when drawing + energy from the grid. + + Parameters + ---------- + input_power : numeric + The real AC power input to the transformer. [W] + + no_load_loss : numeric + The constant losses experienced by a transformer, even + when the transformer is not under load. Fraction of transformer rating, + value from 0 to 1. [unitless] + + load_loss: numeric + The load dependent losses experienced by the transformer. + Fraction of transformer rating, value from 0 to 1. [unitless] + + transformer_rating: numeric + The nominal output power of the transformer. [VA] + + Returns + ------- + output_power : numeric + Real AC power output. [W] + + Notes + ------- + First, assume that the load loss :math:`L_{load}` (as a fraction of rated power + :math:`P_{nom}`) is proportional to the square of output power: + + .. math:: + + L_{load}(P_{out}) &= L_{load}(P_{rated}) \times (P_{out} / P_{nom})^2 + + &= L_{full, load} \times (P_{out} / P_{nom})^2 + + Total loss is the constant no-load loss plus the variable load loss: + + .. math:: + + L_{total}(P_{out}) &= L_{no, load} + L_{load}(P_{out}) + + &= L_{no, load} + L_{full, load} \times (P_{out} / P_{nom})^2 + + + By conservation of energy, total loss is the difference between input and + output power: + + .. math:: + + \frac{P_{in}}{P_{nom}} &= \frac{P_{out}}{P_{nom}} + L_{total}(P_{out}) + + &= \frac{P_{out}}{P_{nom}} + L_{no, load} + L_{full, load} \times (P_{out} / P_{nom})^2 + + Now use the quadratic formula to solve for :math:`P_{out}` as a function of + :math:`P_{in}`. + + .. math:: + + \frac{P_{out}}{P_{nom}} &= \frac{-b \pm \sqrt{b^2 - 4ac}}{2a} + + a &= L_{full, load} + + b &= 1 + + c &= L_{no, load} - P_{in} / P_{nom} + + Therefore: + + .. math:: + + P_{out} = P_{nom} \frac{-1 \pm \sqrt{1 - 4 L_{full, load} + + \times (L_{no, load} - P_{in}/P_{nom})}}{2 L_{full, load}} + + The positive root should be chosen, so that the output power is + positive. + + + References + ---------- + .. [1] Central Station Engineers of the Westinghouse Electric Corporation, + "Electrical Transmission and Distribution Reference Book" 4th Edition. + pg. 101. + ''' # noqa: E501 + + input_power_normalized = input_power / transformer_rating + + a = load_loss + b = 1 + c = no_load_loss - input_power_normalized + + output_power_normalized = (-b + (b**2 - 4*a*c)**0.5) / (2 * a) + + output_power = output_power_normalized * transformer_rating + return output_power