Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions .github/workflows/pytest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,27 @@ jobs:

runs-on: ubuntu-latest
strategy:
fail-fast: true # don't cancel other matrix jobs when one fails
fail-fast: false # don't cancel other matrix jobs when one fails
matrix:
python-version: ["3.8", "3.11"]
python-version: ["3.10"]
# Test two environments:
# 1) dependencies with pinned versions from requirements.txt
# 2) 'pip install --upgrade --upgrade-strategy=eager .' to install upgraded
# dependencies from PyPi using version ranges defined within setup.py
# dependencies from PyPI using version ranges defined within pyproject.toml
env: [
'-r requirements.txt .[all]',
'--upgrade --upgrade-strategy=eager .[all]'
'-r requirements.txt .[all]'
]
include:
- python-version: "3.13"
env: '--upgrade --upgrade-strategy=eager .[all]'
- python-version: "3.14"
env: '--upgrade --upgrade-strategy=eager .[all]'

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

Expand Down
22 changes: 17 additions & 5 deletions bifacialvf/bifacialvf.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ def readInputTMY(TMYtoread):
----------
TMYtoread: TMY3 .csv weather file, which can be downloaded at http://rredc.nrel.gov/solar/old_data/nsrdb/1991-2005/tmy3/by_state_and_city.html
Also .epw weather files, which can be downloaded here: https://energyplus.net/weather and here: http://re.jrc.ec.europa.eu/pvg_tools/en/tools.html#TMY

Returns
as well as NSRDB PSM4 files, which can be downloaded here: https://developer.nlr.gov/docs/solar/nsrdb/
dataframe, meta

'''
Expand All @@ -61,7 +60,11 @@ def _tmy_reader(TMYtoread):
(myTMY3,meta)=pvlib.iotools.read_tmy3(TMYtoread, map_variables=True)
except TypeError:
(myTMY3,meta)=pvlib.iotools.read_tmy3(TMYtoread)
except ValueError:
# try PSM3 format (e.g. NSRDB download) - read_tmy3 fails on its header
(myTMY3,meta) = pvlib.iotools.read_nsrdb_psm4(TMYtoread, map_variables=True)
return(myTMY3,meta)


if TMYtoread is None: # if no file passed in, the readtmy3 graphical file picker will open.
(myTMY3,meta)=_tmy_reader(TMYtoread) # , coerce_year=2001
Expand All @@ -77,10 +80,19 @@ def _tmy_reader(TMYtoread):

myTMY3.rename(columns={'dni':'DNI', 'ghi':'GHI',
'dhi':'DHI',
'Temperature':'DryBulb',
'temp_air':'DryBulb',
'Tdry':'DryBulb',
'wind_speed':'Wspd',
'Wind Speed':'Wspd',
'Surface albedo':'Alb',
'albedo': 'Alb'}, inplace=True)


if "Time Zone" in meta:
meta["TZ"] = meta.pop("Time Zone")
if "City" in meta:
meta["city"] = meta.pop("City")

return myTMY3, meta

def fixintervalTMY(myTMY3, meta):
Expand Down Expand Up @@ -548,7 +560,7 @@ def simulate(myTMY3, meta, writefiletitle=None, tilt=0, sazm=180,
# TODO: Modify so it works with axis_azm different of 0
# (sazm = 90 or 270 only)
if tracking == True:
if sazm == 270.0:
if np.sin(sazm/180 * math.pi) < 0:
rangestart = sensorsy-1
rangeend = -1
steprange = -1
Expand Down Expand Up @@ -576,7 +588,7 @@ def simulate(myTMY3, meta, writefiletitle=None, tilt=0, sazm=180,
outputvalues.append(D)

if agriPV:
outputvalues.append(str(rearGroundGHI).replace(',', ''))
outputvalues.append("[" + ' '.join([str(round(float(v), 4)) for v in rearGroundGHI]) + "]")

Comment thread
cdeline marked this conversation as resolved.
sw.writerow(outputvalues)

Expand Down
17,523 changes: 17,523 additions & 0 deletions bifacialvf/data/Golden_CO_nsrdb-GOES-30.csv

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion bifacialvf/loadVFresults.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,13 @@ def loadVFresults(filename=None):



import numpy as np
data = pd.read_csv(filename, skiprows=1, header=1)


if 'Ground Irradiance Values' in data.columns:
data['Ground Irradiance Values'] = data['Ground Irradiance Values'].apply(
lambda s: np.fromstring(s.strip('[]').replace(',', ' '), sep=' ') if isinstance(s, str) else s)

return data, meta
#
#class Program:
Expand Down
21 changes: 19 additions & 2 deletions bifacialvf/tests/test_bifacialvf.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,21 @@ def test_endtoend():
assert np.allclose(list(round(data['GTIBackavg'][1:4],1)), list(round(data_Marion['GTIBackavg'][1:4],1)))
assert np.allclose(list(round(data['GTIbackBroadBand'][1:10],1)), list(round(data_Marion['GTIbackBroadBand'][1:10],1)))


# Load 30-minute Golden data
TMYtoread2=os.path.join(DATADIR,"Golden_CO_nsrdb-GOES-30.csv") # VA Richmond 724010TYA.csv
writefiletitle2=os.path.join(DATADIR,"_Golden_30.csv")
myPSM, meta2 = bifacialvf.bifacialvf.readInputTMY(TMYtoread2)
myPSM_2 = myPSM.iloc[0:48].copy()
# Simulate just the first 24 hours of the Golden data file
bifacialvf.simulate(myPSM_2, meta2, writefiletitle=writefiletitle2,
tilt=tilt, sazm=sazm, pitch=pitch, clearance_height=clearance_height,
rowType=rowType, transFactor=transFactor, sensorsy=sensorsy,
PVfrontSurface=PVfrontSurface, PVbackSurface=PVbackSurface,
albedo=albedo, tracking=tracking, backtrack=backtrack,
limit_angle=limit_angle, deltastyle=deltastyle)
(data2, metadata2) = loadVFresults(writefiletitle2)
assert np.round(data2.No_1_RowBackGTI.mean(),3) == 20.508

def test_1axis_endtoend():
'''
end to end test, first 24 hours of VA Richmond .EPW file
Expand Down Expand Up @@ -128,6 +142,7 @@ def test_1axis_endtoend():
tracking=True
backtrack=True
limit_angle = 60
agriPV = True

deltastyle = 'TMY3'
# Calculate PV Output Through Various Methods
Expand All @@ -143,7 +158,7 @@ def test_1axis_endtoend():
rowType=rowType, transFactor=transFactor, sensorsy=sensorsy,
PVfrontSurface=PVfrontSurface, PVbackSurface=PVbackSurface,
albedo=albedo, tracking=tracking, backtrack=backtrack,
limit_angle=limit_angle, deltastyle=deltastyle)
limit_angle=limit_angle, deltastyle=deltastyle, agriPV=agriPV)

#Load the results from the resultfile
from bifacialvf import loadVFresults
Expand All @@ -154,6 +169,8 @@ def test_1axis_endtoend():
data['GTIBackavg'] = data[['No_1_RowBackGTI', 'No_2_RowBackGTI','No_3_RowBackGTI','No_4_RowBackGTI','No_5_RowBackGTI','No_6_RowBackGTI']].mean(axis=1)
assert np.allclose(data['GTIFrontavg'].array, TRACKED_ENDTOEND_GTIFRONT)
assert np.allclose(data['GTIBackavg'].array, TRACKED_ENDTOEND_GTIBACK)
assert np.round(np.mean(data['Ground Irradiance Values'].iloc[6]),1) == 111.2


def test_bilininterpol():
import pandas as pd
Expand Down
2 changes: 1 addition & 1 deletion bifacialvf/vf.py
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,7 @@ def getFrontSurfaceIrradiances(rowType, maxShadow, PVfrontSurface, beta, sazm,
print( "division is Nan")


iStopIso = int(round(np.float64((math.pi - beta - elvUP)) / DTOR)) # Last whole degree in arc range that sees sky, first is 0
iStopIso = min(180, int(round(np.float64((math.pi - beta - elvUP)) / DTOR))) # Last whole degree in arc range that sees sky, first is 0
#Console.WriteLine("iStopIso = 0", iStopIso);
iHorBright = int(round(max(0.0, 6.0 - elvUP / DTOR))); # Number of whole degrees for which horizon brightening occurs
iStartGrd = int(round((math.pi - beta + elvDOWN) / DTOR)); # First whole degree in arc range that sees ground, last is 180
Expand Down
Binary file removed docs/sphinx/source/.index.rst.swp
Binary file not shown.
Binary file removed docs/sphinx/source/.index.rst.un~
Binary file not shown.
Binary file removed docs/sphinx/source/.installation.rst.un~
Binary file not shown.
Binary file removed docs/sphinx/source/.whatsnew.rst.un~
Binary file not shown.
13 changes: 6 additions & 7 deletions docs/sphinx/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ def __getattr__(cls, name):
if not on_rtd: # only import and set the theme if we're building docs locally
import sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
else:
html_theme = 'default'

Expand All @@ -144,7 +143,7 @@ def __getattr__(cls, name):

# A workaround for the responsive tables always having annoying scrollbars.
def setup(app):
app.add_stylesheet("no_scrollbars.css")
app.add_css_file("no_scrollbars.css")

"""
# -- Options for LaTeX output ---------------------------------------------
Expand Down Expand Up @@ -189,11 +188,11 @@ def setup(app):
#latex_domain_indices = True
"""
# extlinks alias
extlinks = {'issue': ('https://github.com/NREL/bifacialvf/issues/%s', 'GH'),
'pull': ('https://github.com/NREL/bifacialvf/pull/%s', 'GH'),
'wiki': ('https://github.com/NREL/bifacialvf/wiki/%s', 'wiki '),
'doi': ('http://dx.doi.org/%s', 'DOI: '),
'ghuser': ('https://github.com/%s', '@')}
extlinks = {'issue': ('https://github.com/NREL/bifacialvf/issues/%s', 'GH %s'),
'pull': ('https://github.com/NREL/bifacialvf/pull/%s', 'GH %s'),
'wiki': ('https://github.com/NREL/bifacialvf/wiki/%s', 'wiki %s'),
'doi': ('http://dx.doi.org/%s', 'DOI: %s'),
'ghuser': ('https://github.com/%s', '@%s')}
"""
# -- Options for manual page output ---------------------------------------

Expand Down
43 changes: 0 additions & 43 deletions docs/sphinx/source/index.rst~

This file was deleted.

38 changes: 0 additions & 38 deletions docs/sphinx/source/installation.rst~

This file was deleted.

25 changes: 13 additions & 12 deletions docs/sphinx/source/whatsnew.rst
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
.. _whatsnew:

************
What's New
************

These are new features and improvements of note in each release.

.. include:: whatsnew/v1.8.rst



.. _whatsnew:

************
What's New
************

These are new features and improvements of note in each release.

.. include:: whatsnew/v020.rst
.. include:: whatsnew/v1.8.rst



12 changes: 0 additions & 12 deletions docs/sphinx/source/whatsnew.rst~

This file was deleted.

Binary file removed docs/sphinx/source/whatsnew/.v0.1.8.rst.un~
Binary file not shown.
Binary file removed docs/sphinx/source/whatsnew/.v1.8.rst.un~
Binary file not shown.
8 changes: 0 additions & 8 deletions docs/sphinx/source/whatsnew/v0.1.8.rst~

This file was deleted.

28 changes: 28 additions & 0 deletions docs/sphinx/source/whatsnew/v020.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
.. _whatsnew_020:

v0.2.0 (June 22, 2026)
======================

Enhancements
~~~~~~~~~~~~
* Python version support updated: Py3.10 through Py3.14. Prior versions may still work but are untested. (:pull:`64`)
* NSRDB PSM4 files can now be loaded with bifacialvf.readInputTMY() (:issue:`55`)

Bug fixes
~~~~~~~~~
* With ``agriPV==True``, output file now prints as space separated array and reads back in as np.array object. Values rounded to 4 significant digits. (:pull:`64`)
* Azimuth=270 logic error fixed with tracking systems (:issue:`61`)
* iStopIso > 180 limit error fixed. (:issue:`53`)

Documentation
~~~~~~~~~~~~~~
* Improved pytests. (:pull:`64`)
* Updated to pyproject.toml setup file. (:pull:`64`)


Contributors
~~~~~~~~~~~~
* Silvana Ovaitt (:ghuser:`shirubana`)
* Chris Deline (:ghuser:`cdeline`)
* Mark Mikofski (:ghuser:`mikofski`)
* Kevin Anderson (:ghuser:`kandersolar`)
2 changes: 1 addition & 1 deletion docs/sphinx/source/whatsnew/v1.8.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.. _whatsnew_0108:

v1.8 (18 / 03 / 2022)
v0.1.8 (March 18, 2022)
=====================

* ``agriPV`` as input, so that .csv output has the Ground irradiance at every timestep. The ground irradiance is given in 100 segments between start of the module and start of the module in the next row.
Expand Down
17 changes: 0 additions & 17 deletions docs/sphinx/source/whatsnew/v1.8.rst~

This file was deleted.

Loading
Loading