def test_getSkyConfigurationsRowtype(rowtype, expected): """ Benchmark against to the master branch on 2018-08-20 at 91e785d. """ assert np.allclose(getSkyConfigurationFactors(rowtype, beta=20, C=1, D=1), expected)
def simulate(TMYtoread=None, writefiletitle=None, tilt=0, sazm=180, clearance_height=None, hub_height=None, pitch=None, rowType='interior', transFactor=0.01, sensorsy=6, PVfrontSurface='glass', PVbackSurface='glass', albedo=0.2, tracking=False, backtrack=True, limit_angle=45, calculatePVMismatch=False, portraitorlandscape='NA', calculateBilInterpol=False, BilInterpolParams=None): ''' Description ----------- Main function to run the bifacialvf routines Parameters ---------- 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 writefiletitle: name of output file tilt: tilt angle in degrees. Not used for tracking sazm: surface azimuth orientation in degrees east of north. For tracking this is the tracker axis orientation C: normalized ground clearance. For trackers, this is the module height at zero tilt pitch: row-to-row normalized distance. = 1/GCR transFactor: PV module transmission fraction. Default 1% (0.01) sensorsy: Number of points along the module chord to return irradiance values. Default 6 (1-up landscape module) limit_angle: 1-axis tracking maximum limits of rotation tracking, backtrack: boolean to enable 1-axis tracking and pvlib backtracking algorithm, respectively New Parameters: # Dictionary input example: # calculateBilInterpol = {'interpolA':0.005, 'IVArray':None, 'beta_voc_all':None, 'm_all':None, 'bee_all':None} Returns ------- none ''' metdata = TMYtoread if (clearance_height == None) & (hub_height != None): clearance_height = hub_height if tracking == False: print( 'Warning: hub_height passed and is being used as clearance_height for the fixed_tilt routine.' ) elif (clearance_height == None) & (hub_height == None): raise Exception('No row distance specified in either D or pitch') else: print('Warning: clearance_height and hub_height passed in. Using ' + ('hub_height' if tracking else 'clearance_height')) if tracking == True: clearance_height = hub_height C = clearance_height heightlabel = 'Clearance_Height' if tracking == True: axis_tilt = 0 # algorithm only allows for zero north-south tilt with SAT #limit_angle = 45 # maximum tracker rotation axis_azimuth = sazm # axis_azimuth is degrees east of North tilt = 0 # start with tracker tilt = 0 hub_height = C # Ground clearance at tilt = 0. C >= 0.5 if hub_height < 0.5: print( 'Warning: tracker hub height C < 0.5 may result in ground clearance errors' ) heightlabel = 'Hub_Height' D = pitch - math.cos(tilt / 180.0 * math.pi) if writefiletitle == None: writefiletitle = "data/Output/TEST.csv" ## Read TMY3 data and start loop ~ if TMYtoread is None: # if no file passed in, the readtmy3 graphical file picker will open. (myTMY3, meta) = pvlib.tmy.readtmy3(TMYtoread) elif TMYtoread.lower().endswith('.csv'): (myTMY3, meta) = pvlib.tmy.readtmy3(TMYtoread) elif TMYtoread.lower().endswith('.epw'): (myTMY3, meta) = readepw(TMYtoread) # rename different field parameters to match DNI, DHI, DryBulb, Wspd myTMY3.rename(columns={ 'Direct normal radiation in Wh/m2': 'DNI', 'Diffuse horizontal radiation in Wh/m2': 'DHI', 'Dry bulb temperature in C': 'DryBulb', 'Wind speed in m/s': 'Wspd' }, inplace=True) else: raise Exception( 'Incorrect extension for TMYtoread. Either .csv (TMY3) .epw or None' ) #myAxisTitles=myTMY3.axes noRows, noCols = myTMY3.shape lat = meta['latitude'] lng = meta['longitude'] tz = meta['TZ'] name = meta['Name'] ## infer the data frequency in minutes dataInterval = (myTMY3.index[1] - myTMY3.index[0]).total_seconds() / 60 ## Distance between rows for no shading on Dec 21 at 9 am print(" ") print("********* ") print("Running Simulation for TMY3: ", TMYtoread) print("Location: ", name) print("Lat: ", lat, " Long: ", lng, " Tz ", tz) print("Parameters: tilt: ", tilt, " Sazm: ", sazm, " ", heightlabel, ": ", C, " Pitch: ", pitch, " Row type: ", rowType, " Albedo: ", albedo) print("Saving into", writefiletitle) print(" ") print(" ") DD = rowSpacing(tilt, sazm, lat, lng, tz, 9, 0.0) ## Distance between rows for no shading on Dec 21 at 9 am print( "Distance between rows for no shading on Dec 21 at 9 am solar time = ", DD) print("Actual distance between rows = ", D) print(" ") if tracking == False: ## Sky configuration factors are the same for all times, only based on geometry and row type [rearSkyConfigFactors, frontSkyConfigFactors ] = getSkyConfigurationFactors(rowType, tilt, C, D) ## Sky configuration factors are the same for all times, only based on geometry and row type ## Create WriteFile and write labels at this time #check that the save directory exists, unless it's in root savedirectory = os.path.dirname(writefiletitle) if ((not os.path.exists(savedirectory)) and (savedirectory is not '')): os.makedirs(savedirectory) with open(writefiletitle, 'w') as csvfile: sw = csv.writer(csvfile, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL, lineterminator='\n') # Write Simulation Parameters (from setup file) if tracking == False and backtrack == True: print( "Warning: tracking=False, but backtrac=True. Setting backtrac=False because it doesn't make sense to backtrack on fixed tilt systems." ) backtrack = False outputheader = [ 'Latitude(deg)', 'Longitude(deg)', 'Time Zone', 'Tilt(deg)', 'PV Azimuth(deg)', heightlabel, 'Pitch', 'RowType(first interior last single)', 'TransmissionFactor(open area fraction)', 'sensorsy(# hor rows in panel)', 'PVfrontSurface(glass or ARglass)', 'PVbackSurface(glass or ARglass)', 'Albedo', 'Tracking', 'backtracking', 'CalculatePVOutput (Bilinear Interpol)', 'CalculatePVOutput (PVMismatch)', 'PortraitorLandscape' ] outputheadervars = [ lat, lng, tz, tilt, sazm, clearance_height, pitch, rowType, transFactor, sensorsy, PVfrontSurface, PVbackSurface, albedo, tracking, backtrack, calculateBilInterpol, calculatePVMismatch, portraitorlandscape ] if calculatePVMismatch == True: cellCenterPVM, stdpl, cellsx, cellsy = analysis.setupforPVMismatch( portraitorlandscape=portraitorlandscape, sensorsy=sensorsy) if calculateBilInterpol == True: cellCenterBI, interpolA, IVArray, beta_voc_all, m_all, bee_all = analysis.setupforBilinearInterpolation( portraitorlandscape=portraitorlandscape, sensorsy=sensorsy, BilInterpolParams=BilInterpolParams) sw.writerow(outputheader) sw.writerow(outputheadervars) # Write Results names" allrowfronts = [] allrowbacks = [] for k in range(0, sensorsy): allrowfronts.append("No_" + str(k + 1) + "_RowFrontGTI") allrowbacks.append("No_" + str(k + 1) + "_RowBackGTI") outputtitles = [ 'Year', 'Month', 'Day', 'Hour', 'Minute', 'DNI', 'DHI', 'decHRs', 'ghi', 'inc', 'zen', 'azm', 'pvFrontSH', 'aveFrontGroundGHI', 'GTIfrontBroadBand', 'pvBackSH', 'aveBackGroundGHI', 'GTIbackBroadBand', 'maxShadow', 'Tamb', 'VWind' ] outputtitles += allrowfronts outputtitles += allrowbacks if tracking == True: print( " ***** IMPORTANT --> THIS SIMULATION Has Tracking Activated") print("Backtracking Option is set to: ", backtrack) outputtitles += ['tilt'] outputtitles += ['sazm'] outputtitles += ['height'] outputtitles += ['D'] if calculateBilInterpol == True: outputtitles += [ 'BilInterpol FRONT + BACK (Averaged) PmaxIdeal [W]' ] outputtitles += [ 'BilInterpol FRONT + BACK (Detailed) PmaxUnmatched [W]' ] if calculatePVMismatch == True: outputtitles += [ 'PVMismatch FRONT + BACK (Averaged) PmaxIdeal [W]' ] outputtitles += [ 'PVMismatch FRONT + BACK (Detailed) PmaxUnmatched [W]' ] sw.writerow(outputtitles) ## Loop through file. TODO: replace this with for loop. rl = 0 while (rl < noRows): myTimestamp = myTMY3.index[rl] year = myTimestamp.year month = myTimestamp.month day = myTimestamp.day hour = myTimestamp.hour minute = myTimestamp.minute dni = myTMY3.DNI[rl] #get_value(rl,5,"False") dhi = myTMY3.DHI[rl] #get_value(rl,8,"False") Tamb = myTMY3.DryBulb[rl] #get_value(rl,29,"False") VWind = myTMY3.Wspd[rl] #get_value(rl,44,"False") # rl = rl + 1 # increasing while count azm = 9999.0 zen = 9999.0 elv = 9999.0 if (dataInterval == 60): azm, zen, elv, dec, sunrise, sunset, Eo, tst, suntime = hrSolarPos( year, month, day, hour, lat, lng, tz) elif (dataInterval == 1 or dataInterval == 5 or dataInterval == 15): azm, zen, elv, dec, sunrise, sunset, Eo, tst = solarPos( year, month, day, hour, minute - 0.5 * dataInterval, lat, lng, tz) else: print("ERROR: data interval not 1, 5, 15, or 60 minutes.") #123 check abouve this for reading / printing functions if (zen < 0.5 * math.pi): # If daylight hours # a. CALCULATE THE IRRADIANCE DISTRIBUTION ON THE GROUND ********************************************************************************************* #double[] rearGroundGHI = new double[100], frontGroundGHI = new double[100]; ; # For global horizontal irradiance for each of 100 ground segments, to the rear and front of front of row edge # Determine where on the ground the direct beam is shaded for a sun elevation and azimuth #int[] rearGroundSH = new int[100], frontGroundSH = new int[100]; # Front and rear row-to-row spacing divided into 100 segments, (later becomes 1 if direct beam is shaded, 0 if not shaded) #double pvFrontSH = 0.0, pvBackSH = 0.0, maxShadow; # Initialize fraction of PV module front and back surfaces that are shaded to zero (not shaded), and maximum shadow projected from front of row. # TRACKING ROUTINE CALULATING GETSKYCONFIGURATION FACTORS if tracking == True: #solpos = pvlib.solarposition.get_solarposition(myTimestamp, lat, lng) #aazi= solpos['azimuth'] #azen= solpos['zenith'] aazi = pd.Series([azm * 180.0 / math.pi], index=[myTimestamp]) azen = pd.Series([zen * 180.0 / math.pi], index=[myTimestamp]) gcr = 1 / pitch trackingdata = pvlib.tracking.singleaxis( azen, aazi, axis_tilt, axis_azimuth, limit_angle, backtrack, gcr) ## Sky configuration factors are not the same for all times, since the geometry is changing with the tracking. tilt = trackingdata['surface_tilt'][ 0] # Trackingdata tracker_theta sazm = trackingdata['surface_azimuth'][0] if math.isnan(tilt): tilt = 90 # Rotate system if past sun's zenith ~ #123 Check if system breaks withot doing this. if tilt < 0: #sazm = sazm+180 # Rotate detectors tilt = -tilt [C, D] = trackingBFvaluescalculator(tilt, hub_height, pitch) [rearSkyConfigFactors, frontSkyConfigFactors ] = getSkyConfigurationFactors(rowType, tilt, C, D) ## Sky configuration factors are the same for all times, only based on geometry and row type rearGroundGHI = [] frontGroundGHI = [] pvFrontSH, pvBackSH, maxShadow, rearGroundSH, frontGroundSH = getGroundShadeFactors( rowType, tilt, C, D, elv, azm, sazm) # Sum the irradiance components for each of the ground segments, to the front and rear of the front of the PV row #double iso_dif = 0.0, circ_dif = 0.0, horiz_dif = 0.0, grd_dif = 0.0, beam = 0.0; # For calling PerezComp to break diffuse into components for zero tilt (horizontal) ghi, iso_dif, circ_dif, horiz_dif, grd_dif, beam = perezComp( dni, dhi, albedo, zen, 0.0, zen) for k in range(0, 100): rearGroundGHI.append(iso_dif * rearSkyConfigFactors[k]) # Add diffuse sky component viewed by ground if (rearGroundSH[k] == 0): rearGroundGHI[k] += beam + circ_dif # Add beam and circumsolar component if not shaded else: rearGroundGHI[k] += (beam + circ_dif) * transFactor # Add beam and circumsolar component transmitted thru module spacing if shaded frontGroundGHI.append(iso_dif * frontSkyConfigFactors[k]) # Add diffuse sky component viewed by ground if (frontGroundSH[k] == 0): frontGroundGHI[k] += beam + circ_dif # Add beam and circumsolar component if not shaded else: frontGroundGHI[k] += (beam + circ_dif) * transFactor # Add beam and circumsolar component transmitted thru module spacing if shaded # b. CALCULATE THE AOI CORRECTED IRRADIANCE ON THE FRONT OF THE PV MODULE, AND IRRADIANCE REFLECTED FROM FRONT OF PV MODULE *************************** #double[] frontGTI = new double[sensorsy], frontReflected = new double[sensorsy]; #double aveGroundGHI = 0.0; # Average GHI on ground under PV array aveGroundGHI, frontGTI, frontReflected = getFrontSurfaceIrradiances( rowType, maxShadow, PVfrontSurface, tilt, sazm, dni, dhi, C, D, albedo, zen, azm, sensorsy, pvFrontSH, frontGroundGHI) #double inc, tiltr, sazmr; inc, tiltr, sazmr = sunIncident( 0, tilt, sazm, 45.0, zen, azm ) # For calling PerezComp to break diffuse into components for save_inc = inc gtiAllpc, iso_dif, circ_dif, horiz_dif, grd_dif, beam = perezComp( dni, dhi, albedo, inc, tiltr, zen) # Call to get components for the tilt save_gtiAllpc = gtiAllpc #sw.Write(strLine); #sw.Write(",{0,6:0.00}", hour - 0.5 * dataInterval / 60.0 + minute / 60.0); #sw.Write(",{0,6:0.0},{1,5:0.0},{2,5:0.0},{3,5:0.0},{4,4:0.00},{5,6:0.0},{6,6:0.0}", #dni * Math.Cos(zen) + dhi, inc * 180.0 / Math.PI, zen * 180.0 / Math.PI, azm * 180.0 / Math.PI, pvFrontSH, aveGroundGHI, gtiAllpc); # CALCULATE THE AOI CORRECTED IRRADIANCE ON THE BACK OF THE PV MODULE, #double[] backGTI = new double[sensorsy]; backGTI, aveGroundGHI = getBackSurfaceIrradiances( rowType, maxShadow, PVbackSurface, tilt, sazm, dni, dhi, C, D, albedo, zen, azm, sensorsy, pvBackSH, rearGroundGHI, frontGroundGHI, frontReflected, offset=0) inc, tiltr, sazmr = sunIncident( 0, 180.0 - tilt, sazm - 180.0, 45.0, zen, azm ) # For calling PerezComp to break diffuse into components for gtiAllpc, iso_dif, circ_dif, horiz_dif, grd_dif, beam = perezComp( dni, dhi, albedo, inc, tiltr, zen) # Call to get components for the tilt ## Write output decHRs = hour - 0.5 * dataInterval / 60.0 + minute / 60.0 ghi_calc = dni * math.cos(zen) + dhi incd = save_inc * 180.0 / math.pi zend = zen * 180.0 / math.pi azmd = azm * 180.0 / math.pi outputvalues = [ year, month, day, hour, minute, dni, dhi, decHRs, ghi_calc, incd, zend, azmd, pvFrontSH, aveGroundGHI, save_gtiAllpc, pvBackSH, aveGroundGHI, gtiAllpc, maxShadow, Tamb, VWind ] frontGTIrow = [] backGTIrow = [] for k in range(0, sensorsy): frontGTIrow.append(frontGTI[k]) backGTIrow.append(backGTI[k]) outputvalues += frontGTIrow outputvalues += backGTIrow if tracking == True: outputvalues.append(tilt) outputvalues.append(sazm) outputvalues.append(C) outputvalues.append(D) if calculateBilInterpol == True: PowerAveraged, PowerDetailed = analysis.calculateVFBilinearInterpolation( portraitorlandscape, sensorsy, cellCenterBI, interpolA, IVArray, beta_voc_all, m_all, bee_all, frontGTIrow, backGTIrow, Tamb, VWind) outputvalues.append(PowerAveraged) outputvalues.append(PowerDetailed) if calculatePVMismatch == True: PowerAveraged, PowerDetailed = analysis.calculateVFPVMismatch( cellCenterPVM, stdpl, cellsy, cellsx, sensorsy, frontGTIrow, backGTIrow) outputvalues.append(PowerAveraged) outputvalues.append(PowerDetailed) sw.writerow(outputvalues) # End of daylight if loop #strLine = sr.ReadLine(); # Read next line of data # End of while strLine != null loop print("Finished") return
def test_getSkyConfigurationFactors(beta, C, D, expected): """ Benchmark against to the master branch on 2018-08-20 at 91e785d. """ assert np.allclose(getSkyConfigurationFactors("interior", beta, C, D), expected)
def simulate(myTMY3, meta, writefiletitle=None, tilt=0, sazm=180, clearance_height=None, hub_height=None, pitch=None, rowType='interior', transFactor=0.01, sensorsy=6, PVfrontSurface='glass', PVbackSurface='glass', albedo=None, tracking=False, backtrack=True, limit_angle=45, calculatePVMismatch=False, cellsnum=72, portraitorlandscape='landscape', bififactor=1.0, calculateBilInterpol=False, BilInterpolParams=None, deltastyle='TMY3', agriPV=False): ''' Description ----------- Main function to run the bifacialvf routines Parameters ---------- myTMY3 (pd.DataFrame): A pandas DataaFrame containing for each timestep columns: DNI, DHI, it can also have DryBulb, Wspd, zenith, azimuth, meta (dict): A dictionary conatining keys: 'latitude', 'longitude', 'TZ', 'Name' writefiletitle: name of output file tilt: tilt angle in degrees. Not used for tracking sazm: surface azimuth orientation in degrees east of north. For tracking this is the tracker axis orientation C: normalized ground clearance. For trackers, this is the module height at zero tilt pitch: row-to-row normalized distance. = 1/GCR transFactor: PV module transmission fraction. Default 1% (0.01) sensorsy: Number of points along the module chord to return irradiance values. Default 6 (1-up landscape module) limit_angle: 1-axis tracking maximum limits of rotation tracking, backtrack: boolean to enable 1-axis tracking and pvlib backtracking algorithm, respectively albedo: If a value is passed, that value will be used for all the simulations. If None is passed (or albedo argument is not passed), program will search the TMY file for the "Albe (unitless)" column and use those values New Parameters: # Dictionary input example: # calculateBilInterpol = {'interpolA':0.005, 'IVArray':None, 'beta_voc_all':None, 'm_all':None, 'bee_all':None} Returns ------- none ''' if (clearance_height == None) & (hub_height != None): clearance_height = hub_height if tracking == False: print('Warning: hub_height passed and is being used as ', 'clearance_height for the fixed_tilt routine.') elif (clearance_height == None) & (hub_height == None): raise Exception('No row distance specified in either D or pitch') elif (clearance_height != None) & (hub_height == None): if tracking == True: print('Warning: clearance_height passed and is being used as ', 'hub_height for the tracking routine') else: print('Warning: clearance_height and hub_height passed in. Using ' + ('hub_height' if tracking else 'clearance_height')) if tracking == True: clearance_height = hub_height C = clearance_height heightlabel = 'Clearance_Height' if tracking == True: axis_tilt = 0 # algorithm only allows for zero north-south tilt with SAT #limit_angle = 45 # maximum tracker rotation axis_azimuth = sazm # axis_azimuth is degrees east of North tilt = 0 # start with tracker tilt = 0 hub_height = C # Ground clearance at tilt = 0. C >= 0.5 stowingangle = 90 if hub_height < 0.5: print( 'Warning: tracker hub height C < 0.5 may result in ground clearance errors' ) heightlabel = 'Hub_Height' D = pitch - math.cos(tilt / 180.0 * math.pi) if writefiletitle == None: writefiletitle = "data/Output/TEST.csv" noRows, noCols = myTMY3.shape lat = meta['latitude'] lng = meta['longitude'] tz = meta['TZ'] try: name = meta['Name'] #TMY3 except KeyError: name = meta['city'] #EPW ## infer the data frequency in minutes dataInterval = (myTMY3.index[1] - myTMY3.index[0]).total_seconds() / 60 if not (('azimuth' in myTMY3) and ('zenith' in myTMY3) and ('elevation' in myTMY3)): solpos, sunup = sunrisecorrectedsunposition(myTMY3, meta, deltastyle=deltastyle) myTMY3['zenith'] = np.radians(solpos['zenith']) myTMY3['azimuth'] = np.radians(solpos['azimuth']) myTMY3['elevation'] = np.radians(solpos['elevation']) if tracking == True: if not (('trackingdata_surface_tilt' in myTMY3) and ('trackingdata_surface_azimuth' in myTMY3)): gcr = 1 / pitch trackingdata = pvlib.tracking.singleaxis( np.degrees(myTMY3['zenith']), np.degrees(myTMY3['azimuth']), axis_tilt, axis_azimuth, limit_angle, backtrack, gcr) trackingdata.surface_tilt.fillna(stowingangle, inplace=True) myTMY3['trackingdata_surface_tilt'] = trackingdata['surface_tilt'] myTMY3['trackingdata_surface_azimuth'] = trackingdata[ 'surface_azimuth'] [myTMY3['C'], myTMY3['D'] ] = trackingBFvaluescalculator(myTMY3['trackingdata_surface_tilt'], hub_height, pitch) # Check what Albedo to se: if albedo == None: if 'Alb' in myTMY3: print("Using albedo from TMY3 file.") print( "Note that at the moment, no validation check is done", "in the albedo data, so we assume it's correct and valid.\n") useTMYalbedo = True else: print("No albedo value set or included in TMY3 file", "(TMY Column name 'Alb (unitless)' expected)", "Setting albedo default to 0.2\n ") albedo = 0.2 useTMYalbedo = False else: if 'Alb' in myTMY3: print("Albedo value passed, but also present in TMY3 file. ", "Using albedo value passed. To use the ones in TMY3 file", "re-run simulation with albedo=None\n") useTMYalbedo = False ## Distance between rows for no shading on Dec 21 at 9 am print(" ") print("********* ") print("Running Simulation for TMY3: ") print("Location: ", name) print("Lat: ", lat, " Long: ", lng, " Tz ", tz) print("Parameters: tilt: ", tilt, " Sazm: ", sazm, " ", heightlabel, ": ", C, " Pitch: ", pitch, " Row type: ", rowType, " Albedo: ", albedo) print("Saving into", writefiletitle) print(" ") print(" ") DD = rowSpacing(tilt, sazm, lat, lng, tz, 9, 0.0) ## Distance between rows for no shading on Dec 21 at 9 am print( "Distance between rows for no shading on Dec 21 at 9 am solar time = ", DD) print("Actual distance between rows = ", D) print(" ") if tracking == False: ## Sky configuration factors are the same for all times, only based on geometry and row type [ rearSkyConfigFactors, frontSkyConfigFactors ] = getSkyConfigurationFactors( rowType, tilt, C, D ) ## Sky configuration factors are the same for all times, only based on geometry and row type ## Create WriteFile and write labels at this time #check that the save directory exists, unless it's in root savedirectory = os.path.dirname(writefiletitle) if ((not os.path.exists(savedirectory)) and (savedirectory != '')): os.makedirs(savedirectory) with open(writefiletitle, 'w') as csvfile: sw = csv.writer(csvfile, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL, lineterminator='\n') # Write Simulation Parameters (from setup file) if tracking == False and backtrack == True: print("Warning: tracking=False, but backtracking=True. ", "Setting backtracking=False because it doesn't make ", "sense to backtrack on fixed tilt systems.") backtrack = False outputheader = [ 'Latitude(deg)', 'Longitude(deg)', 'Time Zone', 'Tilt(deg)', 'PV Azimuth(deg)', heightlabel, 'Pitch', 'RowType(first interior last single)', 'TransmissionFactor(open area fraction)', 'sensorsy(# hor rows in panel)', 'PVfrontSurface(glass or ARglass)', 'PVbackSurface(glass or ARglass)', 'Albedo', 'Tracking', 'backtracking' ] outputheadervars = [ lat, lng, tz, tilt, sazm, clearance_height, pitch, rowType, transFactor, sensorsy, PVfrontSurface, PVbackSurface, albedo, tracking, backtrack ] sw.writerow(outputheader) sw.writerow(outputheadervars) # Write Results names" allrowfronts = [] allrowbacks = [] for k in range(0, sensorsy): allrowfronts.append("No_" + str(k + 1) + "_RowFrontGTI") allrowbacks.append("No_" + str(k + 1) + "_RowBackGTI") outputtitles = [ 'date', 'DNI', 'DHI', 'albedo', 'decHRs', 'ghi', 'inc', 'zen', 'azm', 'pvFrontSH', 'aveFrontGroundGHI', 'GTIfrontBroadBand', 'pvBackSH', 'aveBackGroundGHI', 'GTIbackBroadBand', 'maxShadow', 'Tamb', 'VWind' ] outputtitles += allrowfronts outputtitles += allrowbacks if tracking == True: print( " ***** IMPORTANT --> THIS SIMULATION Has Tracking Activated") print("Backtracking Option is set to: ", backtrack) outputtitles += ['tilt'] outputtitles += ['sazm'] outputtitles += ['height'] outputtitles += ['D'] if agriPV: print("Saving Ground Irradiance Values for AgriPV Analysis. ") outputtitles += ['Ground Irradiance Values'] sw.writerow(outputtitles) ## Loop through file. TODO: replace this with for loop. rl = 0 for rl in tqdm(range(noRows)): myTimestamp = myTMY3.index[rl] hour = myTimestamp.hour minute = myTimestamp.minute dni = myTMY3.DNI[rl] #get_value(rl,5,"False") dhi = myTMY3.DHI[rl] #get_value(rl,8,"False") if 'DryBulb' in myTMY3: Tamb = myTMY3.DryBulb[rl] else: Tamb = 0 if 'Wspd' in myTMY3: VWind = myTMY3.Wspd[rl] else: VWind = 0 if useTMYalbedo: albedo = myTMY3.Alb[rl] zen = myTMY3['zenith'][rl] azm = myTMY3['azimuth'][rl] elv = myTMY3['elevation'][rl] if (zen < 0.5 * math.pi): # If daylight hours # a. CALCULATE THE IRRADIANCE DISTRIBUTION ON THE GROUND #******************************************************** #double[] rearGroundGHI = new double[100], frontGroundGHI = new double[100] # For global horizontal irradiance for each of 100 ground segments, to the rear and front of front of row edge # Determine where on the ground the direct beam is shaded for a sun elevation and azimuth #int[] rearGroundSH = new int[100], frontGroundSH = new int[100] # Front and rear row-to-row spacing divided into 100 segments, (later becomes 1 if direct beam is shaded, 0 if not shaded) #double pvFrontSH = 0.0, pvBackSH = 0.0, maxShadow # Initialize fraction of PV module front and back surfaces that are shaded to zero (not shaded), and maximum shadow projected from front of row. # TRACKING ROUTINE CALULATING GETSKYCONFIGURATION FACTORS if tracking == True: tilt = myTMY3['trackingdata_surface_tilt'][rl] sazm = myTMY3['trackingdata_surface_azimuth'][rl] C = myTMY3['C'][rl] D = myTMY3['D'][rl] [ rearSkyConfigFactors, frontSkyConfigFactors ] = getSkyConfigurationFactors( rowType, tilt, C, D ) ## Sky configuration factors are the same for all times, only based on geometry and row type rearGroundGHI = [] frontGroundGHI = [] pvFrontSH, pvBackSH, maxShadow, rearGroundSH, frontGroundSH = getGroundShadeFactors( rowType, tilt, C, D, elv, azm, sazm) # Sum the irradiance components for each of the ground segments, to the front and rear of the front of the PV row #double iso_dif = 0.0, circ_dif = 0.0, horiz_dif = 0.0, grd_dif = 0.0, beam = 0.0 # For calling PerezComp to break diffuse into components for zero tilt (horizontal) ghi, iso_dif, circ_dif, horiz_dif, grd_dif, beam = perezComp( dni, dhi, albedo, zen, 0.0, zen) for k in range(0, 100): rearGroundGHI.append( iso_dif * rearSkyConfigFactors[k] ) # Add diffuse sky component viewed by ground if (rearGroundSH[k] == 0): rearGroundGHI[ k] += beam + circ_dif # Add beam and circumsolar component if not shaded else: rearGroundGHI[k] += ( beam + circ_dif ) * transFactor # Add beam and circumsolar component transmitted thru module spacing if shaded frontGroundGHI.append( iso_dif * frontSkyConfigFactors[k] ) # Add diffuse sky component viewed by ground if (frontGroundSH[k] == 0): frontGroundGHI[ k] += beam + circ_dif # Add beam and circumsolar component if not shaded else: frontGroundGHI[k] += ( beam + circ_dif ) * transFactor # Add beam and circumsolar component transmitted thru module spacing if shaded # b. CALCULATE THE AOI CORRECTED IRRADIANCE ON THE FRONT OF THE PV MODULE, AND IRRADIANCE REFLECTED FROM FRONT OF PV MODULE *************************** #double[] frontGTI = new double[sensorsy], frontReflected = new double[sensorsy] #double aveGroundGHI = 0.0 # Average GHI on ground under PV array aveGroundGHI, frontGTI, frontReflected = getFrontSurfaceIrradiances( rowType, maxShadow, PVfrontSurface, tilt, sazm, dni, dhi, C, D, albedo, zen, azm, sensorsy, pvFrontSH, frontGroundGHI) #double inc, tiltr, sazmr inc, tiltr, sazmr = sunIncident( 0, tilt, sazm, 45.0, zen, azm ) # For calling PerezComp to break diffuse into components for save_inc = inc gtiAllpc, iso_dif, circ_dif, horiz_dif, grd_dif, beam = perezComp( dni, dhi, albedo, inc, tiltr, zen) # Call to get components for the tilt save_gtiAllpc = gtiAllpc #sw.Write(strLine) #sw.Write(",{0,6:0.00}", hour - 0.5 * dataInterval / 60.0 + minute / 60.0) #sw.Write(",{0,6:0.0},{1,5:0.0},{2,5:0.0},{3,5:0.0},{4,4:0.00},{5,6:0.0},{6,6:0.0}", #dni * Math.Cos(zen) + dhi, inc * 180.0 / Math.PI, zen * 180.0 / Math.PI, azm * 180.0 / Math.PI, pvFrontSH, aveGroundGHI, gtiAllpc) # CALCULATE THE AOI CORRECTED IRRADIANCE ON THE BACK OF THE PV MODULE #double[] backGTI = new double[sensorsy] backGTI, aveGroundGHI = getBackSurfaceIrradiances( rowType, maxShadow, PVbackSurface, tilt, sazm, dni, dhi, C, D, albedo, zen, azm, sensorsy, pvBackSH, rearGroundGHI, frontGroundGHI, frontReflected, offset=0) inc, tiltr, sazmr = sunIncident( 0, 180.0 - tilt, sazm - 180.0, 45.0, zen, azm ) # For calling PerezComp to break diffuse into components for gtiAllpc, iso_dif, circ_dif, horiz_dif, grd_dif, beam = perezComp( dni, dhi, albedo, inc, tiltr, zen) # Call to get components for the tilt ## Write output decHRs = hour - 0.5 * dataInterval / 60.0 + minute / 60.0 ghi_calc = dni * math.cos(zen) + dhi incd = save_inc * 180.0 / math.pi zend = zen * 180.0 / math.pi azmd = azm * 180.0 / math.pi outputvalues = [ myTimestamp, dni, dhi, albedo, decHRs, ghi_calc, incd, zend, azmd, pvFrontSH, aveGroundGHI, save_gtiAllpc, pvBackSH, aveGroundGHI, gtiAllpc, maxShadow, Tamb, VWind ] frontGTIrow = [] backGTIrow = [] # INVERTING Sensor measurements for tracking when tracker # facing the west side. # TODO: Modify so it works with axis_azm different of 0 # (sazm = 90 or 270 only) if tracking == True: if sazm == 270.0: rangestart = sensorsy - 1 rangeend = -1 steprange = -1 rearGroundGHI.reverse() else: rangestart = 0 rangeend = sensorsy steprange = 1 else: rangestart = 0 rangeend = sensorsy steprange = 1 for k in range(rangestart, rangeend, steprange): frontGTIrow.append(frontGTI[k]) backGTIrow.append(backGTI[k]) outputvalues += frontGTIrow outputvalues += backGTIrow if tracking == True: outputvalues.append(tilt) outputvalues.append(sazm) outputvalues.append(C) outputvalues.append(D) if agriPV: outputvalues.append(str(rearGroundGHI).replace(',', '')) sw.writerow(outputvalues) # End of daylight if loop # End of myTMY3 rows of data if calculateBilInterpol == True: analyseVFResultsBilInterpol(filename=writefiletitle, portraitorlandscape=portraitorlandscape, bififactor=bififactor, writefilename=writefiletitle) if calculatePVMismatch == True: analyseVFResultsPVMismatch(filename=writefiletitle, portraitorlandscape=portraitorlandscape, bififactor=bififactor, numcells=cellsnum, writefilename=writefiletitle) print("Finished") return