|
| 1 | +import numpy as np |
| 2 | +from numpy import cos, sin |
| 3 | +import pandas as pd |
| 4 | +import os |
| 5 | +from pyFAST.input_output.hawc2_htc_file import HAWC2HTCFile |
| 6 | +from pyFAST.input_output.csv_file import CSVFile |
| 7 | +from pyFAST.input_output.fast_input_file import FASTInputFile, EDBladeFile,EDTowerFile |
| 8 | +from pyFAST.tools.pandalib import pd_interp1 |
| 9 | + |
| 10 | + |
| 11 | +def htcToElastoDyn(HTCFile, outDir='./', prefix='', suffix='', bladeBodyName='blade1', towerBodyName='tower', rBlade=None, hTower=None): |
| 12 | + """ |
| 13 | + Writes ElastoDyn inputs files from a HAWC2 htc file and the blade body name |
| 14 | +
|
| 15 | +
|
| 16 | + NOTE: This is only a preliminary implementation.. |
| 17 | + An attempt is maded for the blade and tower file |
| 18 | + A lot of conversion remains (and might be extremely hard to achieve generically): |
| 19 | + - Shape functions for tower and blade (could use cbeam from welib) |
| 20 | + - Damping for tower and blade |
| 21 | + - Shaft |
| 22 | + - RNA masses and inertia |
| 23 | + - Platform |
| 24 | +
|
| 25 | + - Wont work if bodies are defined using FPM |
| 26 | +
|
| 27 | + INPUTS: |
| 28 | + - HTCFile: path to a htc file |
| 29 | + - bladeBodyName: name of blade in htc file |
| 30 | + - towerBodyName: name of blade in htc file |
| 31 | +
|
| 32 | + - rBlade: array of radial positions for the blade (between 0 and 1) |
| 33 | +
|
| 34 | + """ |
| 35 | + htc = HAWC2HTCFile(HTCFile) |
| 36 | + dfs = htc.toDataFrame() |
| 37 | + |
| 38 | + |
| 39 | + # --- Blade |
| 40 | + H2BMeanLine = dfs[bladeBodyName+'_c2'] |
| 41 | + H2BStructure = dfs[bladeBodyName+'_st'] |
| 42 | + H2BMeanLine = H2BMeanLine[['x_[m]','y_[m]','z_[m]','twist_[deg]']] # Changing order |
| 43 | + if rBlade is None: |
| 44 | + rB_new = np.abs(H2BMeanLine['z_[m]'].values) # NOTE: this should be a curvilinear length, but ElastoDyn is straight, so... |
| 45 | + else: |
| 46 | + rB_new = rBlade* np.abs(H2BMeanLine['z_[m]'].values[-1]) |
| 47 | + H2BStructure = pd_interp1(rB_new, 'r_[m]', H2BStructure) |
| 48 | + |
| 49 | + # --- Tower |
| 50 | + H2TMeanLine = dfs[towerBodyName+'_c2'] |
| 51 | + H2TStructure = dfs[towerBodyName+'_st'] |
| 52 | + H2TMeanLine = H2TMeanLine[['x_[m]','y_[m]','z_[m]','twist_[deg]']] # Changing order |
| 53 | + if hTower is None: |
| 54 | + hT_new = np.abs(H2BMeanLine['z_[m]'].values) |
| 55 | + else: |
| 56 | + hT_new = hBlade* np.abs(H2TMeanLine['z_[m]'].values[-1]) |
| 57 | + H2TStructure = pd_interp1(hT_new, 'r_[m]', H2TStructure) |
| 58 | + |
| 59 | + # --- ElastoDyn Blade |
| 60 | + bld = EDBladeFile() |
| 61 | + M = np.zeros( (len(rB_new) ,6) ) |
| 62 | + M[:,0] = rB_new / rB_new[-1] # BlFract |
| 63 | + #M[:,1] = PitchAxis # PitchAxis |
| 64 | + M[:,2] = - H2BMeanLine['twist_[deg]'] # StrcTwst [deg] |
| 65 | + M[:,3] = H2BStructure['m_[kg/m]'] # BMassDen [kg/m] |
| 66 | + M[:,4] = H2BStructure['E_[N/m^2]'] * H2BStructure['I_x_[m^4]'] # FlpStff [Nm^2] TODO, with twist, make sure that's correct.. |
| 67 | + M[:,5] = H2BStructure['E_[N/m^2]'] * H2BStructure['I_y_[m^4]'] # EdgStff [Nm^2] |
| 68 | + bld['BldProp'] = M |
| 69 | + # TODO find mode shapes |
| 70 | + bldFileName = os.path.join(outDir, '{}ED_blade{}.dat'.format(prefix,suffix)) |
| 71 | + bld.write(bldFileName) |
| 72 | + print('Writing ElastoDyn blade file:', bldFileName) |
| 73 | + |
| 74 | + # --- ElastoDyn Tower |
| 75 | + twr = EDTowerFile() |
| 76 | + M = np.zeros( (len(hT_new), 4) ) |
| 77 | + M[:,0] = hT_new / hT_new[-1] # TwFract |
| 78 | + M[:,1] = H2TStructure['m_[kg/m]'] # TMassDen [kg/m] |
| 79 | + M[:,2] = H2BStructure['E_[N/m^2]'] * H2BStructure['I_x_[m^4]'] # TwFAStif [Nm^2] TODO TODO TODO VERIFY xy |
| 80 | + M[:,3] = H2BStructure['E_[N/m^2]'] * H2BStructure['I_y_[m^4]'] # TwSSStif [Nm^2] |
| 81 | + twr['TowProp'] = M |
| 82 | + # TODO find mode shapes |
| 83 | + twrFileName = os.path.join(outDir, '{}ED_tower{}.dat'.format(prefix,suffix)) |
| 84 | + twr.write(twrFileName) |
| 85 | + print('Writing ElastoDyn tower file:', twrFileName) |
0 commit comments