From 4a10751e76fe5d43b8db6c81c614d5a8e8880b2f Mon Sep 17 00:00:00 2001 From: Alireza Aghamohammadi Date: Sun, 24 Dec 2023 19:25:51 +0330 Subject: [PATCH 01/13] Refine solar irradiation discussion and comparison with `pvlib python` This commit refines the discussion on solar irradiation in the paper. The focus is now on direct beam irradiation, which contributes the most to solar irradiation. The conditions assumed are a clear sky with no clouds and an atmosphere free of pollutants The commit also updates the comparison of `pysolorie` with other libraries. Instead of comparing with `Astropy`, the comparison is now with `pvlib python`, a library for simulating the performance of photovoltaic energy systems. The discussion on backtracking and shading effect for a field of one-axis sun-trackers, as discussed in the paper by Anderson & Mikofski, is also included. --- paper/paper.bib | 116 +++++++++++++++++++++++++++++++++++++++++++++++- paper/paper.md | 16 ++++--- 2 files changed, 124 insertions(+), 8 deletions(-) diff --git a/paper/paper.bib b/paper/paper.bib index ba6b416..cdf05cc 100644 --- a/paper/paper.bib +++ b/paper/paper.bib @@ -40,13 +40,13 @@ @article{Foulaadvand2023 month = sep } -@book{DuffieDeceased2020, +@book{Duffie2020, title = {Solar Engineering of Thermal Processes, Photovoltaics and Wind}, ISBN = {9781119540328}, url = {http://dx.doi.org/10.1002/9781119540328}, DOI = {10.1002/9781119540328}, publisher = {Wiley}, - author = {Duffie (Deceased), John A. and Beckman, William A. and Blair, Nathan}, + author = {Duffie, John A. and Beckman, William A. and Blair, Nathan}, year = {2020}, month = feb } @@ -64,3 +64,115 @@ @article{Astropy2022 title = {The Astropy Project: Sustaining and Growing a Community-oriented Open-source Project and the Latest Major Release (v5.0) of the Core Package*}, journal = {The Astrophysical Journal}, } + +@article{AntonanzasTorres2019, + title = {Clear sky solar irradiance models: A review of seventy models}, + volume = {107}, + ISSN = {1364-0321}, + url = {http://dx.doi.org/10.1016/j.rser.2019.02.032}, + DOI = {10.1016/j.rser.2019.02.032}, + journal = {Renewable and Sustainable Energy Reviews}, + publisher = {Elsevier BV}, + author = {Antonanzas-Torres, F. and Urraca, R. and Polo, J. and Perpiñán-Lamigueiro, O. and Escobar, R.}, + year = {2019}, + month = jun, + pages = {374–387} +} + +@article{Calabr2013, + title = {An Algorithm to Determine the Optimum Tilt Angle of a Solar Panel from Global Horizontal Solar Radiation}, + volume = {2013}, + ISSN = {2314-4394}, + url = {http://dx.doi.org/10.1155/2013/307547}, + DOI = {10.1155/2013/307547}, + journal = {Journal of Renewable Energy}, + publisher = {Hindawi Limited}, + author = {Calabrò, Emanuele}, + year = {2013}, + pages = {1–12} +} + +@article{Hafez2017, + title = {Tilt and azimuth angles in solar energy applications – A review}, + volume = {77}, + ISSN = {1364-0321}, + url = {http://dx.doi.org/10.1016/j.rser.2017.03.131}, + DOI = {10.1016/j.rser.2017.03.131}, + journal = {Renewable and Sustainable Energy Reviews}, + publisher = {Elsevier BV}, + author = {Hafez, A.Z. and Soliman, A. and El-Metwally, K.A. and Ismail, I.M.}, + year = {2017}, + month = sep, + pages = {147–168} +} + + @article{Goshayeshi2019, + title={Effect of absorber plate surface shape and glass cover inclination angle on the performance of a passive solar still}, + volume={30}, + ISSN={0961-5539}, + url={http://dx.doi.org/10.1108/HFF-01-2019-0018}, + DOI={10.1108/hff-01-2019-0018}, + number={6}, + journal={International Journal of Numerical Methods for Heat & Fluid Flow}, + publisher={Emerald}, + author={Goshayeshi, Hamid Reza and Safaei, Mohammad Reza}, + year={2019}, + month=jul, + pages={3183–3198} + } + +@book{Goswami2015, + title = {Principles of Solar Engineering}, + ISBN = {9780429100208}, + url = {http://dx.doi.org/10.1201/b18119}, + DOI = {10.1201/b18119}, + publisher = {CRC Press}, + author = {Goswami, D. Yogi}, + year = {2015}, + month = feb +} + +@book{Iqbal2012, + title={An Introduction to Solar Radiation}, + ISBN = {9780323151818}, + author={Iqbal, Muhammad}, + publisher={Elsevier}, + month=dec, + year={2012}, + language={en} +} + +@techreport{Anderson2020, + title = {Slope-Aware Backtracking for Single-Axis Trackers}, + url = {http://dx.doi.org/10.2172/1660126}, + DOI = {10.2172/1660126}, + institution = {Office of Scientific and Technical Information (OSTI)}, + author = {Anderson, Kevin and Mikofski, Mark}, + year = {2020}, + month = jul +} + +@techreport{Marion2013, + title = {Rotation Angle for the Optimum Tracking of One-Axis Trackers}, + url = {http://dx.doi.org/10.2172/1089596}, + DOI = {10.2172/1089596}, + institution = {Office of Scientific and Technical Information (OSTI)}, + author = {Marion, W. F. and Dobos, A. P.}, + year = {2013}, + month = jul +} + +@article{FHolmgren2018, + title = {pvlib python: a python package for modeling solar energy systems}, + volume = {3}, + ISSN = {2475-9066}, + url = {http://dx.doi.org/10.21105/joss.00884}, + DOI = {10.21105/joss.00884}, + number = {29}, + journal = {Journal of Open Source Software}, + publisher = {The Open Journal}, + author = {F. Holmgren, William and W. Hansen, Clifford and A. Mikofski, Mark}, + year = {2018}, + month = sep, + pages = {884} +} diff --git a/paper/paper.md b/paper/paper.md index 224969c..3f740cd 100644 --- a/paper/paper.md +++ b/paper/paper.md @@ -35,7 +35,7 @@ How can one maximize the solar irradiation energy received by a fixed flat solar - Finding the optimal tilt angle for a fixed solar panel, assuming a clear-sky condition. - Plotting the optimal tilt angle over a range of days. -- Plotting the total direct irradiation over a range of days. +- Plotting the direct irradiation over a range of days. - Generating a CSV, JSON, or XML report detailing the optimal tilt angle over a range of days. - Utilizing Hottel's model to quantify clear-sky conditions and estimate the atmospheric transmission of clear-sky beam radiation [@Hottel1976]. @@ -43,21 +43,25 @@ How can one maximize the solar irradiation energy received by a fixed flat solar # Statement of need The amount of solar irradiation energy harvested by a solar collector depends on several factors. These include the time of irradiation (both the time of day and the day of the year), the latitude and climate of the location, and the shape and orientation of the solar panel [@Foulaadvand2023]. A solar collector can be positioned at a fixed orientation to maximize energy reception for a specific time period, such as daily, weekly, monthly, or seasonally, or it can be fixed for optimal performance throughout the year. The orientation can then be adjusted for the next time period. -Solar irradiation is composed of three components: the direct beam, sky diffusion, and ground reflection. For flat solar panels, we focus on direct beam irradiation, which contributes the most to solar irradiation. There are various models available for different climate types. We assume a clear sky condition with no clouds in the sky and an atmosphere free of pollutants. However, a cloudy sky or polluted air may affect the amount of solar energy received on Earth. In this context, we focus on the overall received irradiation energy. There are some other issues which may require careful consideration and further investigation in future studies, such as panel efficiency, energy conversion, and the effects of air pollution. +Solar irradiation is composed of three components: the direct beam, sky diffusion, and ground reflection. For flat solar panels, we focus on direct beam irradiation, which contributes the most to solar irradiation. There are various models available for different climate types. We assume a clear sky condition with no clouds in the sky and an atmosphere free of pollutants. However, a cloudy sky or polluted air may affect the amount of solar energy received on Earth. There are some other issues which may require careful consideration and further investigation in future studies, such as panel efficiency, energy conversion, and the effects of air pollution. In our case, we use Hottel’s model to estimate the transmittance of direct solar radiation through a clear and sunny atmosphere [@Hottel1976]. With a well-defined, user-friendly, and extensible API, multiple audiences can benefit from `pysolorie`. These include solar energy researchers, solar panel manufacturers and installers, and instructors. -`Astropy` is the most well-known Python package with comprehensive functionality for astronomy and astrophysics [@Astropy2022]. It provides astronomical coordinate systems, cosmological calculations, and many more features. However, it lacks the ability to determine the optimal orientation of a flat solar panel, a feature that `pysolarorie` provides. +`pvlib python` is a library for simulating the performance of photovoltaic energy systems [@FHolmgren2018]. `pvlib python` implements two papers related to sun tracking [@Anderson2020;@Marion2013]. In the paper by Anderson & Mikofski, +the idea of backtracking and shading effect for a field of one-axis sun-trackers is discussed [@Anderson2020]. `pysolorie`, in contrast, considers a single flat-plate collector. This collector does not track the Sun and its orientation is optimally fixed. In the paper by Marion & Dobos, the optimal tracking angle for one-axis solar tracker is discussed [@Marion2013]. With the constraint of one-axis tracking, the incidence angle is minimized. However, `pysolorie` focuses on finding the optimal tilt angle for the solar panel, instead of sun tracking. + +`Astropy` is the most well-known Python package with comprehensive functionality for astronomy and astrophysics [@Astropy2022]. It provides astronomical coordinate systems, cosmological calculations, and many more features. However, it lacks the ability to determine the optimal orientation of a flat solar panel, a feature that `pysolorie` provides. + # Background -The energy collected by a solar panel can be calculated using the formula in Equation \ref{eq:totaldirect}, where: +The energy collected by a solar panel can be calculated using the formula in Equation \ref{eq:direct}, where: - $n$ is the day of the year, - $\phi$ is the latitude of the observer, -- $I(n)$ is the amount of solar energy received per unit area per second [@DuffieDeceased2020] on day number $n$ of the year, +- $I(n)$ is the amount of solar energy received per unit area per second [@Duffie2020] on day number $n$ of the year, - $\Omega$ is the Earth angular velocity around its axis with the value `7.15 * 1e-5` rad/s, - $\theta$ is the angle between the position vector of the sun and the normal vector to the solar panel (incidence angle), - $\omega_s$ is the sunrise hour angle, @@ -65,7 +69,7 @@ The energy collected by a solar panel can be calculated using the formula in Equ - $H$ is the Heaviside step function, - $\tau_b$ is the beam atmospheric transmittance [@Hottel1976]. -\begin{equation}\label{eq:totaldirect} +\begin{equation}\label{eq:direct} E(n,\phi) = \frac{I(n)}{\Omega} \int_{\omega_s}^{\omega_t}\cos(\theta) \times H(\cos(\theta)) \times \tau_b~d\omega \end{equation} From 8cd9236021bef40762b7a97f9de6239a923fce9b Mon Sep 17 00:00:00 2001 From: Alireza Aghamohammadi Date: Sun, 24 Dec 2023 19:40:40 +0330 Subject: [PATCH 02/13] Update text to reflect 'direct' rather than 'total direct' irradiation - Updated README and documentation phrases to replace "total direct irradiation" with "direct irradiation" to adhere to variable renaming in the codebase. - Adjusted method descriptions and tool-tips to align with the new terminology. --- README.md | 2 +- docs/getting_started.rst | 24 +++++++++---------- docs/index.rst | 2 +- .../pysolorie.numerical_integration.rst | 4 ++-- src/pysolorie/numerical_integration.py | 17 ++++++------- 5 files changed, 25 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index be61d59..d9cfaec 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ How can one maximize the solar irradiation energy received by a solar panel? - Finding the optimal tilt angle for a fixed solar panel, assuming a clear-sky condition. - Plotting the optimal tilt angle over a range of days. -- Plotting the total direct irradiation over a range of days. +- Plotting the direct irradiation over a range of days. - Generating a CSV, JSON, or XML report detailing the optimal tilt angle over a range of days. - Calculating the sunrise and sunset hour angles for a specific day. - Utilizing Hottel's model to quantify clear-sky conditions and estimate the atmospheric transmission of clear-sky beam radiation. diff --git a/docs/getting_started.rst b/docs/getting_started.rst index 867192e..df5b201 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -13,10 +13,10 @@ The easiest way to install ``pysolorie`` is from PyPI. python3 -m pip install pysolorie -Calculating Total Direct Irradiation for a Year ------------------------------------------------ +Calculating Direct Irradiation for a Year +----------------------------------------- -Suppose we aim to calculate the total direct irradiation for a specific location. The following code determines the total direct irradiation received by a solar panel, assuming an optimal tilt angle for each day of the year at a given location. In this scenario, the location is Tehran, Iran. +Suppose we aim to calculate the direct irradiation for a specific location. The following code determines the direct irradiation received by a solar panel, assuming an optimal tilt angle for each day of the year at a given location. In this scenario, the location is Tehran, Iran. .. code-block:: python @@ -80,7 +80,7 @@ The ``climate_type`` can be one of the following: Calculating Direct Irradiation ------------------------------ -The ``calculate_direct_irradiation`` method calculates the total direct irradiation received by a solar panel for a specified tilt angle and day of the year. +The ``calculate_direct_irradiation`` method calculates the direct irradiation received by a solar panel for a specified tilt angle and day of the year. The ``climate_type`` can be one of the following: @@ -156,10 +156,10 @@ The plot will be saved to the specified path. The ``plot_kwargs`` and ``savefig_ parameters can be used to customize the plot and the savefig function, respectively. If no path is provided, the plot will be displayed but not saved. If the path is provided, the plot will be saved to the specified path and not displayed. If you want to both display and save the plot, you should call ``plt.show()`` after this function. -Plotting the Total Direct Irradiation +Plotting the Direct Irradiation ------------------------------------- -The ``plot_total_direct_irradiation`` method plots the total direct irradiation for a range of days. +The ``plot_total_direct_irradiation`` method plots the direct irradiation for a range of days. .. code-block:: python @@ -175,7 +175,7 @@ The ``plot_total_direct_irradiation`` method plots the total direct irradiation observer_latitude=35.6892 ) - # Plot the total direct irradiation for days 60 to 70 + # Plot the direct irradiation for days 60 to 70 plotter.plot_total_direct_irradiation( irradiation_calculator, from_day=60, @@ -183,8 +183,8 @@ The ``plot_total_direct_irradiation`` method plots the total direct irradiation path=Path("results.png"), plot_kwargs={ "xlabel": "Day", - "ylabel": "Total Direct Irradiation (Megajoules per square meter)", - "title": "Total Direct Irradiation", + "ylabel": "Direct Irradiation (Megajoules per square meter)", + "title": "Direct Irradiation", }, savefig_kwargs={"dpi": 300}, ) @@ -346,10 +346,10 @@ and the ``hour_angle`` method calculates the hour angle given the solar time. This will print the solar declination and hour angle in radians. For example, on January 1st at 1pm, the solar declination is approximately ``-0.401`` radians and the hour angle is approximately ``0.262`` radians. -Calculating Transmittance Components with the Hottel Model ----------------------------------------------------------- +Calculating Transmittance Components with the Hottel's Model +------------------------------------------------------------ -The Hottel Model is used for estimating clear-sky beam radiation transmittance based on climate type and observer altitude. The `calculate_transmittance_components` method of the `HottelModel` class calculates the components of clear-sky beam radiation transmittance :math:`a_0`, :math:`a_1`, and :math:`k` based on climate type and observer altitude. +The Hottel's model is used for estimating clear-sky beam radiation transmittance based on climate type and observer altitude. The `calculate_transmittance_components` method of the `HottelModel` class calculates the components of clear-sky beam radiation transmittance :math:`a_0`, :math:`a_1`, and :math:`k` based on climate type and observer altitude. .. code-block:: python diff --git a/docs/index.rst b/docs/index.rst index 4128868..849feed 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -31,7 +31,7 @@ In our case, we are using Hottel's model to estimate the transmittance of direct - Finding the optimal tilt angle for a fixed solar panel, assuming a clear-sky condition. - Plotting the optimal tilt angle over a range of days. -- Plotting the total direct irradiation over a range of days. +- Plotting the direct irradiation over a range of days. - Generating a CSV, JSON, or XML report detailing the optimal tilt angle over a range of days. - Calculating the sunrise and sunset hour angles for a specific day. - Utilizing Hottel's model to quantify clear-sky conditions and estimate the atmospheric transmission of clear-sky beam radiation. diff --git a/docs/reference/pysolorie.numerical_integration.rst b/docs/reference/pysolorie.numerical_integration.rst index fe4c7cb..1b8c52c 100644 --- a/docs/reference/pysolorie.numerical_integration.rst +++ b/docs/reference/pysolorie.numerical_integration.rst @@ -1,5 +1,5 @@ -Total Direct Irradiation -======================== +Direct Irradiation +================== .. automodule:: pysolorie.numerical_integration :members: diff --git a/src/pysolorie/numerical_integration.py b/src/pysolorie/numerical_integration.py index d5b2bc7..7d48017 100644 --- a/src/pysolorie/numerical_integration.py +++ b/src/pysolorie/numerical_integration.py @@ -26,7 +26,7 @@ class IrradiationCalculator: r""" A class to find the optimal orientation and - calculate the total direct irradiation for a solar panel [1]_. + calculate the direct irradiation for a solar panel [1]_. References ---------- @@ -111,13 +111,13 @@ def calculate_direct_irradiation( self, panel_orientation: float, day_of_year: int ) -> float: r""" - Calculate the total direct irradiation + Calculate the direct irradiation for a given solar panel orientation (i.e., :math:`\beta`). - | The total direct irradiation is calculated using the formula: + | The direct irradiation is calculated using the formula: .. math:: - E(n,\phi) = \frac{I}{\Omega} \int_{\omega_s}^{\omega_t} + E(n,\phi) = \frac{I(n)}{\Omega} \int_{\omega_s}^{\omega_t} \cos(\theta) \times H(\cos(\theta)) \times \tau_b~d\omega @@ -125,8 +125,9 @@ def calculate_direct_irradiation( | - :math:`\phi` is the latitude of the observer - | - :math:`I` is the amount of - solar energy received per unit area per second. + | - :math:`I(n)` is the amount of + solar energy received per unit area per second + on day number :math:`n` of the year | - :math:`\Omega` = ``7.15 * 1e-5`` @@ -144,7 +145,7 @@ def calculate_direct_irradiation( :type panel_orientation: float :param day_of_year: The day of the year. :type day_of_year: int - :return: The total direct irradiation in Megajoules per square meter. + :return: The direct irradiation in Megajoules per square meter. :rtype: float """ sunrise_hour_angle, sunset_hour_angle = self._observer.calculate_sunrise_sunset( @@ -162,7 +163,7 @@ def calculate_direct_irradiation( def find_optimal_orientation(self, day_of_year: int) -> float: """ Find the optimal orientation :math:`beta` that maximizes - the total direct irradiation. + the direct irradiation. :param day_of_year: The day of the year. :type day_of_year: int From adfe4863d777e75adcf0b2dfc024da21b75fd506 Mon Sep 17 00:00:00 2001 From: Alireza Aghamohammadi Date: Sun, 24 Dec 2023 20:26:46 +0330 Subject: [PATCH 03/13] Refactor code and update README - Added SonarCloud badge to README - Updated 'plotter.py' to remove unused 'fig' variable - Renamed 'Total Direct Irradiation' to 'Direct Irradiation' in 'report.py' --- README.md | 5 ++++- src/pysolorie/plotter.py | 2 +- src/pysolorie/report.py | 12 ++++++------ tests/test_report.py | 16 +++++++--------- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index d9cfaec..48e6a2d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # pysolorie -[![CodeQL](https://github.com/aaghamohammadi/pysolorie/actions/workflows/github-code-scanning/codeql/badge.svg?branch=main)](https://github.com/aaghamohammadi/pysolorie/actions/workflows/github-code-scanning/codeql) [![Quality Checks](https://github.com/aaghamohammadi/pysolorie/actions/workflows/quality_checks.yml/badge.svg?branch=main)](https://github.com/aaghamohammadi/pysolorie/actions/workflows/quality_checks.yml) [![Publish](https://github.com/aaghamohammadi/pysolorie/actions/workflows/publish.yml/badge.svg?branch=main)](https://github.com/aaghamohammadi/pysolorie/actions/workflows/publish.yml) +[![CodeQL](https://github.com/aaghamohammadi/pysolorie/actions/workflows/github-code-scanning/codeql/badge.svg?branch=main)](https://github.com/aaghamohammadi/pysolorie/actions/workflows/github-code-scanning/codeql) ![GitHub License](https://img.shields.io/github/license/aaghamohammadi/pysolorie) ![PyPI - Downloads](https://img.shields.io/pypi/dm/pysolorie) [![Documentation Status](https://readthedocs.org/projects/pysolorie/badge/?version=latest)](https://pysolorie.readthedocs.io/en/latest/?badge=latest) @@ -13,6 +13,9 @@ ![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white) ![code style: black](https://img.shields.io/badge/code%20style-black-black) +[![SonarCloud](https://sonarcloud.io/images/project_badges/sonarcloud-white.svg)](https://sonarcloud.io/summary/new_code?id=aaghamohammadi_pysolorie) + + **pysolorie** stands for **Py**thon **Sol**ar **Orie**ntation Analysis of Solar Panel. It is a Python library designed to help you analyze the orientation of solar panels. diff --git a/src/pysolorie/plotter.py b/src/pysolorie/plotter.py index 14d82f3..a3df8ef 100644 --- a/src/pysolorie/plotter.py +++ b/src/pysolorie/plotter.py @@ -135,7 +135,7 @@ def _plot( savefig_kwargs: Dict[str, str], ) -> None: figsize = plot_kwargs.get("figsize", (10, 6)) - fig, ax = plt.subplots(figsize=figsize) + _, ax = plt.subplots(figsize=figsize) ax.plot(days, betas) ax.set_xlabel(plot_kwargs.get("xlabel", "X Axis Title")) ax.set_ylabel(plot_kwargs.get("ylabel", "Y Axis Title")) diff --git a/src/pysolorie/report.py b/src/pysolorie/report.py index 87055aa..c4455f2 100644 --- a/src/pysolorie/report.py +++ b/src/pysolorie/report.py @@ -69,7 +69,7 @@ def _calculate_optimal_orientation_and_irradiation( { "Day": day, "Beta (degrees)": beta, - "Total Direct Irradiation " + "Direct Irradiation " "(Megajoules per square meter)": total_direct_irradiation, } ) @@ -109,7 +109,7 @@ def generate_optimal_orientation_csv_report( [ "Day", "Beta (degrees)", - "Total Direct Irradiation (Megajoules per square meter)", + "Direct Irradiation (Megajoules per square meter)", ] ) @@ -118,7 +118,7 @@ def generate_optimal_orientation_csv_report( [ row["Day"], row["Beta (degrees)"], - row["Total Direct Irradiation (Megajoules per square meter)"], + row["Direct Irradiation (Megajoules per square meter)"], ] ) @@ -189,12 +189,12 @@ def generate_optimal_orientation_xml_report( day_element = ET.SubElement(root, "Day") day_element.set("id", str(row["Day"])) - # Create 'Beta' and 'TotalDirectIrradiation' elements for each day + # Create 'Beta' and 'DirectIrradiation' elements for each day beta_element = ET.SubElement(day_element, "Beta") beta_element.text = str(row["Beta (degrees)"]) - tdi_element = ET.SubElement(day_element, "TotalDirectIrradiation") + tdi_element = ET.SubElement(day_element, "DirectIrradiation") tdi_element.text = str( - row["Total Direct Irradiation (Megajoules per square meter)"] + row["Direct Irradiation (Megajoules per square meter)"] ) # Write the XML data to the file diff --git a/tests/test_report.py b/tests/test_report.py index 2549979..6c3f1a8 100644 --- a/tests/test_report.py +++ b/tests/test_report.py @@ -53,7 +53,7 @@ def test_generate_optimal_orientation_csv_report(caplog, tmpdir) -> None: assert header == [ "Day", "Beta (degrees)", - "Total Direct Irradiation (Megajoules per square meter)", + "Direct Irradiation (Megajoules per square meter)", ] for i, row in enumerate(reader, start=from_day): day, beta, total_direct_irradiation = ( @@ -107,21 +107,21 @@ def test_generate_optimal_orientation_json_report(caplog, tmpdir) -> None: with open(json_path, "r") as file: data = json.load(file) for i, row in enumerate(data, start=from_day): - day, beta, total_direct_irradiation = ( + day, beta, direct_irradiation = ( row["Day"], row["Beta (degrees)"], - row["Total Direct Irradiation (Megajoules per square meter)"], + row["Direct Irradiation (Megajoules per square meter)"], ) assert day == i expected_beta = irradiation_calculator.find_optimal_orientation(i) - expected_total_direct_irradiation = ( + expected_direct_irradiation = ( irradiation_calculator.calculate_direct_irradiation(beta, i) ) assert pytest.approx(beta, abs=1e-3) == expected_beta assert ( - pytest.approx(total_direct_irradiation, abs=1e-3) - == expected_total_direct_irradiation + pytest.approx(direct_irradiation, abs=1e-3) + == expected_direct_irradiation ) # Check the logs for day in range(from_day, to_day): @@ -160,9 +160,7 @@ def test_generate_optimal_orientation_xml_report(caplog, tmpdir) -> None: for i, day_element in enumerate(root.findall("Day"), start=from_day): day = int(day_element.get("id")) beta = float(day_element.find("Beta").text) - total_direct_irradiation = float( - day_element.find("TotalDirectIrradiation").text - ) + total_direct_irradiation = float(day_element.find("DirectIrradiation").text) assert day == i expected_beta = irradiation_calculator.find_optimal_orientation(i) From 84bdd10f08937d02b3862d61e53284588f773979 Mon Sep 17 00:00:00 2001 From: Alireza Aghamohammadi Date: Mon, 25 Dec 2023 16:56:08 +0330 Subject: [PATCH 04/13] Update contributing.rst to remove $ from bash commands and clarify pull request guidelines - Removing the $ symbol from the start of bash commands for easier copy-pasting. - Adding a note to clarify that pull requests should be created for the dev branch, not the main branch. --- docs/contributing.rst | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index f899790..ccefaa7 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -26,9 +26,9 @@ It is highly recommended to use ``virtualenv`` for the development. ``virtualenv .. code-block:: bash - $ python3 -m venv .venv - $ source .venv/bin/activate - $ pip install -r dev-requirements.txt + python3 -m venv .venv + source .venv/bin/activate + pip install -r dev-requirements.txt 5. **Install pre-commit**: @@ -37,7 +37,7 @@ remote repository. ``pre-commit`` is a tool that manages and maintains multi-lan .. code-block:: bash - $ pre-commit install + pre-commit install Running Tests @@ -56,31 +56,31 @@ For example, to run the linter, you would use the following command: .. code-block:: bash - $ tox -e lint + tox -e lint If you want to reformat the source code. You can use the following command: .. code-block:: bash - $ tox -e format -- src tests + tox -e format -- src tests To verify the correctness of the formatting, execute the command below: .. code-block:: bash - $ tox -e format + tox -e format To check the types in the code with mypy, use this: .. code-block:: bash - $ tox -e typecheck + tox -e typecheck To run unit tests for the python, e.g., python 3.10, you can run this command: .. code-block:: bash - $ tox -e py310 + tox -e py310 Submitting Your Contributions ----------------------------- @@ -92,6 +92,7 @@ We welcome and appreciate your contributions to the pysolorie project! Here are - **Adding New Features**: Contribute by introducing new features that can enhance the functionality of the project. After making your changes and ensuring all tests pass, you can submit your contributions by creating a pull request on GitHub. +Please be informed that the pull request should be created for the **dev branch**. We do not accept pull requests for the main branch. Please note, we strive to keep our dependencies to a minimum. Any addition of a new dependency should be well justified and absolutely necessary. From f411a96ebeb87aff0444c67457947e8a7c4c0932 Mon Sep 17 00:00:00 2001 From: Alireza Aghamohammadi Date: Mon, 25 Dec 2023 17:12:54 +0330 Subject: [PATCH 05/13] Add pull request template to .github directory - Describing the changes made and their motivation - Linking related issues - Specifying the type of change (bug fix, new feature, breaking change, documentation update) - Describing how the changes have been tested --- .github/pull_request_template.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..0996a2a --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,18 @@ +# Description + +Please include a summary of the changes, along with relevant motivation and context. If there are any related issues, please mention them. Also, list any dependencies required for this change. + +Fixes # (issue) + +## Type of change + +We use semantic versioning for the pysolorie project. Therefore, to determine the appropriate version, please delete the options that are not relevant. + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] This change requires a documentation update + +# How Has This Been Tested? + +Please describe the tests that you ran to verify your changes. From 8ea6d687875ae93f738278465dc978221c07b3c4 Mon Sep 17 00:00:00 2001 From: Alireza Aghamohammadi Date: Tue, 26 Dec 2023 19:03:27 +0330 Subject: [PATCH 06/13] Update references and content details for solar panel orientation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace one outdated reference in the .bib file with a relevant book by Soteris A. Kalogirou. - Correct the year information for Muhammad Iqbal's book to reflect the original publication date. - Expand the address details for the Department of Physics, University of Zanjan. - Introduce the azimuthal angle concept in the summary section of the paper. - Highlight the addition of the optimal azimuthal angle information for solar panel orientation. - Update the figures and documentation to incorporate the combined usage of Hottel’s model and direct irradiation principles. - Revise citation details to include additional relevant works in both the .md and .bib files. --- paper/paper.bib | 27 +++++++++++---------------- paper/paper.md | 16 +++++++++------- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/paper/paper.bib b/paper/paper.bib index cdf05cc..674d572 100644 --- a/paper/paper.bib +++ b/paper/paper.bib @@ -106,20 +106,15 @@ @article{Hafez2017 pages = {147–168} } - @article{Goshayeshi2019, - title={Effect of absorber plate surface shape and glass cover inclination angle on the performance of a passive solar still}, - volume={30}, - ISSN={0961-5539}, - url={http://dx.doi.org/10.1108/HFF-01-2019-0018}, - DOI={10.1108/hff-01-2019-0018}, - number={6}, - journal={International Journal of Numerical Methods for Heat & Fluid Flow}, - publisher={Emerald}, - author={Goshayeshi, Hamid Reza and Safaei, Mohammad Reza}, - year={2019}, - month=jul, - pages={3183–3198} - } +@BOOK{Kalogirou2013, + title = {Solar Energy Engineering: Processes and systems}, + ISBN = {9780123972569}, + author = {Kalogirou, Soteris A}, + publisher = {Academic Press}, + month = oct, + year = {2013} +} + @book{Goswami2015, title = {Principles of Solar Engineering}, @@ -132,13 +127,13 @@ @book{Goswami2015 month = feb } -@book{Iqbal2012, +@book{Iqbal1983, title={An Introduction to Solar Radiation}, ISBN = {9780323151818}, author={Iqbal, Muhammad}, publisher={Elsevier}, month=dec, - year={2012}, + year={1983}, language={en} } diff --git a/paper/paper.md b/paper/paper.md index 3f740cd..1209426 100644 --- a/paper/paper.md +++ b/paper/paper.md @@ -19,7 +19,7 @@ affiliations: index: 1 - name: Department of Fundamental Physics, Faculty of Physics, Alzahra University, Tehran, Iran index: 2 - - name: Department of Physics, University of Zanjan, Zanjan, Iran + - name: Department of Physics, University of Zanjan, PC 45371-38791 Zanjan, Iran index: 3 date: 21 December 2023 @@ -27,24 +27,26 @@ bibliography: paper.bib --- # Summary -How can one maximize the solar irradiation energy received by a fixed flat solar panel [@Aghamohammadi2023]? +How can one maximize the solar irradiation energy received by a fixed flat solar panel [@Aghamohammadi2023]? The orientation of a solar panel is determined by two angles: the tilt angle and the azimuthal angle [@Hafez2017]. ![Orientational angles of a flat solar panel.\label{fig:opt}](solarpanel.svg) -**pysolorie** stands for **Py**thon **Sol**ar **Orie**ntation Analysis of Solar Panels. It is a Python package designed to help you find the optimal tilt angle of solar panels, $\beta$, to maximize the energy received for a given day. Its features include but are not limited to: +**pysolorie** stands for **Py**thon **Sol**ar **Orie**ntation Analysis of Solar Panels. It is a Python package designed to help you find the optimal tilt angle of solar panels, $\beta$, to maximize the energy received for a given day. The optimal azimuthal angle is zero. + +Its features include but are not limited to: - Finding the optimal tilt angle for a fixed solar panel, assuming a clear-sky condition. - Plotting the optimal tilt angle over a range of days. - Plotting the direct irradiation over a range of days. - Generating a CSV, JSON, or XML report detailing the optimal tilt angle over a range of days. -- Utilizing Hottel's model to quantify clear-sky conditions and estimate the atmospheric transmission of clear-sky beam radiation [@Hottel1976]. +- Utilizing Hottel's model to quantify clear-sky conditions and estimate the atmospheric transmission of clear-sky beam radiation [@Hottel1976;@Iqbal1983]. # Statement of need The amount of solar irradiation energy harvested by a solar collector depends on several factors. These include the time of irradiation (both the time of day and the day of the year), the latitude and climate of the location, and the shape and orientation of the solar panel [@Foulaadvand2023]. A solar collector can be positioned at a fixed orientation to maximize energy reception for a specific time period, such as daily, weekly, monthly, or seasonally, or it can be fixed for optimal performance throughout the year. The orientation can then be adjusted for the next time period. Solar irradiation is composed of three components: the direct beam, sky diffusion, and ground reflection. For flat solar panels, we focus on direct beam irradiation, which contributes the most to solar irradiation. There are various models available for different climate types. We assume a clear sky condition with no clouds in the sky and an atmosphere free of pollutants. However, a cloudy sky or polluted air may affect the amount of solar energy received on Earth. There are some other issues which may require careful consideration and further investigation in future studies, such as panel efficiency, energy conversion, and the effects of air pollution. - In our case, we use Hottel’s model to estimate the transmittance of direct solar radiation through a clear and sunny atmosphere [@Hottel1976]. + In our case, we use Hottel’s model to estimate the transmittance of direct solar radiation through a clear and sunny atmosphere [@Hottel1976;@AntonanzasTorres2019]. With a well-defined, user-friendly, and extensible API, multiple audiences can benefit from `pysolorie`. These include solar energy researchers, solar panel manufacturers and installers, and instructors. @@ -61,9 +63,9 @@ The energy collected by a solar panel can be calculated using the formula in Equ - $n$ is the day of the year, - $\phi$ is the latitude of the observer, -- $I(n)$ is the amount of solar energy received per unit area per second [@Duffie2020] on day number $n$ of the year, +- $I(n)$ is the amount of solar energy received per unit area per second [@Duffie2020;@Goswami2015] on day number $n$ of the year, - $\Omega$ is the Earth angular velocity around its axis with the value `7.15 * 1e-5` rad/s, -- $\theta$ is the angle between the position vector of the sun and the normal vector to the solar panel (incidence angle), +- $\theta$ is the angle between the position vector of the sun and the normal vector to the solar panel (incidence angle) [@Kalogirou2013], - $\omega_s$ is the sunrise hour angle, - $\omega_t$ is the sunset hour angle, - $H$ is the Heaviside step function, From a28fa8a0c2f9a3757fb7ba532c6d686a6f2c79e2 Mon Sep 17 00:00:00 2001 From: Alireza Aghamohammadi Date: Tue, 26 Dec 2023 19:18:41 +0330 Subject: [PATCH 07/13] Add pip upgrade step in virtualenv setup of contributing.rst --- docs/contributing.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/contributing.rst b/docs/contributing.rst index ccefaa7..1066d6b 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -28,6 +28,7 @@ It is highly recommended to use ``virtualenv`` for the development. ``virtualenv python3 -m venv .venv source .venv/bin/activate + pip install --upgrade pip pip install -r dev-requirements.txt 5. **Install pre-commit**: From bc0d0c1a77d654113766732343bcac3dfcadaad1 Mon Sep 17 00:00:00 2001 From: Alireza Aghamohammadi Date: Thu, 28 Dec 2023 16:31:42 +0330 Subject: [PATCH 08/13] Refined irradiation descriptions in README and docs - Updated the description of irradiation plotting in README.md and docs/index.rst to specify 'daily direct irradiation energy' instead of 'direct irradiation'. - Enhanced the definition of 'pysolorie' in docs/index.rst to clarify that it helps maximize the 'beam energy' received by solar panels. --- README.md | 2 +- docs/index.rst | 2 +- paper/paper.md | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 48e6a2d..bf4a946 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ How can one maximize the solar irradiation energy received by a solar panel? - Finding the optimal tilt angle for a fixed solar panel, assuming a clear-sky condition. - Plotting the optimal tilt angle over a range of days. -- Plotting the direct irradiation over a range of days. +- Plotting the daily direct irradiation energy over a range of days. - Generating a CSV, JSON, or XML report detailing the optimal tilt angle over a range of days. - Calculating the sunrise and sunset hour angles for a specific day. - Utilizing Hottel's model to quantify clear-sky conditions and estimate the atmospheric transmission of clear-sky beam radiation. diff --git a/docs/index.rst b/docs/index.rst index 849feed..c65a718 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -31,7 +31,7 @@ In our case, we are using Hottel's model to estimate the transmittance of direct - Finding the optimal tilt angle for a fixed solar panel, assuming a clear-sky condition. - Plotting the optimal tilt angle over a range of days. -- Plotting the direct irradiation over a range of days. +- Plotting the daily direct irradiation energy over a range of days. - Generating a CSV, JSON, or XML report detailing the optimal tilt angle over a range of days. - Calculating the sunrise and sunset hour angles for a specific day. - Utilizing Hottel's model to quantify clear-sky conditions and estimate the atmospheric transmission of clear-sky beam radiation. diff --git a/paper/paper.md b/paper/paper.md index 1209426..1131cd8 100644 --- a/paper/paper.md +++ b/paper/paper.md @@ -31,13 +31,13 @@ How can one maximize the solar irradiation energy received by a fixed flat solar ![Orientational angles of a flat solar panel.\label{fig:opt}](solarpanel.svg) -**pysolorie** stands for **Py**thon **Sol**ar **Orie**ntation Analysis of Solar Panels. It is a Python package designed to help you find the optimal tilt angle of solar panels, $\beta$, to maximize the energy received for a given day. The optimal azimuthal angle is zero. +**pysolorie** stands for **Py**thon **Sol**ar **Orie**ntation Analysis of Solar Panels. It is a Python package designed to help you find the optimal tilt angle of solar panels, $\beta$, to maximize the beam energy received for a given day. The optimal azimuthal angle is zero. Its features include but are not limited to: - Finding the optimal tilt angle for a fixed solar panel, assuming a clear-sky condition. - Plotting the optimal tilt angle over a range of days. -- Plotting the direct irradiation over a range of days. +- Plotting the daily direct irradiation energy over a range of days. - Generating a CSV, JSON, or XML report detailing the optimal tilt angle over a range of days. - Utilizing Hottel's model to quantify clear-sky conditions and estimate the atmospheric transmission of clear-sky beam radiation [@Hottel1976;@Iqbal1983]. @@ -63,7 +63,7 @@ The energy collected by a solar panel can be calculated using the formula in Equ - $n$ is the day of the year, - $\phi$ is the latitude of the observer, -- $I(n)$ is the amount of solar energy received per unit area per second [@Duffie2020;@Goswami2015] on day number $n$ of the year, +- $I(n)$ is the amount of extraterrestrial solar energy received per unit area per second [@Duffie2020;@Goswami2015] on day number $n$ of the year, - $\Omega$ is the Earth angular velocity around its axis with the value `7.15 * 1e-5` rad/s, - $\theta$ is the angle between the position vector of the sun and the normal vector to the solar panel (incidence angle) [@Kalogirou2013], - $\omega_s$ is the sunrise hour angle, From 9403b81ac0a839bf3ee861b6aeeb52bee4079686 Mon Sep 17 00:00:00 2001 From: Alireza Aghamohammadi Date: Thu, 28 Dec 2023 17:24:57 +0330 Subject: [PATCH 09/13] Handle edge cases for sunrise/sunset calculations and direct irradiation in polar regions - Add special case handling in `IrradiationCalculator` for conditions during the polar night where no direct irradiation occurs by returning zero - Implement checks for invalid `tan_product` values in `Observer` leading to exceptions for sunrise and sunset hour angles, providing correct behavior during the Midnight Sun and Polar Night scenarios - Introduce logging for significant solar events such as endless day or night - Extend `test_calculate_direct_irradiation` and `test_find_optimal_orientation` unit tests with scenarios for extreme latitudes to validate the new edge case handling - Decorate `calculate_sunrise_sunset` in `Observer` with `logger_decorator` to enable event logging --- src/pysolorie/numerical_integration.py | 7 +++++++ src/pysolorie/observer.py | 21 ++++++++++++++++++--- tests/test_numerical_integration.py | 22 ++++++++++++++++++++++ tests/test_observer.py | 17 ++++++++++++----- 4 files changed, 59 insertions(+), 8 deletions(-) diff --git a/src/pysolorie/numerical_integration.py b/src/pysolorie/numerical_integration.py index 7d48017..8a6ad93 100644 --- a/src/pysolorie/numerical_integration.py +++ b/src/pysolorie/numerical_integration.py @@ -158,6 +158,13 @@ def calculate_direct_irradiation( ) for hour_angle in np.arange(sunrise_hour_angle, sunset_hour_angle, 0.01) ] + + # During polar night, the sun doesn't rise and both hour angles are zero. + # This results in an empty irradiance_components list. In this case, + # we return 0 as there is no direct irradiation. + if not irradiance_components: + return 0 + return integrate.simpson(irradiance_components, dx=0.01) def find_optimal_orientation(self, day_of_year: int) -> float: diff --git a/src/pysolorie/observer.py b/src/pysolorie/observer.py index 383df6e..8d3d5dd 100644 --- a/src/pysolorie/observer.py +++ b/src/pysolorie/observer.py @@ -16,6 +16,7 @@ from typing import Optional from .exceptions import MissingObserverLatitudeError +from .logger import logger_decorator from .sun_position import SunPosition @@ -76,6 +77,7 @@ def calculate_zenith_angle(self, day_of_year: int, solar_time: float) -> float: * math.cos(hour_angle) ) + @logger_decorator def calculate_sunrise_sunset(self, day_of_year: int) -> tuple: r""" Calculate the hour angle at sunrise and sunset. @@ -98,9 +100,22 @@ def calculate_sunrise_sunset(self, day_of_year: int) -> tuple: observer_latitude = self._ensure_latitude_provided() solar_declination = self.sun_position.solar_declination(day_of_year) - hour_angle = math.acos( - -math.tan(observer_latitude) * math.tan(solar_declination) - ) + + tan_product = -math.tan(observer_latitude) * math.tan(solar_declination) + + if tan_product > 1: + self.logger.info( # type: ignore + "In winter, there is no sunrise or sunset (Polar Night)" + ) + return 0, 0 + + if tan_product < -1: + self.logger.info( # type: ignore + "In summer, the sun does not set (Midnight Sun)" + ) + return -math.pi, math.pi + + hour_angle = math.acos(tan_product) sunrise = -hour_angle sunset = hour_angle diff --git a/tests/test_numerical_integration.py b/tests/test_numerical_integration.py index d64d6e7..a81667c 100644 --- a/tests/test_numerical_integration.py +++ b/tests/test_numerical_integration.py @@ -57,6 +57,14 @@ 45.0, 21.371, # Fairbanks Summer, day_of_year=200 (July 19) ), + ( + "SUBARCTIC SUMMER", + 356, + 70.00, + 355, + 45.0, + 0, # Finnmark Winter, day_of_year=355 (December 21) + ), ], ) def test_calculate_direct_irradiation( @@ -107,6 +115,20 @@ def test_calculate_direct_irradiation( 200, 32.614, ), # Fairbanks Summer, day_of_year=200 (July 19) + ( + "SUBARCTIC SUMMER", + 356, + 70.00, + 355, + 90, # Finnmark Winter, day_of_year=355 (December 21) + ), + ( + "SUBARCTIC SUMMER", + 356, + 70.00, + 172, + 31.505, # Finnmark Summer, day_of_year=172 (June 21) + ), ], ) def test_find_optimal_orientation( diff --git a/tests/test_observer.py b/tests/test_observer.py index 5842f63..f1f78dc 100644 --- a/tests/test_observer.py +++ b/tests/test_observer.py @@ -89,19 +89,26 @@ def test_calculate_zenith_angle_without_latitude(): @pytest.mark.parametrize( - "day_of_year, expected_sunrise_hour_angle, expected_sunset_hour_angle", + "observer_latitude," + + "day_of_year," + + "expected_sunrise_hour_angle," + + "expected_sunset_hour_angle", [ - (1, -1.261, 1.261), # January 1st - (81, -math.pi / 2, math.pi / 2), # March 22nd (equinox) - (172, -1.888, 1.888), # June 21st (solstice) + (35.69, 1, -1.261, 1.261), # January 1st, Tehran + (35.69, 81, -math.pi / 2, math.pi / 2), # March 22nd (equinox), Tehran + (35.69, 172, -1.888, 1.888), # June 21st (solstice), Tehran + (70.00, 1, 0, 0), # January 1st, Finnmark + (70.00, 81, -math.pi / 2, math.pi / 2), # March 22nd (equinox), Finnmark + (70.00, 172, -math.pi, math.pi), # June 21st (solstice), Finnmark ], ) def test_calculate_sunrise_sunset( + observer_latitude: float, day_of_year: int, expected_sunrise_hour_angle: float, expected_sunset_hour_angle: float, ) -> None: - observer: Observer = Observer(observer_latitude=35.69) # Tehran + observer: Observer = Observer(observer_latitude=observer_latitude) sunrise_hour_angle, sunset_hour_angle = observer.calculate_sunrise_sunset( day_of_year ) From 4fbef9cf055ace112f8b074045108204a6d63aec Mon Sep 17 00:00:00 2001 From: Alireza Aghamohammadi Date: Thu, 28 Dec 2023 17:52:41 +0330 Subject: [PATCH 10/13] Fix the typo --- docs/getting_started.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/getting_started.rst b/docs/getting_started.rst index df5b201..1243e3a 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -23,7 +23,7 @@ Suppose we aim to calculate the direct irradiation for a specific location. The from pysolorie import IrradiationCalculator # Instantiate an IrradiationCalculator object for the city of Tehran - calculator = IrradiationCalculator( + irradiation_calculator = IrradiationCalculator( climate_type="MIDLATITUDE SUMMER", observer_altitude=1200, observer_latitude=35.6892 @@ -36,9 +36,9 @@ Suppose we aim to calculate the direct irradiation for a specific location. The # Loop over each day of the year for day in range(from_day, to_day + 1): # Find the optimal tilt angle for the given day - optimal_tilt_angle = calculator.find_optimal_orientation(day) + optimal_tilt_angle = irradiation_calculator.find_optimal_orientation(day) # Calculate the direct irradiation for the given day and add it to the total - total_irradiation += calculator.calculate_direct_irradiation( + total_irradiation += irradiation_calculator.calculate_direct_irradiation( optimal_tilt_angle, day ) @@ -65,7 +65,7 @@ The ``climate_type`` can be one of the following: from pysolorie import IrradiationCalculator # Instantiate an IrradiationCalculator object for the city of Tehran - calculator = IrradiationCalculator( + irradiation_calculator = IrradiationCalculator( climate_type="MIDLATITUDE SUMMER", observer_altitude=1200, observer_latitude=35.6892 @@ -94,7 +94,7 @@ The ``climate_type`` can be one of the following: from pysolorie import IrradiationCalculator # Instantiate an IrradiationCalculator object for the city of Tehran - calculator = IrradiationCalculator( + irradiation_calculator = IrradiationCalculator( climate_type="MIDLATITUDE SUMMER", observer_altitude=1200, observer_latitude=35.6892 From 3860142350badb1b7c1e9d88ba2bf9b61b0c7436 Mon Sep 17 00:00:00 2001 From: Alireza Aghamohammadi Date: Thu, 28 Dec 2023 17:53:34 +0330 Subject: [PATCH 11/13] Added 'shell' environment to tox configuration - Created a new 'shell' environment in the tox configuration. - This environment installs the test dependencies and starts a Python shell. - This allows for interactive testing and debugging within the tox-managed virtual environment. --- setup.cfg | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/setup.cfg b/setup.cfg index 2d532a9..167b544 100644 --- a/setup.cfg +++ b/setup.cfg @@ -105,3 +105,9 @@ deps = sphinx-copybutton commands = sphinx-build -W -b html docs/ docs/_build/ + +[testenv:shell] +deps = + .[test] # Install the test dependencies +commands = + python From b19aa236612e6f7c63af615e15620a9e84dfe28b Mon Sep 17 00:00:00 2001 From: Alireza Aghamohammadi Date: Thu, 28 Dec 2023 18:03:42 +0330 Subject: [PATCH 12/13] Ready to publish v1.5.3 --- docs/changelog.rst | 37 +++++++++++++++++++++++++++++++++++++ setup.cfg | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 974f61b..9d56d38 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,43 @@ Changelog ========= +Changelog +========= + +Version 1.5.3 +------------- + +Release date: 2023-12-28 + +Changed +^^^^^^^ + +- Improved documentation and code comments to clarify the calculation and representation of direct irradiation, rather than total direct irradiation. +- Standardized exception handling in the ``observer.py`` by decorating relevant methods, ensuring consistency in logging exceptions. +- Made code improvements in ``tests/test_*`` files for comprehensive coverage and robust testing of the solar irradiation logic under different geographical and temporal conditions. + +Fixed +^^^^^ +- Modified ``numerical_integration.py`` to return 0 for direct irradiation during the polar night when the sun does not rise. +- Addressed improper handling of zero values for sunrise and sunset hour angles representing extreme latitude scenarios (Midnight Sun and Polar Night). +- Enhanced the ``observer.py`` to handle cases of Midnight Sun and Polar Night with appropriate logging for exceptional circumstances. +- Fixed issues with missing logger instances in ``plotter.py`` by correctly setting up decorators and ensuring log messages are adequately recorded. + +Documentation +^^^^^^^^^^^^^ +- Refactored ``README.md`` for syntactical accuracy in the representation of solar irradiance and optimized the explanation of solar panel orientation. +- Updated all instances in documentation where "total direct irradiation" was mentioned to "direct irradiation" to maintain consistency with the recent code updates. +- Included explanation for Midnight Sun and Polar Night phenomena in solar irradiance context to educate users about edge cases in solar panel energy calculations. +- Refined code examples and added clarifications on special cases where zero irradiation is expected, enhancing the user's understanding. + +Testing +^^^^^^^ + +- Expanded the test suite to cover new scenarios, like polar regions and edge calendar days where the sun's behavior significantly differs (e.g., Midnight Sun and Polar Night). +- Implemented additional assertions in unit tests to cover the new edge cases introduced by the recent geographic and temporal scenarios handled in the update. + + + Version 1.5.2 ------------- diff --git a/setup.cfg b/setup.cfg index 167b544..71f65d6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = pysolorie -version = 1.5.2 +version = 1.5.3 description = Orientation Analysis of Solar Panel long_description = file: README.md long_description_content_type = text/markdown From 0182922380b01997dcac9771539a0e7cf7c78d9a Mon Sep 17 00:00:00 2001 From: Alireza Aghamohammadi Date: Thu, 28 Dec 2023 18:03:42 +0330 Subject: [PATCH 13/13] Ready to publish v1.5.3 --- docs/changelog.rst | 34 ++++++++++++++++++++++++++++++++++ setup.cfg | 2 +- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 974f61b..3ef799c 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,40 @@ Changelog ========= +Version 1.5.3 +------------- + +Release date: 2023-12-28 + +Changed +^^^^^^^ + +- Improved documentation and code comments to clarify the calculation and representation of direct irradiation, rather than total direct irradiation. +- Standardized exception handling in the ``observer.py`` by decorating relevant methods, ensuring consistency in logging exceptions. +- Made code improvements in ``tests/test_*`` files for comprehensive coverage and robust testing of the solar irradiation logic under different geographical and temporal conditions. + +Fixed +^^^^^ +- Modified ``numerical_integration.py`` to return 0 for direct irradiation during the polar night when the sun does not rise. +- Addressed improper handling of zero values for sunrise and sunset hour angles representing extreme latitude scenarios (Midnight Sun and Polar Night). +- Enhanced the ``observer.py`` to handle cases of Midnight Sun and Polar Night with appropriate logging for exceptional circumstances. +- Fixed issues with missing logger instances in ``plotter.py`` by correctly setting up decorators and ensuring log messages are adequately recorded. + +Documentation +^^^^^^^^^^^^^ +- Refactored ``README.md`` for syntactical accuracy in the representation of solar irradiance and optimized the explanation of solar panel orientation. +- Updated all instances in documentation where "total direct irradiation" was mentioned to "direct irradiation" to maintain consistency with the recent code updates. +- Included explanation for Midnight Sun and Polar Night phenomena in solar irradiance context to educate users about edge cases in solar panel energy calculations. +- Refined code examples and added clarifications on special cases where zero irradiation is expected, enhancing the user's understanding. + +Testing +^^^^^^^ + +- Expanded the test suite to cover new scenarios, like polar regions and edge calendar days where the sun's behavior significantly differs (e.g., Midnight Sun and Polar Night). +- Implemented additional assertions in unit tests to cover the new edge cases introduced by the recent geographic and temporal scenarios handled in the update. + + + Version 1.5.2 ------------- diff --git a/setup.cfg b/setup.cfg index 167b544..71f65d6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = pysolorie -version = 1.5.2 +version = 1.5.3 description = Orientation Analysis of Solar Panel long_description = file: README.md long_description_content_type = text/markdown