{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Validation\n", "\n", "This document shows how the shading calculations using the ``twoaxistracking`` package compare to existing methods found in the literature. Specifically, the annual shading loss is calculated for nine different field layouts and compared with the values presented in Cumpston and Pye (2014).\n", "\n", "Import necessary packages:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import numpy as np\n", "from shapely import geometry\n", "import twoaxistracking" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Definition of collector geometry\n", "\n", "The study by Cumpston and Pye (2014) simulated shading for a circular aperture. The study made no distinction between gross and aperture area, i.e., the two geometries were assumed to be the same." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "" ], "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "radius = np.sqrt(1/np.pi) # radius for a circle with an area of 1\n", "collector_geometry = geometry.Point(0,0).buffer(radius)\n", "\n", "collector_geometry" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "## Reference dataset\n", "The simulations carried out in the reference study were based on the 1976 irradiance dataset from Barstow.\n", "\n", "A stringent quality-control of this dataset was carried out as described in the [Reference irradiance dataset](reference_dataset.ipynb) section. This step was necessary as the dataset contained several periods of erroneous data, e.g., irradiance at night and periods with unfeasible irradiance levels.\n", "\n", "Load the quality-controlled dataset:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "tags": [ "hide-output" ] }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ghidnidhi_calctemp_airapparent_zenithzenithapparent_elevationelevationazimuthdni_extra
time
1976-01-01 00:15:00-08:000.880.940.88-1.59167.092519167.092519-77.092519-77.09251925.2785341413.981805
1976-01-01 00:30:00-08:000.000.940.00-1.94165.467857165.467857-75.467857-75.46785738.1537101413.981805
1976-01-01 00:45:00-08:000.881.880.88-2.36163.355080163.355080-73.355080-73.35508048.3335211413.981805
1976-01-01 01:00:00-08:000.000.940.00-2.50160.917391160.917391-70.917391-70.91739156.3114531413.981805
1976-01-01 01:15:00-08:000.880.000.88-2.78158.265917158.265917-68.265917-68.26591762.6527701413.981805
\n", "
" ], "text/plain": [ " ghi dni dhi_calc temp_air apparent_zenith \\\n", "time \n", "1976-01-01 00:15:00-08:00 0.88 0.94 0.88 -1.59 167.092519 \n", "1976-01-01 00:30:00-08:00 0.00 0.94 0.00 -1.94 165.467857 \n", "1976-01-01 00:45:00-08:00 0.88 1.88 0.88 -2.36 163.355080 \n", "1976-01-01 01:00:00-08:00 0.00 0.94 0.00 -2.50 160.917391 \n", "1976-01-01 01:15:00-08:00 0.88 0.00 0.88 -2.78 158.265917 \n", "\n", " zenith apparent_elevation elevation \\\n", "time \n", "1976-01-01 00:15:00-08:00 167.092519 -77.092519 -77.092519 \n", "1976-01-01 00:30:00-08:00 165.467857 -75.467857 -75.467857 \n", "1976-01-01 00:45:00-08:00 163.355080 -73.355080 -73.355080 \n", "1976-01-01 01:00:00-08:00 160.917391 -70.917391 -70.917391 \n", "1976-01-01 01:15:00-08:00 158.265917 -68.265917 -68.265917 \n", "\n", " azimuth dni_extra \n", "time \n", "1976-01-01 00:15:00-08:00 25.278534 1413.981805 \n", "1976-01-01 00:30:00-08:00 38.153710 1413.981805 \n", "1976-01-01 00:45:00-08:00 48.333521 1413.981805 \n", "1976-01-01 01:00:00-08:00 56.311453 1413.981805 \n", "1976-01-01 01:15:00-08:00 62.652770 1413.981805 " ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "filename = '../../../twoaxistracking/data/barstow_1976_irradiance_data_quality_controlled.csv'\n", "df = pd.read_csv(filename, index_col=0, parse_dates=[0])\n", "\n", "df.head() # print the first five rows of the dataframe" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "Furthermore, it is important to note that the reference study only performed simulations \"for solar elevation angles greater than 10°\".\n", "\n", "Therefore, a new column of the direct normal irradiance (DNI) is derived where the irradiance below 10° elevation is set to zero." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "df['dni>10deg'] = df.loc[df['elevation']>10, 'dni']\n", "df['dni>10deg'] = df['dni>10deg'].fillna(0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "## Field layouts\n", "\n", "Cumpston and Pye (2010) provided the annual shading loss (ASL) for nine different field layouts (GCR ranging from 0.1 to 0.9). The field layout parameters and their annual shading loss were:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "tags": [ "hide-input" ] }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
gcraspect_ratiorotationoffsetasl_cumpston
00.12.300.00.00.04
10.21.610.00.01.53
20.31.111.0-0.54.50
30.41.000.0-0.58.14
40.50.870.0-0.512.40
50.60.870.0-0.517.20
60.70.870.0-0.522.30
70.80.8789.0-0.527.60
80.90.87167.0-0.533.10
\n", "
" ], "text/plain": [ " gcr aspect_ratio rotation offset asl_cumpston\n", "0 0.1 2.30 0.0 0.0 0.04\n", "1 0.2 1.61 0.0 0.0 1.53\n", "2 0.3 1.11 1.0 -0.5 4.50\n", "3 0.4 1.00 0.0 -0.5 8.14\n", "4 0.5 0.87 0.0 -0.5 12.40\n", "5 0.6 0.87 0.0 -0.5 17.20\n", "6 0.7 0.87 0.0 -0.5 22.30\n", "7 0.8 0.87 89.0 -0.5 27.60\n", "8 0.9 0.87 167.0 -0.5 33.10" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dfc = pd.DataFrame(\n", " columns=['gcr', 'aspect_ratio', 'rotation', 'offset', 'asl_cumpston'],\n", " data=[\n", " [0.1, 2.3, 0.0, 0.0, 0.04],\n", " [0.2, 1.61, 0.0, 0.0, 1.53],\n", " [0.3, 1.11, 1.0, -0.5, 4.50],\n", " [0.4, 1.0, 0.0, -0.5, 8.14],\n", " [0.5, np.sqrt(3)/2, 0.0, -0.5, 12.4],\n", " [0.6, np.sqrt(3)/2, 0.0, -0.5, 17.2],\n", " [0.7, np.sqrt(3)/2, 0.0, -0.5, 22.3],\n", " [0.8, np.sqrt(3)/2, 89.0, -0.5, 27.6],\n", " [0.9, np.sqrt(3)/2, 167.0, -0.5, 33.1]])\n", "\n", "dfc.round(2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "For comparison the annual shading loss for the nine field layouts were therefore calculated using the `twoaxistracking` package:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "C:\\Users\\arajen\\Documents\\GitHub\\twoaxistracking\\twoaxistracking\\layout.py:176: RuntimeWarning: invalid value encountered in arcsin\n", " (tracker_distance * np.cos(delta_gamma_rad)))) + relative_slope\n" ] } ], "source": [ "field_parameters = ['gcr', 'aspect_ratio', 'rotation', 'offset']\n", "\n", "for index, (gcr, aspect_ratio, rotation, offset) in dfc[field_parameters].iterrows():\n", " # Define the tracker field for each configuration\n", " tracker_field = twoaxistracking.TrackerField(\n", " total_collector_geometry=collector_geometry,\n", " active_collector_geometry=collector_geometry,\n", " neighbor_order=2,\n", " gcr=gcr,\n", " aspect_ratio=aspect_ratio,\n", " rotation=rotation,\n", " offset=offset)\n", " \n", " # Calculate shaded fraction for each timestamp\n", " df['shaded_fraction'] = tracker_field.get_shaded_fraction(df['elevation'], df['azimuth'])\n", "\n", " # Calculate annual shading loss\n", " dfc.loc[index, 'asl_twoaxistracking'] = (df['shaded_fraction'].multiply(df['dni>10deg'], axis='rows').sum() / \n", " df['dni>10deg'].sum())*100" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "### Comparison of annual shading loss\n", "The annual shading loss (ASL) presented in Cumpston and Pye (2014) and those calculated using the `twoaxistracking` package are shown below. The deviations between the shading fractions are presented both in absolute and relative terms." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "tags": [ "hide-input" ] }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
asl_cumpstonasl_twoaxistrackingabsolute_deviationrelative_deviation
gcr
0.10.04 %0.04 %0.00 %0.00 %
0.21.53 %1.51 %-0.02 %-1.31 %
0.34.50 %4.49 %-0.01 %-0.22 %
0.48.14 %8.09 %-0.05 %-0.61 %
0.512.40 %12.30 %-0.10 %-0.81 %
0.617.20 %17.10 %-0.10 %-0.58 %
0.722.30 %22.20 %-0.10 %-0.45 %
0.827.60 %27.40 %-0.20 %-0.72 %
0.933.10 %32.90 %-0.20 %-0.60 %
\n", "
" ], "text/plain": [ " asl_cumpston asl_twoaxistracking absolute_deviation relative_deviation\n", "gcr \n", "0.1 0.04 % 0.04 % 0.00 % 0.00 %\n", "0.2 1.53 % 1.51 % -0.02 % -1.31 %\n", "0.3 4.50 % 4.49 % -0.01 % -0.22 %\n", "0.4 8.14 % 8.09 % -0.05 % -0.61 %\n", "0.5 12.40 % 12.30 % -0.10 % -0.81 %\n", "0.6 17.20 % 17.10 % -0.10 % -0.58 %\n", "0.7 22.30 % 22.20 % -0.10 % -0.45 %\n", "0.8 27.60 % 27.40 % -0.20 % -0.72 %\n", "0.9 33.10 % 32.90 % -0.20 % -0.60 %" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Limit asl_twoaxistracking to three significant figures and two decimal places\n", "dfc['asl_twoaxistracking'] = dfc['asl_twoaxistracking'].\\\n", " apply(lambda s: f\"{s:.3g}\").astype(float).round(2)\n", "# Calculate absolute and relatieve deviation\n", "dfc['absolute_deviation'] = (dfc['asl_twoaxistracking'] - dfc['asl_cumpston'])\n", "dfc['relative_deviation'] = (dfc['asl_twoaxistracking'] - dfc['asl_cumpston']).\\\n", " divide(dfc['asl_cumpston']).multiply(100)\n", "\n", "result_columns = ['asl_cumpston', 'asl_twoaxistracking', 'absolute_deviation', 'relative_deviation']\n", "dfc.set_index('gcr')[result_columns].round(2).applymap(lambda s: f\"{s:.2f} %\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The comparison above shows that the differences between the annual shading losses are very low (always lower than 1.3%). The discrepancies are believed to be due to minor differences in the quality control procedure applied to reference data.\n", "\n", "The reference study (Cumpston and Pye, 2014) utilized the shading calculation algorithm developed by Meller (2010). Meller's algorithm has previously been compared to results from Pons & Dugan (1984)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## References\n", "\n", "[Cumpston, J. and Pye, J., 2014. Shading and land use in regularly-spaced sun-tracking collectors. Sol. Energy 108, 199–209.](https://doi.org/10.1016/j.solener.2014.06.012)\n", "\n", "[Meller, Y., 2010. Analytically calculating shading in regular arrays of sun-pointing collectors. Sol. Energy 84, 1967–1974. ](https://doi.org/10.1016/j.solener.2010.08.006)\n", "\n", "[Pons, R.L., Dugan, A.F., 1984. The effect of concentrator field layout on the performance of point-focus distributed receiver systems. J. Sol. Energy Eng. Trans. ASME 106, 35–38.](https://doi.org/10.1115/1.3267559)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.12" }, "mystnb": { "execution_timeout": 120 } }, "nbformat": 4, "nbformat_minor": 4 }