Пример #1
0
def read_airfoils(airfoilFileNames, workdir=''):
    airfoils = []
    for f in airfoilFileNames:
        AF = weio.FASTInFile(os.path.join(workdir, f))
        af = dict()
        af['name'] = os.path.splitext(os.path.basename(f))[0]
        af['polar'] = AF['AFCoeff']
        Tab = af['polar']
        # Total range of alpha values, and window where we focus
        aRange = [-180, 180]
        aWindow = [-40, 40]
        # Finding min/max Cl Cd in windows range of alpha values
        iStart = np.argmin(abs(Tab[:, 0] - aWindow[0]))
        iEnd = np.argmin(abs(Tab[:, 0] - aWindow[1]))
        af['Clmin'] = np.min(Tab[iStart:iEnd, 1])
        af['Clmax'] = np.max(Tab[iStart:iEnd, 1])
        af['Cdmin'] = np.min(Tab[iStart:iEnd, 2])
        af['iClmin'] = np.argmin(Tab[iStart:iEnd, 1]) + iStart
        af['iClmax'] = np.argmax(Tab[iStart:iEnd, 1]) + iStart
        af['iCdmin'] = np.argmin(Tab[iStart:iEnd, 2]) + iStart
        # For convenience
        aBefore = [aWindow[0] - 2, aWindow[0] - 1, aWindow[0]]
        aAfter = [aWindow[1], aWindow[1] + 1, aWindow[1] + 2]
        af['aClDelta'] = aBefore + [
            Tab[af['iClmin'], 0], Tab[af['iClmax'], 0]
        ] + aAfter
        af['aCdDelta'] = aBefore + [Tab[af['iCdmin'], 0]] + aAfter
        af['ClDeltaMax'] = np.array([0, 0, 0, 0, 1, 0, 0, 0])
        af['ClDeltaMin'] = np.array([0, 0, 0, -1, 0, 0, 0, 0])
        af['CdDelta'] = np.array([0, 0, 0, 1, 0, 0, 0])
        airfoils.append(af)
    return airfoils
Пример #2
0
def genotype_to_FASTphenotype(chromosome):
    """ Given a chromosome, create a FAST simulation folder
        Uses the global variables: RefValues, CH_MAP, ref_dir
    """
    if not hasattr(chromosome,'data'):
        raise NotImplementedError('')

    def naming(p):
        return '_{:02.0f}'.format(p['InflowFile|HWindSpeed'])

    if len(chromosome)!=CH_MAP.nBases:
        raise Exception('Chromosome length ({}) not compatible with CH_MAP length ({})'.format(len(chromosome),CH_MAP.nBases))

    #print('')
    #for gm,gene in zip(CH_MAP, CH_MAP.split(chromosome)):
    #    print(gm.show_full_raw(gene))

    PARAMS=[]
    for wsp,rpm,pit in zip(RefValues['WS'],RefValues['RPM'],RefValues['Pitch']):
        p=dict()
        p['FAST|TMax']             = 30
        p['FAST|DT']               = 0.01
        p['FAST|DT_Out']           = 0.1
        p['FAST|OutFileFmt']       = 1 # TODO
        p['EDFile|RotSpeed']       = rpm
        p['EDFile|BlPitch(1)']     = pit
        p['EDFile|BlPitch(2)']     = pit
        p['EDFile|BlPitch(3)']     = pit
        p['InflowFile|HWindSpeed'] = wsp
        p['InflowFile|WindType']   = 1 # Setting steady wind
        for gm,gene in zip(CH_MAP, CH_MAP.split(chromosome)):
            if gm.kind=='fast_param':
                p[gm.name]=gm.decode(gene)
            elif gm.kind=='builtin':
                if gm.name=='pitch':
                    p['EDFile|BlPitch(1)']     = gm.decode(gene)
                    p['EDFile|BlPitch(2)']     = gm.decode(gene)
                    p['EDFile|BlPitch(3)']     = gm.decode(gene)
                #print(gm.name, '->',p[gm.name],gene)
    
        PARAMS.append(p)

    sim_dir=chromosome.data['dir']
    fastlib.templateReplace(ref_dir,PARAMS,workdir=sim_dir,name_function=naming,RemoveRefSubFiles=True)

    # --- Patching the airfoil files
    for gm,gene in zip(CH_MAP, CH_MAP.split(chromosome)):
        if gm.kind=='airfoil':
            af_mut = copy.deepcopy(gm.meta)
            af_mut = patch_airfoil(gene,af_mut)
            AF = weio.FASTInFile(os.path.join(sim_dir,gm.name))
            AF['AFCoeff'] = af_mut['polar']
            AF.write()
Пример #3
0
def spanwisePostProFF(fastfarm_input,
                      avgMethod='constantwindow',
                      avgParam=30,
                      D=1,
                      df=None,
                      fastfarm_out=None):
    """ 
    Opens a FASTFarm output file, extract the radial data, average them and returns spanwise data

    D: diameter TODO, extract it from the main file

    See faslibt.averageDF for `avgMethod` and `avgParam`.
    """
    # --- Opening input file and extracting inportant variables
    main = weio.FASTInFile(fastfarm_input)
    iOut = main['OutRadii']
    dr = main['dr']  # Radial increment of radial finite-difference grid (m)
    OutDist = main[
        'OutDist']  # List of downstream distances for wake output for an individual rotor
    WT = main['WindTurbines']
    nWT = len(WT)
    vr_bar = dr * np.array(iOut) / (D / 2)
    vD = np.array(OutDist) / D
    nr = len(vr_bar)
    nD = len(vD)
    # --- Opening ouputfile
    if df is None:
        df = weio.read(fastfarm_out).toDataFrame()

    # --- Extracting time series of radial data only
    colRadial = SensorsFARMRadial(nWT=nWT,
                                  nD=nD,
                                  nR=nr,
                                  signals=df.columns.values)
    colRadial = ['Time_[s]'] + colRadial
    dfRadialTime = df[
        colRadial]  # TODO try to do some magic with it, display it with a slider

    # --- Averaging data
    dfAvg = fastlib.averageDF(df, avgMethod='constantwindow', avgParam=30)

    # --- Brute force storing of radial data
    Columns = [vr_bar]
    if D == 1:
        ColumnNames = ['r_[m]']
    else:
        ColumnNames = ['r/R_[-]']
    for iWT in range(nWT):
        Values = np.zeros((len(vr_bar), 1))
        nCount = 0
        col_out = 'CtT{:d}_[-]'.format(iWT + 1)
        for ir in range(nr):
            col = 'CtT{:d}N{:02d}_[-]'.format(iWT + 1, ir + 1)
            if col in dfAvg.columns.values:
                Values[ir, 0] = dfAvg[col]
                nCount += 1
        if nCount != nr and nCount > 0:
            print('[WARN] Not all values found for {}, found {}/{}'.format(
                col_out, nCount, nr))
        if nCount > 0:
            Columns.append(Values)
            ColumnNames.append('CtT{:d}'.format(iWT + 1))
    for iWT in range(nWT):
        for iD in range(nD):
            Values = np.zeros((len(vr_bar), 1))
            nCount = 0
            col_out = 'WkDfVxT{:d}D{:d}_[m/s]'.format(iWT + 1, iD + 1)
            for ir in range(nr):
                col = 'WkDfVxT{:d}N{:02d}D{:d}_[m/s]'.format(
                    iWT + 1, ir + 1, iD + 1)
                if col in dfAvg.columns.values:
                    Values[ir, 0] = dfAvg[col]
                    nCount += 1
            if nCount != nr and nCount > 0:
                print('[WARN] Not all values found for {}, found {}/{}'.format(
                    col_out, nCount, nr))
            if nCount > 0:
                Columns.append(Values)
                ColumnNames.append(col_out)
    for iWT in range(nWT):
        for iD in range(nD):
            Values = np.zeros((len(vr_bar), 1))
            nCount = 0
            col_out = 'WkDfVrT{:d}D{:d}_[m/s]'.format(iWT + 1, iD + 1)
            for ir in range(nr):
                col = 'WkDfVrT{:d}N{:02d}D{:d}_[m/s]'.format(
                    iWT + 1, ir + 1, iD + 1)
                if col in dfAvg.columns.values:
                    Values[ir, 0] = dfAvg[col]
                    nCount += 1
            if nCount != nr and nCount > 0:
                print('[WARN] Not all values found for {}, found {}/{}'.format(
                    col_out, nCount, nr))
            if nCount > 0:
                Columns.append(Values)
                ColumnNames.append(col_out)

    data = np.column_stack(Columns)
    dfRad = pd.DataFrame(data=data, columns=ColumnNames)
    return dfRad, dfRadialTime
Пример #4
0
def generateParametricInputs(template_dir,workdir=None,main_file=None,OPER=None,RemoveAllowed=False,bStiff=False,bSteadyAero=False,TMax=None):
    if template_dir[-1]=='/'  or template_dir[-1]=='\\' :
        template_dir=template_dir[0:-1]

    if workdir is None:
        workdir=template_dir+'_Parametric'

    # Copying template folder
    print(template_dir, '  ',workdir)
    if os.path.exists(workdir) and RemoveAllowed:
        rmtree(workdir)
    #distutils.dir_util.copy_tree(template_dir, workdir)
    copytree(template_dir, workdir, ignore=ignore_patterns('.git'))
    fastlib.removeFASTOuputs(workdir)

    print('Generating fast input files...')

    # --- Fast main file use as "master"
    if main_file is None:
        FstFiles=set(glob.glob(os.path.join(template_dir,'*.fst'))+glob.glob(os.path.join(template_dir,'*.FST')))
        print(FstFiles)
        if len(FstFiles)>1:
            raise Exception('More than one fst file found in template folder') 
        main_file=FstFiles.pop()
    main_file=os.path.join(workdir, main_file)

    # --- Reading Master File
    print('Reading template file: '+main_file)
    FST = weio.FASTInFile(main_file);
    windfilename_ref = os.path.join(workdir,FST['InflowFile'].strip('"'))
    edfilename_ref   = os.path.join(workdir,FST['EDFile'].strip('"'))
    adfilename_ref   = os.path.join(workdir,FST['AeroFile'].strip('"'))
    sdfilename_ref   = os.path.join(workdir,FST['ServoFile'].strip('"'))
# 
    Wnd = weio.FASTInFile(windfilename_ref);
    ED  = weio.FASTInFile(edfilename_ref);
    AD  = weio.FASTInFile(adfilename_ref);
    windbasename_ref = os.path.basename(windfilename_ref)
    edbasename_ref   = os.path.basename(edfilename_ref)
    adbasename_ref   = os.path.basename(adfilename_ref)
    sdbasename_ref   = os.path.basename(sdfilename_ref)
    fastbasename_ref = os.path.basename(main_file)

    # Rewritting SD file, making sure the controller is off
    SD  = weio.FASTInFile(sdfilename_ref);
    SD['PCMode']=0;
    SD['VSContrl']=0;
    SD['YCMode']=0;
    SD.write (os.path.join(workdir,sdbasename_ref))
# 
    # --- Generating inputs
    fastfiles=[]
    if OPER is None:
        raise Exception('Please provide OPER')
    Keys = list(OPER.keys())
    nValues = len(OPER[Keys[0]])
    print('Number of values ',nValues)
    for i in range(nValues):
        Params = [(k,OPER[k][i]) for k in Keys]
        strID = '_{:03d}'.format(i)
        print(Params)
        for k in Keys:
            val = OPER[k][i]
            if k.lower()=='ws':
                strID += '_ws{:04.1f}'.format(val)
            elif k.lower()=='omega':
                strID += '_om{:04.2f}'.format(val)
            elif k.lower()=='pitch':
                strID += '_pt{:04.2f}'.format(val)
            else:
                raise Exception('Not supported {}'.format(k))
        fastfilename = fastbasename_ref.replace('.fst',strID+'.fst')
        windfilename = windbasename_ref.replace('.dat',strID+'.dat')
        edfilename   = edbasename_ref.replace('.dat',strID+'.dat')
        adfilename   = adbasename_ref.replace('.dat',strID+'.dat')
        sdfilename   = sdbasename_ref.replace('.dat',strID+'.dat')
        for k in Keys:
            val = OPER[k][i]
            if k.lower()=='ws':
                Wnd['WindType']   = 1
                Wnd['HWindSpeed'] = val
                FST['InflowFile'] = '"'+windfilename+'"'
                Wnd.write(os.path.join(workdir,windfilename))
            elif k.lower()=='omega':
                ED['RotSpeed'] = val
            elif k.lower()=='pitch':
                ED['BlPitch(1)'] = val
                ED['BlPitch(2)'] = val
                ED['BlPitch(3)'] = val

        if TMax is not None:
           FST['TMax'] = TMax
        if bSteadyAero:
            AD['AFAeroMod']=1 # remove dynamic effects dynamic
        #
        ED['GenDOF'] = 'False' # important to prescribe rot speed
        if bStiff:
            ED['FlapDOF1']='False'
            ED['FlapDOF2']='False'
            ED['EdgeDOF' ]='False'
            ED['TeetDOF' ]='False'
            ED['DrTrDOF' ]='False'
            ED['YawDOF'  ]='False'
            ED['TwFADOF1']='False'
            ED['TwFADOF2']='False'
            ED['TwSSDOF1']='False'
            ED['TwSSDOF2']='False'
        FST['EDFile'] = '"'+edfilename+'"'
        FST['AeroFile'] = '"'+adfilename+'"'
        #FST['ServoFile'] = '"'+sdfilename+'"'
        ED.write (os.path.join(workdir,edfilename))
        AD.write (os.path.join(workdir,adfilename))
        FST.write(os.path.join(workdir,fastfilename))
        fastfiles.append(os.path.join(workdir,fastfilename))
#     os.remove(os.path.join(workdir,fastbasename_ref))
#     os.remove(edfilename_ref)
    return fastfiles,workdir
Пример #5
0

# --- Main Parameters
refdir   = '../OF2-SimpleGen/'
workdir  ='Model_Parametric_Focus/'
fastfile = 'SWT-2.3-93OpenFAST2_R2.fst';
TMax=10
ColKeep=['RotSpeed_[rpm]','BldPitch1_[deg]','RtAeroCp_[-]','RtAeroCt_[-]','Wind1VelX_[m/s]','Time_[s]']
#fastlib.FAST_EXE='OpenFAST2_x64d_ebra.exe'
fastlib.FAST_EXE='OpenFAST2_win32d_ebra.exe'




# --- Parametric
fst = weio.FASTInFile(os.path.join(refdir,fastfile))
print(fst['EDFile'])
ed  = weio.FASTInFile(os.path.join(refdir,fst['EDFile'].replace('"','')))
print('R=', ed['TipRad'])

U0=5
R=ed['TipRad']
Lambda = np.linspace(7.5,8.5,11);
Pitch  = np.linspace(-1.0,1.0,22);
Omega  = U0 * Lambda/R*60/(2*np.pi)  # TODO, use more realistic combinations of WS and Omega

OPER=dict()
OPER['WS']    = []
OPER['Pitch'] = []
OPER['Omega'] = []
for p in Pitch:
Пример #6
0
def spanwisePostProFF(fastfarm_input,
                      avgMethod='constantwindow',
                      avgParam=30,
                      D=1,
                      df=None,
                      fastfarm_out=None):
    """ 
    Opens a FASTFarm output file, extract the radial data, average them and returns spanwise data

    D: diameter TODO, extract it from the main file

    See faslibt.averageDF for `avgMethod` and `avgParam`.
    """
    # --- Opening ouputfile
    if df is None:
        df = weio.read(fastfarm_out).toDataFrame()

    # --- Opening input file and extracting inportant variables
    if fastfarm_input is None:
        # We don't have an input file, guess numbers of turbine, diameters, Nodes...
        cols, sIdx = fastlib.find_matching_pattern(df.columns.values, 'T(\d+)')
        nWT = np.array(sIdx).astype(int).max()
        cols, sIdx = fastlib.find_matching_pattern(df.columns.values, 'D(\d+)')
        nD = np.array(sIdx).astype(int).max()
        cols, sIdx = fastlib.find_matching_pattern(df.columns.values, 'N(\d+)')
        nr = np.array(sIdx).astype(int).max()
        vr = None
        vD = None
        D = 0
    else:
        main = weio.FASTInFile(fastfarm_input)
        iOut = main['OutRadii']
        dr = main[
            'dr']  # Radial increment of radial finite-difference grid (m)
        OutDist = main[
            'OutDist']  # List of downstream distances for wake output for an individual rotor
        WT = main['WindTurbines']
        nWT = len(WT)
        vr = dr * np.array(iOut)
        vD = np.array(OutDist)
        nr = len(iOut)
        nD = len(vD)

    # --- Extracting time series of radial data only
    colRadial = SensorsFARMRadial(nWT=nWT,
                                  nD=nD,
                                  nR=nr,
                                  signals=df.columns.values)
    colRadial = ['Time_[s]'] + colRadial
    dfRadialTime = df[
        colRadial]  # TODO try to do some magic with it, display it with a slider

    # --- Averaging data
    dfAvg = fastlib.averageDF(df, avgMethod=avgMethod, avgParam=avgParam)

    # --- Extract radial data
    ColsInfo, nrMax = spanwiseColFastFarm(df.columns.values, nWT=nWT, nD=nD)
    dfRad = fastlib.extract_spanwise_data(ColsInfo,
                                          nrMax,
                                          df=None,
                                          ts=dfAvg.iloc[0])
    #dfRad       = fastlib.insert_radial_columns(dfRad, vr)
    if vr is None:
        dfRad.insert(0, 'i_[#]', np.arange(nrMax) + 1)
    else:
        dfRad.insert(0, 'r_[m]', vr[:nrMax])
    dfRad['i/n_[-]'] = np.arange(nrMax) / nrMax

    # --- Extract downstream data
    ColsInfo, nDMax = diameterwiseColFastFarm(df.columns.values, nWT=nWT)
    dfDiam = fastlib.extract_spanwise_data(ColsInfo,
                                           nDMax,
                                           df=None,
                                           ts=dfAvg.iloc[0])
    #dfDiam      = fastlib.insert_radial_columns(dfDiam)
    if vD is None:
        dfDiam.insert(0, 'i_[#]', np.arange(nDMax) + 1)
    else:
        dfDiam.insert(0, 'x_[m]', vD[:nDMax])
    dfDiam['i/n_[-]'] = np.arange(nDMax) / nDMax
    return dfRad, dfRadialTime, dfDiam