Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/NREL/main' into development
Browse files Browse the repository at this point in the history
  • Loading branch information
cdeline committed Oct 1, 2024
2 parents facf604 + 5e7fae7 commit aae0f5d
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 70 deletions.
105 changes: 52 additions & 53 deletions bifacial_radiance/load.py
Original file line number Diff line number Diff line change
Expand Up @@ -610,8 +610,10 @@ def readconfigurationinputfile(inifile=None):
trackingParamsDict : Dictionary
torquetubeParamsDict : Dictionary
analysisParamsDict : Dictionary
cellLevelModuleParamsDict : Dictionary
cellModuleDict : Dictionary
CECMod : Dictionary
frameParamsDict : Dictionary
omegaParamsDict : Dictionary
"""

Expand All @@ -623,13 +625,17 @@ def readconfigurationinputfile(inifile=None):
import ast

def boolConvert(d):
""" convert strings 'True' and 'False' to boolean
""" convert strings 'True' and 'False' to boolean and convert numbers to float
"""
for key,value in d.items():
if value.lower() == 'true':
d[key] = True
elif value.lower() == 'false':
d[key] = False
try:
d[key] = float(value)
except ValueError:
pass
return d

if inifile is None:
Expand All @@ -654,7 +660,7 @@ def boolConvert(d):

if simulationParamsDict['selectTimes']:
if config.has_section("timeControlParamsDict"):
timeControlParamsDict = boolConvert(confdict['timeControlParamsDict'])
timeControlParamsDict = confdict['timeControlParamsDict']

if simulationParamsDict['getEPW']:
try:
Expand Down Expand Up @@ -712,6 +718,10 @@ def boolConvert(d):
except:
moduleParamsDict['zgap'] = 0.1 #Default
print("Load Warning: moduleParamsDict['zgap'] not specified, setting to default value: %s" % moduleParamsDict['zgap'] )
if 'glass' in moduleParamsDict2:
moduleParamsDict['glass'] = moduleParamsDict2['glass']
if moduleParamsDict2.get('glassEdge'):
moduleParamsDict['glassEdge'] = moduleParamsDict2['glassEdge']

try:
moduleParamsDict['customtext'] = moduleParamsDict2['customtext']
Expand All @@ -723,40 +733,18 @@ def boolConvert(d):
except:
moduleParamsDict['customObject'] = ''

if 'Efficiency' in moduleParamsDict2:
moduleParamsDict['Efficiency'] = moduleParamsDict2['Efficiency']
print("'Efficiency' input found in moduleParamsDict. This value "+
"will be propagated but is not currently used in "+
"bifacial_radiance\n.")

if 'Temp_coeff' in moduleParamsDict2:
moduleParamsDict['Temp_coeff'] = moduleParamsDict2['Temp_coeff']
print("'Temp_coeff' input found in moduleParamsDict. This value "+
"will be propagated but is not currently used in "+
"bifacial_radiance\n.")

if 'Peak_Power' in moduleParamsDict2:
moduleParamsDict['Peak_Power'] = moduleParamsDict2['Peak_Power']
print("'Peak_Power' input found in moduleParamsDict. This value "+
"will be propagated but is not currently used in "+
"bifacial_radiance\n.")

if 'Module_name' in moduleParamsDict2:
moduleParamsDict['Module_name'] = moduleParamsDict2['Module_name']
print("'Module_name' input found in moduleParamsDict. This value "+
"will be propagated but is not currently used in "+
"bifacial_radiance\n.")

if simulationParamsDict['cellLevelModule']:
if config.has_section("cellLevelModuleParamsDict"):
cellLevelModuleParamsDict = confdict['cellLevelModuleParamsDict']
cellModuleDict = confdict['cellLevelModuleParamsDict']
try: # being lazy so just validating the whole dictionary as a whole. #TODO: validate individually maybe.
cellLevelModuleParamsDict['numcellsx'] = int(cellLevelModuleParamsDict['numcellsx'])
cellLevelModuleParamsDict['numcellsy'] = int(cellLevelModuleParamsDict['numcellsy'])
cellLevelModuleParamsDict['xcell'] = round(float(cellLevelModuleParamsDict['xcell']),3)
cellLevelModuleParamsDict['xcellgap'] = round(float(cellLevelModuleParamsDict['xcellgap']),3)
cellLevelModuleParamsDict['ycell'] = round(float(cellLevelModuleParamsDict['ycell']),3)
cellLevelModuleParamsDict['ycellgap'] = round(float(cellLevelModuleParamsDict['ycellgap']),3)
cellModuleDict['numcellsx'] = int(cellModuleDict['numcellsx'])
cellModuleDict['numcellsy'] = int(cellModuleDict['numcellsy'])
cellModuleDict['xcell'] = round(float(cellModuleDict['xcell']),3)
cellModuleDict['xcellgap'] = round(float(cellModuleDict['xcellgap']),3)
cellModuleDict['ycell'] = round(float(cellModuleDict['ycell']),3)
cellModuleDict['ycellgap'] = round(float(cellModuleDict['ycellgap']),3)
if 'centerJB' in cellModuleDict:
cellModuleDict['centerJB'] = round(float(cellModuleDict['centerJB']),3)
except:
print("Load Warning: celllevelModule set to True,",\
"but celllevelModule parameters are missing/not numbers.")
Expand All @@ -771,12 +759,12 @@ def boolConvert(d):
except:
print("Attempted to load x and y instead of celllevelModule parameters,",\
"Failed, so default values for cellLevelModule will be passed")
cellLevelModuleParamsDict['numcellsx'] = 12
cellLevelModuleParamsDict['numcellsy'] = 6
cellLevelModuleParamsDict['xcell'] = 0.15
cellLevelModuleParamsDict['xcellgap'] = 0.1
cellLevelModuleParamsDict['ycell'] = 0.15
cellLevelModuleParamsDict['ycellgap'] = 0.1
cellModuleDict['numcellsx'] = 12
cellModuleDict['numcellsy'] = 6
cellModuleDict['xcell'] = 0.15
cellModuleDict['xcellgap'] = 0.1
cellModuleDict['ycell'] = 0.15
cellModuleDict['ycellgap'] = 0.1
else: # no cellleveldictionary passed
print("Load Warning: celllevelmodule selected, but no dictionary was passed in input file.",\
"attempting to proceed with regular custom module and setting celllevelmodule to false")
Expand Down Expand Up @@ -843,7 +831,14 @@ def boolConvert(d):
sceneParamsDict['customObject'] = sceneParamsDict2['customObject']

if simulationParamsDict['tracking']:
sceneParamsDict['axis_azimuth']=round(float(sceneParamsDict2['axis_azimuth']),2)
if 'axis_aziumth' in sceneParamsDict2:
azimuth = round(float(sceneParamsDict2['axis_azimuth']),2)
elif sceneParamsDict2.get('azimuth'):
azimuth = sceneParamsDict2.get('azimuth')
else:
raise Exception(f'Neither "axis_azimuth" or "azimuth" in .inifile {inifile}' )

sceneParamsDict['azimuth']=round(float(azimuth),2)
sceneParamsDict['hub_height']=round(float(sceneParamsDict2['hub_height']),2)

if config.has_section("trackingParamsDict"):
Expand Down Expand Up @@ -930,6 +925,7 @@ def boolConvert(d):
"R_sh_ref, R_s, and Adjust."
"Performance calculations, if performed, will use default module")


# Add omegas, frames, piles here
if config.has_section("omegaParamsDict"):
omegaParamsDict = confdict['omegaParamsDict']
Expand Down Expand Up @@ -986,8 +982,8 @@ def boolConvert(d):
try: analysisParamsDict
except: analysisParamsDict = None

try: cellLevelModuleParamsDict
except: cellLevelModuleParamsDict = None
try: cellModuleDict
except: cellModuleDict = None

try: CECModParamsDict
except: CECModParamsDict = None
Expand All @@ -1005,14 +1001,14 @@ def boolConvert(d):
#return returnParams
return (simulationParamsDict, sceneParamsDict, timeControlParamsDict,
moduleParamsDict, trackingParamsDict, torquetubeParamsDict,
analysisParamsDict, cellLevelModuleParamsDict, CECModParamsDict,
analysisParamsDict, cellModuleDict, CECModParamsDict,
frameParamsDict, omegaParamsDict, pilesParamsDict)


def savedictionariestoConfigurationIniFile(simulationParamsDict, sceneParamsDict,
timeControlParamsDict=None, moduleParamsDict=None,
trackingParamsDict=None, torquetubeParamsDict=None,
analysisParamsDict=None, cellLevelModuleParamsDict=None,
analysisParamsDict=None, cellModuleDict=None,
CECModParamsDict=None, frameParamsDict=None,
omegaParamsDict=None, pilesParamsDict=None,
inifilename=None):
Expand All @@ -1034,7 +1030,7 @@ def savedictionariestoConfigurationIniFile(simulationParamsDict, sceneParamsDict
Default None
analysisParamsDict
Default None,
cellLevelModuleParamsDict
cellModuleDict
Default None
Returns
Expand Down Expand Up @@ -1065,20 +1061,23 @@ def savedictionariestoConfigurationIniFile(simulationParamsDict, sceneParamsDict
try: config['analysisParamsDict'] = analysisParamsDict
except: pass

try: config['cellLevelModuleParamsDict'] = cellLevelModuleParamsDict
try: config['cellLevelModuleParamsDict'] = cellModuleDict
except: pass

try: config['CECModParamsDict'] = CECModParamsDict
except: pass

try: config['frameParamsDict'] = frameParamsDict
except: pass
if frameParamsDict:
try: config['frameParamsDict'] = frameParamsDict
except: pass

try: config['omegaParamsDict'] = omegaParamsDict
except: pass
if omegaParamsDict:
try: config['omegaParamsDict'] = omegaParamsDict
except: pass

try: config['pilesParamsDict'] = pilesParamsDict
except: pass
if pilesParamsDict:
try: config['pilesParamsDict'] = pilesParamsDict
except: pass

if inifilename is None:
inifilename = 'example.ini'
Expand Down
6 changes: 5 additions & 1 deletion bifacial_radiance/modelchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ def runModelChain(simulationParamsDict, sceneParamsDict, timeControlParamsDict=N
demo = bifacial_radiance.RadianceObj(
simulationParamsDict['simulationname'], path=testfolder) # Create a RadianceObj 'object'


# Save INIFILE in folder
inifilename = os.path.join(
simulationParamsDict['testfolder'], 'simulation.ini')
Expand Down Expand Up @@ -188,6 +189,9 @@ def runModelChain(simulationParamsDict, sceneParamsDict, timeControlParamsDict=N

else:
# Run everything through TrackerDict.
# check for deprecated axis_azimuth
if (sceneParamsDict.get('axis_azimuth') is not None) and (sceneParamsDict.get('azimuth') is None):
sceneParamsDict['azimuth'] = sceneParamsDict['axis_azimuth']

if simulationParamsDict['tracking'] == False:
trackerdict = demo.set1axis(metdata,
Expand All @@ -196,7 +200,7 @@ def runModelChain(simulationParamsDict, sceneParamsDict, timeControlParamsDict=N
azimuth=sceneParamsDict['azimuth'])
else:
trackerdict = demo.set1axis(metdata, gcr=sceneParamsDict['gcr'],
azimuth=sceneParamsDict['axis_azimuth'],
azimuth=sceneParamsDict['azimuth'],
limit_angle=trackingParamsDict['limit_angle'],
angledelta=trackingParamsDict['angle_delta'],
backtrack=trackingParamsDict['backtrack'],
Expand Down
11 changes: 7 additions & 4 deletions bifacial_radiance/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,11 @@ def __init__(self, name=None, x=None, y=None, z=None, bifi=1, modulefile=None,
except AttributeError:
self.axisofrotationTorqueTube = False
"""

# set data object attributes from datakey list.
for key in self.keys:
setattr(self, key, eval(key))

if tubeParams:
if 'bool' in tubeParams: # backward compatible with pre-0.4
tubeParams['visible'] = tubeParams.pop('bool')
Expand All @@ -189,9 +194,7 @@ def __init__(self, name=None, x=None, y=None, z=None, bifi=1, modulefile=None,
f'generated: {self._manual_text}')


# set data object attributes from datakey list.
for key in self.keys:
setattr(self, key, eval(key))


if self.modulefile is None:
self.modulefile = os.path.join('objects',
Expand Down Expand Up @@ -474,7 +477,7 @@ def addOmega(self, omega_material='Metal_Grey', omega_thickness=0.004,
recompile : Bool Rewrite .rad file and module.json file (default True)
"""
self.omega = Omega(self, omega_material=omega_material,
self.omega = Omega(module=self, omega_material=omega_material,
omega_thickness=omega_thickness,
inverted=inverted, x_omega1=x_omega1,
x_omega3=x_omega3, y_omega=y_omega,
Expand Down
11 changes: 8 additions & 3 deletions docs/sphinx/source/whatsnew/v0.4.4.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,27 @@ Bugfix Release ...

API Changes
~~~~~~~~~~~~
* New input parameter to :py:class:`~bifacial_radiance.ModuleObj and :py:class:`~bifacial_radiance.RadianceObj.makeModule`: `glassEdge`. If :py:class:`~bifacial_radiance.RadianceObj.makeModule` `glass` = True, then this extends the glass past the absorber edge by this total amount (half in each x and y direction). Default 10mm.
* Module glass thickness can be changed. In :py:class:`~bifacial_radiance.RadianceObj.makeModule`, if `glass` = True, then setting the `z` parameter will indicate the total (front + back) glass thickness with the 1mm absorber in the middle. The default is z = 10mm.
* New input parameter to :py:class:`~bifacial_radiance.ModuleObj and :py:func:`~bifacial_radiance.RadianceObj.makeModule`: `glassEdge`. If :py:class:`~bifacial_radiance.RadianceObj.makeModule` `glass` = True, then this extends the glass past the absorber edge by this total amount (half in each x and y direction). Default 10mm.
* Module glass thickness can be changed. In :py:func:`~bifacial_radiance.RadianceObj.makeModule`, if `glass` = True, then setting the `z` parameter will indicate the total (front + back) glass thickness with the 1mm absorber in the middle. The default is z = 10mm.

Enhancements
~~~~~~~~~~~~
* Conduct an automated check for proper radiance RAYPATH setting (:issue:`525`)(:pull:`537`)


Deprecations
~~~~~~~~~~~~~~
* .ini files loaded with :py:func:`bifacial_radiance.load.readconfigurationinputfile` use `azimuth` key instead of `axis_azimuth` (:issue:`438`)(:pull:`551`)

Bug fixes
~~~~~~~~~
* Fixed a major error with indexing the irradiance conditions with :py:func:`~bifacial_radiance.RadianceObj.gendaylit1axis`. This could result in the trackerdict entry being mismatched from the metdata resource. (:issue:`441`)
* versioning with setuptools_scm- set fallback_version to bifirad v0.4.3 to prevent crashes if git is not present (:issue:`535`)(:pull:`539`)
* :py:func:`bifacial_radiance.load.readconfigurationinputfile` now properly handles loading moduleObj parameters from .ini files: `glass`, `glassEdge`, `frameParamsDict`, `omegaParamsDict` (:pull:`551`)

Documentation
~~~~~~~~~~~~~~
* No longer provide a warning message when both `hub_height` and `clearance_height` are passed to :py:class:`~bifacial_radiance.AnalysisObj.moduleAnalysis` (:pull:`540`)
* No longer provide a warning message when both `hub_height` and `clearance_height` are passed to :py:func:`~bifacial_radiance.AnalysisObj.moduleAnalysis` (:pull:`540`)
* More useful __repr__ output in :py:class:`~bifacial_radiance.AnalysisObj and :py:class:`~bifacial_radiance.MetObj (:issue:`471`)

Contributors
Expand Down
2 changes: 1 addition & 1 deletion tests/ini_1axis.ini
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ albedo = 0.3
nMods = 10
nRows = 3
hub_height = 2.0
axis_azimuth = 180.0
azimuth = 180.0

[timeControlParamsDict]
starttime: 2001-01-01_1100
Expand Down
1 change: 0 additions & 1 deletion tests/ini_cell_level_module.ini
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ azimuth = 180.0
tilt = 10.0
clearance_height = 0.8
hub_height = 0.9
axis_azimuth = 180.0

[timeControlParamsDict]
starttime: 06_21_11_00
Expand Down
15 changes: 8 additions & 7 deletions tests/ini_soltec.ini
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ getEPW: True
simulationname: Demo1
moduletype: Longi
rewriteModule: True
cellLevelModule: False
cellLevelModule: True
axisofrotationTorqueTube: False
torqueTube: True
tracking: True
Expand Down Expand Up @@ -43,10 +43,13 @@ trackerAnglesFile: C:\Users\cdeline\Documents\Python Scripts\Test2.csv
numpanels: 2
x: 0.98
y: 1.980
z: 0.010
bifi: 0.90
xgap: 0.020
ygap: 0.150
zgap: 0.100
glass: True
glassEdge: 0.02

[cellLevelModuleParamsDict]
numcellsx: 12
Expand All @@ -64,7 +67,7 @@ frame_z: 0.02
frame_width: 0.02
nSides_frame: 4

[omegaParams]
[omegaParamsDict]
omega_material: Metal_Grey
x_omega1: 0.05
mod_overlap: 0.04
Expand All @@ -78,13 +81,11 @@ diameter: 0.10
tubetype: Hex

[analysisParamsDict]
fullRow: False
modWanted: 10
rowWanted: 3
sensorsy_back: 9
sensorsy_front: 9
sensorsx_back: 1
sensorsx_front: 1
sensorsy: 9
sensorsx: 1


[Posts]
spacingPost: 6
Expand Down
Loading

0 comments on commit aae0f5d

Please sign in to comment.