def loadMeasureFromFile(xmlFile): if not os.path.isfile(xmlFile): raise Exception("Can't find measure at " + xmlFile) measure = OpenStudio.BCLMeasure(OpenStudio.Path(_)) if measure.arguments().Count == 0: print "Measure contains no arguments." # load arguments args = get_measureArgs(xmlFile) path = gh.Data.GH_Path(0) for i, key in enumerate(sorted(args.keys())): addInputParam(args[key], path, i + 1) with open(xmlFile, "r") as measure: lines = "".join(measure.readlines()) if 'EnergyPlusMeasure' in lines: measureType = 'EnergyPlus' elif 'ModelMeasure' in lines: measureType = 'OpenStudio' elif 'ReportingMeasure' in lines: measureType = 'Reporting' # create an OSMeasure based on default values OSMeasure = OpenStudioMeasure(ghenv.Component.Name, ghenv.Component.NickName, ghenv.Component.Description, _, args, measureType) # add the measure to sticky to be able to load and update it key = ghenv.Component.InstanceGuid.ToString() if "osMeasures" not in sc.sticky.keys(): sc.sticky["osMeasures"] = dict() sc.sticky["osMeasures"][key] = OSMeasure OSMeasure.updateArguments() return OSMeasure
def tryGetOSPath(path): """Try to convert a string path to OpenStudio Path.""" try: return OpenStudio.Path(path) except TypeError: # OpenStudio 2.6.1 ospath = OpenStudio.OpenStudioUtilitiesCore.toPath(path) return OpenStudio.Path(ospath)
def load_ops_helper(openstudio_dir): """ if os.path.exists(openstudio_dir_1_12): print("using openstudio 1.12") openstudio_dir = openstudio_dir_1_12 elif os.path.exists(openstudio_dir_1_10): print("using openstudio 1.10") openstudio_dir = openstudio_dir_1_10 else: print("No openstudio installation exists.") """ if openstudio_dir not in sys.path: sys.path.insert(0, openstudio_dir) # Make sure to add openstudio dir to path before importing clr import clr clr.AddReference("OpenStudio") import OpenStudio as ops if not os.path.exists(OSM_TEST): print("error at ", OSM_TEST) osm_path_test = ops.Path(OSM_TEST) # will fail if ops not loaded correctly return ops
def loadMeasureFromFile(xmlFile): if not os.path.isfile(xmlFile): raise Exception("Can't find measure at " + xmlFile) directory, f_name = os.path.split(xmlFile) measure = OpenStudio.BCLMeasure(tryGetOSPath(directory)) if measure.arguments().Count == 0: print "Measure contains no arguments." measureType = updateComponentDescription(xmlFile) # load arguments args = get_measureArgs(xmlFile) # create an OSMeasure based on default values OSMeasure = OpenStudioMeasure(ghenv.Component.Name, ghenv.Component.NickName, ghenv.Component.Description, _, args, measureType) OSMeasure.updateArguments() # add the measure to sticky to be able to load and update it key = ghenv.Component.InstanceGuid.ToString() if "osMeasures" not in sc.sticky.keys(): sc.sticky["osMeasures"] = dict() sc.sticky["osMeasures"][key] = OSMeasure return OSMeasure
def createOSArgument(arg): if arg.type == 'Choice': chs = OpenStudio.StringVector() for choice in arg.choices: chs.Add(choice.value) argument = OpenStudio.OSArgument.makeChoiceArgument( arg.name, chs, arg.required, arg.model_dependent) elif arg.type == 'Boolean': argument = OpenStudio.OSArgument.makeBoolArgument( arg.name, arg.required, arg.model_dependent) elif arg.type == 'Double': argument = OpenStudio.OSArgument.makeDoubleArgument( arg.name, arg.required, arg.model_dependent) else: raise Exception("%s is not Implemented" % arg.type) argument.setDisplayName(arg.display_name) argument.setDefaultValue( arg.default_value) #I'm not sure if this is neccessary argument.setDescription(arg.description) if arg.userInput is not None: if arg.type == 'Double': argument.setValue(float(arg.userInput)) elif arg.type != 'Boolean': argument.setValue(str(arg.userInput)) else: argument.setValue(bool(arg.userInput)) return argument
def load_osm(osm_file_path, ops): ops_file_path = ops.Path(osm_file_path) osm = ops.Model.load(ops_file_path).get() # sql file #sqlfile = os.path.join(RESOURCE_DIR, "office\\ModelToIdf\\in.sql") #sqlfileops = ops.SqlFile(ops.Path(sqlfile)) #sqlfileops.setSqlFile() return osm
msg2 = "https://www.openstudio.net/downloads" print msg1 print msg2 ghenv.Component.AddRuntimeMessage(gh.GH_RuntimeMessageLevel.Warning, msg1) ghenv.Component.AddRuntimeMessage(gh.GH_RuntimeMessageLevel.Warning, msg2) else: openStudioIsReady = False if openStudioIsReady and _import and _filepath: _filepath = _filepath.replace('\\\\', '/').replace('\\', '/') assert os.path.isfile(_filepath), \ 'Failed to find the xml file at {}.'.format(_filepath) assert _filepath.lower().endswith('.xml'), \ '{} does not end with .xml. Not a valid xml file.'.format(_filepath) translator = ops.GbXMLReverseTranslator() try: model = translator.loadModel(ops.Path(os.path.normpath(_filepath))) except TypeError: filepath = ops.OpenStudioUtilitiesCore.toPath(os.path.normpath(_filepath)) if vers < 27: # OpenStudio 2.6.1 model = translator.loadModel(ops.Path(filepath)) else: # OpenStudio 2.7.0 model = translator.loadModel(filepath) errors = translator.errors() warnings = translator.warnings() if ''.join(errors): raise Exception('\n'.join(errors)) for warn in warnings:
def main(sqlPath): pp = pprint.PrettyPrinter(indent=4) sqlPath = _sqlFilePath print sqlPath sqlFile = ops.SqlFile(ops.Path(sqlPath)) print sqlFile conversionFactorElec = float(str(ops.OptionalDouble(277.777778))) outputs = {} electricity = {} naturalgas = {} try: print 'starting' elecVals = elecSqlVals(sqlFile) waterVals = waterSqlVals(sqlFile) electricity = { 'units': 'kilowatt-hours', 'Electricity Interior Lights': float(elecVals.intlighting) * conversionFactorElec, 'Electricity Exterior Lights': float(elecVals.extlighting) * conversionFactorElec, 'Electricity Interior Equipment': float(elecVals.intequip) * conversionFactorElec, 'Electricity Exterior Equipment': float(elecVals.extequip) * conversionFactorElec, 'Electricity Heating': float(elecVals.heating) * conversionFactorElec, 'Electricity Water Systems': float(elecVals.watersystems) * conversionFactorElec, 'Electricity Cooling': float(elecVals.cooling) * conversionFactorElec, 'Electricity Humidification': float(elecVals.humidity) * conversionFactorElec, 'Electricity Heat Recovery': float(elecVals.hr) * conversionFactorElec, 'Electricity Heat Rejection': float(elecVals.heatrej) * conversionFactorElec, 'Electricity Refrigeration': float(elecVals.refrig) * conversionFactorElec, 'Electricity Generators': float(elecVals.generators) * conversionFactorElec, 'Fan Electricity': float(elecVals.fans) * conversionFactorElec, 'Pumps Electricity': float(elecVals.pumps) * conversionFactorElec, 'Electricity Total End Uses': float(elecVals.totalenduses) * conversionFactorElec } conversionFactorNG = 9.480434 naturalgas = { 'units': 'therms', 'Natural Gas Heating': float(str(sqlFile.naturalGasHeating())) * conversionFactorNG, 'Natural Gas Cooling': float(str(sqlFile.naturalGasCooling())) * conversionFactorNG, 'Natural Gas Interior Lighting': float(str(sqlFile.naturalGasInteriorLighting())) * conversionFactorNG, 'Natural Gas Exterior Lighting': float(str(sqlFile.naturalGasExteriorLighting())) * conversionFactorNG, 'Natural Gas Interior Equipment': float(str(sqlFile.naturalGasInteriorEquipment())) * conversionFactorNG, 'Natural Gas Exterior Equipment': float(str(sqlFile.naturalGasExteriorEquipment())) * conversionFactorNG, 'Natural Gas Fans': float(str(sqlFile.naturalGasFans())) * conversionFactorNG, 'Natural Gas Pumps': float(str(sqlFile.naturalGasPumps())) * conversionFactorNG, 'Natural Gas Heat Rejection': float(str(sqlFile.naturalGasHeatRejection())) * conversionFactorNG, 'Natural Gas Humidification': float(str(sqlFile.naturalGasHumidification())) * conversionFactorNG, 'Natural Gas Heat Recovery': float(str(sqlFile.naturalGasHeatRecovery())) * conversionFactorNG, 'Natural Gas Water Systems': float(str(sqlFile.naturalGasWaterSystems())) * conversionFactorNG, 'Natural Gas Refrigeration': float(str(sqlFile.naturalGasRefrigeration())) * conversionFactorNG, 'Natural Gas Generators': float(str(sqlFile.naturalGasGenerators())) * conversionFactorNG, 'Natural Gas Total End Uses': float(str(sqlFile.naturalGasTotalEndUses())) * conversionFactorNG, } conversionFactorPropane = 9.480434 propane = { 'units': 'therms', #'Propane Heating':float(str(sqlFile.propaneHeating())) * conversionFactorPropane } conversionFactorWater = 1 water = { 'units': 'm3', 'Water Interior Lights': float(waterVals.intlighting) * conversionFactorWater, 'Water Exterior Lights': float(waterVals.extlighting) * conversionFactorWater, 'Water Interior Equipment': float(waterVals.intequip) * conversionFactorWater, 'Water Exterior Equipment': float(waterVals.extequip) * conversionFactorWater, 'Water Heating': float(waterVals.heating) * conversionFactorWater, 'Water Water Systems': float(waterVals.watersystems) * conversionFactorWater, 'Water Cooling': float(waterVals.cooling) * conversionFactorWater, 'Water Humidification': float(waterVals.humidity) * conversionFactorWater, 'Water Heat Recovery': float(waterVals.hr) * conversionFactorWater, 'Water Heat Rejection': float(waterVals.heatrej) * conversionFactorWater, 'Water Refrigeration': float(waterVals.refrig) * conversionFactorWater, 'Water Generators': float(waterVals.generators) * conversionFactorWater, 'Fan Water': float(waterVals.fans) * conversionFactorWater, 'Pumps Water': float(waterVals.pumps) * conversionFactorWater, 'Water Total End Uses': float(waterVals.total) * conversionFactorWater } outputs['elec'] = electricity outputs['ng'] = naturalgas outputs['water'] = water pp.pprint(outputs) print "GJ to kWy Conversion Factor: " + str(conversionFactorElec) print "GH to therms Conversion Factor: " + str(conversionFactorNG) print "m3 to m3 Conversion Factor: " + str(conversionFactorWater) retval = checkVals(outputs['elec'], 'Electricity Total End Uses') print "Electricty test: " + retval retval = checkVals(outputs['ng'], 'Natural Gas Total End Uses') print "Natural gas test: " + retval retval = checkVals(outputs['water'], 'Water Total End Uses') print "Water test: " + retval allAnnualTotals = dictToClass(outputs) annualElectricity = dictToClass(electricity) annualNaturalGas = dictToClass(naturalgas) annualWater = dictToClass(water) sqlFile.close() print "Closing sql file..." print "Is Sqlite file still open?", sqlFile.connectionOpen() return allAnnualTotals, annualElectricity, annualNaturalGas, annualWater except Exception, e: print e
print msg1 print msg2 ghenv.Component.AddRuntimeMessage(gh.GH_RuntimeMessageLevel.Warning, msg1) ghenv.Component.AddRuntimeMessage(gh.GH_RuntimeMessageLevel.Warning, msg2) else: openStudioIsReady = False if openStudioIsReady and _export and _filepath and _model: working_dir, file_name = os.path.split(_filepath) if not os.path.isdir(working_dir): os.mkdir(working_dir) _filepath = _filepath.replace('\\\\', '/').replace('\\', '/') translator = ops.GbXMLForwardTranslator() _model.getFacility() try: result = translator.modelToGbXML(_model, ops.Path(os.path.normpath(_filepath))) except TypeError: filepath = ops.OpenStudioUtilitiesCore.toPath( os.path.normpath(_filepath)) if vers < 27: # OpenStudio 2.6.1 result = translator.modelToGbXML(_model, ops.Path(filepath)) else: # OpenStudio 2.7.0 result = translator.modelToGbXML(_model, filepath) errors = translator.errors() warnings = translator.warnings()
except: initCheck = False warning = "You need a newer version of Honeybee to use this compoent." + \ "Use updateHoneybee component to update userObjects.\n" + \ "If you have already updated userObjects drag Honeybee_Honeybee component " + \ "into canvas and try again." ghenv.Component.AddRuntimeMessage(w, warning) if openStudioIsReady == True and initCheck == True and fileLoad == False: if ghenv.Component.Params.Input.Count == 1 and _OSMeasure: # first time loading xmlFile = os.path.join(_OSMeasure, "measure.xml") if not os.path.isfile(xmlFile): raise Exception("Can't find measure at " + xmlFile) measure = OpenStudio.BCLMeasure(tryGetOSPath(_OSMeasure)) if measure.arguments().Count == 0: print "Measure contains no arguments." # load arguments args = get_measureArgs(xmlFile) # add arguments to component path = gh.Data.GH_Path(0) for key in sorted(args.keys()): addInputParam(args[key], path) measureType = updateComponentDescription(xmlFile) # create an OSMeasure based on default values OSMeasure = OpenStudioMeasure(ghenv.Component.Name,
def main(runIt, epwFile, OSMeasures, osmFile, hb_OpenStudioMeasure): # check inputs if not os.path.isfile(epwFile) or not epwFile.lower().endswith(".epw"): raise Exception("Can't find epw file") if not os.path.isfile(osmFile) or not osmFile.lower().endswith(".osm"): raise Exception("Can't find OpenStudio file") for OSMeasure in OSMeasures: try: measureArgs = OSMeasure.args measurePath = OSMeasure.path except: raise Exception( "Not a valid Honeybee measure. \nUse the Honeybee_Load OpenStudio Measure component to create one!" ) # Set up the paths to the files osmName = os.path.split(osmFile)[-1].split('.osm')[0] workingDir = os.path.split(osmFile)[0] oswAddress = workingDir + '\\' + 'workflow.osw' osmPath = tryGetOSPath(osmFile) epwPath = tryGetOSPath(epwFile) oswPath = tryGetOSPath(oswAddress) # Create the workflow JSON. wf = OpenStudio.WorkflowJSON() wf.setOswPath(oswPath) wf.setSeedFile(osmPath) if runIt == 4: wf.setWeatherFile(epwPath) # Sort the measures so that the OpenStudio ones come first, then E+, then reporting. measureOrder = {"OpenStudio": [], "EnergyPlus": [], "Reporting": []} for measure in OSMeasures: measureOrder[measure.type].append(measure) sortedMeasures = measureOrder["OpenStudio"] sortedMeasures.extend(measureOrder["EnergyPlus"]) sortedMeasures.extend(measureOrder["Reporting"]) # Add the measures to the workflow. workflowSteps = [] for OSMeasure in sortedMeasures: # Copy measure files to a folder next to the OSM. measureName = OSMeasure.path.split('\\')[-1] destDir = workingDir + '\\measures\\' + measureName + '\\' if os.path.isdir(destDir): shutil.rmtree(destDir) shutil.copytree(OSMeasure.path, destDir) # Create the measure step measure = OpenStudio.MeasureStep(measureName) for arg in OSMeasure.args.values(): if str(arg.userInput) != str(arg.default_value): measure.setArgument(arg.name, str(arg.userInput)) workflowSteps.append(measure) # Set the workflow steps and save the JSON. stepVector = OpenStudio.WorkflowStepVector(workflowSteps) wf.setWorkflowSteps(stepVector) wf.save() # Write the batch file. workingDrive = workingDir[:2].upper() osExePath = '/'.join(openStudioLibFolder.split('/')[:-2]) + '/bin/' osExePath = osExePath.replace('/', '\\') osExePath = osExePath.replace((workingDrive + '\\'), '') # Write the batch file to apply the measures. batchStr = workingDrive + '\ncd\\' + osExePath + '\n"' + 'openstudio.exe"' + ' run -w ' + oswAddress batchFileAddress = workingDir + '\\' + osmName.replace(" ", "_") + '.bat' batchfile = open(batchFileAddress, 'w') batchfile.write(batchStr) batchfile.close() # Apply the measures. if runIt == 2: runCmd(batchFileAddress) else: os.system(batchFileAddress) # Run the resulting IDF through EnergyPlus using EPl-Run. runDir = workingDir + '\\' + 'run\\' epRunDir = workingDir + '\\' + osmName + '\\' idfFolder = os.path.join(epRunDir) idfFolder = os.path.join(idfFolder, "ModelToIdf") idfFilePath = os.path.join(idfFolder, "in.idf") if not os.path.isfile(runDir + "in.idf"): # The simulation has not run correctly and we must parse the error log. logfile = runDir + 'run.log' if os.path.isfile(logfile): errorFound = False errorMsg = 'The measures did not correctly as a result of the following error:\n' with open(logfile, "r") as log: for line in log: if 'ERROR]' in line and errorFound == False: errorFound = True msg = line.split('ERROR]')[-1] errorMsg = errorMsg + msg print errorMsg ghenv.Component.AddRuntimeMessage( gh.GH_RuntimeMessageLevel.Warning, errorMsg) return -1 if runIt < 3: try: os.mkdir(epRunDir) except: pass try: os.mkdir(idfFolder) except: pass shutil.copy(runDir + "pre-preprocess.idf", idfFilePath) resultFile = writeBatchFile(epRunDir, "ModelToIdf\\in.idf", epwFile, runIt > 1) else: idfFilePath = None resultFile = [None, None, None, None, None, None] osmFileAddress = runDir + 'in.osm' return osmFileAddress, idfFilePath, resultFile[2], resultFile[ 1], resultFile[4], resultFile[3], resultFile[5], workingDir
def main(epwFile, OSMeasure, osmFile): # check inputs if not os.path.isfile(epwFile) or not epwFile.lower().endswith(".epw"): raise Exception("Can't find epw file") try: measureArgs = OSMeasure.args measurePath = OSMeasure.path except: raise Exception( "Not a valid Honeybee measure. Use load OpenStudio measure component to create one!" ) if not os.path.isfile(osmFile) or not osmFile.lower().endswith(".osm"): raise Exception("Can't find OpenStudio file") workingDir = os.path.split(osmFile)[0] rmDBPath = OpenStudio.Path(workingDir + '/runmanager.db') osmPath = OpenStudio.Path(osmFile) epwPath = OpenStudio.Path(epwFile) epPath = OpenStudio.Path(getEPFolder(openStudioFolder)) radPath = OpenStudio.Path( 'c:\radince\bin' ) #openStudioFolder + r'\share\openstudio\Radiance\bin') rubyPath = OpenStudio.Path(openStudioFolder + r'\ruby-install\ruby\bin') outDir = OpenStudio.Path(workingDir + '\\' + OSMeasure.name.replace( " ", "_")) # I need to have extra check here to make sure name is valid copyRubyFolder(openStudioFolder) wf = OpenStudio.Workflow() measure = OpenStudio.BCLMeasure(OpenStudio.Path(OSMeasure.path)) args = OpenStudio.OSArgumentVector() # check if user has input any new value # create them and set the value for arg in OSMeasure.args.values(): if str(arg.userInput) != str(arg.default_value): # this argument has been updated # create it first - we won't need to do this once we can load arguments programmatically osArgument = createOSArgument(arg) args.Add(osArgument) # create the workflow rjb = OpenStudio.RubyJobBuilder(measure, args) rjb.setIncludeDir(OpenStudio.Path(rubyPath)) wf.addJob(rjb.toWorkItem()) # add energyplus jobs wf.addJob(OpenStudio.JobType("ModelToIdf")) wf.addJob(OpenStudio.JobType("EnergyPlus")) # set up tool info to pass to run manager tools = OpenStudio.ConfigOptions.makeTools(epPath, OpenStudio.Path(), radPath, rubyPath, OpenStudio.Path()) # add tools to workflow, has to happen after jobs are added wf.add(tools) wf.addParam(OpenStudio.JobParam("flatoutdir")) # turn the workflow definition into a specific instance jobtree = wf.create(outDir, osmPath, epwPath) try: # make a run manager rm = OpenStudio.RunManager(rmDBPath, True, True, False, False) # run the job tree rm.enqueue(jobtree, True) rm.setPaused(False) # one of these two is redundant # I keep this while rm.workPending(): time.sleep(1) print "Running simulation..." # wait until done rm.waitForFinished() jobErrors = jobtree.errors() print "Errors and Warnings:" print "\n".join(jobErrors.errors()) if jobErrors.succeeded(): print "Passed!" else: print "Failed!" rm.Dispose() except Exception as e: print str(e) finally: rm.Dispose() projectFolder = os.path.normpath(workingDir + '\\' + OSMeasure.name.replace(" ", "_") + "\\0-UserScript") return projectFolder
except: initCheck = False warning = "You need a newer version of Honeybee to use this compoent." + \ "Use updateHoneybee component to update userObjects.\n" + \ "If you have already updated userObjects drag Honeybee_Honeybee component " + \ "into canvas and try again." ghenv.Component.AddRuntimeMessage(w, warning) if openStudioIsReady == True and initCheck == True and fileLoad == False: if ghenv.Component.Params.Input.Count == 1 and _OSMeasure: # first time loading xmlFile = os.path.join(_OSMeasure, "measure.xml") if not os.path.isfile(xmlFile): raise Exception("Can't find measure at " + xmlFile) measure = OpenStudio.BCLMeasure(OpenStudio.Path(_OSMeasure)) if measure.arguments().Count == 0: print "Measure contains no arguments." # load arguments args = get_measureArgs(xmlFile) # add arguments to component path = gh.Data.GH_Path(0) for key in sorted(args.keys()): addInputParam(args[key], path) measureType = updateComponentDescription(xmlFile) # create an OSMeasure based on default values OSMeasure = OpenStudioMeasure(ghenv.Component.Name,
if (key != totaltag): if (type(dictionary[key]) is float): subtotal += dictionary[key] else: storedtotal = dictionary[key] if (subtotal == storedtotal): return "PASS" else: return "FAIL" #ops. #sqlPath = r'C:\Users\Administrator\Downloads\eplusout.sql' pp = pprint.PrettyPrinter(indent=4) sqlPath = _sqlFilePath sqlFile = ops.SqlFile(ops.Path(sqlPath)) conversionFactorElec = float(str(ops.OptionalDouble(277.777778))) outputs = {} electricity = { 'units': 'kilowatt-hours', 'Electricity Interior Lights': float(str(sqlFile.electricityInteriorLighting())) * conversionFactorElec, 'Electricity Exterior Lights': float(str(sqlFile.electricityExteriorLighting())) * conversionFactorElec, 'Electricity Interior Equipment': float(str(sqlFile.electricityInteriorEquipment())) * conversionFactorElec, 'Electricity Exterior Equipment': float(str(sqlFile.electricityExteriorEquipment())) * conversionFactorElec, 'Electricity Heating': float(str(sqlFile.electricityHeating())) * conversionFactorElec,
else: openStudioIsReady = False # let the user know that they need to download OpenStudio libraries msg1 = "You do not have OpenStudio installed on Your System.\n" + \ "You wont be able to use this component until you install it.\n" + \ "Download the latest OpenStudio for Windows from:\n" msg2 = "https://www.openstudio.net/downloads" print msg1 print msg2 ghenv.Component.AddRuntimeMessage(gh.GH_RuntimeMessageLevel.Warning, msg1) ghenv.Component.AddRuntimeMessage(gh.GH_RuntimeMessageLevel.Warning, msg2) else: openStudioIsReady = False if openStudioIsReady and _export and _filepath and _model: _filepath = _filepath.replace('\\\\', '/').replace('\\', '/') translator = ops.GbXMLForwardTranslator() _model.getFacility() result = translator.modelToGbXML(_model, ops.Path(os.path.normpath(_filepath))) errors = translator.errors() warnings = translator.warnings() if ''.join(errors): raise Exception('\n'.join(errors)) for warn in warnings: print warn print 'File exported to: {}'.format(os.path.normpath(_filepath)) success = True
def get_norm_vec(face, points, brep_vec): normal, normal_reverse, face_cpt = get_vectors(face, points, brep_vec) return face_cpt, normal, normal_reverse TOL = sc.doc.ModelAbsoluteTolerance if not openStudioIsReady: print "Problem loading OSM. Have you let HB fly?" else: osm = ops.Model() # BREP for i in range(len(breps)): brep = breps[i] osm_space = ops.Space(osm) osm_space.setName("space_{}".format(i)) # ghlib methods faces = ghlib.components.DeconstructBrep(rs.coercebrep(brep))[0] brep_vec = rs.coerce3dvector(ghlib.components.Area(brep)[1]) # SURFACES for j in range(len(faces)):