def example(owExe): debug = True # set True so user sees final 'break' message start_once = False modify_turbine = False opt_log = False extOpt = False for arg in sys.argv[1:]: if arg == '-debug': debug = True if arg == '-once': start_once = True if arg == '-log': opt_log = True if arg == '-modturb': modify_turbine = True if arg == '-extopt': extOpt = True if arg == '-help': sys.stderr.write( 'USAGE: python openWindComponent.py [-once] [-debug] [-modturb] [-extopt]\n' ) exit() # Find OpenWind executable if not os.path.isfile(owExe): sys.stderr.write( 'OpenWind executable file "{:}" not found\n'.format(owExe)) exit() # set the external optimiser flag to extOpt: # True : can use our optimizing routines acutils.owIniSet(owExe, extVal=extOpt, debug=True) # If we are not externally optimizing, we can start OW once and let it run to completion if not extOpt: start_once = True # Set OpenWind script name testpath = 'templates/' #owXMLname = testpath + 'rtecScript.xml' # replace turb, energy capture #KLD - this script does not work for me with this component owXMLname = testpath + 'owScript.xml' # optimize operation #owXMLname = testpath + 'rtopScript.xml' # replace turb, optimize if modify_turbine: owXMLname = testpath + 'rtopScript.xml' # replace turb, optimize if not os.path.isfile(owXMLname): sys.stderr.write( 'OpenWind script file "{:}" not found\n'.format(owXMLname)) exit() dscript = rwScriptXML.rdScript(owXMLname, debug=debug) # Show our operations workbook = dscript['workbook'] # default turbine positions and size of translation wt_positions = [[456000.00, 4085000.00], [456500.00, 4085000.00]] deltaX = 3000.0 deltaY = -2000.0 #deltaX = 200.0 #deltaY = -200.0 deltaX = 3.000 deltaY = -2.000 # Read turbine positions from workbook if debug: sys.stderr.write( 'Getting turbine positions from {:}\n'.format(workbook)) wb = acutils.WTWkbkFile(wkbk=workbook, owexe=owExe) wt_positions = wb.xy if debug: sys.stderr.write('Got {:} turbine positions\n'.format( len(wt_positions))) # Initialize OWcomp component ow = OWcomp(owExe=owExe, debug=debug, scriptFile=owXMLname, extOpt=extOpt, start_once=start_once, opt_log=opt_log) #, stopOW=False) if not ow.scriptOK: sys.stderr.write("\n*** ERROR found in script file\n\n") exit() # starting point for turbine mods #wt_list_elem = dummy_wt_list() base_turbine_file = testpath + 'NREL5MW.owtg' wt_list_elem = turbfuncs.owtg_to_wtpc(base_turbine_file) if not extOpt: # If we're not optimizing externally, run ow and return ow.execute() print '\nFinal values' owd = ow.dump() print ' {:}'.format(owd) print '-' * 40, '\n' return # external optimization ow.wt_layout.wt_list = [wt_list_elem for i in range(len(wt_positions))] if debug: sys.stderr.write('Initialized {:} turbines in wt_layout\n'.format( len(wt_positions))) # With each iteration # move turbines farther offshore # possibly modify the turbine rotor diam and power curve and replace turbine if debug: ofh = open('wtp.txt', 'w') for irun in range(1, 4): for i in range(len(wt_positions)): wt_positions[i][0] += deltaX wt_positions[i][1] += deltaY if debug: ofh.write('{:2d} {:3d} {:.1f} {:.1f}\n'.format( irun, i, wt_positions[i][0], wt_positions[i][1])) ow.wt_layout.wt_positions = wt_positions # modify the turbine ow.rotor_diameter += 1.0 if ow.replace_turbine: wt_list_elem = ow.wt_layout.wt_list[0] wt_list_elem.power_rating *= 1.05 for i in range(len(wt_list_elem.power_curve)): wt_list_elem.power_curve[i][1] *= 1.05 ow.wt_layout.wt_list = [ wt_list_elem for i in range(len(ow.wt_layout.wt_list)) ] if debug: ofh.write('Updated {:} turbines with:\n'.format( len(ow.wt_layout.wt_list))) ofh.write(turbfuncs.wtpc_dump(ow.wt_layout.wt_list[0])) ow.execute() # run the openWind process print '\nFinal values' owd = ow.dump() print ' {:}'.format(owd) print '-' * 40, '\n' if start_once: ow.terminateOW()
def execute(self): """ Executes our component. """ if self.debug: sys.stderr.write("In {0}.execute() {1}...\n".format( self.__class__, self.script_file)) if (len(self.resname) < 1): sys.stderr.write( '\n*** ERROR: OWcomp results file name not assigned! (problem with script file?)\n\n' ) return False # Prepare input file here # - write a new script file? # - write a new turbine file to overwrite the one referenced # in the existing script_file? # If there is a turbine replacement operation in the script: # write new turbine description file based on contents of first turbine in layout #if 'replturbpath' in self.scriptDict: if self.replace_turbine: if len(self.wt_layout.wt_list) < 1: sys.stderr.write( '\n*** ERROR *** OWcomp::execute(): no turbines in wt_layout!\n\n' ) return False if self.debug: sys.stderr.write('Replacement turbine parameters:\n') #sys.stderr.write('{:}\n'.format(turbfuncs.wtpc_dump(self.wt_layout.wt_list[0]))) sys.stderr.write('{:}\n'.format( turbfuncs.wtpc_dump(self.wt_layout.wt_list[0], shortFmt=True))) #sys.stderr.write('{:}\n'.format(wtlDump(self.wt_layout.wt_list[0]))) newXML = turbfuncs.wtpc_to_owtg(self.wt_layout.wt_list[0], trbname='ReplTurb', desc='OWcomp replacement turbine') if len(newXML) > 50: tfname = self.scriptDict[ 'replturbpath'] # this is the file that will be overwritten with new turbine parameters tfh = open(tfname, 'w') tfh.write(newXML) tfh.close() maxPower = self.wt_layout.wt_list[0].power_rating if self.debug: sys.stderr.write( 'Wrote new turbine file to {:} (rated pwr {:.2f} MW\n'. format(tfname, maxPower * 0.000001)) else: sys.stderr.write('*** NO new turbine file written\n') # Execute the component and save process ID if not self.start_once: self.proc = subprocess.Popen(self.command) self.pid = self.proc.pid if self.debug: sys.stderr.write('Started OpenWind with pid {:}\n'.format( self.pid)) sys.stderr.write(' OWComp: dummyVbl {:}\n'.format( self.dummyVbl)) #sys.stderr.write('Report Path: {:}\n'.format(self.rptpath)) # Watch for 'results.txt', meaning that OW has run once with the default locations if self.debug: sys.stderr.write( 'OWComp waiting for {:} (first run - positions unchanged)\n' .format(self.resname)) acutils.waitForNotify(watchFile=self.resname, path=self.dname, debug=False, callback=self.getCBvalue) # Now OW is waiting for a new position file # Write new positions and notify file - this time it should use updated positions acutils.writePositionFile(self.wt_layout.wt_positions, path=self.dname, debug=self.debug) # see if results.txt is there already if os.path.exists(self.resname): resmtime = os.path.getmtime(self.resname) if self.debug: sys.stderr.write('ModTime({:}): {:}\n'.format( self.resname, time.asctime(time.localtime(resmtime)))) else: if self.debug: sys.stderr.write('{:} does not exist yet\n'.format( self.resname)) acutils.writeNotify( path=self.dname, debug=self.debug ) # tell OW that we're ready for the next (only) iteration # 'results.txt' is in the same directory as the *blb file if os.path.exists(self.resname): resNewmtime = os.path.getmtime(self.resname) if resNewmtime > resmtime: # file has changed if self.debug: sys.stderr.write('results.txt already updated') else: acutils.waitForNotify(watchFile=self.resname, path=self.dname, callback=self.getCBvalue, debug=self.debug) else: if self.debug: sys.stderr.write( 'OWComp waiting for {:} (modified positions)\n'.format( self.resname)) acutils.waitForNotify(watchFile=self.resname, path=self.dname, callback=self.getCBvalue, debug=self.debug) # Parse output file # Enterprise OW writes the report file specified in the script BUT # Academic OW writes 'results.txt' (which doesn't have as much information) netEnergy, netNRGturb, grossNRGturb = acutils.parseACresults( fname=self.resname) if netEnergy is None: sys.stderr.write("Error reading results file\n") if self.debug: sys.stderr.write('Stopping OpenWind with pid {:}\n'.format( self.pid)) self.proc.terminate() return False # Set the output variables # - array_aep is not available from Academic 'results.txt' file self.nTurbs = len(netNRGturb) self.net_aep = netEnergy self.gross_aep = sum(grossNRGturb) if self.debug: sys.stderr.write('{:}\n'.format(self.dump())) # Log optimization values if self.opt_log: self.olfh.write('{:3d} G {:.4f} N {:.4f} XY '.format( self.exec_count, self.gross_aep, self.net_aep)) for ii in range(len(wt_positions)): self.olfh.write('{:8.1f} {:9.1f} '.format( self.wt_layout.wt_positions[ii][0], self.wt_layout.wt_positions[ii][1])) self.olfh.write('\n') if not self.start_once and self.stopOW: if self.debug: sys.stderr.write('Stopping OpenWind with pid {:}\n'.format( self.pid)) self.proc.terminate() self.checkReport() # check for execution errors if self.debug: sys.stderr.write("Leaving {0}.execute() {1}...\n\n".format( self.__class__, self.script_file))
def execute(self): """ Executes our component. """ if self.debug: sys.stderr.write("In {0}.execute() {1}...\n".format(self.__class__, self.script_file)) if (len(self.resname) < 1): sys.stderr.write('\n*** ERROR: OWcomp results file name not assigned! (problem with script file?)\n\n') return False # Prepare input file here # - write a new script file? # - write a new turbine file to overwrite the one referenced # in the existing script_file? # If there is a turbine replacement operation in the script: # write new turbine description file based on contents of first turbine in layout #if 'replturbpath' in self.scriptDict: if self.replace_turbine: if len(self.wt_layout.wt_list) < 1: sys.stderr.write('\n*** ERROR *** OWcomp::execute(): no turbines in wt_layout!\n\n') return False if self.debug: sys.stderr.write('Replacement turbine parameters:\n') #sys.stderr.write('{:}\n'.format(turbfuncs.wtpc_dump(self.wt_layout.wt_list[0]))) sys.stderr.write('{:}\n'.format(turbfuncs.wtpc_dump(self.wt_layout.wt_list[0], shortFmt=True))) #sys.stderr.write('{:}\n'.format(wtlDump(self.wt_layout.wt_list[0]))) newXML = turbfuncs.wtpc_to_owtg(self.wt_layout.wt_list[0], trbname='ReplTurb', desc='OWcomp replacement turbine') if len(newXML) > 50: tfname = self.scriptDict['replturbpath'] # this is the file that will be overwritten with new turbine parameters tfh = open(tfname, 'w') tfh.write(newXML) tfh.close() maxPower = self.wt_layout.wt_list[0].power_rating if self.debug: sys.stderr.write('Wrote new turbine file to {:} (rated pwr {:.2f} MW\n'.format(tfname, maxPower*0.000001)) else: sys.stderr.write('*** NO new turbine file written\n') # Execute the component and save process ID if not self.start_once: self.proc = subprocess.Popen(self.command) self.pid = self.proc.pid if self.debug: sys.stderr.write('Started OpenWind with pid {:}\n'.format(self.pid)) sys.stderr.write(' OWComp: dummyVbl {:}\n'.format(self.dummyVbl)) #sys.stderr.write('Report Path: {:}\n'.format(self.rptpath)) # Watch for 'results.txt', meaning that OW has run once with the default locations if self.debug: sys.stderr.write('OWComp waiting for {:} (first run - positions unchanged)\n'.format(self.resname)) acutils.waitForNotify(watchFile=self.resname, path=self.dname, debug=False, callback=self.getCBvalue) # Now OW is waiting for a new position file # Write new positions and notify file - this time it should use updated positions acutils.writePositionFile(self.wt_layout.wt_positions, path=self.dname, debug=self.debug) # see if results.txt is there already if os.path.exists(self.resname): resmtime = os.path.getmtime(self.resname) if self.debug: sys.stderr.write('ModTime({:}): {:}\n'.format(self.resname, time.asctime(time.localtime(resmtime)))) else: if self.debug: sys.stderr.write('{:} does not exist yet\n'.format(self.resname)) acutils.writeNotify(path=self.dname, debug=self.debug) # tell OW that we're ready for the next (only) iteration # 'results.txt' is in the same directory as the *blb file if os.path.exists(self.resname): resNewmtime = os.path.getmtime(self.resname) if resNewmtime > resmtime: # file has changed if self.debug: sys.stderr.write('results.txt already updated') else: acutils.waitForNotify(watchFile=self.resname, path=self.dname, callback=self.getCBvalue, debug=self.debug) else: if self.debug: sys.stderr.write('OWComp waiting for {:} (modified positions)\n'.format(self.resname)) acutils.waitForNotify(watchFile=self.resname, path=self.dname, callback=self.getCBvalue, debug=self.debug) # Parse output file # Enterprise OW writes the report file specified in the script BUT # Academic OW writes 'results.txt' (which doesn't have as much information) netEnergy, netNRGturb, grossNRGturb = acutils.parseACresults(fname=self.resname) if netEnergy is None: sys.stderr.write("Error reading results file\n") if self.debug: sys.stderr.write('Stopping OpenWind with pid {:}\n'.format(self.pid)) self.proc.terminate() return False # Set the output variables # - array_aep is not available from Academic 'results.txt' file self.nTurbs = len(netNRGturb) self.net_aep = netEnergy self.gross_aep = sum(grossNRGturb) if self.debug: sys.stderr.write('{:}\n'.format(self.dump())) # Log optimization values if self.opt_log: self.olfh.write('{:3d} G {:.4f} N {:.4f} XY '.format(self.exec_count, self.gross_aep, self.net_aep)) for ii in range(len(wt_positions)): self.olfh.write('{:8.1f} {:9.1f} '.format(self.wt_layout.wt_positions[ii][0], self.wt_layout.wt_positions[ii][1])) self.olfh.write('\n') if not self.start_once and self.stopOW: if self.debug: sys.stderr.write('Stopping OpenWind with pid {:}\n'.format(self.pid)) self.proc.terminate() self.checkReport() # check for execution errors if self.debug: sys.stderr.write("Leaving {0}.execute() {1}...\n\n".format(self.__class__, self.script_file))
def example(owExe): debug = True # set True so user sees final 'break' message start_once = False modify_turbine = False opt_log = False extOpt = False for arg in sys.argv[1:]: if arg == '-debug': debug = True if arg == '-once': start_once = True if arg == '-log': opt_log = True if arg == '-modturb': modify_turbine = True if arg == '-extopt': extOpt = True if arg == '-help': sys.stderr.write('USAGE: python openWindComponent.py [-once] [-debug] [-modturb] [-extopt]\n') exit() # Find OpenWind executable if not os.path.isfile(owExe): sys.stderr.write('OpenWind executable file "{:}" not found\n'.format(owExe)) exit() # set the external optimiser flag to extOpt: # True : can use our optimizing routines acutils.owIniSet(owExe, extVal=extOpt, debug=True) # If we are not externally optimizing, we can start OW once and let it run to completion if not extOpt: start_once = True # Set OpenWind script name testpath = 'templates/' #owXMLname = testpath + 'rtecScript.xml' # replace turb, energy capture #KLD - this script does not work for me with this component owXMLname = testpath + 'owScript.xml' # optimize operation #owXMLname = testpath + 'rtopScript.xml' # replace turb, optimize if modify_turbine: owXMLname = testpath + 'rtopScript.xml' # replace turb, optimize if not os.path.isfile(owXMLname): sys.stderr.write('OpenWind script file "{:}" not found\n'.format(owXMLname)) exit() dscript = rwScriptXML.rdScript(owXMLname,debug=debug) # Show our operations workbook = dscript['workbook'] # default turbine positions and size of translation wt_positions = [[456000.00,4085000.00], [456500.00,4085000.00]] deltaX = 3000.0 deltaY = -2000.0 #deltaX = 200.0 #deltaY = -200.0 deltaX = 3.000 deltaY = -2.000 # Read turbine positions from workbook if debug: sys.stderr.write('Getting turbine positions from {:}\n'.format(workbook)) wb = acutils.WTWkbkFile(wkbk=workbook, owexe=owExe) wt_positions = wb.xy if debug: sys.stderr.write('Got {:} turbine positions\n'.format(len(wt_positions))) # Initialize OWcomp component ow = OWcomp(owExe=owExe, debug=debug, scriptFile=owXMLname, extOpt=extOpt, start_once=start_once, opt_log=opt_log) #, stopOW=False) if not ow.scriptOK: sys.stderr.write("\n*** ERROR found in script file\n\n") exit() # starting point for turbine mods #wt_list_elem = dummy_wt_list() base_turbine_file = testpath + 'NREL5MW.owtg' wt_list_elem = turbfuncs.owtg_to_wtpc(base_turbine_file) if not extOpt: # If we're not optimizing externally, run ow and return ow.execute() print '\nFinal values' owd = ow.dump() print ' {:}'.format(owd) print '-' * 40, '\n' return # external optimization ow.wt_layout.wt_list = [ wt_list_elem for i in range(len(wt_positions)) ] if debug: sys.stderr.write('Initialized {:} turbines in wt_layout\n'.format(len(wt_positions))) # With each iteration # move turbines farther offshore # possibly modify the turbine rotor diam and power curve and replace turbine if debug: ofh = open('wtp.txt', 'w') for irun in range(1,4): for i in range(len(wt_positions)): wt_positions[i][0] += deltaX wt_positions[i][1] += deltaY if debug: ofh.write('{:2d} {:3d} {:.1f} {:.1f}\n'.format(irun, i, wt_positions[i][0], wt_positions[i][1])) ow.wt_layout.wt_positions = wt_positions # modify the turbine ow.rotor_diameter += 1.0 if ow.replace_turbine: wt_list_elem = ow.wt_layout.wt_list[0] wt_list_elem.power_rating *= 1.05 for i in range(len(wt_list_elem.power_curve)): wt_list_elem.power_curve[i][1] *= 1.05 ow.wt_layout.wt_list = [wt_list_elem for i in range(len(ow.wt_layout.wt_list)) ] if debug: ofh.write('Updated {:} turbines with:\n'.format(len(ow.wt_layout.wt_list))) ofh.write(turbfuncs.wtpc_dump(ow.wt_layout.wt_list[0])) ow.execute() # run the openWind process print '\nFinal values' owd = ow.dump() print ' {:}'.format(owd) print '-' * 40, '\n' if start_once: ow.terminateOW()
def execute(self): """ Set up XML and run OpenWind """ if self.debug: sys.stderr.write("\nIn {0}.execute()...\n".format(self.__class__)) # ---- Set up parameters # initial positions are 'connect'ed to OWcomp object with passthrough of wt_layout # set turbine positions # - from initial positions? # - using another component that sets positions? self.wt_layout.wt_positions = self.init_wt_positions # use initial positions # 2014 05 26 - initialize or modify the turbine type here # - read from file # - modify existing turbine type # - add component that returns a new turbine type # trb == ExtendedWindTurbinePowerCurveVT() nt = len(self.wt_layout.wt_positions) # initialize from file #owtg_file = '../test/NREL5MW.owtg' #sys.stderr.write('\n*** WARNING: initializing turbine from {:} - why??\n\n'.format(owtg_file)) #trb = turbfuncs.owtg_to_wtpc(owtg_file) if self.debug: sys.stderr.write('\n*** WARNING: initializing turbine from ExtendedWindTurbinePowerCurveVT\n\n') trb = ExtendedWindTurbinePowerCurveVT() #trb.power_rating = 1000000.0 # watts! trb.power_rating = self.machine_rating for i in range(nt): self.wt_layout.wt_list[i] = trb # show parameters if self.debug: sys.stderr.write('Initial Turbine Positions\n') for i in range(len(self.wt_layout.wt_positions)): sys.stderr.write('{:3d} {:.1f} {:.1f}\n'.format(i, self.wt_layout.wt_positions[i][0],self.wt_layout.wt_positions[i][1])) s = turbfuncs.wtpc_dump(self.wt_layout.wt_list[0]) sys.stderr.write('\n' + s) #report_path = self.workDir + '/' + 'scrtest1.txt' #workbook_path = self.workbook_path # Prepare for next iteration here... # - write new scripts # - write new turbine files # - etc. # owtg_str = turbfuncs.wtpc_to_owtg(self.turb_props) # write new script for execution # newScriptName = 'OpenWind_Script.xml' # self.writeNewScript(newScriptName) # self.command[1] = newScriptName # ---- Run the workflow super(openwindAC_assembly, self).execute() # ---- Process results # calculate capacity factor # - assumes that all turbines have the same power rating # and that self.wt_layout is correct if (self.wt_layout.wt_list[0].power_rating is None or self.wt_layout.wt_list[0].power_rating == 0.0): self.capacity_factor = 0.0 sys.stderr.write('\n*** WARNING: turbine power_rating not set\n\n') else: # power_rating is in W, but net_aep is in kWh #self.capacity_factor = ((self.net_aep) / (self.wt_layout.wt_list[0].power_rating*0.001 * 8760.0 * self.nTurbs)) # 8766 hrs = 365.25 days to agree with OpenWind self.capacity_factor = ((self.net_aep) / (self.wt_layout.wt_list[0].power_rating*0.001 * 8766.0 * self.nTurbs)) self.total_losses = (self.gross_aep - self.net_aep) / self.gross_aep