def execute(self): ctrl = self.control n = self.npts R = self.R # # attempt to distribute points mostly before rated # cpguess = 0.5 # Vr0 = (ctrl.ratedPower/(cpguess*0.5*rho*pi*R**2))**(1.0/3) # Vr0 *= 1.20 # V1 = np.linspace(Vin, Vr0, 15) # V2 = np.linspace(Vr0, Vout, 6) # V = np.concatenate([V1, V2[1:]]) # velocity sweep V = np.linspace(ctrl.Vin, ctrl.Vout, n) # corresponding rotation speed Omega_d = ctrl.tsr*V/R*RS2RPM Omega, dOmega_dOmegad, dOmega_dmaxOmega = smooth_min(Omega_d, ctrl.maxOmega, pct_offset=0.01) # store values self.Uhub = V self.Omega = Omega self.pitch = ctrl.pitch*np.ones_like(V) # gradients dV = np.zeros((n, 3)) dOmega_dtsr = dOmega_dOmegad * V/R*RS2RPM dOmega_dR = dOmega_dOmegad * -ctrl.tsr*V/R**2*RS2RPM dOmega = hstack([dOmega_dtsr, dOmega_dR, dOmega_dmaxOmega]) dpitch = np.zeros((n, 3)) self.J = vstack([dV, dOmega, dpitch])
def solve_nonlinear(self, params, unknowns, resids): n = params['npts'] R = params['R'] # # attempt to distribute points mostly before rated # cpguess = 0.5 # Vr0 = (ctrl.ratedPower/(cpguess*0.5*rho*pi*R**2))**(1.0/3) # Vr0 *= 1.20 # V1 = np.linspace(Vin, Vr0, 15) # V2 = np.linspace(Vr0, Vout, 6) # V = np.concatenate([V1, V2[1:]]) # velocity sweep V = np.linspace(params['control:Vin'], params['control:Vout'], n) # corresponding rotation speed Omega_d = params['control:tsr'] * V / R * RS2RPM Omega, dOmega_dOmegad, dOmega_dmaxOmega = smooth_min( Omega_d, params['control:maxOmega'], pct_offset=0.01) # store values unknowns['Uhub'] = V unknowns['Omega'] = Omega unknowns['pitch'] = params['control:pitch'] * np.ones_like(V) # gradients J = {} J['Omega', 'control:tsr'] = dOmega_dOmegad * V / R * RS2RPM J['Omega', 'R'] = dOmega_dOmegad * -params['control:tsr'] * V / R**2 * RS2RPM J['Omega', 'control:maxOmega'] = dOmega_dmaxOmega self.J = J
def CSMDrivetrain(aeroPower, ratedPower, drivetrainType): if drivetrainType == DRIVETRAIN_TYPE['GEARED']: constant = 0.01289 linear = 0.08510 quadratic = 0.0 elif drivetrainType == DRIVETRAIN_TYPE['SINGLE_STAGE']: constant = 0.01331 linear = 0.03655 quadratic = 0.06107 elif drivetrainType == DRIVETRAIN_TYPE['MULTI_DRIVE']: constant = 0.01547 linear = 0.04463 quadratic = 0.05790 elif drivetrainType == DRIVETRAIN_TYPE['PM_DIRECT_DRIVE']: constant = 0.01007 linear = 0.02000 quadratic = 0.06899 Pbar0 = aeroPower / ratedPower # handle negative power case (with absolute value) Pbar1, dPbar1_dPbar0 = smooth_abs(Pbar0, dx=0.01) # truncate idealized power curve for purposes of efficiency calculation Pbar, dPbar_dPbar1, _ = smooth_min(Pbar1, 1.0, pct_offset=0.01) # compute efficiency eff = 1.0 - (constant/Pbar + linear + quadratic*Pbar) return aeroPower * eff, eff
def ApiFa(E, fy, D, t, Klr): """Allowable axial stress in compression""" #make inputs into arrays just incase they were simple floats fyy = np.array([fy]) EE = np.array([E]) DD = np.array([D]) tt = np.array([t]) KlrK = np.array([Klr]) n = len(fyy.squeeze()) fyy2 = np.zeros(n) for i in range(n): fyy2[i], _, _ = smooth_min( ApiFxc(EE.squeeze()[i], fyy.squeeze()[i], DD.squeeze()[i], tt.squeeze()[i]), fyy.squeeze()[i]) Cc = np.sqrt(2. * np.pi**2 * EE / fyy2) out = (1 - KlrK**2 / (2. * Cc**2)) * fyy2 / (5. / 3. + 3. / 8. * KlrK / Cc - KlrK**3 / (8. * Cc**3)) idx = (Klr >= Cc) out[idx] = 12. * np.pi**2 * EE[idx] / (23. * KlrK[idx]**2) return out.squeeze()
def execute(self): drivetrainType = self.drivetrainType aeroPower = self.aeroPower aeroTorque = self.aeroTorque ratedPower = self.ratedPower if drivetrainType == 'geared': constant = 0.01289 linear = 0.08510 quadratic = 0.0 elif drivetrainType == 'single_stage': constant = 0.01331 linear = 0.03655 quadratic = 0.06107 elif drivetrainType == 'multi_drive': constant = 0.01547 linear = 0.04463 quadratic = 0.05790 elif drivetrainType == 'pm_direct_drive': constant = 0.01007 linear = 0.02000 quadratic = 0.06899 Pbar0 = aeroPower / ratedPower # handle negative power case (with absolute value) Pbar1, dPbar1_dPbar0 = smooth_abs(Pbar0, dx=0.01) # truncate idealized power curve for purposes of efficiency calculation Pbar, dPbar_dPbar1, _ = smooth_min(Pbar1, 1.0, pct_offset=0.01) # compute efficiency eff = 1.0 - (constant/Pbar + linear + quadratic*Pbar) self.power = aeroPower * eff # gradients dPbar_dPa = dPbar_dPbar1*dPbar1_dPbar0/ratedPower dPbar_dPr = -dPbar_dPbar1*dPbar1_dPbar0*aeroPower/ratedPower**2 deff_dPa = dPbar_dPa*(constant/Pbar**2 - quadratic) deff_dPr = dPbar_dPr*(constant/Pbar**2 - quadratic) dP_dPa = eff + aeroPower*deff_dPa dP_dPr = aeroPower*deff_dPr self.J = hstack([np.diag(dP_dPa), dP_dPr])
def execute(self): drivetrainType = self.drivetrainType aeroPower = self.aeroPower aeroTorque = self.aeroTorque ratedPower = self.ratedPower if drivetrainType == 'geared': constant = 0.01289 linear = 0.08510 quadratic = 0.0 elif drivetrainType == 'single_stage': constant = 0.01331 linear = 0.03655 quadratic = 0.06107 elif drivetrainType == 'multi_drive': constant = 0.01547 linear = 0.04463 quadratic = 0.05790 elif drivetrainType == 'pm_direct_drive': constant = 0.01007 linear = 0.02000 quadratic = 0.06899 Pbar0 = aeroPower / ratedPower # handle negative power case (with absolute value) Pbar1, dPbar1_dPbar0 = smooth_abs(Pbar0, dx=0.01) # truncate idealized power curve for purposes of efficiency calculation Pbar, dPbar_dPbar1, _ = smooth_min(Pbar1, 1.0, pct_offset=0.01) # compute efficiency eff = 1.0 - (constant / Pbar + linear + quadratic * Pbar) self.power = aeroPower * eff # gradients dPbar_dPa = dPbar_dPbar1 * dPbar1_dPbar0 / ratedPower dPbar_dPr = -dPbar_dPbar1 * dPbar1_dPbar0 * aeroPower / ratedPower**2 deff_dPa = dPbar_dPa * (constant / Pbar**2 - quadratic) deff_dPr = dPbar_dPr * (constant / Pbar**2 - quadratic) dP_dPa = eff + aeroPower * deff_dPa dP_dPr = aeroPower * deff_dPr self.J = hstack([np.diag(dP_dPa), dP_dPr])
def hoopStressEurocode(z, d, t, L_reinforced, q_dyn): """default method for computing hoop stress using Eurocode method""" r = d/2.0-t/2.0 # radius of cylinder middle surface omega = L_reinforced/np.sqrt(r*t) C_theta = 1.5 # clamped-clamped k_w = 0.46*(1.0 + 0.1*np.sqrt(C_theta/omega*r/t)) kw = smooth_max(k_w, 0.65) kw = smooth_min(k_w, 1.0) Peq = k_w*q_dyn hoop_stress = -Peq*r/t return hoop_stress
def hoopStressEurocode(z, d, t, L_reinforced, q_dyn): """default method for computing hoop stress using Eurocode method""" r = d / 2.0 - t / 2.0 # radius of cylinder middle surface omega = L_reinforced / np.sqrt(r * t) C_theta = 1.5 # clamped-clamped k_w = 0.46 * (1.0 + 0.1 * np.sqrt(C_theta / omega * r / t)) kw = smooth_max(k_w, 0.65) kw = smooth_min(k_w, 1.0) Peq = k_w * q_dyn hoop_stress = -Peq * r / t return hoop_stress
def hoopStressEurocode(z, d, t, L_reinforced, q_dyn): """default method for computing hoop stress using Eurocode method GB 06/21/2018: Ansys comparisons for submerged case suggests this over-compensates for stiffener I'm not even sure the Eurocode is implemented correctly here. Suggest using the standard hoop stress expression above or API's handling of ring stiffeners below. """ r = d / 2.0 - t / 2.0 # radius of cylinder middle surface omega = L_reinforced / np.sqrt(r * t) C_theta = 1.5 # clamped-clamped k_w = 0.46 * (1.0 + 0.1 * np.sqrt(C_theta / omega * r / t)) kw = smooth_max(k_w, 0.65) kw = smooth_min(k_w, 1.0) Peq = k_w * q_dyn return hoopStress(d, t, Peq)
def hoopStressEurocode(z, d, t, L_reinforced, q_dyn): """default method for computing hoop stress using Eurocode method GB 06/21/2018: Ansys comparisons for submerged case suggests this over-compensates for stiffener I'm not even sure the Eurocode is implemented correctly here. Suggest using the standard hoop stress expression above or API's handling of ring stiffeners below. """ r = d/2.0-t/2.0 # radius of cylinder middle surface omega = L_reinforced/np.sqrt(r*t) C_theta = 1.5 # clamped-clamped k_w = 0.46*(1.0 + 0.1*np.sqrt(C_theta/omega*r/t)) kw = smooth_max(k_w, 0.65) kw = smooth_min(k_w, 1.0) Peq = k_w*q_dyn return hoopStress(d, t, Peq)
def ApiFa(E,fy,D,t,Klr): """Allowable axial stress in compression""" #make inputs into arrays just incase they were simple floats fyy=np.array([fy]) EE=np.array([E]) DD=np.array([D]) tt=np.array([t]) KlrK=np.array([Klr]) n = len(fyy.squeeze()) fyy2 = np.zeros(n) for i in range(n): fyy2[i], _ , _ = smooth_min(ApiFxc(EE.squeeze()[i], fyy.squeeze()[i], DD.squeeze()[i], tt.squeeze()[i]), fyy.squeeze()[i]) Cc=np.sqrt(2.*np.pi**2*EE/fyy2) out=(1-KlrK**2/(2.*Cc**2))*fyy2 / (5./3. + 3./8.*KlrK/Cc - KlrK**3/(8.*Cc**3)) idx= (Klr>=Cc) out[idx]=12.*np.pi**2 * EE[idx]/ (23. * KlrK[idx]**2) return out.squeeze()
def apply_nonlinear(self, params, unknowns, resids): n = params['npts'] Vrated = unknowns['Vrated'] # residual spline = Akima(params['Vcoarse'], params['Pcoarse']) P, dres_dVrated, dres_dVcoarse, dres_dPcoarse = spline.interp(Vrated) resids['Vrated'] = P - params['control:ratedPower'] if True: P1, _, _, _ = spline.interp(params['control:Vin']) P2, _, _, _ = spline.interp(params['control:Vout']) resids1 = P1 - params['control:ratedPower'] resids2 = P2 - params['control:ratedPower'] if ((resids1 < 0) == (resids2 < 0)): if Vrated == params['control:Vout']: resids['Vrated'] = 10000 elif Vrated != params['control:Vin']: resids['Vrated'] = 0 ## Test on # region 2 V2, _, dV2_dVrated = linspace_with_deriv(params['control:Vin'], Vrated, n / 2) P2, dP2_dV2, dP2_dVcoarse, dP2_dPcoarse = spline.interp(V2) # region 3 V3, dV3_dVrated, _ = linspace_with_deriv(Vrated, params['control:Vout'], n / 2 + 1) V3 = V3[1:] # remove duplicate point dV3_dVrated = dV3_dVrated[1:] P3 = params['control:ratedPower'] * np.ones_like(V3) # concatenate unknowns['V'] = np.concatenate([V2, V3]) unknowns['P'] = np.concatenate([P2, P3]) R = params['R'] # rated speed conditions Omega_d = params['control:tsr'] * Vrated / R * RS2RPM OmegaRated, dOmegaRated_dOmegad, dOmegaRated_dmaxOmega \ = smooth_min(Omega_d, params['control:maxOmega'], pct_offset=0.01) splineT = Akima(params['Vcoarse'], params['Tcoarse']) Trated, dT_dVrated, dT_dVcoarse, dT_dTcoarse = splineT.interp(Vrated) unknowns['ratedConditions:V'] = Vrated unknowns['ratedConditions:Omega'] = OmegaRated unknowns['ratedConditions:pitch'] = params['control:pitch'] unknowns['ratedConditions:T'] = Trated unknowns['ratedConditions:Q'] = params['control:ratedPower'] / ( OmegaRated * RPM2RS) unknowns['azimuth'] = 180.0 # gradients ncoarse = len(params['Vcoarse']) dV_dVrated = np.concatenate([dV2_dVrated, dV3_dVrated]) dP_dVcoarse = vstack([dP2_dVcoarse, np.zeros((n / 2, ncoarse))]) dP_dPcoarse = vstack([dP2_dPcoarse, np.zeros((n / 2, ncoarse))]) dP_dVrated = np.concatenate([dP2_dV2 * dV2_dVrated, np.zeros(n / 2)]) drOmega = np.concatenate( [[dOmegaRated_dOmegad * Vrated / R * RS2RPM], np.zeros(3 * ncoarse), [ dOmegaRated_dOmegad * params['control:tsr'] / R * RS2RPM, -dOmegaRated_dOmegad * params['control:tsr'] * Vrated / R**2 * RS2RPM, dOmegaRated_dmaxOmega ]]) drQ = -params['control:ratedPower'] / (OmegaRated**2 * RPM2RS) * drOmega J = {} J['Vrated', 'Vcoarse'] = np.reshape(dres_dVcoarse, (1, len(dres_dVcoarse))) J['Vrated', 'Pcoarse'] = np.reshape(dres_dPcoarse, (1, len(dres_dPcoarse))) J['Vrated', 'Vrated'] = dres_dVrated J['V', 'Vrated'] = dV_dVrated J['P', 'Vrated'] = dP_dVrated J['P', 'Vcoarse'] = dP_dVcoarse J['P', 'Pcoarse'] = dP_dPcoarse J['ratedConditions:V', 'Vrated'] = 1.0 J['ratedConditions:Omega', 'control:tsr'] = dOmegaRated_dOmegad * Vrated / R * RS2RPM J['ratedConditions:Omega', 'Vrated'] = dOmegaRated_dOmegad * params['control:tsr'] / R * RS2RPM J['ratedConditions:Omega', 'R'] = -dOmegaRated_dOmegad * params[ 'control:tsr'] * Vrated / R**2 * RS2RPM J['ratedConditions:Omega', 'control:maxOmega'] = dOmegaRated_dmaxOmega J['ratedConditions:T', 'Vcoarse'] = np.reshape(dT_dVcoarse, (1, len(dT_dVcoarse))) J['ratedConditions:T', 'Tcoarse'] = np.reshape(dT_dTcoarse, (1, len(dT_dTcoarse))) J['ratedConditions:T', 'Vrated'] = dT_dVrated J['ratedConditions:Q', 'control:tsr'] = drQ[0] J['ratedConditions:Q', 'Vrated'] = drQ[-3] J['ratedConditions:Q', 'R'] = drQ[-2] J['ratedConditions:Q', 'control:maxOmega'] = drQ[-1] self.J = J
def evaluate(self): ctrl = self.control n = self.npts Vrated = self.Vrated # residual spline = Akima(self.Vcoarse, self.Pcoarse) P, dres_dVrated, dres_dVcoarse, dres_dPcoarse = spline.interp(Vrated) self.residual = P - ctrl.ratedPower # functional # place half of points in region 2, half in region 3 # even though region 3 is constant we still need lots of points there # because we will be integrating against a discretized wind # speed distribution # region 2 V2, _, dV2_dVrated = linspace_with_deriv(ctrl.Vin, Vrated, n/2) P2, dP2_dV2, dP2_dVcoarse, dP2_dPcoarse = spline.interp(V2) # region 3 V3, dV3_dVrated, _ = linspace_with_deriv(Vrated, ctrl.Vout, n/2+1) V3 = V3[1:] # remove duplicate point dV3_dVrated = dV3_dVrated[1:] P3 = ctrl.ratedPower*np.ones_like(V3) # concatenate self.V = np.concatenate([V2, V3]) self.P = np.concatenate([P2, P3]) # rated speed conditions Omega_d = ctrl.tsr*Vrated/self.R*RS2RPM OmegaRated, dOmegaRated_dOmegad, dOmegaRated_dmaxOmega \ = smooth_min(Omega_d, ctrl.maxOmega, pct_offset=0.01) splineT = Akima(self.Vcoarse, self.Tcoarse) Trated, dT_dVrated, dT_dVcoarse, dT_dTcoarse = splineT.interp(Vrated) self.ratedConditions.V = Vrated self.ratedConditions.Omega = OmegaRated self.ratedConditions.pitch = ctrl.pitch self.ratedConditions.T = Trated self.ratedConditions.Q = ctrl.ratedPower / (self.ratedConditions.Omega * RPM2RS) # gradients ncoarse = len(self.Vcoarse) dres = np.concatenate([[0.0], dres_dVcoarse, dres_dPcoarse, np.zeros(ncoarse), np.array([dres_dVrated]), [0.0, 0.0]]) dV_dVrated = np.concatenate([dV2_dVrated, dV3_dVrated]) dV = hstack([np.zeros((n, 1)), np.zeros((n, 3*ncoarse)), dV_dVrated, np.zeros((n, 2))]) dP_dVcoarse = vstack([dP2_dVcoarse, np.zeros((n/2, ncoarse))]) dP_dPcoarse = vstack([dP2_dPcoarse, np.zeros((n/2, ncoarse))]) dP_dVrated = np.concatenate([dP2_dV2*dV2_dVrated, np.zeros(n/2)]) dP = hstack([np.zeros((n, 1)), dP_dVcoarse, dP_dPcoarse, np.zeros((n, ncoarse)), dP_dVrated, np.zeros((n, 2))]) drV = np.concatenate([[0.0], np.zeros(3*ncoarse), [1.0, 0.0, 0.0]]) drOmega = np.concatenate([[dOmegaRated_dOmegad*Vrated/self.R*RS2RPM], np.zeros(3*ncoarse), [dOmegaRated_dOmegad*ctrl.tsr/self.R*RS2RPM, -dOmegaRated_dOmegad*ctrl.tsr*Vrated/self.R**2*RS2RPM, dOmegaRated_dmaxOmega]]) drpitch = np.zeros(3*ncoarse+4) drT = np.concatenate([[0.0], dT_dVcoarse, np.zeros(ncoarse), dT_dTcoarse, [dT_dVrated, 0.0, 0.0]]) drQ = -ctrl.ratedPower / (self.ratedConditions.Omega**2 * RPM2RS) * drOmega self.J = vstack([dres, dV, dP, drV, drOmega, drpitch, drT, drQ])
def ApiCmPile(fa, Fe): """Reduction factor for buckling allowables for pile and leg""" Cm, _, _ = smooth_min(1. - 0.4 * fa / Fe, 0.85, pct_offset=0.01) return Cm
def ApiCmPile(fa,Fe): """Reduction factor for buckling allowables for pile and leg""" Cm, _, _ = smooth_min(1.-0.4*fa/Fe, 0.85, pct_offset=0.01) return Cm