def provideJ(self): if self.run_case == 'power': dP = self.dP dT = self.dT dQ = self.dQ jP = hstack([dP['dprecone'], dP['dtilt'], dP['dhubHt'], dP['dRhub'], dP['dRtip'], dP['dyaw'], dP['dUinf'], dP['dOmega'], dP['dpitch'], dP['dr'], dP['dchord'], dP['dtheta'], dP['dprecurve'], dP['dprecurveTip']]) jT = hstack([dT['dprecone'], dT['dtilt'], dT['dhubHt'], dT['dRhub'], dT['dRtip'], dT['dyaw'], dT['dUinf'], dT['dOmega'], dT['dpitch'], dT['dr'], dT['dchord'], dT['dtheta'], dT['dprecurve'], dT['dprecurveTip']]) jQ = hstack([dQ['dprecone'], dQ['dtilt'], dQ['dhubHt'], dQ['dRhub'], dQ['dRtip'], dQ['dyaw'], dQ['dUinf'], dQ['dOmega'], dQ['dpitch'], dQ['dr'], dQ['dchord'], dQ['dtheta'], dQ['dprecurve'], dQ['dprecurveTip']]) J = vstack([jP, jT, jQ]) elif self.run_case == 'loads': dNp = self.dNp dTp = self.dTp n = len(self.r) dr_dr = vstack([np.zeros(n), np.eye(n), np.zeros(n)]) dr_dRhub = np.zeros(n+2) dr_dRtip = np.zeros(n+2) dr_dRhub[0] = 1.0 dr_dRtip[-1] = 1.0 dr = hstack([dr_dr, np.zeros((n+2, 2*n)), dr_dRhub, dr_dRtip, np.zeros((n+2, 8+n))]) jNp = hstack([dNp['dr'], dNp['dchord'], dNp['dtheta'], dNp['dRhub'], dNp['dRtip'], dNp['dhubHt'], dNp['dprecone'], dNp['dtilt'], dNp['dyaw'], dNp['dUinf'], dNp['dOmega'], dNp['dpitch'], dNp['dazimuth'], dNp['dprecurve']]) jTp = hstack([dTp['dr'], dTp['dchord'], dTp['dtheta'], dTp['dRhub'], dTp['dRtip'], dTp['dhubHt'], dTp['dprecone'], dTp['dtilt'], dTp['dyaw'], dTp['dUinf'], dTp['dOmega'], dTp['dpitch'], dTp['dazimuth'], dTp['dprecurve']]) dPx = vstack([np.zeros(4*n+10), jNp, np.zeros(4*n+10)]) dPy = vstack([np.zeros(4*n+10), -jTp, np.zeros(4*n+10)]) dPz = np.zeros((n+2, 4*n+10)) dV = np.zeros(4*n+10) dV[3*n+6] = 1.0 dOmega = np.zeros(4*n+10) dOmega[3*n+7] = 1.0 dpitch = np.zeros(4*n+10) dpitch[3*n+8] = 1.0 dazimuth = np.zeros(4*n+10) dazimuth[3*n+9] = 1.0 J = vstack([dr, dPx, dPy, dPz, dV, dOmega, dpitch, dazimuth]) return J
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 provideJ(self): V = self.V R = self.R CT = self.CT CQ = self.CQ CP = self.CP n = len(self.V) q = 0.5 * self.rho * V**2 A = pi * R**2 zeronn = np.zeros((n, n)) dCT_dV = np.diag(-2.0*CT/V) dCT_dT = np.diag(1.0/(q*A)) dCT_dR = -2.0*CT/R dCT = hstack((dCT_dV, dCT_dT, zeronn, zeronn, dCT_dR)) dCQ_dV = np.diag(-2.0*CQ/V) dCQ_dQ = np.diag(1.0/(q*R*A)) dCQ_dR = -3.0*CQ/R dCQ = hstack((dCQ_dV, zeronn, dCQ_dQ, zeronn, dCQ_dR)) dCP_dV = np.diag(-3.0*CP/V) dCP_dP = np.diag(1.0/(q*A*V)) dCP_dR = -2.0*CP/R dCP = hstack((dCP_dV, zeronn, zeronn, dCP_dP, dCP_dR)) J = vstack((dCT, dCQ, dCP)) return J
def provideJ(self): dF = DirectionVector.fromArray(self.F).hubToYaw(self.tilt) dFx, dFy, dFz = dF.dx, dF.dy, dF.dz dtopF_dFx = np.array([dFx['dx'], dFy['dx'], dFz['dx']]) dtopF_dFy = np.array([dFx['dy'], dFy['dy'], dFz['dy']]) dtopF_dFz = np.array([dFx['dz'], dFy['dz'], dFz['dz']]) dtopF_dF = hstack([dtopF_dFx, dtopF_dFy, dtopF_dFz]) dtopF_w_dm = np.array([0.0, 0.0, -self.g]) dtopF = hstack( [dtopF_dF, np.zeros((3, 6)), dtopF_w_dm, np.zeros((3, 3))]) dM = DirectionVector.fromArray(self.M).hubToYaw(self.tilt) dMx, dMy, dMz = dM.dx, dM.dy, dM.dz dMxcross, dMycross, dMzcross = self.save_rhub.cross_deriv( self.saveF, 'dr', 'dF') dtopM_dMx = np.array([dMx['dx'], dMy['dx'], dMz['dx']]) dtopM_dMy = np.array([dMx['dy'], dMy['dy'], dMz['dy']]) dtopM_dMz = np.array([dMx['dz'], dMy['dz'], dMz['dz']]) dtopM_dM = hstack([dtopM_dMx, dtopM_dMy, dtopM_dMz]) dM_dF = np.array([dMxcross['dF'], dMycross['dF'], dMzcross['dF']]) dtopM_dFx = np.dot(dM_dF, dtopF_dFx) dtopM_dFy = np.dot(dM_dF, dtopF_dFy) dtopM_dFz = np.dot(dM_dF, dtopF_dFz) dtopM_dF = hstack([dtopM_dFx, dtopM_dFy, dtopM_dFz]) dtopM_dr = np.array([dMxcross['dr'], dMycross['dr'], dMzcross['dr']]) dMx_w_cross, dMy_w_cross, dMz_w_cross = self.save_rcm.cross_deriv( self.saveF_w, 'dr', 'dF') if self.rna_weightM: dtopM_drnacm = np.array( [dMx_w_cross['dr'], dMy_w_cross['dr'], dMz_w_cross['dr']]) dtopM_dF_w = np.array( [dMx_w_cross['dF'], dMy_w_cross['dF'], dMz_w_cross['dF']]) else: dtopM_drnacm = np.zeros((3, 3)) dtopM_dF_w = np.zeros((3, 3)) dtopM_dm = np.dot(dtopM_dF_w, dtopF_w_dm) if self.downwind: dtopM_dr[:, 0] *= -1 dtopM_drnacm[:, 0] *= -1 dtopM = hstack([dtopM_dF, dtopM_dM, dtopM_dr, dtopM_dm, dtopM_drnacm]) J = vstack([dtopF, dtopM]) return J
def provideJ(self): dF = DirectionVector.fromArray(self.F).hubToYaw(self.tilt) dFx, dFy, dFz = dF.dx, dF.dy, dF.dz dtopF_dFx = np.array([dFx['dx'], dFy['dx'], dFz['dx']]) dtopF_dFy = np.array([dFx['dy'], dFy['dy'], dFz['dy']]) dtopF_dFz = np.array([dFx['dz'], dFy['dz'], dFz['dz']]) dtopF_dF = hstack([dtopF_dFx, dtopF_dFy, dtopF_dFz]) dtopF_w_dm = np.array([0.0, 0.0, -self.g]) dtopF = hstack([dtopF_dF, np.zeros((3, 6)), dtopF_w_dm, np.zeros((3, 3))]) dM = DirectionVector.fromArray(self.M).hubToYaw(self.tilt) dMx, dMy, dMz = dM.dx, dM.dy, dM.dz dMxcross, dMycross, dMzcross = self.save_rhub.cross_deriv(self.saveF, 'dr', 'dF') dtopM_dMx = np.array([dMx['dx'], dMy['dx'], dMz['dx']]) dtopM_dMy = np.array([dMx['dy'], dMy['dy'], dMz['dy']]) dtopM_dMz = np.array([dMx['dz'], dMy['dz'], dMz['dz']]) dtopM_dM = hstack([dtopM_dMx, dtopM_dMy, dtopM_dMz]) dM_dF = np.array([dMxcross['dF'], dMycross['dF'], dMzcross['dF']]) dtopM_dFx = np.dot(dM_dF, dtopF_dFx) dtopM_dFy = np.dot(dM_dF, dtopF_dFy) dtopM_dFz = np.dot(dM_dF, dtopF_dFz) dtopM_dF = hstack([dtopM_dFx, dtopM_dFy, dtopM_dFz]) dtopM_dr = np.array([dMxcross['dr'], dMycross['dr'], dMzcross['dr']]) dMx_w_cross, dMy_w_cross, dMz_w_cross = self.save_rcm.cross_deriv(self.saveF_w, 'dr', 'dF') if self.rna_weightM: dtopM_drnacm = np.array([dMx_w_cross['dr'], dMy_w_cross['dr'], dMz_w_cross['dr']]) dtopM_dF_w = np.array([dMx_w_cross['dF'], dMy_w_cross['dF'], dMz_w_cross['dF']]) else: dtopM_drnacm = np.zeros((3, 3)) dtopM_dF_w = np.zeros((3, 3)) dtopM_dm = np.dot(dtopM_dF_w, dtopF_w_dm) if self.downwind: dtopM_dr[:, 0] *= -1 dtopM_drnacm[:, 0] *= -1 dtopM = hstack([dtopM_dF, dtopM_dM, dtopM_dr, dtopM_dm, dtopM_drnacm]) J = vstack([dtopF, dtopM]) return 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 provideJ(self): dbyx = self.blade_yaw.dx # dbyy = self.blade_yaw.dy dbyz = self.blade_yaw.dz # Rtip drtower_dRtip = self.drtower_dztower * dbyz['dz'] / self.towerHt if self.precone >= 0: dtd_dRtip = -dbyx['dz'] - drtower_dRtip else: dtd_dRtip = dbyx['dz'] - drtower_dRtip dgc_dRtip = dbyz['dz'] # precurveTip drtower_dprecurveTip = self.drtower_dztower * dbyz['dx'] / self.towerHt if self.precone >= 0: dtd_dprecurveTip = -dbyx['dx'] - drtower_dprecurveTip else: dtd_dprecurveTip = dbyx['dx'] - drtower_dprecurveTip dgc_dprecurveTip = dbyz['dx'] # presweep drtower_dpresweepTip = self.drtower_dztower * dbyz['dy'] / self.towerHt if self.precone >= 0: dtd_dpresweepTip = -dbyx['dy'] - drtower_dpresweepTip else: dtd_dpresweepTip = dbyx['dy'] - drtower_dpresweepTip dgc_dpresweepTip = dbyz['dy'] # precone drtower_dprecone = self.drtower_dztower * dbyz[ 'dprecone'] / self.towerHt if self.precone >= 0: dtd_dprecone = -dbyx['dprecone'] - drtower_dprecone else: dtd_dprecone = dbyx['dprecone'] - drtower_dprecone dgc_dprecone = dbyz['dprecone'] # tilt drtower_dtilt = self.drtower_dztower * dbyz['dtilt'] / self.towerHt if self.precone >= 0: dtd_dtilt = -dbyx['dtilt'] - drtower_dtilt else: dtd_dtilt = dbyx['dtilt'] - drtower_dtilt dgc_dtilt = dbyz['dtilt'] # hubtt drtower_dhubtt = self.drtower_dztower * np.array( [0.0, 0.0, 1.0 / self.towerHt]) dtd_dhubtt = np.array([-1.0, 0.0, 0.0]) - drtower_dhubtt dgc_dhubtt = np.array([0.0, 0.0, 1.0]) # tower_z dtd_dtowerz = -self.drtower_dtowerz dgc_dtowerz = np.zeros_like(self.tower_z) # tower_d dtd_dtowerd = -self.drtower_dtowerd dgc_dtowerd = np.zeros_like(self.tower_d) # towerHt drtower_dtowerHt = self.drtower_dztower * -( self.hub_tt[2] + self.blade_yaw.z) / self.towerHt**2 dtd_dtowerHt = -drtower_dtowerHt dgc_dtowerHt = 1.0 dtd = hstack([ dtd_dRtip, dtd_dprecurveTip, dtd_dpresweepTip, dtd_dprecone, dtd_dtilt, dtd_dhubtt, dtd_dtowerz, dtd_dtowerd, dtd_dtowerHt ]) dgc = np.concatenate([[dgc_dRtip], [dgc_dprecurveTip], [dgc_dpresweepTip], [dgc_dprecone], [dgc_dtilt], dgc_dhubtt, dgc_dtowerz, dgc_dtowerd, [dgc_dtowerHt]]) J = vstack([dtd, dgc]) return J
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 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 provideJ(self): if self.run_case == 'power': dP = self.dP dT = self.dT dQ = self.dQ jP = hstack([ dP['dprecone'], dP['dtilt'], dP['dhubHt'], dP['dRhub'], dP['dRtip'], dP['dyaw'], dP['dUinf'], dP['dOmega'], dP['dpitch'], dP['dr'], dP['dchord'], dP['dtheta'], dP['dprecurve'], dP['dprecurveTip'] ]) jT = hstack([ dT['dprecone'], dT['dtilt'], dT['dhubHt'], dT['dRhub'], dT['dRtip'], dT['dyaw'], dT['dUinf'], dT['dOmega'], dT['dpitch'], dT['dr'], dT['dchord'], dT['dtheta'], dT['dprecurve'], dT['dprecurveTip'] ]) jQ = hstack([ dQ['dprecone'], dQ['dtilt'], dQ['dhubHt'], dQ['dRhub'], dQ['dRtip'], dQ['dyaw'], dQ['dUinf'], dQ['dOmega'], dQ['dpitch'], dQ['dr'], dQ['dchord'], dQ['dtheta'], dQ['dprecurve'], dQ['dprecurveTip'] ]) J = vstack([jP, jT, jQ]) elif self.run_case == 'loads': dNp = self.dNp dTp = self.dTp n = len(self.r) dr_dr = vstack([np.zeros(n), np.eye(n), np.zeros(n)]) dr_dRhub = np.zeros(n + 2) dr_dRtip = np.zeros(n + 2) dr_dRhub[0] = 1.0 dr_dRtip[-1] = 1.0 dr = hstack([ dr_dr, np.zeros((n + 2, 2 * n)), dr_dRhub, dr_dRtip, np.zeros((n + 2, 8 + n)) ]) jNp = hstack([ dNp['dr'], dNp['dchord'], dNp['dtheta'], dNp['dRhub'], dNp['dRtip'], dNp['dhubHt'], dNp['dprecone'], dNp['dtilt'], dNp['dyaw'], dNp['dUinf'], dNp['dOmega'], dNp['dpitch'], dNp['dazimuth'], dNp['dprecurve'] ]) jTp = hstack([ dTp['dr'], dTp['dchord'], dTp['dtheta'], dTp['dRhub'], dTp['dRtip'], dTp['dhubHt'], dTp['dprecone'], dTp['dtilt'], dTp['dyaw'], dTp['dUinf'], dTp['dOmega'], dTp['dpitch'], dTp['dazimuth'], dTp['dprecurve'] ]) dPx = vstack([np.zeros(4 * n + 10), jNp, np.zeros(4 * n + 10)]) dPy = vstack([np.zeros(4 * n + 10), -jTp, np.zeros(4 * n + 10)]) dPz = np.zeros((n + 2, 4 * n + 10)) dV = np.zeros(4 * n + 10) dV[3 * n + 6] = 1.0 dOmega = np.zeros(4 * n + 10) dOmega[3 * n + 7] = 1.0 dpitch = np.zeros(4 * n + 10) dpitch[3 * n + 8] = 1.0 dazimuth = np.zeros(4 * n + 10) dazimuth[3 * n + 9] = 1.0 J = vstack([dr, dPx, dPy, dPz, dV, dOmega, dpitch, dazimuth]) return J
def provideJ(self): dbyx = self.blade_yaw.dx # dbyy = self.blade_yaw.dy dbyz = self.blade_yaw.dz # Rtip drtower_dRtip = self.drtower_dztower * dbyz['dz']/self.towerHt if self.precone >= 0: dtd_dRtip = -dbyx['dz'] - drtower_dRtip else: dtd_dRtip = dbyx['dz'] - drtower_dRtip dgc_dRtip = dbyz['dz'] # precurveTip drtower_dprecurveTip = self.drtower_dztower * dbyz['dx']/self.towerHt if self.precone >= 0: dtd_dprecurveTip = -dbyx['dx'] - drtower_dprecurveTip else: dtd_dprecurveTip = dbyx['dx'] - drtower_dprecurveTip dgc_dprecurveTip = dbyz['dx'] # presweep drtower_dpresweepTip = self.drtower_dztower * dbyz['dy']/self.towerHt if self.precone >= 0: dtd_dpresweepTip = -dbyx['dy'] - drtower_dpresweepTip else: dtd_dpresweepTip = dbyx['dy'] - drtower_dpresweepTip dgc_dpresweepTip = dbyz['dy'] # precone drtower_dprecone = self.drtower_dztower * dbyz['dprecone']/self.towerHt if self.precone >= 0: dtd_dprecone = -dbyx['dprecone'] - drtower_dprecone else: dtd_dprecone = dbyx['dprecone'] - drtower_dprecone dgc_dprecone = dbyz['dprecone'] # tilt drtower_dtilt = self.drtower_dztower * dbyz['dtilt']/self.towerHt if self.precone >= 0: dtd_dtilt = -dbyx['dtilt'] - drtower_dtilt else: dtd_dtilt = dbyx['dtilt'] - drtower_dtilt dgc_dtilt = dbyz['dtilt'] # hubtt drtower_dhubtt = self.drtower_dztower * np.array([0.0, 0.0, 1.0/self.towerHt]) dtd_dhubtt = np.array([-1.0, 0.0, 0.0]) - drtower_dhubtt dgc_dhubtt = np.array([0.0, 0.0, 1.0]) # tower_z dtd_dtowerz = -self.drtower_dtowerz dgc_dtowerz = np.zeros_like(self.tower_z) # tower_d dtd_dtowerd = -self.drtower_dtowerd dgc_dtowerd = np.zeros_like(self.tower_d) # towerHt drtower_dtowerHt = self.drtower_dztower * -(self.hub_tt[2] + self.blade_yaw.z)/self.towerHt**2 dtd_dtowerHt = -drtower_dtowerHt dgc_dtowerHt = 1.0 dtd = hstack([dtd_dRtip, dtd_dprecurveTip, dtd_dpresweepTip, dtd_dprecone, dtd_dtilt, dtd_dhubtt, dtd_dtowerz, dtd_dtowerd, dtd_dtowerHt]) dgc = np.concatenate([[dgc_dRtip], [dgc_dprecurveTip], [dgc_dpresweepTip], [dgc_dprecone], [dgc_dtilt], dgc_dhubtt, dgc_dtowerz, dgc_dtowerd, [dgc_dtowerHt]]) J = vstack([dtd, dgc]) return J