{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "%matplotlib inline"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# Modeling Transposition Gain\n\nCalculating the gain in insolation of a tilted module over a flat module.\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "This example shows how to evaluate the transposition gain of a racking\nstrategy.  The transposition gain is the additional insolation collected\nby orienting at a tilt instead of horizontal; using PV modeling lingo, it's\nthe increase in POA (plane of array) insolation over GHI (global horizontal\nirradiance) insolation.\n\nThis example uses a TMY dataset and the\n:py:meth:`pvlib.irradiance.get_total_irradiance` function to transpose\nirradiance components to POA irradiance for various fixed tilts.  It also\nmodels a single-axis tracking system for comparison. The monthly POA\ninsolation is calculated for each strategy to show how orientation affects\nseasonal irradiance collection.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import pvlib\nfrom pvlib import location\nfrom pvlib import irradiance\nfrom pvlib import tracking\nfrom pvlib.iotools import read_tmy3\nimport pandas as pd\nfrom matplotlib import pyplot as plt\nimport pathlib\n\n# get full path to the data directory\nDATA_DIR = pathlib.Path(pvlib.__file__).parent / 'data'\n\n# get TMY3 dataset\ntmy, metadata = read_tmy3(DATA_DIR / '723170TYA.CSV', coerce_year=1990)\n# TMY3 datasets are right-labeled (AKA \"end of interval\") which means the last\n# interval of Dec 31, 23:00 to Jan 1 00:00 is labeled Jan 1 00:00. When rolling\n# up hourly irradiance to monthly insolation, a spurious January value is\n# calculated from that last row, so we'll just go ahead and drop it here:\ntmy = tmy.iloc[:-1, :]\n\n# create location object to store lat, lon, timezone\nlocation = location.Location.from_tmy(metadata)\n\n# calculate the necessary variables to do transposition.  Note that solar\n# position doesn't depend on array orientation, so we just calculate it once.\n# Note also that TMY datasets are right-labeled hourly intervals, e.g. the\n# 10AM to 11AM interval is labeled 11.  We should calculate solar position in\n# the middle of the interval (10:30), so we subtract 30 minutes:\ntimes = tmy.index - pd.Timedelta('30min')\nsolar_position = location.get_solarposition(times)\n# but remember to shift the index back to line up with the TMY data:\nsolar_position.index += pd.Timedelta('30min')\n\n\n# create a helper function to do the transposition for us\ndef calculate_poa(tmy, solar_position, surface_tilt, surface_azimuth):\n    # Use the get_total_irradiance function to transpose the irradiance\n    # components to POA irradiance\n    poa = irradiance.get_total_irradiance(\n        surface_tilt=surface_tilt,\n        surface_azimuth=surface_azimuth,\n        dni=tmy['DNI'],\n        ghi=tmy['GHI'],\n        dhi=tmy['DHI'],\n        solar_zenith=solar_position['apparent_zenith'],\n        solar_azimuth=solar_position['azimuth'],\n        model='isotropic')\n    return poa['poa_global']  # just return the total in-plane irradiance\n\n\n# create a dataframe to keep track of our monthly insolations\ndf_monthly = pd.DataFrame()\n\n# fixed-tilt:\nfor tilt in range(0, 50, 10):\n    # we will hardcode azimuth=180 (south) for all fixed-tilt cases\n    poa_irradiance = calculate_poa(tmy, solar_position, tilt, 180)\n    column_name = f\"FT-{tilt}\"\n    # TMYs are hourly, so we can just sum up irradiance [W/m^2] to get\n    # insolation [Wh/m^2]:\n    df_monthly[column_name] = poa_irradiance.resample('m').sum()\n\n# single-axis tracking:\norientation = tracking.singleaxis(solar_position['apparent_zenith'],\n                                  solar_position['azimuth'],\n                                  axis_tilt=0,  # flat array\n                                  axis_azimuth=180,  # south-facing azimuth\n                                  max_angle=60,  # a common maximum rotation\n                                  backtrack=True,  # backtrack for a c-Si array\n                                  gcr=0.4)  # a common ground coverage ratio\n\npoa_irradiance = calculate_poa(tmy,\n                               solar_position,\n                               orientation['surface_tilt'],\n                               orientation['surface_azimuth'])\ndf_monthly['SAT-0.4'] = poa_irradiance.resample('m').sum()\n\n# calculate the percent difference from GHI\nghi_monthly = tmy['GHI'].resample('m').sum()\ndf_monthly = 100 * (df_monthly.divide(ghi_monthly, axis=0) - 1)\n\ndf_monthly.plot()\nplt.xlabel('Month of Year')\nplt.ylabel('Monthly Transposition Gain [%]')\nplt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Note that in summer, steeper tilts actually collect less insolation than\nflatter tilts because the sun is so high in the sky at solar noon.  However,\nthe steeper tilts significantly increase insolation capture in winter when\nthe sun is lower in the sky.  In contrast to the highly seasonal gain shown\nby fixed tilts, the tracker system shows a much more consistent gain\nyear-round.\n\nBecause the seasonality of the fixed-tilt transposition gain is driven by\nsolar position angles, the relative behavior of different orientations will\nbe different for different locations.  For example, a common rule of thumb\n(considered somewhat outdated today) used to be to set tilt equal to the\nlatitude of the system location.  At higher latitudes, the sun doesn't get\nas high in the sky, so steeper tilts make more sense.\n\n"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.7.9"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}