def initialise(self, data, custom_settings=None, caller=None): self.data = data if custom_settings is None: self.settings = data.settings[self.solver_id] else: self.settings = custom_settings settings.to_custom_types(self.settings, self.settings_types, self.settings_default, self.settings_options) self.dir = self.data.case_route + 'output/' + self.data.case_name + '/' + 'GenerateFlowField/' if not os.path.isdir(self.dir): os.makedirs(self.dir) # init velocity generator velocity_generator_type = gen_interface.generator_from_string( self.settings['velocity_field_generator']) self.velocity_generator = velocity_generator_type() self.velocity_generator.initialise( self.settings['velocity_field_input']) # init postproc grid generator postproc_grid_generator_type = gen_interface.generator_from_string( self.settings['postproc_grid_generator']) self.postproc_grid_generator = postproc_grid_generator_type() self.postproc_grid_generator.initialise( self.settings['postproc_grid_input']) self.caller = caller
def initialise(self, data, custom_settings=None): self.data = data if custom_settings is None: self.settings = data.settings[self.solver_id] else: self.settings = custom_settings settings.to_custom_types(self.settings, self.settings_types, self.settings_default) # update beam orientation # beam orientation is used as the parametrisation of the aero orientation # too (it will come handy for the fully coupled simulation) # euler = np.array([self.settings['roll'].value, # self.settings['alpha'].value, # self.settings['beta'].value]) # euler_rot = algebra.euler2rot(euler) # this is Cag # quat = algebra.mat2quat(euler_rot.T) # self.data.structure.update_orientation(quat, self.data.ts) # self.data.aero.update_orientation(quat, self.data.ts) self.update_step() # init velocity generator velocity_generator_type = gen_interface.generator_from_string( self.settings['velocity_field_generator']) self.velocity_generator = velocity_generator_type() self.velocity_generator.initialise( self.settings['velocity_field_input'])
def initialise(self, data): self.data = data self.settings = data.settings[self.solver_id] settings.to_custom_types(self.settings, self.settings_types, self.settings_default) self.dt = self.settings['dt'].value self.solver = solver_interface.initialise_solver( self.settings['trajectory_solver']) self.settings['trajectory_solver_settings']['n_time_steps'] = 1 self.solver.initialise(self.data, self.settings['trajectory_solver_settings']) self.n_controlled_points = len(self.settings['nodes_trajectory']) # initialized controllers for the trayectory nodes # there will be 3 controllers per node (one per dimension) for i_trajec in range(self.n_controlled_points): self.controllers.append(list()) for i_dim in range(3): self.controllers[i_trajec].append( PID(self.settings['PID_P_gain'].value, self.settings['PID_I_gain'].value, self.settings['PID_D_gain'].value, self.dt)) self.trajectory = np.zeros((self.settings['n_time_steps'].value, len(self.settings['nodes_trajectory']), 3)) self.input_trajectory = np.zeros( (self.settings['n_time_steps'].value, len(self.settings['nodes_trajectory']), 3)) self.force_history = np.zeros( (self.settings['n_time_steps'].value, len(self.settings['nodes_trajectory']), 3)) # initialise trayectory generator trajectory_generator_type = gen_interface.generator_from_string( self.settings['trajectory_generator']) self.trajectory_generator = trajectory_generator_type() self.trajectory_generator.initialise( self.settings['trajectory_generator_input']) self.trajectory_steps = self.trajectory_generator.get_n_steps() # generate coordinates offset in order to be able to use only one # generator self.ini_coord_a = self.data.structure.ini_info.glob_pos( include_rbm=False) self.print_info = self.settings['print_info'] if self.print_info: self.residual_table = cout.TablePrinter(4, 14, ['g', 'f', 'f', 'e']) self.residual_table.field_length[0] = 6 self.residual_table.field_length[1] = 6 self.residual_table.field_length[1] = 6 self.residual_table.print_header( ['ts', 't', 'traj. offset', 'norm(force)'])
def initialise(self, data, custom_settings=None): self.data = data if custom_settings is None: self.settings = data.settings[self.solver_id] else: self.settings = custom_settings settings.to_custom_types(self.settings, self.settings_types, self.settings_default) self.update_step() # init velocity generator velocity_generator_type = gen_interface.generator_from_string( self.settings['velocity_field_generator']) self.velocity_generator = velocity_generator_type() self.velocity_generator.initialise(self.settings['velocity_field_input'])
def initialise(self, data): self.data = data self.settings = data.settings[self.solver_id] # init settings settings_utils.to_custom_types(self.settings, self.settings_types, self.settings_default) # read input file (aero) self.read_files() wake_shape_generator_type = gen_interface.generator_from_string( self.settings['wake_shape_generator']) self.wake_shape_generator = wake_shape_generator_type() self.wake_shape_generator.initialise( data, self.settings['wake_shape_generator_input'])
def initialise(self, data, custom_settings=None): self.data = data if custom_settings is None: self.settings = data.settings[self.solver_id] else: self.settings = custom_settings settings.to_custom_types(self.settings, self.settings_types, self.settings_default) self.data.structure.add_unsteady_information( self.data.structure.dyn_dict, self.settings['n_time_steps'].value) # init velocity generator velocity_generator_type = gen_interface.generator_from_string( self.settings['velocity_field_generator']) self.velocity_generator = velocity_generator_type() self.velocity_generator.initialise( self.settings['velocity_field_input'])
def initialise(self, data, custom_settings=None): self.data = data if custom_settings is None: self.settings = data.settings[self.solver_id] else: self.settings = custom_settings settings.to_custom_types(self.settings, self.settings_types, self.settings_default) # self.data.structure.add_unsteady_information(self.data.structure.dyn_dict, self.settings['n_time_steps'].value) # init velocity generator velocity_generator_type = gen_interface.generator_from_string( self.settings['velocity_field_generator']) self.velocity_generator = velocity_generator_type() self.velocity_generator.initialise(self.settings['velocity_field_input']) # Checks if not self.settings['convection_scheme'].value == 2: sys.exit("ERROR: convection_scheme: %u. Only 2 supported" % self.settings['convection_scheme'].value)
def initialise(self, data, custom_settings=None): """ To be called just once per simulation. """ self.data = data if custom_settings is None: self.settings = data.settings[self.solver_id] else: self.settings = custom_settings settings.to_custom_types(self.settings, self.settings_types, self.settings_default, self.settings_options) self.data.structure.add_unsteady_information( self.data.structure.dyn_dict, self.settings['n_time_steps'].value) # Filtering if self.settings['gamma_dot_filtering'].value == 1: cout.cout_wrap( "gamma_dot_filtering cannot be one. Changing it to None", 2) self.settings['gamma_dot_filtering'] = None if self.settings['gamma_dot_filtering'] is not None: if self.settings['gamma_dot_filtering'].value: if not self.settings['gamma_dot_filtering'].value % 2: cout.cout_wrap( "gamma_dot_filtering does not support even numbers." + "Changing " + str(self.settings['gamma_dot_filtering'].value) + " to " + str(self.settings['gamma_dot_filtering'].value + 1), 2) self.settings['gamma_dot_filtering'] = ( ct.c_int(self.settings['gamma_dot_filtering'].value + 1)) # init velocity generator velocity_generator_type = gen_interface.generator_from_string( self.settings['velocity_field_generator']) self.velocity_generator = velocity_generator_type() self.velocity_generator.initialise( self.settings['velocity_field_input'])
def generate(self, aero_dict, beam, aero_settings, ts): self.aero_dict = aero_dict self.beam = beam self.aero_settings = aero_settings # number of total nodes (structural + aero&struc) self.n_node = len(aero_dict['aero_node']) # number of elements self.n_elem = len(aero_dict['surface_distribution']) # surface distribution self.surface_distribution = aero_dict['surface_distribution'] # number of surfaces temp = set(aero_dict['surface_distribution']) self.n_surf = sum(1 for i in temp if i >= 0) # number of chordwise panels self.surface_m = aero_dict['surface_m'] # number of aero nodes self.n_aero_node = sum(aero_dict['aero_node']) # get N per surface self.calculate_dimensions() # write grid info to screen self.output_info() # allocating initial grid storage self.ini_info = AeroTimeStepInfo(self.aero_dimensions, self.aero_dimensions_star) # load airfoils db # for i_node in range(self.n_node): for i_elem in range(self.n_elem): for i_local_node in range(self.beam.num_node_elem): try: self.airfoil_db[self.aero_dict['airfoil_distribution'][ i_elem, i_local_node]] except KeyError: airfoil_coords = self.aero_dict['airfoils'][str( self.aero_dict['airfoil_distribution'][i_elem, i_local_node])] self.airfoil_db[self.aero_dict['airfoil_distribution'][ i_elem, i_local_node]] = (scipy.interpolate.interp1d( airfoil_coords[:, 0], airfoil_coords[:, 1], kind='quadratic', copy=False, fill_value='extrapolate', assume_sorted=True)) try: self.n_control_surfaces = np.sum( np.unique(self.aero_dict['control_surface']) >= 0) except KeyError: pass # Backward compatibility: check whether control surface deflection settings have been specified. If not, create # section with empty list, such that no cs generator is appended try: aero_settings['control_surface_deflection'] except KeyError: aero_settings.update( {'control_surface_deflection': [''] * self.n_control_surfaces}) # pad ctrl surfaces dict with empty strings if not defined if len(aero_settings['control_surface_deflection'] ) != self.n_control_surfaces: undef_ctrl_sfcs = [''] * (self.n_control_surfaces - len( aero_settings['control_surface_deflection'])) aero_settings['control_surface_deflection'].extend(undef_ctrl_sfcs) # initialise generators for i_cs in range(self.n_control_surfaces): if aero_settings['control_surface_deflection'][i_cs] == '': self.cs_generators.append(None) else: generator_type = gen_interface.generator_from_string( aero_settings['control_surface_deflection'][i_cs]) self.cs_generators.append(generator_type()) self.cs_generators[i_cs].initialise(aero_settings[ 'control_surface_deflection_generator_settings'][i_cs]) self.add_timestep() self.generate_mapping() self.generate_zeta(self.beam, self.aero_settings, ts) if 'polars' in aero_dict: import sharpy.aero.utils.airfoilpolars as ap self.polars = [] nairfoils = np.amax(self.aero_dict['airfoil_distribution']) + 1 for iairfoil in range(nairfoils): new_polar = ap.polar() new_polar.initialise(aero_dict['polars'][str(iairfoil)]) self.polars.append(new_polar)
def initialise(self, data, custom_settings=None): r""" Initialises the Linear UVLM aerodynamic solver and the chosen velocity generator. Settings are parsed into the standard SHARPy settings format for solvers. It then checks whether there is any previous information about the linearised system (in order for a solution to be restarted without overwriting the linearisation). If a linearised system does not exist, a linear UVLM system is created linearising about the current time step. The reference values for the input and output are transformed into column vectors :math:`\mathbf{u}` and :math:`\mathbf{y}`, respectively. The information pertaining to the linear system is stored in a dictionary ``self.data.aero.linear`` within the main ``data`` variable. Args: data (PreSharpy): class containing the problem information custom_settings (dict): custom settings dictionary """ self.data = data if custom_settings is None: self.settings = data.settings[self.solver_id] else: self.settings = custom_settings settings.to_custom_types(self.settings, self.settings_types, self.settings_default, no_ctype=True) settings.to_custom_types(self.settings['ScalingDict'], self.scaling_settings_types, self.scaling_settings_default, no_ctype=True) # Check whether linear UVLM has been initialised try: self.data.aero.linear except AttributeError: self.data.aero.linear = dict() aero_tstep = self.data.aero.timestep_info[-1] ### Record body orientation/velocities at time 0 # This option allows to rotate the linearised UVLM with the A frame # or a specific body (multi-body solution) if self.settings['track_body']: self.num_body_track = self.settings['track_body_number'] # track A frame if self.num_body_track == -1: self.quat0 = self.data.structure.timestep_info[ -1].quat.copy() self.for_vel0 = self.data.structure.timestep_info[ -1].for_vel.copy() else: # track a specific body self.quat0 = \ self.data.structure.timestep_info[-1].mb_quat[self.num_body_track,:].copy() self.for_vel0 = \ self.data.structure.timestep_info[-1].mb_FoR_vel[self.num_body_track ,:].copy() # convert to G frame self.Cga0 = algebra.quat2rotation(self.quat0) self.Cga = self.Cga0.copy() self.for_vel0[:3] = self.Cga0.dot(self.for_vel0[:3]) self.for_vel0[3:] = self.Cga0.dot(self.for_vel0[3:]) else: # check/record initial rotation speed self.num_body_track = None self.quat0 = None self.Cag0 = None self.Cga = None self.for_vel0 = np.zeros((6, )) # TODO: verify of a better way to implement rho aero_tstep.rho = self.settings['density'] # Generate instance of linuvlm.Dynamic() lin_uvlm_system = linuvlm.DynamicBlock( aero_tstep, dynamic_settings=self.settings, # dt=self.settings['dt'].value, # integr_order=self.settings['integr_order'].value, # ScalingDict=self.settings['ScalingDict'], # RemovePredictor=self.settings['remove_predictor'].value, # UseSparse=self.settings['use_sparse'].value, for_vel=self.for_vel0) # add rotational speed for ii in range(lin_uvlm_system.MS.n_surf): lin_uvlm_system.MS.Surfs[ii].omega = self.for_vel0[3:] # Save reference values # System Inputs u_0 = self.pack_input_vector() # Linearised state dt = self.settings['dt'] x_0 = self.pack_state_vector(aero_tstep, None, dt, self.settings['integr_order']) # Reference forces f_0 = np.concatenate([ aero_tstep.forces[ss][0:3].reshape(-1, order='C') for ss in range(aero_tstep.n_surf) ]) # Assemble the state space system lin_uvlm_system.assemble_ss() self.data.aero.linear['System'] = lin_uvlm_system self.data.aero.linear['SS'] = lin_uvlm_system.SS self.data.aero.linear['x_0'] = x_0 self.data.aero.linear['u_0'] = u_0 self.data.aero.linear['y_0'] = f_0 # self.data.aero.linear['gamma_0'] = gamma # self.data.aero.linear['gamma_star_0'] = gamma_star # self.data.aero.linear['gamma_dot_0'] = gamma_dot # TODO: Implement in AeroTimeStepInfo a way to store the state vectors # aero_tstep.linear.x = x_0 # aero_tstep.linear.u = u_0 # aero_tstep.linear.y = f_0 # Initialise velocity generator velocity_generator_type = gen_interface.generator_from_string( self.settings['velocity_field_generator']) self.velocity_generator = velocity_generator_type() self.velocity_generator.initialise( self.settings['velocity_field_input'])
def initialise(self, data, custom_settings=None): """ Controls the initialisation process of the solver, including processing the settings and initialising the aero and structural solvers, postprocessors and controllers. """ self.data = data if custom_settings is None: self.settings = data.settings[self.solver_id] else: self.settings = custom_settings settings.to_custom_types(self.settings, self.settings_types, self.settings_default, options=self.settings_options) self.original_settings = copy.deepcopy(self.settings) self.dt = self.settings['dt'] self.substep_dt = (self.dt.value / (self.settings['structural_substeps'].value + 1)) self.initial_n_substeps = self.settings['structural_substeps'].value self.print_info = self.settings['print_info'] if self.settings['cleanup_previous_solution']: # if there's data in timestep_info[>0], copy the last one to # timestep_info[0] and remove the rest self.cleanup_timestep_info() self.structural_solver = solver_interface.initialise_solver( self.settings['structural_solver']) self.structural_solver.initialise( self.data, self.settings['structural_solver_settings']) self.aero_solver = solver_interface.initialise_solver( self.settings['aero_solver']) self.aero_solver.initialise(self.structural_solver.data, self.settings['aero_solver_settings']) self.data = self.aero_solver.data # initialise postprocessors self.postprocessors = dict() if self.settings['postprocessors']: self.with_postprocessors = True for postproc in self.settings['postprocessors']: self.postprocessors[postproc] = solver_interface.initialise_solver( postproc) self.postprocessors[postproc].initialise( self.data, self.settings['postprocessors_settings'][postproc], caller=self) # initialise controllers self.controllers = dict() self.with_controllers = False if self.settings['controller_id']: self.with_controllers = True for controller_id, controller_type in self.settings[ 'controller_id'].items(): self.controllers[controller_id] = ( controller_interface.initialise_controller(controller_type)) self.controllers[controller_id].initialise( self.settings['controller_settings'][controller_id], controller_id) # print information header if self.print_info: self.residual_table = cout.TablePrinter( 8, 12, ['g', 'f', 'g', 'f', 'f', 'f', 'e', 'e']) self.residual_table.field_length[0] = 5 self.residual_table.field_length[1] = 6 self.residual_table.field_length[2] = 4 self.residual_table.print_header([ 'ts', 't', 'iter', 'struc ratio', 'iter time', 'residual vel', 'FoR_vel(x)', 'FoR_vel(z)' ]) # Define the function to correct aerodynamic forces if self.settings['correct_forces_method'] is not '': self.correct_forces = True self.correct_forces_function = cf.dict_of_corrections[ self.settings['correct_forces_method']] # check for empty dictionary if self.settings['network_settings']: self.network_loader = network_interface.NetworkLoader() self.network_loader.initialise( in_settings=self.settings['network_settings']) # initialise runtime generators self.runtime_generators = dict() if self.settings['runtime_generators']: self.with_runtime_generators = True for id, param in self.settings['runtime_generators'].items(): gen = gen_interface.generator_from_string(id) self.runtime_generators[id] = gen() self.runtime_generators[id].initialise(param, data=self.data)