def process_rose_data(windSpeeds, windDirections, windFrequencies, nDirections, nSpeeds): """take arbitrary wind rose data, and return data equally spaced for a desired number of directions""" spline_freq = Akima(windDirections, windFrequencies) spline_speed = Akima(windDirections, windSpeeds) num = nDirections dirs = np.linspace(0., 360. - 360. / float(num), num) ddir = dirs[1] - dirs[0] frequencies = np.zeros(num) speeds = np.zeros(num) num_int = 100 dir_int1 = np.linspace(dirs[0], dirs[0] + ddir / 2., num_int / 2) freq_int1 = np.zeros(num_int / 2) speed_freq_int1 = np.zeros(num_int / 2) for j in range(num_int / 2): freq_int1[j], _, _, _ = spline_freq.interp(dir_int1[j]) ws, _, _, _ = spline_speed.interp(dir_int1[j]) speed_freq_int1[j] = freq_int1[j] * ws dir_int2 = np.linspace(dirs[0], dirs[0] + ddir / 2., num_int / 2) freq_int2 = np.zeros(num_int / 2) speed_freq_int2 = np.zeros(num_int / 2) for j in range(num_int / 2): freq_int2[j], _, _, _ = spline_freq.interp(dir_int2[j]) ws, _, _, _ = spline_speed.interp(dir_int2[j]) speed_freq_int2[j] = freq_int2[j] * ws frequencies[0] = np.trapz(freq_int1, dir_int1) + np.trapz( freq_int2, dir_int2) speeds[0] = (np.trapz(speed_freq_int1,dir_int1)+np.trapz(speed_freq_int2,dir_int2))/\ (np.trapz(freq_int1,dir_int1)+np.trapz(freq_int2,dir_int2)) for i in range(1, num): dir_int = np.linspace(dirs[i] - ddir / 2., dirs[i] + ddir / 2., num_int) freq_int = np.zeros(num_int) speed_freq_int = np.zeros(num_int) for j in range(num_int): freq_int[j], _, _, _ = spline_freq.interp(dir_int[j]) ws, _, _, _ = spline_speed.interp(dir_int[j]) speed_freq_int[j] = freq_int[j] * ws frequencies[i] = np.trapz(freq_int, dir_int) speeds[i] = np.trapz(speed_freq_int, dir_int) / np.trapz( freq_int, dir_int) frequencies = frequencies / sum(frequencies) for i in range(len(frequencies)): if speeds[i] < 0.: speeds[i] = 0. if frequencies[i] < 0.: frequencies[i] = 0. dirs, frequencies, speeds = setup_weibull(dirs, frequencies, speeds, nSpeeds) return dirs, frequencies, speeds
def execute(self): ctrl = self.control n = self.npts # finer power curve self.V, _, _ = linspace_with_deriv(ctrl.Vin, ctrl.Vout, n) spline = Akima(self.Vcoarse, self.Pcoarse) self.P, dP_dV, dP_dVcoarse, dP_dPcoarse = spline.interp(self.V) self.J = hstack([dP_dVcoarse, dP_dPcoarse])
def solve_nonlinear(self, params, unknowns, resids): n = params['npts'] # finer power curve V, _, _ = linspace_with_deriv(params['control:Vin'], params['control:Vout'], n) unknowns['V'] = V spline = Akima(params['Vcoarse'], params['Pcoarse']) P, dP_dV, dP_dVcoarse, dP_dPcoarse = spline.interp(unknowns['V']) unknowns['P'] = P J = {} J['P', 'Vcoarse'] = dP_dVcoarse J['P', 'Pcoarse'] = dP_dPcoarse self.J = J
def execute(self): nc = len(self.chord_sub) nt = len(self.theta_sub) Rhub = self.Rhub Rtip = self.Rtip idxc = self.idx_cylinder r_max_chord = Rhub + (Rtip-Rhub)*self.r_max_chord r_cylinder = Rhub + (Rtip-Rhub)*self.r_af[idxc] # chord parameterization rc_outer, drc_drcmax, drc_drtip = linspace_with_deriv(r_max_chord, Rtip, nc-1) r_chord = np.concatenate([[Rhub], rc_outer]) drc_drcmax = np.concatenate([[0.0], drc_drcmax]) drc_drtip = np.concatenate([[0.0], drc_drtip]) drc_drhub = np.concatenate([[1.0], np.zeros(nc-1)]) # theta parameterization r_theta, drt_drcyl, drt_drtip = linspace_with_deriv(r_cylinder, Rtip, nt) # spline chord_spline = Akima(r_chord, self.chord_sub) theta_spline = Akima(r_theta, self.theta_sub) self.r = Rhub + (Rtip-Rhub)*self.r_af self.chord, dchord_dr, dchord_drchord, dchord_dchordsub = chord_spline.interp(self.r) theta_outer, dthetaouter_dr, dthetaouter_drtheta, dthetaouter_dthetasub = theta_spline.interp(self.r[idxc:]) theta_inner = theta_outer[0] * np.ones(idxc) self.theta = np.concatenate([theta_inner, theta_outer]) self.r_af_spacing = np.diff(self.r_af) self.precurve = np.zeros_like(self.chord) # TODO: for now I'm forcing this to zero, just for backwards compatibility # gradients (TODO: rethink these a bit or use Tapenade.) n = len(self.r_af) dr_draf = (Rtip-Rhub)*np.ones(n) dr_dRhub = 1.0 - self.r_af dr_dRtip = self.r_af dr = hstack([np.diag(dr_draf), np.zeros((n, 1)), dr_dRhub, dr_dRtip, np.zeros((n, nc+nt))]) dchord_draf = dchord_dr * dr_draf dchord_drmaxchord0 = np.dot(dchord_drchord, drc_drcmax) dchord_drmaxchord = dchord_drmaxchord0 * (Rtip-Rhub) dchord_drhub = np.dot(dchord_drchord, drc_drhub) + dchord_drmaxchord0*(1.0 - self.r_max_chord) + dchord_dr*dr_dRhub dchord_drtip = np.dot(dchord_drchord, drc_drtip) + dchord_drmaxchord0*(self.r_max_chord) + dchord_dr*dr_dRtip dchord = hstack([np.diag(dchord_draf), dchord_drmaxchord, dchord_drhub, dchord_drtip, dchord_dchordsub, np.zeros((n, nt))]) dthetaouter_dcyl = np.dot(dthetaouter_drtheta, drt_drcyl) dthetaouter_draf = dthetaouter_dr*dr_draf[idxc:] dthetaouter_drhub = dthetaouter_dr*dr_dRhub[idxc:] dthetaouter_drtip = dthetaouter_dr*dr_dRtip[idxc:] + np.dot(dthetaouter_drtheta, drt_drtip) dtheta_draf = np.concatenate([np.zeros(idxc), dthetaouter_draf]) dtheta_drhub = np.concatenate([dthetaouter_drhub[0]*np.ones(idxc), dthetaouter_drhub]) dtheta_drtip = np.concatenate([dthetaouter_drtip[0]*np.ones(idxc), dthetaouter_drtip]) sub = dthetaouter_dthetasub[0, :] dtheta_dthetasub = vstack([np.dot(np.ones((idxc, 1)), sub[np.newaxis, :]), dthetaouter_dthetasub]) dtheta_draf = np.diag(dtheta_draf) dtheta_dcyl = np.concatenate([dthetaouter_dcyl[0]*np.ones(idxc), dthetaouter_dcyl]) dtheta_draf[idxc:, idxc] += dthetaouter_dcyl*(Rtip-Rhub) dtheta_drhub += dtheta_dcyl*(1.0 - self.r_af[idxc]) dtheta_drtip += dtheta_dcyl*self.r_af[idxc] dtheta = hstack([dtheta_draf, np.zeros((n, 1)), dtheta_drhub, dtheta_drtip, np.zeros((n, nc)), dtheta_dthetasub]) drafs_dr = np.zeros((n-1, n)) for i in range(n-1): drafs_dr[i, i] = -1.0 drafs_dr[i, i+1] = 1.0 drafs = hstack([drafs_dr, np.zeros((n-1, 3+nc+nt))]) dprecurve = np.zeros((len(self.precurve), n+3+nc+nt)) self.J = vstack([dr, dchord, dtheta, drafs, dprecurve])
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])
# Helper Functions # ----------------- # "Experiments on the Flow Past a Circular Cylinder at Very High Reynolds Numbers", Roshko Re_pt = [ 0.00001, 0.0001, 0.0010, 0.0100, 0.0200, 0.1220, 0.2000, 0.3000, 0.4000, 0.5000, 1.0000, 1.5000, 2.0000, 2.5000, 3.0000, 3.5000, 4.0000, 5.0000, 10.0000 ] cd_pt = [ 4.0000, 2.0000, 1.1100, 1.1100, 1.2000, 1.2000, 1.1700, 0.9000, 0.5400, 0.3100, 0.3800, 0.4600, 0.5300, 0.5700, 0.6100, 0.6400, 0.6700, 0.7000, 0.7000 ] drag_spline = Akima( np.log10(Re_pt), cd_pt, delta_x=0.0) # exact akima because control points do not change def cylinderDrag(Re): """Drag coefficient for a smooth circular cylinder. Parameters ---------- Re : array_like Reynolds number Returns ------- cd : array_like drag coefficient (normalized by cylinder diameter)
#!/usr/bin/env python # encoding: utf-8 """ example.py Created by Andrew Ning on 2013-12-17. """ import numpy as np from akima import Akima, akima_interp # setup spline based on fixed points xpt = np.array([1.0, 2.0, 4.0, 6.0, 10.0, 12.0]) ypt = np.array([5.0, 12.0, 14.0, 16.0, 21.0, 29.0]) spline = Akima(xpt, ypt) # interpolate (extrapolation will work, but beware the results may be silly) n = 50 x = np.linspace(0.0, 13.0, n) y, dydx, dydxpt, dydypt = spline.interp(x) # an alternative way to call akima if you don't care about derivatives # (and also don't care about evaluating the spline multiple times) # a slight amount of smoothing is used for the one with derivatives so # y will not exactly match y2 unless you set delta_x=0.0 in the Akima constructor y2 = akima_interp(xpt, ypt, x) # compare derivatives w.r.t. x to finite differencing h = 1e-6 xstep = x + h # can do all steps at same time b.c. they are independent ystep, _, _, _ = spline.interp(xstep)
def execute(self): nc = len(self.chord_sub) nt = len(self.theta_sub) Rhub = self.Rhub Rtip = self.Rtip idxc = self.idx_cylinder r_max_chord = Rhub + (Rtip - Rhub) * self.r_max_chord r_cylinder = Rhub + (Rtip - Rhub) * self.r_af[idxc] # chord parameterization rc_outer, drc_drcmax, drc_drtip = linspace_with_deriv( r_max_chord, Rtip, nc - 1) r_chord = np.concatenate([[Rhub], rc_outer]) drc_drcmax = np.concatenate([[0.0], drc_drcmax]) drc_drtip = np.concatenate([[0.0], drc_drtip]) drc_drhub = np.concatenate([[1.0], np.zeros(nc - 1)]) # theta parameterization r_theta, drt_drcyl, drt_drtip = linspace_with_deriv( r_cylinder, Rtip, nt) # spline chord_spline = Akima(r_chord, self.chord_sub) theta_spline = Akima(r_theta, self.theta_sub) self.r = Rhub + (Rtip - Rhub) * self.r_af self.chord, dchord_dr, dchord_drchord, dchord_dchordsub = chord_spline.interp( self.r) theta_outer, dthetaouter_dr, dthetaouter_drtheta, dthetaouter_dthetasub = theta_spline.interp( self.r[idxc:]) theta_inner = theta_outer[0] * np.ones(idxc) self.theta = np.concatenate([theta_inner, theta_outer]) self.r_af_spacing = np.diff(self.r_af) self.precurve = np.zeros_like( self.chord ) # TODO: for now I'm forcing this to zero, just for backwards compatibility # gradients (TODO: rethink these a bit or use Tapenade.) n = len(self.r_af) dr_draf = (Rtip - Rhub) * np.ones(n) dr_dRhub = 1.0 - self.r_af dr_dRtip = self.r_af dr = hstack([ np.diag(dr_draf), np.zeros((n, 1)), dr_dRhub, dr_dRtip, np.zeros((n, nc + nt)) ]) dchord_draf = dchord_dr * dr_draf dchord_drmaxchord0 = np.dot(dchord_drchord, drc_drcmax) dchord_drmaxchord = dchord_drmaxchord0 * (Rtip - Rhub) dchord_drhub = np.dot( dchord_drchord, drc_drhub) + dchord_drmaxchord0 * ( 1.0 - self.r_max_chord) + dchord_dr * dr_dRhub dchord_drtip = np.dot(dchord_drchord, drc_drtip) + dchord_drmaxchord0 * ( self.r_max_chord) + dchord_dr * dr_dRtip dchord = hstack([ np.diag(dchord_draf), dchord_drmaxchord, dchord_drhub, dchord_drtip, dchord_dchordsub, np.zeros((n, nt)) ]) dthetaouter_dcyl = np.dot(dthetaouter_drtheta, drt_drcyl) dthetaouter_draf = dthetaouter_dr * dr_draf[idxc:] dthetaouter_drhub = dthetaouter_dr * dr_dRhub[idxc:] dthetaouter_drtip = dthetaouter_dr * dr_dRtip[idxc:] + np.dot( dthetaouter_drtheta, drt_drtip) dtheta_draf = np.concatenate([np.zeros(idxc), dthetaouter_draf]) dtheta_drhub = np.concatenate( [dthetaouter_drhub[0] * np.ones(idxc), dthetaouter_drhub]) dtheta_drtip = np.concatenate( [dthetaouter_drtip[0] * np.ones(idxc), dthetaouter_drtip]) sub = dthetaouter_dthetasub[0, :] dtheta_dthetasub = vstack([ np.dot(np.ones((idxc, 1)), sub[np.newaxis, :]), dthetaouter_dthetasub ]) dtheta_draf = np.diag(dtheta_draf) dtheta_dcyl = np.concatenate( [dthetaouter_dcyl[0] * np.ones(idxc), dthetaouter_dcyl]) dtheta_draf[idxc:, idxc] += dthetaouter_dcyl * (Rtip - Rhub) dtheta_drhub += dtheta_dcyl * (1.0 - self.r_af[idxc]) dtheta_drtip += dtheta_dcyl * self.r_af[idxc] dtheta = hstack([ dtheta_draf, np.zeros((n, 1)), dtheta_drhub, dtheta_drtip, np.zeros((n, nc)), dtheta_dthetasub ]) drafs_dr = np.zeros((n - 1, n)) for i in range(n - 1): drafs_dr[i, i] = -1.0 drafs_dr[i, i + 1] = 1.0 drafs = hstack([drafs_dr, np.zeros((n - 1, 3 + nc + nt))]) dprecurve = np.zeros((len(self.precurve), n + 3 + nc + nt)) self.J = vstack([dr, dchord, dtheta, drafs, dprecurve])
for i in range(len(lines)): lines[i] = re.findall("[-+]?\d+[\.]?\d*[eE]?[-+]?\d*", lines[i].strip('\n')) DR_nodes.append(float(lines[i][0])) AeroTwst.append(float(lines[i][1])) DRNodes.append(float(lines[i][2])) Chord.append(float(lines[i][3])) BldNodes = 17.0 tip_length = 64.0 # 35.0 # 25.0, 35.0 49.5, 64.0 hub_length = 3.2 # 1.75 # 1.25, 1.75, 2.475, 3.2 new_drnode_size = (tip_length-hub_length)/BldNodes new_drnode = [] new_drnode.append(hub_length+new_drnode_size/2.0) for i in range(1, int(BldNodes)): new_drnode.append(new_drnode[i-1]+new_drnode_size) chord_spline = Akima(DR_nodes, Chord) new_chord = chord_spline.interp(new_drnode)[0] twist_spline = Akima(DR_nodes, AeroTwst) new_twist = twist_spline.interp(new_drnode)[0] new_airfoil = [1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4] # # RNodes AeroTwst DRNodes Chord NFoil PrnElm for i in range(int(BldNodes)): print new_drnode[i], new_twist[i], new_drnode_size, new_chord[i], new_airfoil[i], "NOPRINT"