class RotorStructureBase(Component): """ Base class for models that can predict blade deflections based on load distribution """ blade_disps = VarTree(BeamDisplacementsVT(), iotype='out', desc='Blade deflections and rotations')
class AeroElasticSolverBase(Component): """ base class for aeroelastic solvers that computes both steady state aerodynamic loads and structural deflections in a monolithic analysis for a single case """ wt = VarTree(AeroelasticHAWTVT(), iotype='in', desc='Turbine definition') inflow = VarTree(TurbineEnvironmentVT(), iotype='in', desc='Inflow conditions') oper = VarTree(RotorOperationalData(), iotype='out', desc='Operational data') rotor_loads = VarTree(RotorLoadsVT(), iotype='out', desc='Rotor torque, power, and thrust') blade_loads = VarTree(DistributedLoadsVT(), iotype='out', desc='Spanwise load distributions') blade_disps = VarTree(BeamDisplacementsVT(), iotype='out', desc='Blade deflections and rotations')
class AEsolver(Component): wt = VarTree(AeroelasticHAWTVT(), iotype='in', desc='Turbine definition') inflow = VarTree(TurbineEnvironmentVT(), iotype='in', desc='Inflow conditions') oper = VarTree(RotorOperationalData(), iotype='out', desc='Operational data') rotor_loads = VarTree(RotorLoadsVT(), iotype='out', desc='Rotor torque, power, and thrust') blade_loads = VarTree(DistributedLoadsExtVT(), iotype='out', desc='Spanwise load distributions') blade_disps = VarTree(BeamDisplacementsVT(), iotype='out', desc='Blade deflections and rotations') def execute(self): print '' print 'running aeroelastic analysis ...'
def execute(self): super(HAWC2SOutputIDO, self).execute() # hack to get around bug in OpenMDAO that causes # the outputs to refer to the same object self.blade_loads = copy.deepcopy(self.blade_loads) self.blade_disps = copy.deepcopy(self.blade_disps) self.rotor_loads = copy.deepcopy(self.rotor_loads) self.oper = copy.deepcopy(self.oper) data = self.operational_data self.oper.wsp = data[:, 0] self.oper.pitch = data[:, 1] self.oper.rpm = data[:, 2] data = self.rotor_loads_data if data.shape[0] == 0: return self.rotor_loads.wsp = data[:, 0] # keeping this for now so I don't break any code relying on this output self.rotor_loads.rpm = data[:, 9] self.rotor_loads.pitch = data[:, 8] self.rotor_loads.P = data[:, 1] * 1000. self.rotor_loads.Q = data[:, 1] * 1000. / data[:, 9] * 2. * np.pi / 60. self.rotor_loads.T = data[:, 2] * 1000. self.rotor_loads.CP = data[:, 3] self.rotor_loads.CT = data[:, 4] self.hub_loads.Mx = data[:, 6] * 1000. self.hub_loads.My = data[:, 7] * 1000. self.hub_loads.Mz = data[:, 5] self.blade_disps.tip_pos = np.zeros((self.rotor_loads.wsp.shape[0], 3)) self.blade_disps.tip_rot = np.zeros(self.rotor_loads.wsp.shape[0]) self.blade_loads.loads_array = [] self.blade_disps.disps_array = [] Fx_array = [] Fy_array = [] for i, wsp in enumerate(self.rotor_loads.wsp): data = self.blade_loads_data[i] if len(data.shape) == 1: data = data.reshape(1, data.shape[0]) loads = DistributedLoadsExtVT() disps = BeamDisplacementsVT() loads.s = data[:, 0] # / self.blade_length loads.aoa = data[:, 4] * 180. / np.pi loads.Ft = data[:, 6] loads.Fn = data[:, 7] loads.cl = data[:, 16] loads.cd = data[:, 17] loads.cm = data[:, 18] loads.ct = data[:, 32] loads.cp = data[:, 33] loads.v_a = data[:, 26] loads.v_t = data[:, 27] Fx_array.append(np.trapz(data[:, 6], x=data[:, 0])) Fy_array.append(np.trapz(data[:, 7], x=data[:, 0])) disps.main_axis = data[:, 13:16] disps.main_axis[:, 2] *= -1. disps.x = disps.main_axis[:, 0] disps.y = disps.main_axis[:, 1] disps.z = disps.main_axis[:, 2] disps.rot_z = data[:, 28] * 180. / np.pi self.blade_loads.loads_array.append(loads) self.blade_disps.disps_array.append(disps) self.blade_disps.tip_pos[i, :] = disps.main_axis[-1, :] self.blade_disps.tip_rot[i] = np.interp(0.98, loads.s, data[:, 28] * 180. / np.pi) self.hub_loads.Fx = np.asarray(Fx_array) self.hub_loads.Fy = np.asarray(Fy_array)