Skip to content

Commit

Permalink
Rename performance functions to match calculatePerformance name conve…
Browse files Browse the repository at this point in the history
…ntion
  • Loading branch information
cdeline committed Sep 6, 2024
1 parent 2caeb8a commit b5cac04
Show file tree
Hide file tree
Showing 9 changed files with 150 additions and 241 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ tests/simulation.ini

# bifacial_radiance temp folder
bifacial_radiance/TEMP/
TEMP/

# bifacial_radiance other
bifacial_radiance/data/source/
Expand Down
20 changes: 10 additions & 10 deletions bifacial_radiance/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ def __init__(self, name=None, path=None, hpc=False):
#self.nMods = None # number of modules per row
#self.nRows = None # number of rows per scene
self.hpc = hpc # HPC simulation is being run. Some read/write functions are modified
self.CompiledResults = None # DataFrame of cumulative results, output from self.calculateResults1axis()
self.CompiledResults = None # DataFrame of cumulative results, output from self.calculatePerformance1axis()

now = datetime.datetime.now()
self.nowstr = str(now.date())+'_'+str(now.hour)+str(now.minute)+str(now.second)
Expand Down Expand Up @@ -2991,7 +2991,7 @@ def analysis1axisground(self, trackerdict=None, singleindex=None, accuracy='low'
return trackerdict


def calculateResults1axis(self, trackerdict=None, module=None,
def calculatePerformance1axis(self, trackerdict=None, module=None,
CECMod2=None, agriPV=False):
'''
Loops through all results in trackerdict and calculates performance,
Expand Down Expand Up @@ -3075,7 +3075,7 @@ def _printRow(analysisobj, key):
module_local = trackerdict[key]['scenes'][analysis.sceneNum].module
else:
module_local = module
power_data = analysis.calc_performance(meteo_data=meteo_data,
power_data = analysis.calculatePerformance(meteo_data=meteo_data,
module=module_local,
cumulativesky=self.cumulativesky,
CECMod2=CECMod2,
Expand Down Expand Up @@ -3103,7 +3103,7 @@ def _printRow(analysisobj, key):
module_local = trackerdict[keys_all[0]]['scenes'][analysis.sceneNum].module
else:
module_local = module
self.CompiledResults = performance.calculateResultsGencumsky1axis(results=self.CompiledResults,
self.CompiledResults = performance.calculatePerformanceGencumsky(results=self.CompiledResults,
bifacialityfactor=module_local.bifi,
fillcleanedSensors=True, agriPV=False)

Expand Down Expand Up @@ -4349,7 +4349,7 @@ def __init__(self, octfile=None, name=None, hpc=False):
self.modWanted = None
self.rowWanted = None
self.sceneNum = 0 # should this be 0 or None by default??
self.power_data = None # results from self.calc_performance() stored here
self.power_data = None # results from self.calculatePerformance() stored here



Expand Down Expand Up @@ -5400,10 +5400,10 @@ def analysis(self, octfile, name, frontscan, backscan=None,
return frontDict, backDict


def calc_performance(self, meteo_data, cumulativesky, module,
def calculatePerformance(self, meteo_data, cumulativesky, module,
CECMod2=None, agriPV=False):
"""
For a given AnalysisObj, use performance.calculateResults to calculate performance,
For a given AnalysisObj, use performance.calculatePerformance to calculate performance,
considering electrical mismatch, using PVLib. Cell temperature is calculated
Parameters
Expand Down Expand Up @@ -5443,17 +5443,17 @@ def calc_performance(self, meteo_data, cumulativesky, module,
# If CECMod details aren't passed, use a default Prism Solar value.
#if type(module) is not ModuleObj: # not working for some reason..
if str(type(module)) != "<class 'bifacial_radiance.module.ModuleObj'>":
raise TypeError('ModuleObj input required for AnalysisObj.calc_performance. '+\
raise TypeError('ModuleObj input required for AnalysisObj.calculatePerformance. '+\
f'type passed: {type(module)}')

self.power_data = performance.calculateResults(module=module, results=self.getResults(),
self.power_data = performance.calculatePerformance(module=module, results=self.getResults(),
CECMod2=CECMod2, agriPV=agriPV,
**meteo_data)

else:
# TODO HERE: SUM all keys for rows that have the same rowWanted/modWanted

self.power_data = performance.calculateResultsGencumsky1axis(results=self.getResults(),
self.power_data = performance.calculatePerformanceGencumsky(results=self.getResults(),
agriPV=agriPV)
#results.to_csv(os.path.join('results', 'Cumulative_Results.csv'))

Expand Down
9 changes: 1 addition & 8 deletions bifacial_radiance/modelchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,14 +241,7 @@ def runModelChain(simulationParamsDict, sceneParamsDict, timeControlParamsDict=N

print("\n--> Calculating Performance values")

"""
#CEC Module
if CECModParamsDict:
CECMod = pd.DataFrame(CECModParamsDict, index=[0])
else:
CECMod = None
"""
demo.calculateResults1axis()
demo.calculatePerformance1axis()
demo.exportTrackerDict(savefile=os.path.join('results','Final_Results.csv'),reindex=False)

# Save example image files
Expand Down
2 changes: 1 addition & 1 deletion bifacial_radiance/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def __init__(self, name=None, x=None, y=None, z=None, bifi=1, modulefile=None,
y : numeric
Length of module (meters)
bifi : numeric
Bifaciality of the panel (used for CalculatePerformance). Between 0 (monofacial)
Bifaciality of the panel (used for calculatePerformance). Between 0 (monofacial)
and 1, default 1.
modulefile : str
Existing radfile location in \objects. Otherwise a default value is used
Expand Down
104 changes: 9 additions & 95 deletions bifacial_radiance/performance.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,88 +7,8 @@

import pvlib
import pandas as pd
import numpy as np

"""
def calculatePerformance(effective_irradiance, CECMod, temp_air=None,
wind_speed=1, temp_cell=None, glassglass=False):
'''
DEPRECATED IN FAVOR OF `module.calculatePerformance`
The module parameters are given at the reference condition.
Use pvlib.pvsystem.calcparams_cec() to generate the five SDM
parameters at your desired irradiance and temperature to use
with pvlib.pvsystem.singlediode() to calculate the IV curve information.:
Inputs
------
effective_irradiance : numeric
Dataframe or single value. Must be same length as temp_cell
CECMod : Dict
Dictionary with CEC Module Parameters for the module selected. Must
contain at minimum alpha_sc, a_ref, I_L_ref, I_o_ref, R_sh_ref,
R_s, Adjust
temp_air : numeric
Ambient temperature in Celsius. Dataframe or single value to calculate.
Must be same length as effective_irradiance. Default = 20C
wind_speed : numeric
Wind speed at a height of 10 meters [m/s]. Default = 1 m/s
temp_cell : numeric
Back of module temperature. If provided, overrides temp_air and
wind_speed calculation. Default = None
glassglass : boolean
If module is glass-glass package (vs glass-polymer) to select correct
thermal coefficients for module temperature calculation
'''
from pvlib.temperature import TEMPERATURE_MODEL_PARAMETERS
# Setting temperature_model_parameters
if glassglass:
temp_model_params = (
TEMPERATURE_MODEL_PARAMETERS['sapm']['open_rack_glass_glass'])
else:
temp_model_params = (
TEMPERATURE_MODEL_PARAMETERS['sapm']['open_rack_glass_polymer'])
if temp_cell is None:
if temp_air is None:
temp_air = 25 # STC
temp_cell = pvlib.temperature.sapm_cell(effective_irradiance, temp_air, wind_speed,
temp_model_params['a'], temp_model_params['b'], temp_model_params['deltaT'])
if isinstance(CECMod, pd.DataFrame):
#CECMod.to_pickle("CECMod.pkl")
if len(CECMod) == 1:
CECMod1 = CECMod.iloc[0]
else:
print("More than one Module passed. Error, using 1st one")
CECMod1 = CECMod.iloc[0]
else:
CECMod1 = CECMod
IL, I0, Rs, Rsh, nNsVth = pvlib.pvsystem.calcparams_cec(
effective_irradiance=effective_irradiance,
temp_cell=temp_cell,
alpha_sc=float(CECMod1.alpha_sc),
a_ref=float(CECMod1.a_ref),
I_L_ref=float(CECMod1.I_L_ref),
I_o_ref=float(CECMod1.I_o_ref),
R_sh_ref=float(CECMod1.R_sh_ref),
R_s=float(CECMod1.R_s),
Adjust=float(CECMod1.Adjust)
)
IVcurve_info = pvlib.pvsystem.singlediode(
photocurrent=IL,
saturation_current=I0,
resistance_series=Rs,
resistance_shunt=Rsh,
nNsVth=nNsVth
)
return IVcurve_info['p_mp']
"""

def MBD(meas, model):
"""
Expand All @@ -111,7 +31,7 @@ def MBD(meas, model):
data.
"""
import pandas as pd

df = pd.DataFrame({'model': model, 'meas': meas})
# rudimentary filtering of modeled irradiance
df = df.dropna()
Expand Down Expand Up @@ -144,8 +64,8 @@ def RMSE(meas, model):
"""

import numpy as np
import pandas as pd


df = pd.DataFrame({'model': model, 'meas': meas})
df = df.dropna()
minirr = meas.min()
Expand Down Expand Up @@ -178,7 +98,6 @@ def MBD_abs(meas, model):
"""

import pandas as pd
df = pd.DataFrame({'model': model, 'meas': meas})
# rudimentary filtering of modeled irradiance
df = df.dropna()
Expand Down Expand Up @@ -212,8 +131,7 @@ def RMSE_abs(meas, model):
"""

#
import numpy as np
import pandas as pd

df = pd.DataFrame({'model': model, 'meas': meas})
df = df.dropna()
minirr = meas.min()
Expand All @@ -226,7 +144,6 @@ def RMSE_abs(meas, model):
def _cleanDataFrameResults(mattype, rearMat, Wm2Front, Wm2Back,
fillcleanedSensors=False, agriPV=False):

import numpy as np

if agriPV:
matchers = ['sky', 'pole', 'tube', 'bar', '3267', '1540']
Expand Down Expand Up @@ -254,7 +171,7 @@ def _cleanDataFrameResults(mattype, rearMat, Wm2Front, Wm2Back,
return filledFront, filledBack


def calculateResults(module, csvfile=None, results=None,
def calculatePerformance(module, csvfile=None, results=None,
temp_air=None, wind_speed=1, temp_cell=None,
CECMod2=None,
fillcleanedSensors=False, agriPV=False, **kwargs):
Expand Down Expand Up @@ -309,9 +226,6 @@ def calculateResults(module, csvfile=None, results=None,

from bifacial_radiance import mismatch

import pandas as pd


dfst = pd.DataFrame()

if csvfile is not None:
Expand Down Expand Up @@ -380,7 +294,7 @@ def calculateResults(module, csvfile=None, results=None,
dfst['BGG'] = dfst['Grear_mean']*100*module.bifi/dfst['Gfront_mean']
dfst['BGE'] = ((dfst['Pout_raw'] - dfst['Pout_Gfront']) * 100 /
dfst['Pout_Gfront'])
dfst['Mismatch'] = mismatch.mismatch_fit3(POA.T)
dfst['Mismatch'] = mismatch.mismatch_fit2(POA.T) # value in percentage [%]
dfst['Pout'] = dfst['Pout_raw']*(1-dfst['Mismatch']/100)
dfst['Wind Speed'] = wind_speed
if "dni" in kwargs:
Expand All @@ -394,7 +308,7 @@ def calculateResults(module, csvfile=None, results=None,
return dfst


def calculateResultsGencumsky1axis(csvfile=None, results=None,
def calculatePerformanceGencumsky(csvfile=None, results=None,
bifacialityfactor=1.0,
fillcleanedSensors=True, agriPV=False):
'''
Expand Down Expand Up @@ -467,7 +381,7 @@ def calculateResultsGencumsky1axis(csvfile=None, results=None,


else:
print("Data or file not passed. Ending calculateResults")
print("Data or file not passed. Ending calculatePerformanceGencumsky")
return

# Data gets cleaned but need to maintain same number of sensors
Expand Down
3 changes: 2 additions & 1 deletion docs/sphinx/source/whatsnew/v0.5.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ Enhancements
~~~~~~~~~~~~
* :py:class:`~bifacial_radiance.RadianceObj` and :py:class:`~bifacial_radiance.GroundObj` and :py:class:`~bifacial_radiance.MetObj` now have `self.columns` and `self.methods` introspection to list data columsn and methods available. (:pull:`495`)
* multiple sceneObjects are tracked by the RadianceObj now. New function :py:class:`~bifacial_radiance.RadianceObj.sceneNames` will return the list of scenes being tracked. (:pull:`487`)
* New function :py:class:`~bifacial_radiance.AnalysisObj.calc_performance` to call CEC performance calculation from within the AnalysisObj
* New function :py:class:`~bifacial_radiance.AnalysisObj.calculatePerformance` and :py:class:`~bifacial_radiance.ModuleObj.calculatePerformance` to call CEC performance calculation from within the AnalysisObj
* New function :py:class:`~bifacial_radiance.RadianceObj.calculatePerformance1axis` to call CEC performance calculation for every entry of a trackerdict
* :py:class:`~bifacial_radiance.AnalysisObj` has new attribute `power_data` to store CEC performance data
* :py:class:`~bifacial_radiance.AnalysisObj` has new function `getResults` to bundle and return irradiance scan results in dataframe form.
* :py:class:`~bifacial_radiance.AnalysisObj` has new function `groundAnalysis` to run a ground scan under the row-row pitch of the scene to support AgriPV applications. (:pull:`499`)
Expand Down
Loading

0 comments on commit b5cac04

Please sign in to comment.