def run3phaseMulti(pointsFile, outputIllName, windowConfig=(), epwFile=None, skyFile=None, geometryFile=None, materialFile=None, reuseVmtx=True, reuseSkyVector=True, reuseDmtx=True, skyDescr=1, klemsForVmtx='kf', vmtxParam=None, dmtxParam=None, TransposeAnnualResults=True, skyVectorParam=None): """ Notes: 1. It is assumed that the surfaces used for the vmtx are inward facing .i.e they need not be flipped. 2. It is also assumed that the surfaces used for vmtx already have a glow modifier assigned to them. Args: outputIllName: Name of the file to which the results should be written. windowConfig: A tuple containing the windowGroupGeometry, the direction of the surface Normal, the corresponding T matrix XML and an option to include or exclude the results from the windowgroup in the calculation. A typical option will be something like ('glazing.rad','+Z', 'blinds.xml',True), specifying that the radiance geometry 'glazing.rad', whose direction normal faces +Z will be used for the calculation of that particular V matrix. 'blinds.xml' indicates the XML file that will be used as T matrix for that window group and True indicates that this window group will be considered for the calculations. epwFile: epwFile corresponding to a particular location. If epwFile and skyFile are provided, the option for epwFile will be prioritized .i.e. the calculation will be annual. skyFile: An input from gensky or gendaylit for creating a point-in-time sky vector. geometryFile: Geometry for All the files in the calculation except the ones for the glazing. materialFile: Materials for all the geometry described in the geometryFile input. reuseVmtx: A boolean value for specifying if the Vmtx needs to be recalculated if it is already present. reuseDmtx: A boolean value for specifying if the Dmtx needs to be recalculated. reuseSkyVector: A boolean value for specifying if sky vector needs to be recalculated. pointsFile: The file containing the grid points that will be used for illumiance calcuations. skyDescr: An integer specifying the sky descretization value to be considered for generating the sky matrix. The values (number, skypataches)corresponding to different sky descretizations are : (1, 145),(2,577),(3,1297),(4,2305), (5,3601),(6,5185). Higher discretizations equal higher values. klemsForVmtx: The klems basis to be considered for sampling the vmtx. Default value is 'kf' vmtxParam: Calculation parameters corresponding to the V matrix. This should be an instance of the class RfluxParameters. If not specified, a default value will be assigned. dmtxParam: Calculation parameters corresponding to the D matrix. This should be an instance of the class RfluxParameters. If not specified, a default value will be assigned. TransposeAnnualResults: A boolean value, which if set to True, will transpose the results of an annual calculation as per the 8760 lines format. Returns: """ def createWinGroupReceivers(surfaceFile, surfaceNormal, klemsBasis): # remove the + or - sign if specified. surfaceNormal = surfaceNormal[-1] if len( surfaceNormal) > 1 else surfaceNormal hemiUp = "+Z" if surfaceNormal.lower() in "xy" else "+X" # check if there is a glow material assigned in the file. # retrieve the first polygon surface for assigning rfluxmtxParameters. surfaceStringNoComments = '' with open(surfaceFile) as surfaceData: for lines in surfaceData: if not lines.strip().startswith("#"): surfaceStringNoComments += lines surfaceStringNoComSplit = surfaceStringNoComments.split() assert surfaceStringNoComSplit[1] == 'glow',\ 'It appears that the glow material has not been applied to this surface.This' \ ' is essential for the Three Phase Method. ' firstPolyPosition = surfaceStringNoComSplit.index('polygon') surfaceName = surfaceStringNoComSplit[firstPolyPosition - 1] rflux = Rfluxmtx() receiverParam = rflux.ControlParameters(hemiType=klemsBasis, hemiUpDirection=hemiUp) receiverFile = rflux.addControlParameters(surfaceFile, {surfaceName: receiverParam}) return receiverFile def calcVmtx(surfaceFile, receiverFile, reuse, vmtxParam, pointsFile, materialFile, geometryFile): vmtxFile = os.path.join('temp', os.path.splitext(surfaceFile)[0] + '.vmtx') if os.path.exists(vmtxFile) and reuse: return vmtxFile if vmtxParam: assert isinstance(vmtxParam, RfluxmtxParameters),\ 'The input for vmtxParam must be an instance of RfluxmtxParamters. ' \ 'The current input is an instance of %s' % (type(vmtxParam)) else: vmtxParam = RfluxmtxParameters() vmtxParam.irradianceCalc = True vmtxParam.ambientAccuracy = 0.1 vmtxParam.ambientBounces = 10 vmtxParam.ambientDivisions = 65536 vmtxParam.limitWeight = 1E-5 rflux = Rfluxmtx() rflux.receiverFile = receiverFile rflux.rfluxmtxParameters = vmtxParam rflux.pointsFile = pointsFile rflux.sender = '-' rflux.outputMatrix = vmtxFile rflux.radFiles = [materialFile, geometryFile] print(rflux.toRadString()) rflux.execute() return vmtxFile def calcDmtx(surfaceFile, senderFile, reuse, skyDescr, dmtxParam, materialFile, geometryFile): dmtxFile = os.path.join('temp', os.path.splitext(surfaceFile)[0] + '.dmtx') if os.path.exists(dmtxFile) and reuse: return dmtxFile if dmtxParam: assert isinstance(dmtxParam, RfluxmtxParameters), \ 'The input for vmtxParam must be an instance of RfluxmtxParamters. ' \ 'The current input is an instance of %s' % (type(dmtxParam)) else: dmtxParam = RfluxmtxParameters() dmtxParam.ambientAccuracy = 0.1 dmtxParam.ambientBounces = 2 dmtxParam.ambientDivisions = 1024 dmtxParam.limitWeight = 1E-5 rflux2 = Rfluxmtx() rflux2.samplingRaysCount = 1000 rflux2.sender = senderFile skyFile = rflux2.defaultSkyGround(r'temp/rfluxSky.rad', skyType="r%s" % skyDescr) rflux2.receiverFile = skyFile rflux2.rfluxmtxParameters = dmtxParam rflux2.radFiles = [materialFile, geometryFile] rflux2.outputMatrix = dmtxFile rflux2.execute() return dmtxFile def calcSkyVector(skyDescr, epwFile=None, skyFile=None, reuse=True, skyVectorParam=None): assert epwFile or skyFile,\ 'Either an epwFile or a skyFile need to be provided for the skyVector to' \ 'be calculated.' if epwFile and os.path.exists(epwFile): epwName = os.path.split(epwFile)[1] skyMtxName = os.path.splitext(epwName)[0] + '%s.smx' % skyDescr weaName = os.path.splitext(epwFile)[0] + '.wea' if os.path.exists(skyMtxName) and reuse: return skyMtxName weaFile = Epw2wea(epwFile=epwFile, outputWeaFile=weaName) weaFile.execute() if skyVectorParam: assert isinstance(skyVectorParam, GendaymtxParameters),\ 'The input for skyVectorParam must be an instance of GendaymtxParameters.' gendayParam = skyVectorParam else: gendayParam = GendaymtxParameters() gendayParam.skyDensity = skyDescr genday = Gendaymtx(weaFile=weaName, outputName=skyMtxName) genday.gendaymtxParameters = skyVectorParam genday.execute() return skyMtxName elif skyFile and os.path.exists(skyFile): skyMtxName = os.path.splitext(skyFile)[0] + '%s.smx' % skyDescr if os.path.exists(skyMtxName) and reuse: return skyMtxName genskv = Genskyvec() genskv.inputSkyFile = skyFile genskv.skySubdivision = skyDescr genskv.outputFile = skyMtxName genskv.execute() return skyMtxName else: raise Exception( 'The input path for the skyFile or epwFile are not valid.') # generate receiver surfaces for all window groups..This is not an intensive process. receiverFiles = [ createWinGroupReceivers(win['windowSurface'], win['surfaceNormal'], klemsForVmtx) for win in windowConfig ] # create the skyVector. skyVector = calcSkyVector(skyDescr=skyDescr, epwFile=epwFile, skyFile=skyFile, reuse=reuseSkyVector, skyVectorParam=skyVectorParam) # create V and D matrices corresponding to each window Group. matrixFilesForResult = [] resultFiles = 0 for idx, recFile in enumerate(receiverFiles): vmtxFile = calcVmtx(windowConfig[idx]['windowSurface'], recFile, reuse=reuseVmtx, vmtxParam=vmtxParam, pointsFile=pointsFile, materialFile=materialFile, geometryFile=geometryFile) dmtxFile = calcDmtx(windowConfig[idx]['windowSurface'], senderFile=recFile, skyDescr=skyDescr, dmtxParam=dmtxParam, materialFile=materialFile, geometryFile=geometryFile, reuse=reuseDmtx) if windowConfig[idx]['includeInCalc']: windowName = os.path.splitext( windowConfig[idx]['windowSurface'])[0] + 'Res.tmp' dctResult = os.path.join('temp', windowName) dct = Dctimestep() dct.dmatrixFile = dmtxFile dct.vmatrixSpec = vmtxFile dct.skyVectorFile = skyVector dct.tmatrixFile = windowConfig[idx]['tMatrix'] dct.outputFileName = dctResult dct.execute() matrixFilesForResult.append(dctResult) resultFiles += 1 assert resultFiles, 'None of the Window Groups were chosen for calculating the results !' # add up values into a single tmp file rmtxAdd = Rmtxop() rmtxAdd.matrixFiles = matrixFilesForResult rmtxAdd.outputFile = os.path.splitext(outputIllName)[0] + '.tmp' rmtxAdd.execute() # convert r g b to illuminance rmtResParam = RmtxopParameters() rmtResParam.combineValues = (47.4, 119.9, 11.6) rmtResParam.outputFormat = 'a' rmtResParam.transposeMatrix = TransposeAnnualResults rmtxRes = Rmtxop() rmtxRes.matrixFiles = [rmtxAdd.outputFile] rmtxRes.outputFile = outputIllName rmtxRes.rmtxopParameters = rmtResParam rmtxRes.execute() return outputIllName
def run3phase(phasesToCalculate={'v': True, 't': True, 'd': True, 's': True}, calculationType='annual', epwFile=None, tmatrixFile=None): if phasesToCalculate['v']: # Step1: Create the view matrix. rfluxPara = RfluxmtxParameters() rfluxPara.irradianceCalc = True rfluxPara.ambientAccuracy = 0.1 rfluxPara.ambientBounces = 10 rfluxPara.ambientDivisions = 65536 rfluxPara.limitWeight = 1E-5 # step 1.1 Invert glazing surface with xform so that it faces inwards xfrPara = XformParameters() xfrPara.invertSurfaces = True xfr = Xform() xfr.xformParameters = xfrPara xfr.radFile = 'glazing.rad' xfr.outputFile = 'glazingI.rad' xfr.execute() rflux = Rfluxmtx() rflux.sender = '-' # This needs to be automated based on the normal of each window. # Klems full basis sampling and the window faces +Y recCtrlPar = rflux.ControlParameters(hemiType='kf', hemiUpDirection='+Z') rflux.receiverFile = rflux.addControlParameters('glazingI.rad', {'Exterior_Window': recCtrlPar}) rflux.rfluxmtxParameters = rfluxPara rflux.pointsFile = 'indoor_points.pts' rflux.outputMatrix = r'temp/vmatrix.vmx' rflux.radFiles = ['room.mat', 'room.rad'] rflux.execute() vMatrix = r'temp/vmatrix.vmx' # Step2: Assign T matrix from precalculated XML files. tMatrix = tmatrixFile or r'xmls/clear.xml' if phasesToCalculate['d']: # Step3: Create D matrix. rfluxPara = RfluxmtxParameters() rfluxPara.ambientAccuracy = 0.1 rfluxPara.ambientDivisions = 1024 rfluxPara.ambientBounces = 2 rfluxPara.limitWeight = 0.0000001 rflux2 = Rfluxmtx() rflux2.samplingRaysCount = 1000 rflux2.sender = 'glazingI_m.rad' skyFile = rflux2.defaultSkyGround(r'temp/rfluxSky.rad', skyType='r1') rflux2.receiverFile = skyFile rflux2.rfluxmtxParameters = rfluxPara rflux2.radFiles = [r"room.mat", r"room.rad"] rflux2.outputMatrix = r"temp/dmatrix.dmx" rflux2.execute() dMatrix = r"temp/dmatrix.dmx" # Step4a: Create the sky vector. # Step4a.1: Create a sky defintion # Step s: Creating the sky matrix if phasesToCalculate['s']: if calculationType == 'annual': weaFile = Epw2wea(epwFile=epwFile or 'test.epw', outputWeaFile=r'temp/test.wea') weaFile.execute() gendayParam = GendaymtxParameters() gendayParam.skyDensity = 1 genday = Gendaymtx(weaFile=r'temp/test.wea', outputName=r'temp/day.smx') genday.gendaymtxParameters = gendayParam genday.execute() skyVector = r'temp/day.smx' else: gensk = Gensky() gensk.monthDayHour = (11, 11, 11) gensk.outputFile = 'temp/sky.rad' # gensk.execute() genskv = Genskyvec() genskv.inputSkyFile = r'temp/sky.rad' genskv.outputFile = r'temp/sky.vec' genskv.skySubdivision = 1 genskv.execute() skyVector = r'temp/sky.vec' else: skyVector = r'temp/sky.vec' # Step5: Generate results dct = Dctimestep() dct.tmatrixFile = tMatrix dct.vmatrixSpec = vMatrix dct.dmatrixFile = dMatrix dct.skyVectorFile = skyVector dct.outputFileName = r'temp/results3p.tmp' dct.execute() mtx2Param = RmtxopParameters() mtx2Param.outputFormat = 'a' mtx2Param.combineValues = (47.4, 119.9, 11.6) mtx2Param.transposeMatrix = True mtx2 = Rmtxop(matrixFiles=[r'temp/results3p.tmp'], outputFile=r'temp/illuminance3p.ill') mtx2.rmtxopParameters = mtx2Param mtx2.execute() return 'temp/illuminance3p.ill'
def run3phase(phasesToCalculate={'v':True,'t':True,'d':True,'s':True}, calculationType='annual',epwFile=None,tmatrixFile=None, hdrResultsFileName=None,numProcessors=1,timeStamp=None): if phasesToCalculate['v']: # Step1: Create the view matrix. rfluxPara = RfluxmtxParameters() rfluxPara.ambientAccuracy = 0.1 rfluxPara.ambientBounces = 10 # using this for a quicker run rfluxPara.ambientBounces = 5 rfluxPara.ambientDivisions = 65536 # using this for a quicker run # rfluxPara.ad = 1000 rfluxPara.limitWeight = 1E-5 # rfluxPara.lw = 1E-2 #step 1.1 Invert glazing surface with xform so that it faces inwards xfrPara = XformParameters() xfrPara.invertSurfaces = True xfr = Xform() xfr.xformParameters = xfrPara xfr.radFile = 'glazing.rad' xfr.outputFile = 'glazingI.rad' xfr.execute() vwrParaDim = VwraysParameters() vwrParaDim.calcImageDim = True vwrParaDim.xResolution = 800 vwrParaDim.yResolution = 800 vwrDim = Vwrays() vwrDim.vwraysParameters = vwrParaDim vwrDim.viewFile = 'viewSouth1.vf' vwrDim.outputFile = r'temp/viewSouthDimensions.txt' vwrDim.execute() vwrParaSamp = VwraysParameters() vwrParaSamp.xResolution = 800 vwrParaSamp.yResolution = 800 vwrParaSamp.samplingRaysCount = 9 # vwrParaSamp.samplingRaysCount = 3 vwrParaSamp.jitter = 0.7 vwrSamp = Vwrays() vwrSamp.vwraysParameters = vwrParaSamp vwrSamp.viewFile = 'viewSouth1.vf' vwrSamp.outputFile = r'temp/viewSouthRays.txt' vwrSamp.outputDataFormat = 'f' vwrSamp.execute() rflux = Rfluxmtx() rflux.sender = '-' #Klems full basis sampling and the window faces +Y recCtrlPar = rflux.ControlParameters(hemiType='kf',hemiUpDirection='+Z') rflux.receiverFile = rflux.addControlParameters('glazingI.rad', {'Exterior_Window':recCtrlPar}) rflux.outputDataFormat = 'fc' rflux.verbose = True rflux.rfluxmtxParameters = rfluxPara rflux.viewInfoFile = r'temp/viewSouthDimensions.txt' rflux.viewRaysFile = r'temp/viewSouthRays.txt' rflux.radFiles = ['room.mat','room.rad','glazing.rad'] rflux.outputFilenameFormat = r'temp/%03d.hdr' rflux.samplingRaysCount = 9 # rflux.samplingRaysCount = 3 rflux.numProcessors = numProcessors rflux.execute() vMatrix = r'temp/vmatrix.vmx' #Step2: Assign T matrix from precalculated XML files. tMatrix = tmatrixFile or r'xmls/clear.xml' if phasesToCalculate['d']: #Step3: Create D matrix. rfluxPara = RfluxmtxParameters() rfluxPara.ambientAccuracy = 0.1 rfluxPara.ambientDivisions = 1024 rfluxPara.ambientBounces = 2 rfluxPara.limitWeight = 0.0000001 rflux2 = Rfluxmtx() rflux2.numProcessors = numProcessors rflux2.samplingRaysCount = 1000 rflux2.sender = 'glazingI.rad_m' skyFile = rflux2.defaultSkyGround(r'temp/rfluxSky.rad', skyType='r4') rflux2.receiverFile = skyFile rflux2.rfluxmtxParameters = rfluxPara rflux2.radFiles = [r"room.mat", r"room.rad", 'glazing.rad'] rflux2.outputMatrix = r"temp/dmatrix.dmx" rflux2.execute() dMatrix = r"temp/dmatrix.dmx" #Step4a: Create the sky vector. #Step4a.1: Create a sky defintion # Step s: Creating the sky matrix if phasesToCalculate['s']: if calculationType == 'annual': weaFile = Epw2wea(epwFile=epwFile or 'test.epw', outputWeaFile=r'temp/test.wea') weaFile.execute() gendayParam = GendaymtxParameters() gendayParam.skyDensity = 4 genday = Gendaymtx(weaFile=r'temp/test.wea', outputName=r'temp/day.smx') genday.gendaymtxParameters = gendayParam genday.execute() skyVector = r'temp/day.smx' else: genskPar = GenskyParameters() gensk = Gensky() gensk.monthDayHour = timeStamp or (11,11,11) gensk.outputFile = 'temp/sky.rad' gensk.execute() genskv = Genskyvec() genskv.inputSkyFile = r'temp/sky.rad' genskv.outputFile = r'temp/sky.vec' genskv.skySubdivision = 4 genskv.execute() skyVector = r'temp/sky.vec' else: skyVector = r'temp/sky.vec' # Step5: Generate results dct = Dctimestep() dct.tmatrixFile = tMatrix dct.vmatrixSpec = r'temp/%03d.hdr' dct.dmatrixFile = dMatrix dct.skyVectorFile = skyVector dct.outputFileName = hdrResultsFileName or r'temp/results.hdr' dct.execute() return 'temp/results.txt'