def test_tiltandazimuthModuleTest(): # test full routine for Vertical Modules. name = "_test_tiltandazimuth" demo = bifacial_radiance.RadianceObj(name) demo.setGround(0.2) metdata = demo.readWeatherFile(weatherFile=MET_FILENAME) demo.gendaylit(4020) demo.makeModule(name='test-module', y=2, x=1) sceneDict = { 'gcr': 0.35, 'hub_height': 2.3, 'tilt': 45, 'azimuth': 135, 'nMods': 1, 'nRows': 1 } scene = demo.makeScene('test-module', sceneDict) octfile = demo.makeOct(demo.getfilelist()) analysis = bifacial_radiance.AnalysisObj(octfile, demo.basename) frontscan, backscan = analysis.moduleAnalysis(scene, sensorsy=[4, 4]) results = analysis.analysis(octfile, demo.basename, frontscan, backscan) assert analysis.mattype[0] == 'a0.0.a0.test-module.6457' assert analysis.mattype[1] == 'a0.0.a0.test-module.6457' assert analysis.mattype[2] == 'a0.0.a0.test-module.6457' assert analysis.mattype[3] == 'a0.0.a0.test-module.6457' assert analysis.rearMat[0] == 'a0.0.a0.test-module.2310' assert analysis.rearMat[1] == 'a0.0.a0.test-module.2310' assert analysis.rearMat[2] == 'a0.0.a0.test-module.2310' assert analysis.rearMat[3] == 'a0.0.a0.test-module.2310'
def test_RadianceObj_fixed_tilt_end_to_end(): # just run the demo example. Rear irradiance fraction roughly 11.8% for 0.95m landscape panel # takes 12 seconds name = "_test_fixed_tilt_end_to_end" demo = bifacial_radiance.RadianceObj(name) # Create a RadianceObj 'object' demo.setGround(0.62) # input albedo number or material name like 'concrete'. To see options, run this without any input. metdata = demo.readEPW(epwfile= MET_FILENAME) # read in the EPW weather data from above #metdata = demo.readTMY() # select a TMY file using graphical picker # Now we either choose a single time point, or use cumulativesky for the entire year. fullYear = False if fullYear: demo.genCumSky(demo.epwfile) # entire year. else: demo.gendaylit(metdata,4020) # Noon, June 17th # create a scene using panels in landscape at 10 deg tilt, 1.5m pitch. 0.2 m ground clearance sceneDict = {'tilt':10,'pitch':1.5,'height':0.2, 'nMods':10, 'nRows':3} demo.makeModule(name='test',y=0.95,x=1.59, xgap=0) scene = demo.makeScene('test',sceneDict) #makeScene creates a .rad file with 20 modules per row, 7 rows. octfile = demo.makeOct(demo.getfilelist()) # makeOct combines all of the ground, sky and object files into a .oct file. analysis = bifacial_radiance.AnalysisObj(octfile, demo.name) # return an analysis object including the scan dimensions for back irradiance (frontscan,backscan) = analysis.moduleAnalysis(scene) analysis.analysis(octfile, demo.name, frontscan, backscan) # compare the back vs front irradiance #assert np.round(np.mean(analysis.backRatio),decimals=2) == 0.12 # NOTE: this value is 0.11 when your module size is 1m, 0.12 when module size is 0.95m assert np.mean(analysis.backRatio) == pytest.approx(0.12, abs = 0.01)
def test_SingleModule_end_to_end(): # 1 module for STC conditions. DNI:900, DHI:100, sun angle: 33 elevation 0 azimuth name = "_test_SingleModule_end_to_end" demo = bifacial_radiance.RadianceObj(name) # Create a RadianceObj 'object' demo.setGround('litesoil') metdata = demo.readEPW(epwfile= MET_FILENAME) demo.gendaylit(metdata,4020,debug=True) # 1pm, June 17th # create a scene using panels in landscape at 10 deg tilt, 1.5m pitch. 0.2 m ground clearance tilt=demo.getSingleTimestampTrackerAngle(metdata=metdata, timeindex=4020, gcr=0.33) assert tilt == pytest.approx(-6.7, abs = 0.4) sceneDict = {'tilt':0,'pitch':1.5,'clearance_height':1, 'nMods':1, 'nRows':1} demo.makeModule() demo.makeModule(name='test',y=0.95,x=1.59, xgap=0) scene = demo.makeScene('test',sceneDict) #objname='Marker' #text='! genbox white_EPDM mymarker 0.02 0.02 2.5 | xform -t -.01 -.01 0' #customObject = demo.makeCustomObject(objname,text) #demo.appendtoScene(scene.radfiles, customObject, '!xform -rz 0') octfile = demo.makeOct(demo.getfilelist(), hpc=True) # makeOct combines all of the ground, sky and object files into a .oct file. analysis = bifacial_radiance.AnalysisObj(octfile, demo.name) # return an analysis object including the scan dimensions for back irradiance (frontscan,backscan) = analysis.moduleAnalysis(scene, sensorsy=1) analysis.analysis(octfile, demo.name, frontscan, backscan) # compare the back vs front irradiance assert analysis.mattype[0][:12] == 'a0.0.a0.test' assert analysis.rearMat[0][:12] == 'a0.0.a0.test' assert analysis.x == [0] assert analysis.y == [0] assert np.mean(analysis.Wm2Front) == pytest.approx(1025, abs = 2) analysis.makeImage('side.vp', hpc=True) analysis.makeFalseColor('side.vp') #TODO: this works on silvanas computer, # side.vp must exist inside of views folder in test folder... make sure this works # in other computers assert np.mean(analysis.Wm2Back) == pytest.approx(166, abs = 6)
def test_SceneObj_makeSceneNxR_hightilt(): # test _makeSceneNxR(tilt, height, pitch, orientation = None, azimuth = 180, nMods = 20, nRows = 7, radname = None) # default scene with simple_panel, 50 degree tilt, 0.2 height, 1.5 row spacing, landscape name = "_test__makeSceneNxR_hightilt" demo = bifacial_radiance.RadianceObj(name) demo.makeModule(name='test', y=0.95, x=1.59) #scene = bifacial_radiance.SceneObj(moduletype = name) #scene._makeSceneNxR(tilt=65,height=0.2,pitch=1.5,azimuth=89) sceneDict = {'tilt': 65, 'height': 0.2, 'pitch': 1.5, 'azimuth': 89} scene = demo.makeScene(moduletype='test', sceneDict=sceneDict) analysis = bifacial_radiance.AnalysisObj() (frontscan, backscan) = analysis.moduleAnalysis(scene) temp = frontscan.pop('orient') ''' assert [float(x) for x in temp.split(' ')] == pytest.approx([-0.999847695156, -0.0174524064373, 0]) assert frontscan == pytest.approx({'Nx': 1, 'Ny': 1, 'Nz': 9, 'xinc': 0, 'xstart': 0, 'yinc': 0, 'ystart': 0, 'zinc': 0.086099239768481745,'zstart': 0.28609923976848173}) temp2 = backscan.pop('orient') assert [float(x) for x in temp2.split(' ')] == pytest.approx([0.999847695156, 0.0174524064373, 0]) assert backscan == pytest.approx({'Nx': 1, 'Ny': 1, 'Nz': 9, 'xinc': 0, 'xstart': -0.94985531039857163, 'yinc': 0, 'ystart': -0.016579786115419416, 'zinc': 0.086099239768481745, 'zstart': 0.28609923976848173}) #assert scene.text == '!xform -rz -90 -t -0.795 0.475 0 -rx 65 -t 0 0 0.2 -a 20 -t 1.6 0 0 -a 7 -t 0 1.5 0 -i 1 -t -15.9 -4.5 0 -rz 91 objects\\simple_panel.rad' assert scene.text[0:93] == '!xform -rx 65 -t 0 0 0.2 -a 20 -t 1.6 0 0 -a 7 -t 0 1.5 0 -i 1 -t -16.0 -4.5 0 -rz 91 objects' ''' assert [float(x) for x in temp.split(' ') ] == pytest.approx([-0.906, -0.016, -0.423]) #was 0,0,-1 in v0.2.4 assert frontscan == pytest.approx({ 'Nx': 1, 'Ny': 9, 'Nz': 1, 'xinc': -0.040142620018581696, 'xstart': 0.1796000448657153, 'yinc': -0.0007006920388131139, 'ystart': 0.0031349304442418674, 'zinc': 0.08609923976848174, 'zstart': 0.2949742232650364 }) temp2 = backscan.pop('orient') assert [float(x) for x in temp2.split(' ') ] == pytest.approx([0.906, 0.016, 0.423]) #was 0,0,1 in v0.2.4 assert backscan == pytest.approx({ 'Nx': 1, 'Ny': 9, 'Nz': 1, 'xinc': -0.040142620018581696, 'xstart': 0.15966431032235584, 'yinc': -0.0007006920388131139, 'ystart': 0.0027869509033958163, 'zinc': 0.08609923976848174, 'zstart': 0.28567662150674106 }) #assert scene.text == '!xform -rz -90 -t -0.795 0.475 0 -rx 65 -t 0 0 0.2 -a 20 -t 1.6 0 0 -a 7 -t 0 1.5 0 -i 1 -t -15.9 -4.5 0 -rz 91 objects\\simple_panel.rad' assert scene.text[ 0: 117] == '!xform -rx 65 -t 0 0 0.6304961988424087 -a 20 -t 1.6 0 0 -a 7 -t 0 1.5 0 -i 1 -t -14.4 -4.5 0 -rz 91 -t 0 0 0 objects'
def test_SingleModule_end_to_end(): # 1 module for STC conditions. DNI:900, DHI:100, sun angle: 33 elevation 0 azimuth name = "_test_SingleModule_end_to_end" demo = bifacial_radiance.RadianceObj(name) # Create a RadianceObj 'object' demo.setGround('litesoil') metdata = demo.readEPW(epwfile=MET_FILENAME) demo.gendaylit(metdata, 4020) # Noon, June 17th # create a scene using panels in landscape at 10 deg tilt, 1.5m pitch. 0.2 m ground clearance sceneDict = { 'tilt': 0, 'pitch': 1.5, 'clearance_height': 1, 'nMods': 1, 'nRows': 1 } demo.makeModule(name='test', y=0.95, x=1.59, xgap=0) scene = demo.makeScene('test', sceneDict) #objname='Marker' #text='! genbox white_EPDM mymarker 0.02 0.02 2.5 | xform -t -.01 -.01 0' #customObject = demo.makeCustomObject(objname,text) #demo.appendtoScene(scene.radfiles, customObject, '!xform -rz 0') octfile = demo.makeOct( demo.getfilelist() ) # makeOct combines all of the ground, sky and object files into a .oct file. analysis = bifacial_radiance.AnalysisObj( octfile, demo.name ) # return an analysis object including the scan dimensions for back irradiance (frontscan, backscan) = analysis.moduleAnalysis(scene, sensorsy=1) analysis.analysis(octfile, demo.name, frontscan, backscan) # compare the back vs front irradiance assert analysis.mattype[0][:12] == 'a0.0.a0.test' assert analysis.rearMat[0][:12] == 'a0.0.a0.test' assert analysis.x == [0] assert analysis.y == [0]
def test_AnalysisObj_linePtsMake3D(): # test linepts = linePtsMake3D(xstart,ystart,zstart,xinc,yinc,zinc,Nx,Ny,Nz,orient): analysis = bifacial_radiance.AnalysisObj() linepts = analysis._linePtsMake3D(0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 2, 3, '0 1 0') assert linepts == '0 0 0 0 1 0 \r1 1 1 0 1 0 \r0 0 0 0 1 0 \r1 1 1 0 1 0 \r0 0 0 0 1 0 \r1 1 1 0 1 0 \r' # v2.5.0 new linepts because now x and z also increase not only y. #assert linepts == '0 0 0 0 1 0 \r0 1 0 0 1 0 \r0 0 1 0 1 0 \r0 1 1 0 1 0 \r0 0 2 0 1 0 \r0 1 2 0 1 0 \r' assert str(analysis)[12:16] == 'None'
def simulate_single(tilt=None, results_folder_fmt=None, weather_file=None): # Verify test_folder exists test_folder = results_folder_fmt.format(f'{tilt:02}') if not os.path.exists(test_folder): os.makedirs(test_folder) # Variables that stay the same #Main Variables needed throughout albedo = 0.6 sim_general_name = 'bifacial_example' lat = 37.5 lon = -77.6 moduletype = 'Prism Solar Bi60 landscape' pitch = 3 clearance_height = 0.2 azimuth = 180 nMods = 20 nRows = 7 hpc = True pitch = 3 clearance_height = 0.2 azimuth = 90 nMods = 20 nRows = 7 hpc = True sim_name = sim_general_name + '_' + str(tilt) demo = bifacial_radiance.RadianceObj(sim_name, str(test_folder)) demo.setGround(albedo) metdata = demo.readWeatherFile(weather_file) demo.genCumSky(savefile=sim_name) sceneDict = { 'tilt': tilt, 'pitch': pitch, 'clearance_height': clearance_height, 'azimuth': azimuth, 'nMods': nMods, 'nRows': nRows } scene = demo.makeScene(moduletype=moduletype, sceneDict=sceneDict, hpc=hpc, radname=sim_name) octfile = demo.makeOct(filelist=demo.getfilelist(), octname=demo.basename, hpc=hpc) analysis = bifacial_radiance.AnalysisObj(octfile=octfile, name=sim_name) frontscan, backscan = analysis.moduleAnalysis(scene=scene) frontdict, backdict = analysis.analysis(octfile, name=sim_name, frontscan=frontscan, backscan=backscan) results = 1 return results
def test_AnalysisObj_linePtsMake3D(): # test linepts = linePtsMake3D(xstart,ystart,zstart,xinc,yinc,zinc,Nx,Ny,Nz,orient): analysis = bifacial_radiance.AnalysisObj() linepts = analysis.linePtsMake3D(0,0,0,1,1,1,1,2,3,'0 1 0') assert linepts == '0 0 0 0 1 0 \r0 1 0 0 1 0 \r0 0 1 0 1 0 \r0 1 1 0 1 0 \r0 0 2 0 1 0 \r0 1 2 0 1 0 \r'
def test_SingleModule_gencumsky(): import datetime # 1 module for STC conditions. DNI:900, DHI:100, sun angle: 33 elevation 0 azimuth name = "_test_fixedtilt_end_to_end" demo = bifacial_radiance.RadianceObj(name) # Create a RadianceObj 'object' demo.setGround(0.62) metdata = demo.readWeatherFile(MET_FILENAME, starttime='06_17_13', endtime='06_17_13') demo.genCumSky() # 1p, June 17th # create a scene using panels in landscape at 10 deg tilt, 1.5m pitch. 0.2 m ground clearance sceneDict = { 'tilt': 10, 'pitch': 1.5, 'clearance_height': 0.2, 'nMods': 10, 'nRows': 3 } demo.makeModule(name='test', y=0.95, x=1.59, xgap=0) scene = demo.makeScene('test', sceneDict) octfile = demo.makeOct( demo.getfilelist() ) # makeOct combines all of the ground, sky and object files into a .oct file. analysis = bifacial_radiance.AnalysisObj( octfile, demo.name ) # return an analysis object including the scan dimensions for back irradiance (frontscan, backscan) = analysis.moduleAnalysis(scene) analysis.analysis(octfile, demo.name, frontscan, backscan) # compare the back vs front irradiance assert analysis.mattype[0][:12] == 'a4.1.a0.test' assert analysis.rearMat[0][:12] == 'a4.1.a0.test' assert np.mean(analysis.x) == pytest.approx(0) assert np.mean(analysis.y) == pytest.approx(0) if DEBUG: print(np.mean(analysis.Wm2Front)) print(np.mean(analysis.Wm2Back)) print(np.mean(analysis.backRatio)) # Note: gencumsky has 30-50 Wm-2 variability from run to run... unsure why. assert np.mean(analysis.Wm2Front) == pytest.approx( 1030, abs=60) #1023,1037,1050, 1035, 1027, 1044, 1015, 1003, 1056 assert np.mean(analysis.Wm2Back) == pytest.approx( 133, abs=15) # 127, 131, 131, 135, 130, 139, 120, 145 # run 1-axis gencumsky option trackerdict = demo.set1axis(metdata, limit_angle=45, backtrack=True, gcr=0.33) demo.genCumSky1axis(trackerdict)
def test_SceneObj_makeSceneNxR_lowtilt(): # test _makeSceneNxR(tilt, height, pitch, azimuth = 180, nMods = 20, nRows = 7, radname = None) # default scene with simple_panel, 10 degree tilt, 0.2 height, 1.5 row spacing, landscape name = "_test_makeSceneNxR_lowtilt" demo = bifacial_radiance.RadianceObj(name) demo.makeModule(name='test-module', y=0.95, x=1.59) #scene = bifacial_radiance.SceneObj(moduletype = name) #scene._makeSceneNxR(tilt=10,height=0.2,pitch=1.5) sceneDict = {'tilt': 10, 'clearance_height': 0.2, 'pitch': 1.5} scene = demo.makeScene(module='test-module', sceneDict=sceneDict) analysis = bifacial_radiance.AnalysisObj() (frontscan, backscan) = analysis.moduleAnalysis(scene) assert frontscan.pop( 'orient') == '-0.000 0.174 -0.985' # was 0,0,-11 in v0.2.4 assert frontscan == pytest.approx({ 'Nx': 1, 'Ny': 9, 'Nz': 1, 'xinc': 0, 'yinc': 0.093556736536159757, 'xstart': 4.627616431348303e-17, 'ystart': -0.3778735578756446, 'zinc': 0.016496576878358378, 'zstart': 0.23717753969161476, 'sx_xinc': 0.0, 'sx_yinc': 0.0, 'sx_zinc': 0.0 }) assert backscan.pop( 'orient') == '0.000 -0.174 0.985' # was 0,0,1 in v0.2.4 assert backscan == pytest.approx({ 'Nx': 1, 'Ny': 9, 'Nz': 1, 'xinc': 0, 'yinc': 0.093556736536159757, 'xstart': 4.580831740657635e-17, 'ystart': -0.3740532979669721, 'zinc': 0.016496576878358378, 'zstart': 0.21551176912534617, 'sx_xinc': 0.0, 'sx_yinc': 0.0, 'sx_zinc': 0.0 }) # zstart was 0.01 and zinc was 0 in v0.2.2 #assert scene.text == '!xform -rz -90 -t -0.795 0.475 0 -rx 10 -t 0 0 0.2 -a 20 -t 1.6 0 0 -a 7 -t 0 1.5 0 -i 1 -t -15.9 -4.5 0 -rz 0 objects\\simple_panel.rad' assert scene.text[ 0: 116] == '!xform -rx 10 -t 0 0 0.2824828843917919 -a 20 -t 1.6 0 0 -a 7 -t 0 1.5 0 -i 1 -t -14.4 -4.5 0 -rz 0 -t 0 0 0 objects' #linux has different directory structure and will error here.
def test_analyzeRow(): # test analyzeRow. Requires metdata for boulder. name = "_test_analyzeRow" demo = bifacial_radiance.RadianceObj(name) demo.setGround(0.2) metdata = demo.readWeatherFile(weatherFile=MET_FILENAME) nMods = 2 nRows = 2 sceneDict = { 'tilt': 0, 'pitch': 30, 'clearance_height': 3, 'azimuth': 90, 'nMods': nMods, 'nRows': nRows } demo.setGround(0.2) demo.gendaylit(4020) demo.makeModule(name='test-module', y=1, x=2, xgap=0.0) scene = demo.makeScene( 'test-module', sceneDict ) #makeScene creates a .rad file with 20 modules per row, 7 rows. octfile = demo.makeOct( demo.getfilelist() ) # makeOct combines all of the ground, sky and object files into a .oct file. analysis = bifacial_radiance.AnalysisObj( octfile, demo.name ) # return an analysis object including the scan dimensions for back irradiance rowscan = analysis.analyzeRow(octfile=octfile, scene=scene, name=name, rowWanted=1, sensorsy=[3, 3]) assert len(rowscan) == 2 assert rowscan.keys()[2] == 'z' assert len(rowscan[rowscan.keys()[2]][0]) == 3 # Assert z is the same for two different modules assert rowscan[rowscan.keys()[2]][0][0] == rowscan[rowscan.keys()[2]][1][0] # Assert Y is different for two different modules assert rowscan[rowscan.keys()[1]][0][0] + 2 == rowscan[rowscan.keys() [1]][1][0]
def test_RadianceObj_high_azimuth_angle_end_to_end(): # modify example for high azimuth angle to test different parts of makesceneNxR. Rear irradiance fraction roughly 17.3% for 0.95m landscape panel # takes 14 seconds for sensorsy = 9, 11 seconds for sensorsy = 2 demo = bifacial_radiance.RadianceObj() # Create a RadianceObj 'object' demo.setGround('white_EPDM') # input albedo number or material name like 'concrete'. To see options, run this without any input. #metdata = demo.readEPW() # read in the EPW weather data from above metdata = demo.readTMY(MET_FILENAME2) # select a TMY file using graphical picker # Now we either choose a single time point, or use cumulativesky for the entire year. fullYear = False if fullYear: demo.genCumSky(demo.epwfile) # entire year. # Don't know how to test this yet in pytest... else: demo.gendaylit(metdata,4020) # Noon, June 17th # create a scene using panels in landscape at 10 deg tilt, 1.5m pitch. 0.2 m ground clearance sceneDict = {'tilt':10,'pitch':1.5,'height':0.2,'orientation':'landscape','azimuth':30} demo.makeModule(name='simple_panel',x=0.95,y=1.59) scene = demo.makeScene('simple_panel',sceneDict, nMods = 10, nRows = 3) #makeScene creates a .rad file with 20 modules per row, 7 rows. octfile = demo.makeOct(demo.getfilelist()) # makeOct combines all of the ground, sky and object files into a .oct file. analysis = bifacial_radiance.AnalysisObj(octfile, demo.name) # return an analysis object including the scan dimensions for back irradiance analysis.analysis(octfile, demo.name, scene.frontscan, scene.backscan) # compare the back vs front irradiance #assert np.round(np.mean(analysis.backRatio),2) == 0.20 # bifi ratio was == 0.22 in v0.2.2 assert np.mean(analysis.Wm2Front) == pytest.approx(899, rel = 0.005) # was 912 in v0.2.3 assert np.mean(analysis.Wm2Back) == pytest.approx(189, rel = 0.015) # was 182 in v0.2.2
'pitch': 5, 'clearance_height': 0.05, 'azimuth': 180, 'nMods': 1, 'nRows': 1, 'originx': 0, 'originy': 0, 'appendRadfile': True } mymodule1 = demo.makeModule(name='test-module', x=2, y=1, numpanels=1) sceneObj1 = demo.makeScene(mymodule1, sceneDict1) # In[5]: octfile = demo.makeOct(demo.getfilelist()) analysis = bifacial_radiance.AnalysisObj(octfile, demo.basename) frontscan, backscan = analysis.moduleAnalysis(sceneObj1, sensorsy=1) results = analysis.analysis(octfile, demo.basename, frontscan, backscan) # In[6]: withoutMirror = bifacial_radiance.load.read1Result( 'results\irr_tutorial_22.csv') withoutMirror # ## 2. Add Mirror # # ### Approach 1: Pretend the mirror is another module. # # We start by creating the mirror material in our ground.rad file, in case it is not there. For mirror or glass primitives (material classes), pecularity and roughness are not needed. #
def _other_cruft(): # In[3]: # Improvements: # Create new SPECTRA Folder on the Radiance Scene Folder to save spectras in automatically # Search for metdata internally if not passed # Start using timestamps instead of indexes # generate spectras and save values internally as part of the rad_obj ~ # generate spectras for all indexes in metdata automatically (might take a while for the year if readWeatherFile is not restricted) # pySMARTS: interactive folder selectro to choose where Smarts executable is at, in case it doesn't find it in the Environment Variables # # 2) Call spectra for that timestamp # In[14]: wavelength = 700 # In[ ]: # spectral_utils generates files with this suffix suffix = f'_{idx:04}.txt' # Load albedo alb_file = Path(spectra_folder, "alb" + suffix) spectral_alb = br.spectral_utils.spectral_property.load_file(alb_file) # Generate/Load dni and dhi dni_file = os.path.join(spectra_folder, "dni" + suffix) dhi_file = os.path.join(spectra_folder, "dhi" + suffix) ghi_file = os.path.join(spectra_folder, "ghi" + suffix) spectral_dni = br.spectral_utils.spectral_property.load_file(dni_file) spectral_dhi = br.spectral_utils.spectral_property.load_file(dhi_file) spectral_ghi = br.spectral_utils.spectral_property.load_file(ghi_file) alb = spectral_alb[wavelength] dni = spectral_dni[wavelength] dhi = spectral_dhi[wavelength] ghi = spectral_ghi[wavelength] rad_obj.setGround(alb) # this option is for spectral-albedo solpos = rad_obj.metdata.solpos.iloc[idx] zen = float(solpos.zenith) azm = float(solpos.azimuth) - 180 rad_obj.gendaylit2manual(dni, dhi, 90 - zen, azm) sceneDict = { 'tilt': tilt, 'pitch': 0.0001, 'clearance_height': 2.0, 'azimuth': 180, 'nMods': 1, 'nRows': 1 } sceneObj = rad_obj.makeScene(moduletype=module_type, sceneDict=sceneDict) # Build oct file octfile = rad_obj.makeOct(octname=f'Oct_{idx:04}') analysis = br.AnalysisObj(octfile, rad_obj.basename) frontscan, backscan = analysis.moduleAnalysis(sceneObj, sensorsy=3) res_name = f'CenterRow_Center_{idx:04}' frontdict, backdict = analysis.analysis(octfile, res_name, frontscan, backscan)
def runModelChain(simulationParamsDict, sceneParamsDict, timeControlParamsDict=None, moduleParamsDict=None, trackingParamsDict=None, torquetubeParamsDict=None, analysisParamsDict=None, cellLevelModuleParamsDict=None): """ This calls config.py values, which are arranged into dictionaries, and runs all the respective processes based on the variables in the config.py. To import the variables from a .ini file, use:: (simulationParamsDict, sceneParamsDict, timeControlParamsDict, moduleParamsDict, trackingParamsDict,torquetubeParamsDict,analysisParamsDict,cellLevelModuleParamsDict) = bifacial_radiance.load.readconfigurationinputfile(inifile) """ import bifacial_radiance import os import numpy as np if 'testfolder' not in simulationParamsDict: simulationParamsDict[ 'testfolder'] = bifacial_radiance.main._interactive_directory( title= 'Select or create an empty directory for the Radiance tree') testfolder = simulationParamsDict['testfolder'] demo = bifacial_radiance.RadianceObj( simulationParamsDict['simulationname'], path=testfolder) # Create a RadianceObj 'object' # Save INIFILE in folder inifilename = os.path.join(simulationParamsDict['testfolder'], 'simulation.ini') bifacial_radiance.load.savedictionariestoConfigurationIniFile( simulationParamsDict, sceneParamsDict, timeControlParamsDict, moduleParamsDict, trackingParamsDict, torquetubeParamsDict, analysisParamsDict, cellLevelModuleParamsDict, inifilename) # re-load configuration file to make sure all booleans are converted (simulationParamsDict, sceneParamsDict, timeControlParamsDict, moduleParamsDict, trackingParamsDict,torquetubeParamsDict, analysisParamsDict,cellLevelModuleParamsDict) = \ bifacial_radiance.load.readconfigurationinputfile(inifilename) # Load weatherfile if simulationParamsDict['getEPW']: simulationParamsDict['weatherFile'] = demo.getEPW( simulationParamsDict['latitude'], simulationParamsDict['longitude'] ) # pull EPW data for any global lat/lon # If file is none, select a EPW file using graphical picker #metdata = demo.readEPW(simulationParamsDict['weatherFile']) #else: # If file is none, select a TMY file using graphical picker #metdata = demo.readTMY(simulationParamsDict['weatherFile']) # load in weatherfile. Check if start/end time if simulationParamsDict['daydateSimulation']: timelist = _returnTimeVals(timeControlParamsDict) starttime = timelist[0] endtime = timelist[-1] else: # read in full TMY file starttime = None endtime = None print('Reading weather file {}'.format( simulationParamsDict['weatherFile'])) metdata = demo.readWeatherFile(simulationParamsDict['weatherFile'], starttime=starttime, endtime=endtime) # input albedo number or material name like 'concrete'. To see options, run this without any input. demo.setGround(sceneParamsDict['albedo']) analysis = None # initialize default analysis return value to none. A = demo.printModules() #cellLeveLParams are none by default. cellLevelModuleParams = None try: if simulationParamsDict['cellLevelModule']: cellLevelModuleParams = cellLevelModuleParamsDict except: pass if torquetubeParamsDict: #kwargs = {**torquetubeParamsDict, **moduleParamsDict} #Py3 Only kwargs = _append_dicts(torquetubeParamsDict, moduleParamsDict) else: kwargs = moduleParamsDict if simulationParamsDict['moduletype'] in A: if simulationParamsDict['rewriteModule'] is True: moduleDict = demo.makeModule( name=simulationParamsDict['moduletype'], torquetube=simulationParamsDict['torqueTube'], axisofrotationTorqueTube=simulationParamsDict[ 'axisofrotationTorqueTube'], cellLevelModuleParams=cellLevelModuleParams, **kwargs) print("\nUsing Pre-determined Module Type: %s " % simulationParamsDict['moduletype']) else: moduleDict = demo.makeModule( name=simulationParamsDict['moduletype'], torquetube=simulationParamsDict['torqueTube'], axisofrotationTorqueTube=simulationParamsDict[ 'axisofrotationTorqueTube'], cellLevelModuleParams=cellLevelModuleParams, **kwargs) # TODO: Refactor as a state machine to run specific routines based on # input flags. That might clean things up here a bit... if simulationParamsDict['tracking'] is False: # Fixed Routine # makeScene creates a .rad file with 20 modules per row, 7 rows. scene = demo.makeScene(moduletype=simulationParamsDict['moduletype'], sceneDict=sceneParamsDict, hpc=simulationParamsDict['hpc']) if simulationParamsDict["cumulativeSky"]: if simulationParamsDict[ 'daydateSimulation']: # was timeIndexSimulation import datetime startdate = datetime.datetime( 2001, timeControlParamsDict['MonthStart'], timeControlParamsDict['DayStart'], timeControlParamsDict['HourStart']) enddate = datetime.datetime(2001, timeControlParamsDict['MonthEnd'], timeControlParamsDict['DayEnd'], timeControlParamsDict['HourEnd']) # entire year. demo.genCumSky(demo.epwfile, startdate, enddate) else: demo.genCumSky(demo.epwfile) # entire year. # makeOct combines all of the ground, sky and object files into a .oct file. octfile = demo.makeOct(demo.getfilelist()) # return an analysis object including the scan dimensions for back irradiance analysis = bifacial_radiance.AnalysisObj(octfile, demo.name) frontscan, backscan = analysis.moduleAnalysis( scene, analysisParamsDict['modWanted'], analysisParamsDict['rowWanted'], analysisParamsDict['sensorsy']) analysis.analysis(octfile, demo.name, frontscan, backscan) print('Bifacial ratio yearly average: %0.3f' % (np.sum(analysis.Wm2Back) / np.sum(analysis.Wm2Front))) else: # Hourly simulation fixed tilt. Use new modified 1-axis tracking workflow # Largely copies the existing 1-axis workflow from below, but # forces trackerdict tilt and azimuth to be fixed. # print('\n***Starting Fixed-tilt hourly simulation ***\n') ## All the rest here is copied from below... # Timestamp range selection if simulationParamsDict[ "timeIndexSimulation"]: # fixed tilt timestamp range for timeindex in range(timeControlParamsDict['timeindexstart'], timeControlParamsDict['timeindexend']): demo.gendaylit(metdata, timeindex) # Noon, June 17th # makeOct combines all of the ground, sky and object files into a .oct file. octfile = demo.makeOct(demo.getfilelist()) # return an analysis object including the scan dimensions for back irradiance analysis = bifacial_radiance.AnalysisObj( octfile, demo.name) frontscan, backscan = analysis.moduleAnalysis( scene, analysisParamsDict['modWanted'], analysisParamsDict['rowWanted'], analysisParamsDict['sensorsy']) analysis.analysis(octfile, demo.name, frontscan, backscan) print( 'Bifacial ratio for %s average: %0.3f' % (metdata.datetime[timeindex], np.sum(analysis.Wm2Back) / np.sum(analysis.Wm2Front))) else: # both daydateSimulation and full year uses this branch.. #TODO: pytest for this section trackerdict = demo.set1axis( cumulativesky=False, fixed_tilt_angle=sceneParamsDict['tilt'], axis_azimuth=sceneParamsDict['azimuth']) # fixed_tilt_angle switches to constant fixed tilt mode. if not (simulationParamsDict['daydateSimulation'] ): # full year. # use default behavior of _returnTimeVals to run # full year simulation if you pass timeDict as none timeControlParamsDict = None print('\n***Full - year hourly simulation ***\n') # _returnTimeVals returns proper string formatted start and end days. timelist = _returnTimeVals(timeControlParamsDict) startday = timelist[0] endday = timelist[-1] # optional parameters 'startdate', 'enddate' inputs = string 'MM/DD' or 'MM_DD' trackerdict = demo.gendaylit1axis(startdate=startday, enddate=endday) # remove times when GHI < 0 by comparing with trackerdict timelist = _returnTimeVals(timeControlParamsDict, trackerdict) print("\n***Timerange from %s to %s. ***\n" % (sorted(timelist)[0], sorted(timelist)[-1])) def _addRadfile(trackerdict): # need to add trackerdict[time]['radfile'] = radfile and # trackerdict[time]['scene'] = scene since we don't do makeScene1axis for i in trackerdict: trackerdict[i]['scene'] = scene trackerdict[i]['radfile'] = scene.radfiles return trackerdict trackerdict = _addRadfile( trackerdict) # instead of makeScene1axis footime = 0 for time in sorted(timelist): footime = footime + 1 trackerdict = demo.makeOct1axis( trackerdict, singleindex=time, hpc=simulationParamsDict['hpc']) trackerdict = demo.analysis1axis( trackerdict, singleindex=time, modWanted=analysisParamsDict['modWanted'], rowWanted=analysisParamsDict['rowWanted'], sensorsy=analysisParamsDict['sensorsy']) analysis = trackerdict[time][ 'AnalysisObj'] # save and return the last run print( 'Bifacial ratio average for %d out of %d datapoints: %0.3f' % (footime, timelist.__len__(), np.sum(demo.Wm2Back) / np.sum(demo.Wm2Front))) else: # Tracking print('\n***Starting 1-axis tracking simulation***\n') if simulationParamsDict['timeIndexSimulation']: raise Exception('timeIndexSimulations not currently ' + 'supported for tracking') if 'gcr' not in sceneParamsDict: # didn't get gcr passed - need to calculate it sceneParamsDict['gcr'] = moduleDict['sceney'] / \ sceneParamsDict['pitch'] trackerdict = demo.set1axis( metdata, axis_azimuth=sceneParamsDict['axis_azimuth'], gcr=sceneParamsDict['gcr'], limit_angle=trackingParamsDict['limit_angle'], angledelta=trackingParamsDict['angle_delta'], backtrack=trackingParamsDict['backtrack'], cumulativesky=simulationParamsDict["cumulativeSky"]) if simulationParamsDict["cumulativeSky"]: # cumulative sky routine if simulationParamsDict['daydateSimulation']: # Start / end passed import datetime startdate = datetime.datetime( 2001, timeControlParamsDict['MonthStart'], timeControlParamsDict['DayStart'], timeControlParamsDict['HourStart']) enddate = datetime.datetime(2001, timeControlParamsDict['MonthEnd'], timeControlParamsDict['DayEnd'], timeControlParamsDict['HourEnd']) trackerdict = demo.genCumSky1axis(trackerdict, startdt=startdate, enddt=enddate) else: trackerdict = demo.genCumSky1axis(trackerdict) # full year trackerdict = demo.makeScene1axis( trackerdict=trackerdict, moduletype=simulationParamsDict['moduletype'], sceneDict=sceneParamsDict, cumulativesky=simulationParamsDict['cumulativeSky'], hpc=simulationParamsDict['hpc']) trackerdict = demo.makeOct1axis(trackerdict, hpc=simulationParamsDict['hpc']) trackerdict = demo.analysis1axis( trackerdict, modWanted=analysisParamsDict['modWanted'], rowWanted=analysisParamsDict['rowWanted'], sensorsy=analysisParamsDict['sensorsy']) print('Annual RADIANCE bifacial ratio for 1-axis tracking: %0.3f' % (np.sum(demo.Wm2Back) / np.sum(demo.Wm2Front))) else: # Hourly tracking # Timestamp range selection #workflow currently identical for timeIndexSimulation and daydateSimulation # TODO: update _returnTimeVals to allow timestartindex and timeEndIndex as well. if not (simulationParamsDict['daydateSimulation']): # full year. # use default behavior of _returnTimeVals to run # full year simulation if you pass timeDict as none timeControlParamsDict = None print('\n***Full - year hourly simulation ***\n') timelist = _returnTimeVals(timeControlParamsDict) startday = timelist[0] endday = timelist[-1] trackerdict = demo.gendaylit1axis(startdate=startday, enddate=endday) # reduce trackerdict to only hours in timeControlParamsDict timelist = _returnTimeVals(timeControlParamsDict, trackerdict) trackerdict = {t: trackerdict[t] for t in timelist} # Tracker dict should go here because sky routine reduces the size of trackerdict. trackerdict = demo.makeScene1axis( trackerdict=trackerdict, moduletype=simulationParamsDict['moduletype'], sceneDict=sceneParamsDict, cumulativesky=simulationParamsDict['cumulativeSky'], hpc=simulationParamsDict['hpc']) ''' if simulationParamsDict['timeIndexSimulation']: for time in timelist: trackerdict = demo.makeOct1axis(trackerdict, singleindex=time, hpc=simulationParamsDict['hpc']) trackerdict = demo.analysis1axis(trackerdict, singleindex=time, modWanted=analysisParamsDict['modWanted'], rowWanted=analysisParamsDict['rowWanted'], sensorsy=analysisParamsDict['sensorsy']) #else: #daydateSimulation. Not sure this is much different from the above... ''' trackerdict = demo.makeOct1axis(trackerdict, hpc=simulationParamsDict['hpc']) trackerdict = demo.analysis1axis( trackerdict, modWanted=analysisParamsDict['modWanted'], rowWanted=analysisParamsDict['rowWanted'], sensorsy=analysisParamsDict['sensorsy']) # end else statement print('Bifacial Tracking simulation complete. Preliminary ' + 'Bifi ratio average: %0.3f' % (np.sum(demo.Wm2Back) / np.sum(demo.Wm2Front)) + ' but final results need cleaning') return demo, analysis
sceneDict=sceneDict) #makeScene creates a .rad file of the Scene octfile = demo.makeOct( demo.getfilelist() ) # makeOct combines all of the ground, sky and object files into a .oct file. # At this point you should be able to go into a command window (cmd.exe) and check the geometry. It should look like the image at the beginning of the journal. Example: # # #### rvu -vf views\front.vp -e .01 -pe 0.02 -vp -2 -12 14.5 Torque_tube_hex_test.oct # # And then proceed happily with your analysis: # In[7]: analysis = bifacial_radiance.AnalysisObj( octfile, demo.name ) # return an analysis object including the scan dimensions for back irradiance sensorsy = 200 # setting this very high to see a detailed profile of the irradiance, including #the shadow of the torque tube on the rear side of the module. frontscan, backscan = analysis.moduleAnalysis(scene, modWanted=2, rowWanted=1, sensorsy=200) frontDict, backDict = analysis.analysis( octfile, demo.name, frontscan, backscan) # compare the back vs front irradiance # print('"Annual" bifacial ratio average: %0.3f' %( sum(analysis.Wm2Back) / sum(analysis.Wm2Front) ) ) # See comment below of why this line is commented out.
demo.makeModule(name=moduletype, x=x, y=y, xgap=xgap) sceneDict = { 'tilt': tilt, 'pitch': pitch, 'clearance_height': clearance_height, 'azimuth': azimuth, 'nMods': nMods, 'nRows': nRows } scene = demo.makeScene(moduletype=moduletype, sceneDict=sceneDict, hpc=hpc, radname=sim_name) octfile = demo.makeOct(octname=demo.basename, hpc=hpc) analysis = bifacial_radiance.AnalysisObj(octfile=octfile, name=sim_name) # Modify sensor position to coffee plant location frontscan, backscan = analysis.moduleAnalysis(scene=scene, sensorsy=1) groundscan = frontscan.copy() groundscan['xstart'] = coffeeplant_x groundscan['ystart'] = coffeeplant_y groundscan['zstart'] = 0.05 groundscan['orient'] = '0 0 -1' analysis.analysis(octfile, name=sim_name + '_Front&Back', frontscan=frontscan, backscan=backscan) analysis.analysis(octfile, name=sim_name + '_Ground&Back',
endtime = pd.to_datetime('2021-05-31 18:0:0') rad_obj = bifacial_radiance.RadianceObj(simulationName) rad_obj.setGround(albedo) metdata = rad_obj.readWeatherFile(epwfile, label='center', coerce_year=2021, starttime=starttime, endtime=endtime) rad_obj.genCumSky() #print(rad_obj.metdata.datetime[idx]) sceneDict = { 'pitch': pitch, 'tilt': 0, 'azimuth': 90, 'hub_height': -0.2, 'nMods': 1, 'nRows': 1 } scene = rad_obj.makeScene(module=moduletype, sceneDict=sceneDict) octfile = rad_obj.makeOct() analysis = bifacial_radiance.AnalysisObj() frontscan, backscan = analysis.moduleAnalysis(scene, sensorsy=1) frontscan['zstart'] = 0.5 frontdict, backdict = analysis.analysis(octfile=octfile, name='FIELDTotal', frontscan=frontscan, backscan=backscan) print("FIELD TOTAL MAY:", analysis.Wm2Front[0]) # # Next STEPS: Raytrace Every hour of the Month on the HPC -- Check HPC Scripts for Jack Solar
def test_moduleFrameandOmegas(): # test moduleFrameandOmegas. Requires metdata for boulder. name = "_test_moduleFrameandOmegas" demo = bifacial_radiance.RadianceObj(name) #demo.setGround(0.2) zgap = 0.10 loopaxisofRotation = [True, True, True, True, True, True, True, True] loopTorquetube = [True, True, True, True, False, False, False, False] loopOmega = [ omegaParams, omegaParams, None, None, omegaParams, omegaParams, None, None ] loopFrame = [ frameParams, None, frameParams, None, frameParams, None, frameParams, None ] expectedModuleZ = [3.179, 3.149, 3.179, 3.149, 3.129, 3.099, 3.129, 3.099] # test inverted=True on the first test loopOmega[0]['inverted'] = True sceneDict = { 'tilt': 0, 'pitch': 3, 'clearance_height': 3, 'azimuth': 90, 'nMods': 1, 'nRows': 1 } for ii in range(0, len(loopOmega)): if loopTorquetube[ii] is False: diam = 0.0 else: diam = 0.1 module = bifacial_radiance.ModuleObj( name='test-module', x=2, y=1, zgap=zgap, ) module.addTorquetube(diameter=diam, axisofrotation=loopaxisofRotation[ii], visible=loopTorquetube[ii]) if loopFrame[ii]: module.addFrame(**loopFrame[ii]) if loopOmega[ii]: module.addOmega( **loopOmega[ii]) #another way to add omega parameters scene = demo.makeScene(module, sceneDict) analysis = bifacial_radiance.AnalysisObj( ) # return an analysis object including the scan dimensions for back irradiance frontscan, backscan = analysis.moduleAnalysis( scene, sensorsy=1) # Gives us the dictionaries with coordinates assert backscan['zstart'] == expectedModuleZ[ii] # read the data back from module.json and check again module = demo.makeModule(name='test-module') scene = demo.makeScene('test-module', sceneDict) analysis = bifacial_radiance.AnalysisObj( ) # return an analysis object including the scan dimensions for back irradiance frontscan, backscan = analysis.moduleAnalysis(scene, sensorsy=1) assert backscan['zstart'] == expectedModuleZ[ii] # do it again by passing everying at once module = bifacial_radiance.ModuleObj(name='test-module', x=2, y=1, zgap=zgap, frameParams=frameParams, omegaParams=omegaParams, tubeParams={ 'diameter': 0.1, 'axisofrotation': True }) scene = demo.makeScene(module, sceneDict) analysis = bifacial_radiance.AnalysisObj( ) # return an analysis object including the scan dimensions for back irradiance frontscan, backscan = analysis.moduleAnalysis( scene, sensorsy=1) # Gives us the dictionaries with coordinates assert backscan['zstart'] == expectedModuleZ[0] # omega default values module.addOmega() assert module.omega.x_omega1 == 0.003 assert module.omega.y_omega == 0.5 assert module.omega.x_omega3 == 0.005 module.addOmega(inverted=True) assert module.omega.x_omega1 == 0.005 assert module.omega.y_omega == 0.5 assert module.omega.x_omega3 == 0.0015 # test cellModulescan (sensorsy = numellsy) module.glass = True module.addCellModule(**cellParams) scene = demo.makeScene(module, sceneDict) analysis = bifacial_radiance.AnalysisObj( ) # return an analysis object including the scan dimensions for back irradiance frontscan, backscan = analysis.moduleAnalysis( scene, sensorsy=10) # Gives us the dictionaries with coordinates assert backscan['xstart'] == pytest.approx(0.792)
def simulate_single(xgap=None, numpanels=None, sensorx=None, test_folder_fmt=None, weather_file=None): ft2m = 0.3048 hub_height = 8.0 * ft2m y = 1 pitch = 0.001 # y * np.cos(np.radians(tilt))+D ygap = 0.15 tilt = 18 sim_name = ('Coffee_' + str(numpanels) + 'up_' + str(round(xgap, 1)) + '_xgap_' + str(sensorx) + 'posx') # Verify test_folder exists before creating radiance obj test_folder = test_folder_fmt.format(f'{numpanels}', f'{round(xgap,1)}', f'{sensorx:03}') if not os.path.exists(test_folder): os.makedirs(test_folder) lat = 18.202142 lon = -66.759187 albedo = 0.25 # Grass value from Torres Molina, "Measuring UHI in Puerto Rico" 18th LACCEI # International Multi-Conference for Engineering, Education, and Technology x = 1.64 azimuth = 180 if numpanels == 3: nMods = 9 if numpanels == 4: nMods = 7 nRows = 1 moduletype = 'PR_' + str(numpanels) + 'up_' + str(round(xgap, 1)) + 'xgap' hpc = False demo = bifacial_radiance.RadianceObj(sim_name, str(test_folder)) demo.setGround(albedo) demo.readWeatherFile(weather_file) sceneDict = { 'tilt': tilt, 'pitch': pitch, 'hub_height': hub_height, 'azimuth': azimuth, 'nMods': nMods, 'nRows': nRows } scene = demo.makeScene(moduletype=moduletype, sceneDict=sceneDict, hpc=hpc, radname=sim_name) demo.genCumSky() octfile = demo.makeOct(filelist=demo.getfilelist(), octname=demo.basename, hpc=hpc) analysis = bifacial_radiance.AnalysisObj(octfile=octfile, name=sim_name) ii = 1 jj = 1 simplesim = False if simplesim: sensorsy_front = 20 sensorsy_back = 1 sensorsx_front = 1 sensorsx_back = 1 else: sensorsy_front = 201 sensorsy_back = 1 sensorsx_front = 1 sensorsx_back = 1 frontscan, backscan = analysis.moduleAnalysis( scene, sensorsy_front=sensorsy_front, sensorsx_front=sensorsx_front, sensorsy_back=sensorsy_back, sensorsx_back=sensorsx_back) xinc = 0.10 # cm . Sampling every 10 cm. yinc = 0.10 # cm . Sampling every 10 cm frontscan['zstart'] = 0.01 frontscan['xstart'] = -20 + sensorx * xinc frontscan['orient'] = '0 0 -1' frontscan['zinc'] = 0 frontscan['yinc'] = yinc frontscan['ystart'] = -10 # n frontdict, backdict = analysis.analysis(octfile=octfile, name='xloc_' + str(sensorx), frontscan=frontscan, backscan=backscan) results = 1 print("***** Finished simulation for " + str(sim_name)) results = 1 return results
def simulate_single(idx=None, test_folder_fmt=None, weather_file=None): # Verify test_folder exists before creating radiance obj test_folder = test_folder_fmt.format(f'{idx}') if not os.path.exists(test_folder): os.makedirs(test_folder) # Input Values radiance_name = 'JackSolar' lat = 40.1217 # Given for the project site at Colorado lon = -105.1310 # Given for the project site at Colorado moduletype = 'CaseA' numpanels = 1 # This site have 1 module in Y-direction x = 1 y = 2.4384 # 6ft zgap = 0.10 # no gap to torquetube. torquetube = True axisofrotationTorqueTube = True diameter = 0.15 # 15 cm diameter for the torquetube tubetype = 'square' # Put the right keyword upon reading the document material = 'black' # Torque tube of this material (0% reflectivity) # Scene variables nMods = 20 nRows = 7 hub_height = 2.4384 # meters pitch = 5.1816 # meters # Pitch is the known parameter albedo = 0.2 #'Grass' # ground albedo gcr = y / pitch cumulativesky = False limit_angle = 60 # tracker rotation limit angle angledelta = 0.01 # we will be doing hourly simulation, we want the angle to be as close to real tracking as possible. backtrack = True # START SIMULATION rad_obj = bifacial_radiance.RadianceObj(radiance_name, str(test_folder)) # Set ground rad_obj.readWeatherFile(weather_file, label='center') # Query data from metadata for index of interest foo = rad_obj.metdata.datetime[idx] dni = rad_obj.metdata.dni[idx] dhi = rad_obj.metdata.dhi[idx] res_name = "irr_Jacksolar_" + str(foo.year) + "_" + str( foo.month) + "_" + str(foo.day) + "_" + str(foo.hour) + "_" + str( foo.minute) rad_obj.setGround(albedo) # Set sky solpos = rad_obj.metdata.solpos.iloc[idx] zen = float(solpos.zenith) azm = float(solpos.azimuth) - 180 if zen > 90: print("Nightime ") return rad_obj.gendaylit2manual(dni, dhi, 90 - zen, azm) # Set tracker information tilt = round( rad_obj.getSingleTimestampTrackerAngle(rad_obj.metdata, idx, gcr, limit_angle=65), 1) sceneDict = { 'pitch': pitch, 'tilt': tilt, 'azimuth': 90, 'hub_height': hub_height, 'nMods': nMods, 'nRows': nRows } scene = rad_obj.makeScene(moduletype=moduletype, sceneDict=sceneDict) octfile = rad_obj.makeOct(octname=res_name) sensorsx = 22 sensorsy = 105 module_scenex = x + 0.01 extra_sampling_space_x = 0.10 spacingsensorsx = (module_scenex + extra_sampling_space_x) / (sensorsx - 1) startxsensors = (module_scenex + extra_sampling_space_x) / 2 xinc = pitch / (sensorsy - 1) analysis = bifacial_radiance.AnalysisObj() frontscan, backscan = analysis.moduleAnalysis(scene, sensorsy=sensorsy) #LOCATION_APOGEES for senx in range(0, sensorsx): frontscan['zstart'] = 0 frontscan['xstart'] = 0 frontscan['orient'] = '0 0 -1' frontscan['zinc'] = 0 frontscan['xinc'] = xinc frontscan['ystart'] = startxsensors - spacingsensorsx * senx frontdict, backdict = analysis.analysis(octfile=octfile, name='xloc_' + str(senx), frontscan=frontscan, backscan=backscan) results = 1 # Saving one value for front of module to calculate bifacial gain frontscan, backscan = analysis.moduleAnalysis(scene, sensorsy=1) frontdict, backdict = analysis.analysis(octfile=octfile, name='frontSide', frontscan=frontscan, backscan=backscan) print("***** Finished simulation for " + str(foo)) return results
def simulate_single(clearance_height=None, xgap=None, tilt = None, D = None, test_folder_fmt=None, weather_file=None): ft2m = 0.3048 y = 1 pitch = y * np.cos(np.radians(tilt))+D sim_name = ('Coffee_ch_'+str(round(clearance_height,1))+ '_xgap_'+str(round(xgap,1))+\ '_tilt_'+str(round(tilt,1))+ '_pitch_'+str(round(pitch,1))) # Verify test_folder exists before creating radiance obj test_folder = test_folder_fmt.format(f'{clearance_height}', f'{xgap}', f'{tilt}', f'{pitch}') if not os.path.exists(test_folder): os.makedirs(test_folder) lat = 18.202142 lon = -66.759187 albedo = 0.25 # Grass value from Torres Molina, "Measuring UHI in Puerto Rico" 18th LACCEI # International Multi-Conference for Engineering, Education, and Technology x = 1.64 azimuth = 180 nMods = 20 nRows = 7 numpanels = 1 moduletype = 'PR_'+str(round(xgap,1)) hpc = False demo = bifacial_radiance.RadianceObj(sim_name,str(test_folder)) demo.setGround(albedo) demo.readWeatherFile(weather_file) sceneDict = {'tilt':tilt,'pitch':pitch,'clearance_height':clearance_height,'azimuth':azimuth, 'nMods': nMods, 'nRows': nRows} scene = demo.makeScene(moduletype=moduletype,sceneDict=sceneDict, hpc=hpc, radname = sim_name) text = '' tree_albedo = 0.165 # Wikipedia [0.15-0.18] trunk_x = 0.8 * ft2m trunk_y = trunk_x trunk_z = 1 * ft2m tree_x = 3 * ft2m tree_y = tree_x tree_z = 4 * ft2m for ii in range(0,3): coffeeplant_x = (x+xgap)/2 + (x+xgap)*ii for jj in range(0,3): coffeeplant_y = pitch/2 + pitch*jj name = 'tree'+str(ii)+str(jj) text = '! genrev litesoil tube{}tree t*{} {} 32 | xform -t {} {} {}'.format('head'+str(ii)+str(jj),tree_z, tree_x/2.0, -trunk_x/2.0 + coffeeplant_x, -trunk_x/2.0 + coffeeplant_y, trunk_z) text += '\r\n! genrev litesoil tube{}tree t*{} {} 32 | xform -t {} {} 0'.format('trunk'+str(ii)+str(jj),trunk_z, trunk_x/2.0, -trunk_x/2.0 + coffeeplant_x, -trunk_x/2.0 + coffeeplant_y) customObject = demo.makeCustomObject(name,text) demo.appendtoScene(radfile=scene.radfiles, customObject=customObject, text="!xform -rz 0") demo.genCumSky() octfile = demo.makeOct(filelist = demo.getfilelist(), octname = demo.basename, hpc=hpc) analysis = bifacial_radiance.AnalysisObj(octfile=octfile, name=sim_name) ii = 1 jj = 1 coffeeplant_x = (x+xgap)/2 + (x+xgap)*ii coffeeplant_y = pitch/2 + pitch*jj frontscan, backscan = analysis.moduleAnalysis(scene=scene, sensorsy=1) treescan_south = frontscan.copy() treescan_north = frontscan.copy() treescan_east = frontscan.copy() treescan_west = frontscan.copy() treescan_south['xstart'] = coffeeplant_x treescan_south['ystart'] = coffeeplant_y - tree_x/2.0 - 0.05 treescan_south['zstart'] = tree_z treescan_south['orient'] = '0 1 0' treescan_north['xstart'] = coffeeplant_x treescan_north['ystart'] = coffeeplant_y + tree_x/2.0 + 0.05 treescan_north['zstart'] = tree_z treescan_north['orient'] = '0 -1 0' treescan_east['xstart'] = coffeeplant_x + tree_x/2.0 + 0.05 treescan_east['ystart'] = coffeeplant_y treescan_east['zstart'] = tree_z treescan_east['orient'] = '-1 0 0' treescan_west['xstart'] = coffeeplant_x - tree_x/2.0 - 0.05 treescan_west['ystart'] = coffeeplant_y treescan_west['zstart'] = tree_z treescan_west['orient'] = '1 0 0' groundscan = frontscan.copy() groundscan['xstart'] = coffeeplant_x groundscan['ystart'] = coffeeplant_y groundscan['zstart'] = 0.05 groundscan['orient'] = '0 0 -1' analysis.analysis(octfile, name=sim_name+'_North&South', frontscan=treescan_north, backscan=treescan_south) analysis.analysis(octfile, name=sim_name+'_East&West', frontscan=treescan_east, backscan=treescan_west) print("***** Finished simulation for "+ str(sim_name)) results=1 return results
mymodule = demo.makeModule(name='test-module', x=2, y=1) sceneDict = { 'tilt': 0, 'pitch': 6, 'clearance_height': 3, 'azimuth': 180, 'nMods': 1, 'nRows': 1 } # In[7]: scene = demo.makeScene(mymodule, sceneDict) octfile = demo.makeOct() analysis = bifacial_radiance.AnalysisObj( ) # return an analysis object including the scan dimensions for back irradiance # #### Same sensors front and back, two sensors accross x # In[8]: name = '2222' sensorsy_front = 2 sensorsy_back = 2 sensorsx_front = 2 sensorsx_back = 2 sensorsy = [sensorsy_front, sensorsy_back] sensorsx = [sensorsx_front, sensorsx_back] frontscan, backscan = analysis.moduleAnalysis(scene,
def runModelChain(simulationParamsDict, sceneParamsDict, timeControlParamsDict=None, moduleParamsDict=None, trackingParamsDict=None, torquetubeParamsDict=None, analysisParamsDict=None, cellLevelModuleParamsDict=None): ''' This calls config.py values, which are arranged into dictionaries, and runs all the respective processes based on the varaibles in the config.py. Still under testing! ''' if 'testfolder' not in simulationParamsDict: simulationParamsDict['testfolder'] = bifacial_radiance.main._interactive_directory( title='Select or create an empty directory for the Radiance tree') testfolder = simulationParamsDict['testfolder'] demo = bifacial_radiance.RadianceObj( simulationParamsDict['simulationname'], path=testfolder) # Create a RadianceObj 'object' # Save INIFILE in folder inifilename = os.path.join( simulationParamsDict['testfolder'], 'simulation.ini') bifacial_radiance.load.savedictionariestoConfigurationIniFile(simulationParamsDict, sceneParamsDict, timeControlParamsDict, moduleParamsDict, trackingParamsDict, torquetubeParamsDict, analysisParamsDict, cellLevelModuleParamsDict, inifilename) # All options for loading data: if simulationParamsDict['weatherFile'][-3:] == 'epw': if simulationParamsDict['getEPW']: simulationParamsDict['weatherFile'] = demo.getEPW( simulationParamsDict['latitude'], simulationParamsDict['longitude']) # pull TMY data for any global lat/lon # If file is none, select a EPW file using graphical picker metdata = demo.readEPW(simulationParamsDict['weatherFile']) else: # If file is none, select a TMY file using graphical picker metdata = demo.readTMY(simulationParamsDict['weatherFile']) # input albedo number or material name like 'concrete'. To see options, run this without any input. demo.setGround(sceneParamsDict['albedo']) analysis = None # initialize default analysis return value to none. A = demo.printModules() #cellLeveLParams are none by default. cellLevelModuleParams = None try: if simulationParamsDict['cellLevelModule']: cellLevelModuleParams = cellLevelModuleParamsDict except: pass if torquetubeParamsDict: #kwargs = {**torquetubeParamsDict, **moduleParamsDict} #Py3 Only kwargs = _append_dicts(torquetubeParamsDict, moduleParamsDict) else: kwargs = moduleParamsDict if simulationParamsDict['moduletype'] in A: if simulationParamsDict['rewriteModule'] is True: moduleDict = demo.makeModule(name=simulationParamsDict['moduletype'], torquetube=simulationParamsDict['torqueTube'], axisofrotationTorqueTube=simulationParamsDict[ 'axisofrotationTorqueTube'], cellLevelModuleParams=cellLevelModuleParams, **kwargs) print("\nUsing Pre-determined Module Type: %s " % simulationParamsDict['moduletype']) else: moduleDict = demo.makeModule(name=simulationParamsDict['moduletype'], torquetube=simulationParamsDict['torqueTube'], axisofrotationTorqueTube=simulationParamsDict['axisofrotationTorqueTube'], cellLevelModuleParams=cellLevelModuleParams, **kwargs) if simulationParamsDict['tracking'] is False: # Fixed Routine # makeScene creates a .rad file with 20 modules per row, 7 rows. scene = demo.makeScene( moduletype=simulationParamsDict['moduletype'], sceneDict=sceneParamsDict, hpc=simulationParamsDict['hpc']) if simulationParamsDict["cumulativeSky"]: if simulationParamsDict['timestampRangeSimulation']: import datetime startdate = datetime.datetime(2001, timeControlParamsDict['MonthStart'], timeControlParamsDict['DayStart'], timeControlParamsDict['HourStart']) enddate = datetime.datetime(2001, timeControlParamsDict['MonthEnd'], timeControlParamsDict['DayEnd'], timeControlParamsDict['HourEnd']) # entire year. demo.genCumSky(demo.epwfile, startdate, enddate) else: demo.genCumSky(demo.epwfile) # entire year. # makeOct combines all of the ground, sky and object files into a .oct file. octfile = demo.makeOct(demo.getfilelist()) # return an analysis object including the scan dimensions for back irradiance analysis = bifacial_radiance.AnalysisObj(octfile, demo.name) frontscan, backscan = analysis.moduleAnalysis(scene, analysisParamsDict['modWanted'], analysisParamsDict['rowWanted'], analysisParamsDict['sensorsy']) analysis.analysis(octfile, demo.name, frontscan, backscan) print('Bifacial ratio yearly average: %0.3f' % (sum(analysis.Wm2Back) / sum(analysis.Wm2Front))) else: if simulationParamsDict["timestampRangeSimulation"]: for timeindex in range(timeControlParamsDict['timeindexstart'], timeControlParamsDict['timeindexend']): demo.gendaylit(metdata, timeindex) # Noon, June 17th # makeOct combines all of the ground, sky and object files into a .oct file. octfile = demo.makeOct(demo.getfilelist()) # return an analysis object including the scan dimensions for back irradiance analysis = bifacial_radiance.AnalysisObj( octfile, demo.name) frontscan, backscan = analysis.moduleAnalysis(scene, analysisParamsDict['modWanted'], analysisParamsDict['rowWanted'], analysisParamsDict['sensorsy']) analysis.analysis(octfile, demo.name, frontscan, backscan) print('Bifacial ratio for %s average: %0.3f' % ( metdata.datetime[timeindex], sum(analysis.Wm2Back) / sum(analysis.Wm2Front))) else: # Run whole year for timeindex in range(0, 8760): demo.gendaylit(metdata, timeindex) # Noon, June 17th # makeOct combines all of the ground, sky and object files into a .oct file. octfile = demo.makeOct(demo.getfilelist()) # return an analysis object including the scan dimensions for back irradiance analysis = bifacial_radiance.AnalysisObj( octfile, demo.name) frontscan, backscan = analysis.moduleAnalysis(scene, analysisParamsDict['modWanted'], analysisParamsDict['rowWanted'], analysisParamsDict['sensorsy']) analysis.analysis(octfile, demo.name, frontscan, backscan) print('Bifacial ratio for %s average: %0.3f' % ( metdata.datetime[timeindex], sum(analysis.Wm2Back) / sum(analysis.Wm2Front))) else: # Tracking print('\n***Starting 1-axis tracking simulation***\n') if 'gcr' not in sceneParamsDict: # didn't get gcr passed - need to calculate it sceneParamsDict['gcr'] = moduleDict['sceney'] / \ sceneParamsDict['pitch'] trackerdict = demo.set1axis(metdata, axis_azimuth=sceneParamsDict['axis_azimuth'], gcr=sceneParamsDict['gcr'], limit_angle=trackingParamsDict['limit_angle'], angledelta=trackingParamsDict['angle_delta'], backtrack=trackingParamsDict['backtrack'], cumulativesky=simulationParamsDict["cumulativeSky"]) if simulationParamsDict["cumulativeSky"]: # cumulative sky routine # This option doesn't work currently.! if simulationParamsDict['timestampRangeSimulation']: import datetime startdate = datetime.datetime(2001, timeControlParamsDict['MonthStart'], timeControlParamsDict['DayStart'], timeControlParamsDict['HourStart']) enddate = datetime.datetime(2001, timeControlParamsDict['MonthEnd'], timeControlParamsDict['DayEnd'], timeControlParamsDict['HourEnd']) trackerdict = demo.genCumSky1axis( trackerdict, startdt=startdate, enddt=enddate) else: trackerdict = demo.genCumSky1axis(trackerdict) trackerdict = demo.makeScene1axis(trackerdict=trackerdict, moduletype=simulationParamsDict['moduletype'], sceneDict=sceneParamsDict, cumulativesky=simulationParamsDict['cumulativeSky'], hpc=simulationParamsDict['hpc']) trackerdict = demo.makeOct1axis( trackerdict, hpc=simulationParamsDict['hpc']) trackerdict = demo.analysis1axis(trackerdict, modWanted=analysisParamsDict['modWanted'], rowWanted=analysisParamsDict['rowWanted'], sensorsy=analysisParamsDict['sensorsy']) print('Annual RADIANCE bifacial ratio for 1-axis tracking: %0.3f' % (sum(demo.Wm2Back)/sum(demo.Wm2Front))) else: # Timestamp range selection if simulationParamsDict['timestampRangeSimulation']: # _returnTimeVals returns proper string formatted start and end days. startday, endday,_= _returnTimeVals(timeControlParamsDict) # optional parameters 'startdate', 'enddate' inputs = string 'MM/DD' or 'MM_DD' trackerdict = demo.gendaylit1axis(startdate=startday, enddate=endday) _,_,timelist = _returnTimeVals(timeControlParamsDict, trackerdict) else: # optional parameters 'startdate', 'enddate' inputs = string 'MM/DD' or 'MM_DD' trackerdict = demo.gendaylit1axis() # Tracker dict should go here becuase sky routine reduces the size of trackerdict. trackerdict = demo.makeScene1axis(trackerdict=trackerdict, moduletype=simulationParamsDict['moduletype'], sceneDict=sceneParamsDict, cumulativesky=simulationParamsDict['cumulativeSky'], hpc=simulationParamsDict['hpc']) if simulationParamsDict['timestampRangeSimulation']: for time in timelist: trackerdict = demo.makeOct1axis(trackerdict, singleindex=time, hpc=simulationParamsDict['hpc']) trackerdict = demo.analysis1axis(trackerdict, singleindex=time, modWanted=analysisParamsDict['modWanted'], rowWanted=analysisParamsDict['rowWanted'], sensorsy=analysisParamsDict['sensorsy']) else: trackerdict = demo.makeOct1axis( trackerdict, hpc=simulationParamsDict['hpc']) trackerdict = demo.analysis1axis(trackerdict, modWanted=analysisParamsDict['modWanted'], rowWanted=analysisParamsDict['rowWanted'], sensorsy=analysisParamsDict['sensorsy']) return demo, analysis
def runModelChain(simulationParamsDict, sceneParamsDict, timeControlParamsDict=None, moduleParamsDict=None, trackingParamsDict=None, torquetubeParamsDict=None, analysisParamsDict=None, cellModuleDict=None): """ This calls config.py values, which are arranged into dictionaries, and runs all the respective processes based on the variables in the config.py. To import the variables from a .ini file, use:: (simulationParamsDict, sceneParamsDict, timeControlParamsDict, moduleParamsDict, trackingParamsDict,torquetubeParamsDict,analysisParamsDict,cellModuleDict) = bifacial_radiance.load.readconfigurationinputfile(inifile) """ import bifacial_radiance import os import numpy as np print("\nNew bifacial_radiance simulation starting. ") print("Version: ", bifacial_radiance.__version__) if 'testfolder' not in simulationParamsDict: simulationParamsDict[ 'testfolder'] = bifacial_radiance.main._interactive_directory( title= 'Select or create an empty directory for the Radiance tree') testfolder = simulationParamsDict['testfolder'] demo = bifacial_radiance.RadianceObj( simulationParamsDict['simulationname'], path=testfolder) # Create a RadianceObj 'object' # Save INIFILE in folder inifilename = os.path.join(simulationParamsDict['testfolder'], 'simulation.ini') bifacial_radiance.load.savedictionariestoConfigurationIniFile( simulationParamsDict, sceneParamsDict, timeControlParamsDict, moduleParamsDict, trackingParamsDict, torquetubeParamsDict, analysisParamsDict, cellModuleDict, inifilename) # re-load configuration file to make sure all booleans are converted (simulationParamsDict, sceneParamsDict, timeControlParamsDict, moduleParamsDict, trackingParamsDict,torquetubeParamsDict, analysisParamsDict,cellModuleDict) = \ bifacial_radiance.load.readconfigurationinputfile(inifilename) # Load weatherfile if simulationParamsDict['getEPW']: simulationParamsDict['weatherFile'] = demo.getEPW( simulationParamsDict['latitude'], simulationParamsDict['longitude'] ) # pull EPW data for any global lat/lon if simulationParamsDict['selectTimes']: starttime = timeControlParamsDict['starttime'] endtime = timeControlParamsDict['endtime'] else: # read in full TMY file starttime = None endtime = None if 'coerce_year' in simulationParamsDict: coerce_year = simulationParamsDict['coerce_year'] else: coerce_year = None print('Reading weather file {}'.format( simulationParamsDict['weatherFile'])) metdata = demo.readWeatherFile(simulationParamsDict['weatherFile'], starttime=starttime, endtime=endtime, coerce_year=coerce_year) # input albedo number or material name like 'concrete'. To see options, run this without any input. demo.setGround(sceneParamsDict['albedo']) analysis = None # initialize default analysis return value to none. A = demo.printModules() #cellLeveLParams are none by default. cellModule = None try: if simulationParamsDict['cellLevelModule']: cellModule = cellModuleDict except: pass """ if not torquetubeParamsDict: #kwargs = {**torquetubeParamsDict, **moduleParamsDict} #Py3 Only torquetubeParamsDict = {} torquetubeParamsDict['axisofrotation'] = simulationParamsDict[ 'axisofrotationTorqueTube'] """ kwargs = moduleParamsDict if torquetubeParamsDict: if not 'visible' in torquetubeParamsDict: torquetubeParamsDict['visible'] = simulationParamsDict[ 'torqueTube'] if 'axisofrotationTorqueTube' in simulationParamsDict: torquetubeParamsDict['axisofrotation'] = simulationParamsDict[ 'axisofrotationTorqueTube'] if simulationParamsDict['moduletype'] in A: if simulationParamsDict['rewriteModule'] is True: module = demo.makeModule(name=simulationParamsDict['moduletype'], tubeParams=torquetubeParamsDict, cellModule=cellModule, **kwargs) print("\nUsing Pre-determined Module Type: %s " % simulationParamsDict['moduletype']) else: module = demo.makeModule(name=simulationParamsDict['moduletype'], tubeParams=torquetubeParamsDict, cellModule=cellModule, **kwargs) if 'gcr' not in sceneParamsDict: # didn't get gcr passed - need to calculate it sceneParamsDict['gcr'] = module.sceney / \ sceneParamsDict['pitch'] if simulationParamsDict['tracking'] == False and simulationParamsDict[ 'cumulativeSky'] == True: # Fixed gencumsky condition scene = demo.makeScene(module=simulationParamsDict['moduletype'], sceneDict=sceneParamsDict) demo.genCumSky(demo.gencumsky_metfile) octfile = demo.makeOct(demo.getfilelist()) analysis = bifacial_radiance.AnalysisObj(octfile, demo.name) frontscan, backscan = analysis.moduleAnalysis( scene, analysisParamsDict['modWanted'], analysisParamsDict['rowWanted'], analysisParamsDict['sensorsy']) analysis.analysis(octfile, demo.name, frontscan, backscan) print('Bifacial ratio yearly average: %0.3f' % (np.mean(analysis.Wm2Back) / np.mean(analysis.Wm2Front))) else: # Run everything through TrackerDict. if simulationParamsDict['tracking'] == False: trackerdict = demo.set1axis( metdata, cumulativesky=simulationParamsDict["cumulativeSky"], fixed_tilt_angle=sceneParamsDict['tilt'], azimuth=sceneParamsDict['azimuth']) else: trackerdict = demo.set1axis( metdata, gcr=sceneParamsDict['gcr'], azimuth=sceneParamsDict['axis_azimuth'], limit_angle=trackingParamsDict['limit_angle'], angledelta=trackingParamsDict['angle_delta'], backtrack=trackingParamsDict['backtrack'], cumulativesky=simulationParamsDict["cumulativeSky"]) if simulationParamsDict['cumulativeSky']: trackerdict = demo.genCumSky1axis(trackerdict=trackerdict) else: trackerdict = demo.gendaylit1axis() trackerdict = demo.makeScene1axis( trackerdict=trackerdict, module=simulationParamsDict['moduletype'], sceneDict=sceneParamsDict, cumulativesky=simulationParamsDict['cumulativeSky']) trackerdict = demo.makeOct1axis(trackerdict=trackerdict) trackerdict = demo.analysis1axis( trackerdict=trackerdict, modWanted=analysisParamsDict['modWanted'], rowWanted=analysisParamsDict['rowWanted'], sensorsy=analysisParamsDict['sensorsy']) # TODO: Chris, not all functions were saving/returning analysis before. # It is also not a very good return as it will only include the last key # in teh trackerdict for this, but that is what we had before. # I would consider removing analysis as a return and modifying # the way teh ini_highAzimuth py test works. # What was before: # analysis = trackerdict[time]['AnalysisObj'] analysis = demo.trackerdict[list( demo.trackerdict.keys())[-1]]['AnalysisObj'] return demo, analysis