sensotwin.lifetime_extrapolation.simulation.lib.staticAnalysisAerodynamicsCentrifugalCCX

  1import os
  2import sys
  3import numpy as np
  4from . import readVTT
  5
  6def f_setupStaticAerodynamicsCentrifugalSimulations(template_name, wind_speed, working_dir = './'):
  7    '''
  8    Sets up a static CCX simulation with the influence
  9    of aerodynamic (only lift) and centrifugal forces.
 10
 11    Parameters:
 12    - template_name (string):
 13        Name of the template file in .inp format to adapt for
 14        the static simulation. The file specifies the geometry
 15        of the rotor blade. Element and Node sets have to be
 16        predefined. Boundary conditions, steps and outputs
 17        have to be predefined.
 18    - wind_speed (float):
 19        Average wind speed acting on the entire rotor disc in m/s.
 20    - working_dir (string):
 21        Working directory to execute file in.
 22
 23    Returns:
 24    - None
 25    '''
 26
 27    # set working directory
 28    current_dir = working_dir
 29    folder_name = "AerodynamicsCentrifugal" 
 30    main_dir = os.path.join(current_dir,"OUT")
 31    save_dir = os.path.join(main_dir, folder_name)
 32    if os.path.exists(save_dir) == False:
 33        os.mkdir(save_dir)
 34
 35    # import aerodynamic loads
 36    aero_normal_df = readVTT.f_readVTT2DF(os.path.join(current_dir, 'IN', 'aero_loads_N_transformed.vtt'))
 37    aero_normal = np.array(aero_normal_df.values.tolist())
 38
 39    # # import coordinates for application of aerodynamic loads
 40    # coord_normal_1_df = readVTT.f_readVTT2DF('./IN/coords_N_web_1.vtt')
 41    # coord_normal_1 = np.array(coord_normal_1_df.values.tolist())
 42
 43    # coord_normal_2_df = readVTT.f_readVTT2DF('./IN/coords_N_web_2.vtt')
 44    # coord_normal_2 = np.array(coord_normal_2_df.values.tolist())
 45
 46    # Import centrifugal loads
 47    loads_data_df = readVTT.f_readVTT2DF(os.path.join(current_dir, 'IN', 'gravity_loads_transformed.vtt'))
 48    is_current_az = loads_data_df.iloc[0] == 0
 49    is_current_az['WindSpeed'] = True
 50    is_current_az = is_current_az.values.tolist()
 51
 52    loads_data_0_df = loads_data_df.iloc[1:,is_current_az]
 53    loads_data = np.array(loads_data_0_df.values.tolist())
 54
 55    windspeed = loads_data[:,0]
 56    windspeed_float = [float(x) for x in windspeed]
 57
 58    angular_velocity = loads_data[:,4]
 59    coord_point_1 = loads_data[:,5:8]
 60    coord_point_2 = loads_data[:,8:11]
 61
 62    # Sets are already defined
 63                                                                                                                                                                                                        
 64    # create loads based on wind speed
 65
 66    # open input file to add loads
 67    with open(os.path.join(current_dir,'IN', template_name + '.inp')) as input_file:
 68        input_lines = input_file.readlines()
 69
 70    step_block_inp = []
 71
 72    # Define aerodynamic loads at each blade section
 73
 74    # find closest wind speed in gravity_loads_transformed.vtt
 75    vwind_diff = []
 76    for vwind in windspeed_float:
 77        vwind_diff.append(abs(wind_speed - vwind))
 78
 79    windspeed_idx = np.argmin(vwind_diff)
 80
 81    for i in range(len(aero_normal[:,0:])):
 82        # region_tangential = mdb.models['Airfoil Project'].rootAssembly.surfaces['Surface-' + str(aero_tangential[i,0]).replace(".","_")]
 83        # region_normal_1 = mdb.models['Airfoil Project'].rootAssembly.sets['BASE_PLANE-1.Set-N1-' + str(aero_normal[i,0]).replace(".","_")]
 84        # region_normal_2 = mdb.models['Airfoil Project'].rootAssembly.sets['BASE_PLANE-1.Set-N2-' + str(aero_normal[i,0]).replace(".","_")]
 85        
 86        # load_tangential = 'Load-T-' + str(aero_tangential[i,0]).replace(".","_") 
 87        load_normal_1 = 'Load-N1-' + str(aero_normal[i,0]).replace(".","_")
 88        load_normal_2 = 'Load-N2-' + str(aero_normal[i,0]).replace(".","_")
 89
 90        step_block_inp.append('** NAME: ' + load_normal_1 + '   Type: Concentrated force' + '\n')
 91        step_block_inp.append('*CLOAD' + '\n')
 92        step_block_inp.append('Set-N1-' + str(aero_normal[i,0]).replace(".","_") + ', 2, ' + str(0.5*aero_normal[i,windspeed_idx+1]) + '\n')
 93
 94        step_block_inp.append('** NAME: ' + load_normal_2 + '   Type: Concentrated force' + '\n')
 95        step_block_inp.append('*CLOAD' + '\n')
 96        step_block_inp.append('Set-N2-' + str(aero_normal[i,0]).replace(".","_") + ', 2, ' + str(0.5*aero_normal[i,windspeed_idx+1]) + '\n')
 97
 98        # mdb.models['Airfoil Project'].SurfaceTraction(name=load_tangential, createStepName=myStep, region=region_tangential, magnitude=surface_scaling_factor[i]*aero_tangential[i,j+1], directionVector=((0.0, 0.0, 0.0), (1.0, 0.0, 0.0)), distributionType=UNIFORM, field='', localCsys=None)
 99        # mdb.models['Airfoil Project'].ConcentratedForce(name=load_normal_1,createStepName=myStep, region=region_normal_1, cf2=0.5*aero_normal[i,j+1],distributionType=UNIFORM, field='', localCsys=None)    
100        # mdb.models['Airfoil Project'].ConcentratedForce(name=load_normal_2,createStepName=myStep, region=region_normal_2, cf2=0.5*aero_normal[i,j+1],distributionType=UNIFORM, field='', localCsys=None)
101
102    # Define centrifugal loads
103    load_centrifugal = 'Load-Centrifugal'
104    step_block_inp.append('** NAME: ' + load_centrifugal + '   Type: Rotational body force' + '\n')
105    step_block_inp.append('*DLOAD' + '\n')
106
107    # length of centrifugal vector
108    norm_centrif = np.sqrt(np.power(coord_point_2[windspeed_idx,0]-coord_point_1[windspeed_idx,0],2)
109                        + np.power(coord_point_2[windspeed_idx,1]-coord_point_1[windspeed_idx,1],2)
110                        + np.power(coord_point_2[windspeed_idx,2]-coord_point_1[windspeed_idx,2],2))
111
112    step_block_inp.append('Set-Centrifugal, CENTRIF, ' 
113                        + str(np.power(angular_velocity[windspeed_idx],2)) + ', '
114                        + str(coord_point_1[windspeed_idx,0]) + ', ' 
115                        + str(coord_point_1[windspeed_idx,1]) + ', ' 
116                        + str(coord_point_1[windspeed_idx,2]) + ', ' 
117                        + str((1/norm_centrif)*(coord_point_2[windspeed_idx,0]-coord_point_1[windspeed_idx,0])) + ', ' 
118                        + str((1/norm_centrif)*(coord_point_2[windspeed_idx,1]-coord_point_1[windspeed_idx,1])) + ', ' 
119                        + str((1/norm_centrif)*(coord_point_2[windspeed_idx,2]-coord_point_1[windspeed_idx,2])) + '\n')
120
121    # Create new input file
122
123    new_input_lines = []
124    for line in input_lines:
125        current_line = line
126        if line.find('<enter wind speed dependent loads here>') != -1:
127            current_line = ''.join(step_block_inp)
128        new_input_lines.append(current_line)
129
130    # write new input file
131    with open(os.path.join(save_dir, template_name.strip('_TEMPLATE') + '_' + str(windspeed_float[windspeed_idx]).replace('.','_') + '.inp'), 'w') as output_file:
132        for line in new_input_lines:
133            output_file.write(line)
134
135def main():
136    template_name = 'STARTER_SNL61p5_13LY_S8R_29052024_TEMPLATE' # without .inp
137    wind_speed = 10
138    f_setupStaticAerodynamicsCentrifugalSimulations(template_name, wind_speed)
139
140if __name__ == '__main__':
141    main()
def f_setupStaticAerodynamicsCentrifugalSimulations(template_name, wind_speed, working_dir='./'):
  7def f_setupStaticAerodynamicsCentrifugalSimulations(template_name, wind_speed, working_dir = './'):
  8    '''
  9    Sets up a static CCX simulation with the influence
 10    of aerodynamic (only lift) and centrifugal forces.
 11
 12    Parameters:
 13    - template_name (string):
 14        Name of the template file in .inp format to adapt for
 15        the static simulation. The file specifies the geometry
 16        of the rotor blade. Element and Node sets have to be
 17        predefined. Boundary conditions, steps and outputs
 18        have to be predefined.
 19    - wind_speed (float):
 20        Average wind speed acting on the entire rotor disc in m/s.
 21    - working_dir (string):
 22        Working directory to execute file in.
 23
 24    Returns:
 25    - None
 26    '''
 27
 28    # set working directory
 29    current_dir = working_dir
 30    folder_name = "AerodynamicsCentrifugal" 
 31    main_dir = os.path.join(current_dir,"OUT")
 32    save_dir = os.path.join(main_dir, folder_name)
 33    if os.path.exists(save_dir) == False:
 34        os.mkdir(save_dir)
 35
 36    # import aerodynamic loads
 37    aero_normal_df = readVTT.f_readVTT2DF(os.path.join(current_dir, 'IN', 'aero_loads_N_transformed.vtt'))
 38    aero_normal = np.array(aero_normal_df.values.tolist())
 39
 40    # # import coordinates for application of aerodynamic loads
 41    # coord_normal_1_df = readVTT.f_readVTT2DF('./IN/coords_N_web_1.vtt')
 42    # coord_normal_1 = np.array(coord_normal_1_df.values.tolist())
 43
 44    # coord_normal_2_df = readVTT.f_readVTT2DF('./IN/coords_N_web_2.vtt')
 45    # coord_normal_2 = np.array(coord_normal_2_df.values.tolist())
 46
 47    # Import centrifugal loads
 48    loads_data_df = readVTT.f_readVTT2DF(os.path.join(current_dir, 'IN', 'gravity_loads_transformed.vtt'))
 49    is_current_az = loads_data_df.iloc[0] == 0
 50    is_current_az['WindSpeed'] = True
 51    is_current_az = is_current_az.values.tolist()
 52
 53    loads_data_0_df = loads_data_df.iloc[1:,is_current_az]
 54    loads_data = np.array(loads_data_0_df.values.tolist())
 55
 56    windspeed = loads_data[:,0]
 57    windspeed_float = [float(x) for x in windspeed]
 58
 59    angular_velocity = loads_data[:,4]
 60    coord_point_1 = loads_data[:,5:8]
 61    coord_point_2 = loads_data[:,8:11]
 62
 63    # Sets are already defined
 64                                                                                                                                                                                                        
 65    # create loads based on wind speed
 66
 67    # open input file to add loads
 68    with open(os.path.join(current_dir,'IN', template_name + '.inp')) as input_file:
 69        input_lines = input_file.readlines()
 70
 71    step_block_inp = []
 72
 73    # Define aerodynamic loads at each blade section
 74
 75    # find closest wind speed in gravity_loads_transformed.vtt
 76    vwind_diff = []
 77    for vwind in windspeed_float:
 78        vwind_diff.append(abs(wind_speed - vwind))
 79
 80    windspeed_idx = np.argmin(vwind_diff)
 81
 82    for i in range(len(aero_normal[:,0:])):
 83        # region_tangential = mdb.models['Airfoil Project'].rootAssembly.surfaces['Surface-' + str(aero_tangential[i,0]).replace(".","_")]
 84        # region_normal_1 = mdb.models['Airfoil Project'].rootAssembly.sets['BASE_PLANE-1.Set-N1-' + str(aero_normal[i,0]).replace(".","_")]
 85        # region_normal_2 = mdb.models['Airfoil Project'].rootAssembly.sets['BASE_PLANE-1.Set-N2-' + str(aero_normal[i,0]).replace(".","_")]
 86        
 87        # load_tangential = 'Load-T-' + str(aero_tangential[i,0]).replace(".","_") 
 88        load_normal_1 = 'Load-N1-' + str(aero_normal[i,0]).replace(".","_")
 89        load_normal_2 = 'Load-N2-' + str(aero_normal[i,0]).replace(".","_")
 90
 91        step_block_inp.append('** NAME: ' + load_normal_1 + '   Type: Concentrated force' + '\n')
 92        step_block_inp.append('*CLOAD' + '\n')
 93        step_block_inp.append('Set-N1-' + str(aero_normal[i,0]).replace(".","_") + ', 2, ' + str(0.5*aero_normal[i,windspeed_idx+1]) + '\n')
 94
 95        step_block_inp.append('** NAME: ' + load_normal_2 + '   Type: Concentrated force' + '\n')
 96        step_block_inp.append('*CLOAD' + '\n')
 97        step_block_inp.append('Set-N2-' + str(aero_normal[i,0]).replace(".","_") + ', 2, ' + str(0.5*aero_normal[i,windspeed_idx+1]) + '\n')
 98
 99        # mdb.models['Airfoil Project'].SurfaceTraction(name=load_tangential, createStepName=myStep, region=region_tangential, magnitude=surface_scaling_factor[i]*aero_tangential[i,j+1], directionVector=((0.0, 0.0, 0.0), (1.0, 0.0, 0.0)), distributionType=UNIFORM, field='', localCsys=None)
100        # mdb.models['Airfoil Project'].ConcentratedForce(name=load_normal_1,createStepName=myStep, region=region_normal_1, cf2=0.5*aero_normal[i,j+1],distributionType=UNIFORM, field='', localCsys=None)    
101        # mdb.models['Airfoil Project'].ConcentratedForce(name=load_normal_2,createStepName=myStep, region=region_normal_2, cf2=0.5*aero_normal[i,j+1],distributionType=UNIFORM, field='', localCsys=None)
102
103    # Define centrifugal loads
104    load_centrifugal = 'Load-Centrifugal'
105    step_block_inp.append('** NAME: ' + load_centrifugal + '   Type: Rotational body force' + '\n')
106    step_block_inp.append('*DLOAD' + '\n')
107
108    # length of centrifugal vector
109    norm_centrif = np.sqrt(np.power(coord_point_2[windspeed_idx,0]-coord_point_1[windspeed_idx,0],2)
110                        + np.power(coord_point_2[windspeed_idx,1]-coord_point_1[windspeed_idx,1],2)
111                        + np.power(coord_point_2[windspeed_idx,2]-coord_point_1[windspeed_idx,2],2))
112
113    step_block_inp.append('Set-Centrifugal, CENTRIF, ' 
114                        + str(np.power(angular_velocity[windspeed_idx],2)) + ', '
115                        + str(coord_point_1[windspeed_idx,0]) + ', ' 
116                        + str(coord_point_1[windspeed_idx,1]) + ', ' 
117                        + str(coord_point_1[windspeed_idx,2]) + ', ' 
118                        + str((1/norm_centrif)*(coord_point_2[windspeed_idx,0]-coord_point_1[windspeed_idx,0])) + ', ' 
119                        + str((1/norm_centrif)*(coord_point_2[windspeed_idx,1]-coord_point_1[windspeed_idx,1])) + ', ' 
120                        + str((1/norm_centrif)*(coord_point_2[windspeed_idx,2]-coord_point_1[windspeed_idx,2])) + '\n')
121
122    # Create new input file
123
124    new_input_lines = []
125    for line in input_lines:
126        current_line = line
127        if line.find('<enter wind speed dependent loads here>') != -1:
128            current_line = ''.join(step_block_inp)
129        new_input_lines.append(current_line)
130
131    # write new input file
132    with open(os.path.join(save_dir, template_name.strip('_TEMPLATE') + '_' + str(windspeed_float[windspeed_idx]).replace('.','_') + '.inp'), 'w') as output_file:
133        for line in new_input_lines:
134            output_file.write(line)

Sets up a static CCX simulation with the influence of aerodynamic (only lift) and centrifugal forces.

Parameters:

  • template_name (string): Name of the template file in .inp format to adapt for the static simulation. The file specifies the geometry of the rotor blade. Element and Node sets have to be predefined. Boundary conditions, steps and outputs have to be predefined.
  • wind_speed (float): Average wind speed acting on the entire rotor disc in m/s.
  • working_dir (string): Working directory to execute file in.

Returns:

  • None
def main():
136def main():
137    template_name = 'STARTER_SNL61p5_13LY_S8R_29052024_TEMPLATE' # without .inp
138    wind_speed = 10
139    f_setupStaticAerodynamicsCentrifugalSimulations(template_name, wind_speed)