Esempio n. 1
0
class DLLMTargetLift(DLLMSolver):
    ERROR_MSG='ERROR in DLLMTargetLift.'
    def __init__(self, tag, wing_param, OC):
        DLLMSolver.__init__(self, tag, wing_param, OC)
        
        self.__N            = self.get_wing_param().get_n_sect()
        self.__ndv          = self.get_wing_param().get_ndv()
        
        self.__R_TL         = numpy.zeros(self.__N+1)
        self.__dpR_TL_dpW   = numpy.zeros((self.__N+1,self.__N+1))
        self.__dpR_TL_dpchi = numpy.zeros((self.__N+1,self.__ndv))
        
        self.__dpF_list_dpW = None 
        
        self.__target_Lift    = 10000.

        # initialize the Newton-Raphson problem
        self.__NRPb = None 
        self.__init_Newton_Raphson()
        
    # -- Accessors
    def get_target_Lift(self):
        return self.__target_Lift
    
    def set_target_Lift(self, target):
        self.__target_Lift   = target
        
    #-- Newton-Raphson related methods
    def __init_Newton_Raphson(self):
        W0= numpy.zeros(self.__N+1)
        self.__NRPb = NewtonRaphsonProblem(W0, self.comp_R_TL, self.comp_dpR_TL_dpW)
        self.__NRPb.set_relax_factor(0.99)
        self.__NRPb.set_stop_residual(1.e-9)
        self.__NRPb.set_max_iterations(100)
        
    def set_relax_factor(self, relax_factor):
        self.__NRPb.set_relax_factor(relax_factor)
    
    def set_stop_residual(self, residual):
        self.__NRPb.set_stop_residual(residual)
        
    def set_max_iterations(self, max_it):
        self.__NRPb.set_max_iterations(max_it)
    
    def set_method(self, method):
        self.__NRPb.set_method(method)

    #-- Residual Related method
    def comp_R_TL(self, W):
        DLLMDirect = self.get_DLLMDirect()
        DLLMPost   = self.get_DLLMPost()
        OC = self.get_OC()
        
        iAoA = W[0:self.__N]
        AoA  = W[self.__N]
        OC.set_AoA_rad(AoA)
        
        R    = DLLMDirect.comp_R(iAoA)
        Lift = DLLMPost.comp_Lift()

        self.__R_TL[:self.__N] = R[:]
        self.__R_TL[self.__N]  = Lift - self.__target_Lift
        
        return self.__R_TL
    
    def comp_dpR_TL_dpW(self, W):
        DLLMDirect = self.get_DLLMDirect()
        DLLMPost   = self.get_DLLMPost()
        OC =  self.get_OC()
        
        iAoA = W[0:self.__N]
        AoA  = W[self.__N]
        OC.set_AoA_rad(AoA)
        
        dpR_dpiAoA    = DLLMDirect.comp_dpR_dpiAoA(iAoA)
        dpLift_dpiAoA = DLLMPost.comp_dpLift_dpiAoA()
        
        dpR_dpAoA   = DLLMDirect.comp_dpR_dpAoA()
        dpLift_dpAoA  = DLLMPost.dpLift_dpAoA()        
        
        self.__dpR_TL_dpW[0:self.__N,0:self.__N] = dpR_dpiAoA[:,:]
        self.__dpR_TL_dpW[self.__N,0:self.__N]   = dpLift_dpiAoA[:]
        
        self.__dpR_TL_dpW[0:self.__N,self.__N]   = dpR_dpAoA[:]
        self.__dpR_TL_dpW[self.__N,self.__N]     = dpLift_dpAoA
        
        return self.__dpR_TL_dpW
    
    def get_R(self):
        return self.__R_TL
    
    def get_dpR_dpW(self):
        return self.__dpR_TL_dpW
    
    def get_dpR_dpchi(self):
        DLLMDirect = self.get_DLLMDirect()
        DLLMPost   = self.get_DLLMPost()
        dpR_dpchi    = DLLMDirect.get_dpR_dpchi()
        dpLift_dpchi = DLLMPost.dpLift_dpchi()
        
        self.__dpR_TL_dpchi[:self.__N,:] = dpR_dpchi[:,:]
        self.__dpR_TL_dpchi[self.__N,:]  = dpLift_dpchi[:]
        
        return self.__dpR_TL_dpchi
    
    def get_dpF_list_dpW(self):
        DLLMPost   = self.get_DLLMPost()
        
        dpF_list_dpiAoA = DLLMPost.get_dpF_list_dpiAoA()
        dpF_list_dpAoA  = DLLMPost.get_dpF_list_dpAoA()
        
        dim = len(dpF_list_dpiAoA)
        
        self.__dpF_list_dpW = numpy.zeros((dim,self.__N+1))
        
        for i in xrange(dim):
            self.__dpF_list_dpW[i,:self.__N] = dpF_list_dpiAoA[i,:]
            self.__dpF_list_dpW[i,self.__N]  = dpF_list_dpAoA[i]
        
        return self.__dpF_list_dpW
    
    
    def run_direct(self):
        DLLMDirect = self.get_DLLMDirect()
#        W0= numpy.zeros(self.__N+1)
#        self.__NRPb.valid_jacobian(W0, iprint=True)
        self.__NRPb.solve()
        DLLMDirect.set_computed(True)
        DLLMDirect.write_gamma_to_file()
        DLLMDirect.comp_dpR_dpchi()
        
        
        

        
        
        
        
        

        
Esempio n. 2
0
class DLLMTargetCl(DLLMSolver):
    ERROR_MSG='ERROR in DLLMTargetCl.'
    def __init__(self, tag,  wing_param, OC, verbose = 0):
        self.__verbose = verbose
        DLLMSolver.__init__(self, tag, wing_param, OC, verbose = self.__verbose)
        
        self.__N            = self.get_wing_param().get_n_sect()
        self.__ndv          = self.get_wing_param().get_ndv()
        
        self.__R_TCl         = numpy.zeros(self.__N+1)
        self.__dpR_TCl_dpW   = numpy.zeros((self.__N+1,self.__N+1))
        self.__dpR_TCl_dpchi = numpy.zeros((self.__N+1,self.__ndv))
        
        self.__dpF_list_dpW = None 
        
        self.__target_Cl    = 0.5

        # initialize the Newton-Raphson problem
        self.__NRPb = None 
        self.__init_Newton_Raphson()
        
    # -- Accessors
    def get_target_Cl(self):
        return self.__target_Cl
    
    def set_target_Cl(self, target):
        self.__target_Cl   = target
        
    #-- Newton-Raphson related methods
    def __init_Newton_Raphson(self):
        W0= numpy.zeros(self.__N+1)
        self.__NRPb = NewtonRaphsonProblem(W0, self.comp_R_TCl, self.comp_dpR_TCl_dpW, verbose = self.__verbose)
        self.__NRPb.set_relax_factor(0.99)
        self.__NRPb.set_stop_residual(1.e-9)
        self.__NRPb.set_max_iterations(100)
        
    def set_relax_factor(self, relax_factor):
        self.__NRPb.set_relax_factor(relax_factor)
    
    def set_stop_residual(self, residual):
        self.__NRPb.set_stop_residual(residual)
        
    def set_max_iterations(self, max_it):
        self.__NRPb.set_max_iterations(max_it)
        
    def set_method(self, method):
        self.__NRPb.set_method(method)
        
    #-- Residual Related method
    def comp_R_TCl(self, W):
        DLLMDirect = self.get_DLLMDirect()
        DLLMPost   = self.get_DLLMPost()
        OC = self.get_OC()
        
        iAoA = W[0:self.__N]
        AoA  = W[self.__N]
        OC.set_AoA_rad(AoA)
        
        R    = DLLMDirect.comp_R(iAoA)
        Cl   = DLLMPost.comp_Cl()

        self.__R_TCl[:self.__N] = R[:]
        self.__R_TCl[self.__N]  = Cl - self.__target_Cl
        
        return self.__R_TCl
    
    def comp_dpR_TCl_dpW(self, W):
        DLLMDirect = self.get_DLLMDirect()
        DLLMPost   = self.get_DLLMPost()
        OC =  self.get_OC()
        
        iAoA = W[0:self.__N]
        AoA  = W[self.__N]
        OC.set_AoA_rad(AoA)
        
        dpR_dpiAoA  = DLLMDirect.comp_dpR_dpiAoA(iAoA)
        dpCl_dpiAoA = DLLMPost.comp_dpCl_dpiAoA()
        
        dpR_dpAoA   = DLLMDirect.comp_dpR_dpAoA()
        dpCl_dpAoA  = DLLMPost.dpCl_dpAoA()        
        
        self.__dpR_TCl_dpW[0:self.__N,0:self.__N] = dpR_dpiAoA[:,:]
        self.__dpR_TCl_dpW[self.__N,0:self.__N]   = dpCl_dpiAoA[:]
        
        self.__dpR_TCl_dpW[0:self.__N,self.__N]   = dpR_dpAoA[:]
        self.__dpR_TCl_dpW[self.__N,self.__N]     = dpCl_dpAoA
        
        return self.__dpR_TCl_dpW
    
    def get_R(self):
        return self.__R_TCl
    
    def get_dpR_dpW(self):
        return self.__dpR_TCl_dpW
    
    def get_dpR_dpchi(self):
        DLLMDirect = self.get_DLLMDirect()
        DLLMPost   = self.get_DLLMPost()
        dpR_dpchi  = DLLMDirect.get_dpR_dpchi()
        dpCl_dpchi = DLLMPost.dpCl_dpchi()
        
        self.__dpR_TCl_dpchi[:self.__N,:] = dpR_dpchi[:,:]
        self.__dpR_TCl_dpchi[self.__N,:]  = dpCl_dpchi[:]
        
        return self.__dpR_TCl_dpchi
    
    def get_dpF_list_dpW(self):
        DLLMPost   = self.get_DLLMPost()
        
        dpF_list_dpiAoA = DLLMPost.get_dpF_list_dpiAoA()
        dpF_list_dpAoA  = DLLMPost.get_dpF_list_dpAoA()
        
        dim = len(dpF_list_dpiAoA)
        
        self.__dpF_list_dpW = numpy.zeros((dim,self.__N+1))
        
        for i in xrange(dim):
            self.__dpF_list_dpW[i,:self.__N] = dpF_list_dpiAoA[i,:]
            self.__dpF_list_dpW[i,self.__N]  = dpF_list_dpAoA[i]
        
        return self.__dpF_list_dpW
    
    
    def run_direct(self):
        DLLMDirect = self.get_DLLMDirect()
#        W0= numpy.zeros(self.__N+1)
#        self.__NRPb.valid_jacobian(W0, iprint=True)
        self.__NRPb.solve()
        DLLMDirect.set_computed(True)
        DLLMDirect.write_gamma_to_file()
        DLLMDirect.comp_dpR_dpchi()
        
        
        

        
        
        
        
        

        
Esempio n. 3
0
wing_param.convert_to_design_variable('tip_height', (0.2, 0.5))
wing_param.build_linear_airfoil(OC, AoA0=-2., Cm0=-0.1, set_as_ref=True)
wing_param.build_airfoils_from_ref()
wing_param.update()

print wing_param

N = wing_param.get_n_sect()
iAoA0 = numpy.zeros(N)

DLLM = DLLMSolver('test', wing_param, OC)

NRPb = NewtonRaphsonProblem(iAoA0, DLLM.comp_R, DLLM.comp_dpR_dpiAoA)
NRPb.set_relax_factor(0.99)
NRPb.set_stop_residual(1.e-9)
NRPb.set_max_iterations(100)

iAoA = NRPb.solve()

DLLM.set_direct_computed()
print iAoA

DLLM.comp_dpR_dpchi()
dpRdpthetaY = DLLM.comp_dpR_dpthetaY()
print 'dpRdpthetaY=', dpRdpthetaY

print DLLM.get_iAoA()

DLLM.run_post()
DLLM.run_adjoint()
Esempio n. 4
0
class DLLMDirect:
    """
    Direct solver for the lifting line wing model
    """
    DEG_TO_RAD = numpy.pi/180.
    RAD_TO_DEG = 180./numpy.pi
    
    def __init__(self, LLW):
        self.__LLW          = LLW
        self.__computed     = False
        self.__gamma_f_name = None
        
        # initialize local variables
        self.__init_local_variables()
        
        # initialize the Newton-Raphson problem
        self.__NRPb = None 
        self.__init_Newton_Raphson()
        
    #-- Accessors
    def get_tag(self):
        return self.__LLW.get_tag()
    
    def get_wing_param(self):
        return self.__LLW.get_wing_param()
    
    def get_airfoils(self):
        return self.__LLW.get_airfoils()
    
    def get_K(self):
        return self.__LLW.get_K()
    
    def get_dK_dchi(self):
        return self.__LLW.get_dK_dchi()
    
    def get_N(self):
        return self.get_wing_param().get_n_sect()
    
    def get_ndv(self):
        return self.get_wing_param().get_ndv()
    
    def get_OC(self):
        return self.__LLW.get_OC()
    
    def get_iAoA(self):
        return self.__iAoA
    
    def get_localAoA(self):
        return self.__localAoA
    
    def get_R(self):
        return self.__R
    
    def get_dpR_dpiAoA(self):
        return self.__dpR_dpiAoA
    
    def get_dpR_dpchi(self):
        return self.__dpR_dpchi
    
    def get_dplocalAoA_dpiAoA(self):
        return self.__dplocalAoA_dpiAoA
    
    def get_dplocalAoA_dpAoA(self):
        return self.__dplocalAoA_dpAoA
    
    def get_dplocalAoA_dpchi(self):
        return self.__dplocalAoA_dpchi
    
    def get_convergence_history(self):
        """
        Accessor to the last computation convergence history as a list of residuals normalized by the first iteration residual.
        """
        return self.__residuals_hist
    
    def is_computed(self):
        return self.__computed
    
    #-- Setters
    def set_computed(self, bool=True):
        self.__computed = bool
        
    def set_gamma_file_name(self, gamma_f_name):
        self.__gamma_f_name = gamma_f_name
    
    #-- Newton-Raphson related methods
    def __init_Newton_Raphson(self):
        N=self.get_N()
        iAoA0= zeros(N)
        self.__NRPb = NewtonRaphsonProblem(iAoA0, self.comp_R, self.comp_dpR_dpiAoA)
        self.__NRPb.set_relax_factor(0.99)
        self.__NRPb.set_stop_residual(1.e-9)
        self.__NRPb.set_max_iterations(100)
        
    def set_relax_factor(self, relax_factor):
        self.__NRPb.set_relax_factor(relax_factor)
    
    def set_stop_residual(self, residual):
        self.__NRPb.set_stop_residual(residual)
        
    def set_max_iterations(self, max_it):
        self.__NRPb.set_max_iterations(max_it)
        
    def set_method(self, method):
        self.__NRPb.set_method(method)

    #-- Computation related methods
    def run(self):
        self.__NRPb.solve()
        self.set_computed(True)
        self.write_gamma_to_file()
        self.comp_dpR_dpchi()
                
    def __init_local_variables(self):
        # Initializing local variables for lifting line computations
        # Residual variables
        N=self.get_N()
        ndv=self.get_ndv()
        self.__R            = zeros([N])
        self.__dpR_dpiAoA   = None
        self.__dpR_dpchi    = None
        self.__dpR_dpthetaY = None
        self.__dpR_dpAoA    = None
        
        # Angle of attack variables
        self.__localAoA            = zeros([N])
        self.__dplocalAoA_dpiAoA   = diag(ones([N])) # This is a constant matrix
        self.__dplocalAoA_dpthetaY = diag(ones([N]))  # This is a constant matrix
        self.__dplocalAoA_dpAoA    = ones(N)
        self.__dplocalAoA_dpchi    = zeros([N,ndv])
        
        # Induced angle of attack variables
        self.__iAoA    = None
        self.__iAoANew = None
        self.__dpiAoAnew_dpchi  = zeros([N,ndv])   
        self.__dpiAoAnew_dpiAoA = None
        
        # Circulation variables
        self.__gamma  = zeros(N)
        self.__dpgamma_dpiAoA   = None
        self.__dpgamma_dpthetaY = None
        self.__dpgamma_dpAoA    = None
        self.__dpgamma_dplocalAoA = zeros([N,N])
        self.__dpgamma_dpchi      = zeros([N,ndv])
                
    #-- Residual related methods
    def comp_R(self, iAoA):
        self.__iAoA = iAoA
        self.__compute_localAoA()
        self.__compute_gamma()
        self.__compute_iAoAnew()
        
        self.__R = self.__iAoA - self.__iAoANew
        
        return self.__R
    
    def comp_dpR_dpiAoA(self, iAoA):
        N=self.get_N()
        R=self.comp_R(iAoA)
        
        # dplocalAoA_dpiAoA is a constant matrix, no need to compute it (self.__dplocalAoA_dpiAoA)
        self.__compute_dpgamma_dpiAoA()
        self.__compute_dpiAoAnew_dpiAoA()
        
        self.__dpR_dpiAoA=numpy.diag(ones([N]))-self.__dpiAoAnew_dpiAoA
        
        return self.__dpR_dpiAoA
    
    def comp_dpR_dpchi(self):
        self.__compute_dplocalAoA_dpchi()
        self.__compute_dpgamma_dpchi()
        self.__compute_dpiAoAnew_dpchi()
        self.__dpR_dpchi = -self.__dpiAoAnew_dpchi
        
        return self.__dpR_dpchi
    
    def comp_dpR_dpthetaY(self):
        K=self.get_K()
        self.__compute_dpgamma_dpthetaY()    
        self.__dpR_dpthetaY = -dot(K,self.__dpgamma_dpthetaY)
        
        return self.__dpR_dpthetaY
    
    def comp_dpR_dpAoA(self):
        K=self.get_K()
        self.__compute_dpgamma_dpAoA()
        self.__dpR_dpAoA = -dot(K,self.__dpgamma_dpAoA)
        
        return self.__dpR_dpAoA
    
    def __compute_dpgamma_dpAoA(self):
        N=self.get_N()
        Mach = self.get_OC().get_Mach()
        for i in xrange(N):
            self.__dpgamma_dplocalAoA[i,i]  = self.get_airfoils()[i].dpgamma_dpAoA(self.__localAoA[i],Mach)
            
        self.__dpgamma_dpAoA = dot(self.__dpgamma_dplocalAoA,self.__dplocalAoA_dpAoA)
        
    def __compute_dpgamma_dpthetaY(self):
        N=self.get_N()
        Mach = self.get_OC().get_Mach()
        for i in xrange(N):
            self.__dpgamma_dplocalAoA[i,i]  = self.get_airfoils()[i].dpgamma_dpAoA(self.__localAoA[i],Mach)
            
        self.__dpgamma_dpthetaY = dot(self.__dpgamma_dplocalAoA,self.__dplocalAoA_dpthetaY)
    
    def __compute_dplocalAoA_dpchi(self):
        N=self.get_N()
        twist_grad  = self.get_wing_param().get_twist_grad()
        AoA_grad    = self.get_wing_param().get_AoA_grad()
        if AoA_grad is None:
            for i in xrange(N):
                self.__dplocalAoA_dpchi[i,:] =twist_grad[i,:] # + dAoAdksi ?? 
        else:
            for i in xrange(N):
                self.__dplocalAoA_dpchi[i,:] = AoA_grad[:] + twist_grad[i,:] 
            
    def __compute_dpgamma_dpchi(self):
        N=self.get_N()
        Mach = self.get_OC().get_Mach()
        for i in xrange(N):
            self.__dpgamma_dpchi[i,:] = self.get_airfoils()[i].dpgamma_dpchi(self.__localAoA[i],Mach)
        
        self.__dpgamma_dpchi = self.__dpgamma_dpchi + dot(self.__dpgamma_dplocalAoA,self.__dplocalAoA_dpchi) 
            
    def __compute_dpiAoAnew_dpchi(self):
        K=self.get_K()
        dK_dchi=self.get_dK_dchi()
        ndv=self.get_ndv()
        self.__dpiAoAnew_dpchi = dot(K,self.__dpgamma_dpchi)
        for n in xrange(ndv):
            self.__dpiAoAnew_dpchi[:,n] += dot(dK_dchi[:,:,n],self.__gamma)

    def __compute_localAoA(self):
        N=self.get_N()
        Thetay = self.get_wing_param().get_thetaY()
        twist  = self.get_wing_param().get_twist()
        AoA    = self.get_wing_param().get_AoA()
        if AoA is None:
           AoA    = self.get_OC().get_AoA_rad()
        else:
           self.get_OC().set_AoA(AoA*180./numpy.pi)
         
         
        # Why this formula ? twist increases the local airfoil angle of attack normally...
        #self.__localAoA=alpha-iaOa-self.get_wing_geom().get_twist()
        self.__localAoA = AoA + twist + self.__iAoA + Thetay
        
        for i in xrange(N):
            if self.__localAoA[i] > numpy.pi/2. or self.__localAoA[i] < -numpy.pi/2.:
                raise Exception, "Local angle of attack out of bounds [-pi/2, pi/2]"

    def __compute_gamma(self):
        """
        Update the circulation
        """
        N=self.get_N()
        Mach = self.get_OC().get_Mach()
        for i in xrange(N):
            self.__gamma[i] = self.get_airfoils()[i].gamma(self.__localAoA[i],Mach)
            
    def __compute_dpgamma_dpiAoA(self):
        N=self.get_N()
        Mach = self.get_OC().get_Mach()
        for i in xrange(N):
            self.__dpgamma_dplocalAoA[i,i]  = self.get_airfoils()[i].dpgamma_dpAoA(self.__localAoA[i],Mach)
            
        self.__dpgamma_dpiAoA = dot(self.__dpgamma_dplocalAoA,self.__dplocalAoA_dpiAoA)

    def __compute_iAoAnew(self):
        '''
        Computes the induced angle on an airfoil for a given circulation on the wing.
        '''
        K=self.get_K()
        self.__iAoANew        = dot(K,self.__gamma)
        
    def __compute_dpiAoAnew_dpiAoA(self):
        """
        Computes the derivative dpiAoAnew_dpiAoA
        """
        K=self.get_K()
        self.__dpiAoAnew_dpiAoA = dot(K,self.__dpgamma_dpiAoA)
        
    def write_gamma_to_file(self):
        '''
        Writes the circulation repartition in a file
        '''
        y   = self.get_wing_param().get_XYZ()[1,:]
        if self.__gamma_f_name is None:
            gamma_f_name='gamma.dat'
        else:
            gamma_f_name=self.__gamma_f_name
        
        mod_gamma_f_name=self.get_tag()+'_'+gamma_f_name
            
        fid=open(mod_gamma_f_name,'w')
        line="#Slice\t%24s"%"y"+"\t%24s"%"Circulation"+"\n"
        fid.write(line)
        i=0
        for i in range(len(self.__gamma)):
            line=str(i)+"\t%24.16e"%y[i]+"\t%24.16e"%self.__gamma[i]+"\n"
            fid.write(line)
        fid.close()
        
        fid=open(self.get_tag()+'_iAoA.dat','w')
        line="#Slice\t%24s"%"y"+"\t%24s"%"iAoA"+"\t%24s"%"iAoA_deg"+"\n"
        fid.write(line)
        i=0
        for i in range(len(self.__gamma)):
            line=str(i)+"\t%24.16e"%y[i]+"\t%24.16e"%self.__iAoA[i]+"\t%24.16e"%(self.__iAoA[i]*self.RAD_TO_DEG)+"\n"
            fid.write(line)
        fid.close()
Esempio n. 5
0
wing_param.import_BC_from_file('input_parameters.par')
wing_param.build_linear_airfoil(OC, AoA0=0.0, set_as_ref=True)
wing_param.build_airfoils_from_ref()
wing_param.update()
wing_param.plot()


N = wing_param.get_n_sect()
iAoA0=numpy.zeros(N)

DLLM = DLLMSolver('test',wing_param,OC)

NRPb = NewtonRaphsonProblem(iAoA0, DLLM.comp_R, DLLM.comp_dpR_dpiAoA)
NRPb.set_relax_factor(0.99)
NRPb.set_stop_residual(1.e-9)
NRPb.set_max_iterations(100)

iAoA=NRPb.solve()

DLLM.set_direct_computed()
print iAoA

DLLM.comp_dpR_dpchi()
dpRdpthetaY=DLLM.comp_dpR_dpthetaY()
print 'dpRdpthetaY=',dpRdpthetaY

print DLLM.get_iAoA()

DLLM.run_post()
DLLM.run_adjoint()
Esempio n. 6
0
class DLLMDirect:
    """
    Direct solver for the lifting line wing model
    """
    DEG_TO_RAD = np.pi / 180.
    RAD_TO_DEG = 180. / np.pi

    def __init__(self, LLW, verbose = 0):
        self.__LLW = LLW
        self.__verbose = verbose
        self.__computed = False
        self.__gamma_f_name = None

        # initialize local variables
        self.__init_local_variables()

        # initialize the Newton-Raphson problem
        self.__NRPb = None
        self.__init_Newton_Raphson()

    #-- Accessors
    def get_tag(self):
        return self.__LLW.get_tag()
    
    def get_grad_active(self):
        return self.__LLW.get_grad_active()

    def get_geom(self):
        return self.__LLW.get_geom()

    def get_airfoils(self):
        return self.__LLW.get_airfoils()

    def get_K(self):
        return self.__LLW.get_K()

    def get_dK_dchi(self):
        return self.__LLW.get_dK_dchi()

    def get_N(self):
        return self.get_geom().get_n_sect()

    def get_ndv(self):
        return self.get_geom().get_ndv()

    def get_OC(self):
        return self.__LLW.get_OC()

    def get_iAoA(self):
        return self.__iAoA

    def get_localAoA(self):
        return self.__localAoA

    def get_R(self):
        return self.__R

    def get_dpR_dpiAoA(self):
        return self.__dpR_dpiAoA

    def get_dpR_dpchi(self):
        return self.__dpR_dpchi

    def get_dplocalAoA_dpiAoA(self):
        return self.__dplocalAoA_dpiAoA

    def get_dplocalAoA_dpAoA(self):
        return self.__dplocalAoA_dpAoA

    def get_dplocalAoA_dpchi(self):
        return self.__dplocalAoA_dpchi

    def get_dplocalAoA_dpthetaY(self):
        return self.__dplocalAoA_dpthetaY
    
    def get_convergence_history(self):
        """
        Accessor to the last computation convergence history as a list of residuals normalized by the first iteration residual.
        """
        return self.__residuals_hist

    def is_computed(self):
        return self.__computed

    #-- Setters
    def set_computed(self, bool=True):
        self.__computed = bool

    def set_gamma_file_name(self, gamma_f_name):
        self.__gamma_f_name = gamma_f_name

    #-- Newton-Raphson related methods
    def __init_Newton_Raphson(self):
        N = self.get_N()
        iAoA0 = zeros(N)
        self.comp_R(iAoA0)
        self.comp_dpR_dpiAoA(iAoA0)
        self.__NRPb = NewtonRaphsonProblem(iAoA0,self.comp_R,self.comp_dpR_dpiAoA,verbose = self.__verbose)
        self.__NRPb.set_relax_factor(0.99)
        self.__NRPb.set_stop_residual(1.e-9)
        self.__NRPb.set_max_iterations(100)

    def set_relax_factor(self, relax_factor):
        self.__NRPb.set_relax_factor(relax_factor)

    def set_stop_residual(self, residual):
        self.__NRPb.set_stop_residual(residual)

    def set_max_iterations(self, max_it):
        self.__NRPb.set_max_iterations(max_it)

    def set_method(self, method):
        self.__NRPb.set_method(method)

    #-- Computation related methods
    def run(self):
        grad_active = self.get_grad_active()
        self.__NRPb.solve()
        self.set_computed(True)
        self.write_gamma_to_file()
        if grad_active:
            self.comp_dpR_dpchi()
            
    def __init_local_variables(self):
        # Initializing local variables for lifting line computations
        # Residual variables
        N = self.get_N()
        ndv = self.get_ndv()
        grad_active = self.get_grad_active()
        self.__R = zeros([N])
        self.__dpR_dpiAoA = None
        self.__dpR_dpchi = None
        self.__dpR_dpthetaY = None
        self.__dpR_dpAoA = None

        # Angle of attack variables
        self.__localAoA = zeros([N])
        self.__dplocalAoA_dpiAoA = diag(ones([N]))  # This is a constant matrix
        self.__dplocalAoA_dpthetaY = diag(ones([N]))  # This is a constant matrix
        self.__dplocalAoA_dpAoA = ones(N)
        if grad_active:
            self.__dplocalAoA_dpchi = zeros([N, ndv])
        else:
            self.__dplocalAoA_dpchi = None

        # Induced angle of attack variables
        self.__iAoA = None
        self.__iAoANew = None
        if grad_active:
            self.__dpiAoAnew_dpchi = zeros([N, ndv])
        else:
            self.__dpiAoAnew_dpchi = None
        self.__dpiAoAnew_dpiAoA = None

        # Circulation variables
        self.__gamma = zeros(N)
        self.__dpgamma_dpiAoA = None
        self.__dpgamma_dpthetaY = None
        self.__dpgamma_dpAoA = None
        self.__dpgamma_dplocalAoA = zeros([N, N])
        if grad_active:
            self.__dpgamma_dpchi = zeros([N, ndv])
        else:
            self.__dpgamma_dpchi = None
            
    #-- Residual related methods
    def comp_R(self, iAoA):
        self.__iAoA = iAoA
        self.__compute_localAoA()
        self.__compute_gamma()
        self.__compute_iAoAnew()

        self.__R = self.__iAoA - self.__iAoANew
        

        return self.__R

    def comp_dpR_dpiAoA(self, iAoA):
        N = self.get_N()
#        R = self.comp_R(iAoA)

        # dplocalAoA_dpiAoA is a constant matrix, no need to compute it
        # (self.__dplocalAoA_dpiAoA)
        self.__compute_dpgamma_dpiAoA()
        self.__compute_dpiAoAnew_dpiAoA()

        self.__dpR_dpiAoA = np.diag(ones([N])) - self.__dpiAoAnew_dpiAoA

        return self.__dpR_dpiAoA

    def comp_dpR_dpchi(self):
        self.__compute_dplocalAoA_dpchi()
        self.__compute_dpgamma_dpchi()
        self.__compute_dpiAoAnew_dpchi()
        self.__dpR_dpchi = -self.__dpiAoAnew_dpchi

        return self.__dpR_dpchi

    def comp_dpR_dpthetaY(self):
        K = self.get_K()
        self.__compute_dpgamma_dpthetaY()
        self.__dpR_dpthetaY = -dot(K, self.__dpgamma_dpthetaY)

        return self.__dpR_dpthetaY

    def comp_dpR_dpAoA(self):
        K = self.get_K()
        self.__compute_dpgamma_dpAoA()
        self.__dpR_dpAoA = -dot(K, self.__dpgamma_dpAoA)

        return self.__dpR_dpAoA

    def __compute_dpgamma_dpAoA(self):
        N = self.get_N()
        
        for i in xrange(N):
            self.__dpgamma_dplocalAoA[i,i] = self.get_airfoils()[i].dgamma_dAoA

        self.__dpgamma_dpAoA = dot(self.__dpgamma_dplocalAoA,self.__dplocalAoA_dpAoA)

    def __compute_dpgamma_dpthetaY(self):
        N = self.get_N()
        for i in xrange(N):
            self.__dpgamma_dplocalAoA[i,i] = self.get_airfoils()[i].dgamma_dAoA

        self.__dpgamma_dpthetaY = dot(self.__dpgamma_dplocalAoA,self.__dplocalAoA_dpthetaY)

    def __compute_dplocalAoA_dpchi(self):
        N = self.get_N()
        twist_grad = self.get_geom().get_twist_grad()
        AoA_grad = self.get_geom().get_AoA_grad()
        if AoA_grad is None:
            self.__dplocalAoA_dpchi =  twist_grad
        else:
            for i in xrange(N):
                self.__dplocalAoA_dpchi[i, :] = AoA_grad[:] + twist_grad[i, :]

    def __compute_dpgamma_dpchi(self):
        N = self.get_N()
        for i in xrange(N):
            self.__dpgamma_dpchi[i,:] = self.get_airfoils()[i].dgamma_dchi

        self.__dpgamma_dpchi = self.__dpgamma_dpchi + dot(self.__dpgamma_dplocalAoA, self.__dplocalAoA_dpchi)

    def __compute_dpiAoAnew_dpchi(self):
        K = self.get_K()
        dK_dchi = self.get_dK_dchi()
        ndv = self.get_ndv()
        self.__dpiAoAnew_dpchi = dot(K, self.__dpgamma_dpchi)
        for n in xrange(ndv):
            self.__dpiAoAnew_dpchi[:, n] += dot(dK_dchi[:, :, n], self.__gamma)

    def __compute_localAoA(self):
        N = self.get_N()
        Thetay = self.get_geom().get_thetaY()
        twist = self.get_geom().get_twist()
        AoA = self.get_geom().get_AoA()
        if AoA is None:
            AoA = self.get_OC().get_AoA_rad()
        else:
            self.get_OC().set_AoA(AoA * 180. / np.pi)

        # Why this formula ? twist increases the local airfoil angle of attack normally...
        # self.__localAoA=alpha-iaOa-self.get_wing_geom().get_twist()
        self.__localAoA = AoA + twist + self.__iAoA + Thetay

        for i in xrange(N):
            if self.__localAoA[i] > np.pi / 2. or self.__localAoA[i] < -np.pi / 2.:
                raise Exception("Local angle of attack out of bounds [-pi/2, pi/2]")

    def __compute_gamma(self):
        """
        Update the circulation
        """
        N = self.get_N()
        Mach = self.get_OC().get_Mach()
        for i in xrange(N):
            self.get_airfoils()[i].compute(self.__localAoA[i],Mach)
            self.__gamma[i] = self.get_airfoils()[i].gamma
            if np.isnan(self.get_airfoils()[i].gamma):
                af = self.get_airfoils()[i]
                print 'Lref = ',af.get_Lref()
                print 'Sref = ',af.get_Sref()
                print 'Cl = ',af.Cl

    def __compute_dpgamma_dpiAoA(self):
        N = self.get_N()
        for i in xrange(N):
            self.__dpgamma_dplocalAoA[i,i] = self.get_airfoils()[i].dgamma_dAoA

        self.__dpgamma_dpiAoA = dot(self.__dpgamma_dplocalAoA, self.__dplocalAoA_dpiAoA)

    def __compute_iAoAnew(self):
        '''
        Computes the induced angle on an airfoil for a given circulation on the wing.
        '''
        K = self.get_K()
        self.__iAoANew = dot(K, self.__gamma)

    def __compute_dpiAoAnew_dpiAoA(self):
        """
        Computes the derivative dpiAoAnew_dpiAoA
        """
        K = self.get_K()
        self.__dpiAoAnew_dpiAoA = dot(K, self.__dpgamma_dpiAoA)

    def write_gamma_to_file(self):
        '''
        Writes the circulation repartition in a file
        '''
        y = self.get_geom().get_XYZ()[1, :]
        if self.__gamma_f_name is None:
            gamma_f_name = 'gamma.dat'
        else:
            gamma_f_name = self.__gamma_f_name

        mod_gamma_f_name = self.get_tag() + '_' + gamma_f_name

        fid = open(mod_gamma_f_name, 'w')
        line = "#Slice\t%24s" % "y" + "\t%24s" % "Circulation" + "\n"
        fid.write(line)
        i = 0
        for i in range(len(self.__gamma)):
            line = str(i) + "\t%24.16e" % y[i] + \
                "\t%24.16e" % self.__gamma[i] + "\n"
            fid.write(line)
        fid.close()

        fid = open(self.get_tag() + '_iAoA.dat', 'w')
        line = "#Slice\t%24s" % "y" + "\t%24s" % "iAoA" + \
            "\t%24s" % "iAoA_deg" + "\n"
        fid.write(line)
        i = 0
        for i in range(len(self.__gamma)):
            line = str(i) + "\t%24.16e" % y[i] + "\t%24.16e" % self.__iAoA[
                i] + "\t%24.16e" % (self.__iAoA[i] * self.RAD_TO_DEG) + "\n"
            fid.write(line)
        fid.close()
    
    def plot(self):
        name = self.get_tag()
        Y_list = self.get_geom().get_XYZ()[1,:]
        plt.xlim(1.1*Y_list[0], 1.1*Y_list[-1])
        plt.xlabel('y')
        plt.ylabel('gamma')
        plt.plot(Y_list,self.__gamma)
        plt.rc("font", size=14)
        plt.savefig(name+"_gamma_distrib.png",format='png')
        plt.close()
        
        plt.xlim(1.1*Y_list[0], 1.1*Y_list[-1])
        plt.xlabel('y')
        plt.ylabel('iAoA')
        plt.plot(Y_list,self.__iAoA*self.RAD_TO_DEG)
        plt.rc("font", size=14)
        plt.savefig(name+"_iAoA_distrib.png",format='png')
        plt.close()
Esempio n. 7
0
class DLLMTargetLift(DLLMSolver):
    ERROR_MSG='ERROR in DLLMTargetLift.'
    def __init__(self, tag, geom, OC,verbose = 0, grad_active=True):
        self.__verbose = verbose
        DLLMSolver.__init__(self, tag, geom, OC, verbose = self.__verbose, grad_active=grad_active)
        
        self.__N            = self.get_geom().get_n_sect()
        self.__ndv          = self.get_geom().get_ndv()
        
        self.__R_TL         = numpy.zeros(self.__N+1)
        self.__dpR_TL_dpW   = numpy.zeros((self.__N+1,self.__N+1))
        self.__dpR_TL_dpchi = numpy.zeros((self.__N+1,self.__ndv))
        
        self.__dpF_list_dpW = None 
        
        self.__target_Lift    = 0.

        # initialize the Newton-Raphson problem
        self.__NRPb = None 
        self.__init_Newton_Raphson()
        
    # -- Accessors
    def get_target_Lift(self):
        return self.__target_Lift
    
    def set_target_Lift(self, target):
        self.__target_Lift   = target
        
    #-- Newton-Raphson related methods
    def __init_Newton_Raphson(self):
        W0= numpy.zeros(self.__N+1)
        self.__NRPb = NewtonRaphsonProblem(W0, self.comp_R_TL, self.comp_dpR_TL_dpW, verbose = self.__verbose)
        self.__NRPb.set_relax_factor(0.99)
        self.__NRPb.set_stop_residual(1.e-9)
        self.__NRPb.set_max_iterations(100)
        
    def set_relax_factor(self, relax_factor):
        self.__NRPb.set_relax_factor(relax_factor)
    
    def set_stop_residual(self, residual):
        self.__NRPb.set_stop_residual(residual)
        
    def set_max_iterations(self, max_it):
        self.__NRPb.set_max_iterations(max_it)
    
    def set_method(self, method):
        self.__NRPb.set_method(method)

    #-- Residual Related method
    def comp_R_TL(self, W):
        DLLMDirect = self.get_DLLMDirect()
        DLLMPost   = self.get_DLLMPost()
        OC = self.get_OC()
        
        iAoA = W[0:self.__N]
        AoA  = W[self.__N]
        OC.set_AoA_rad(AoA)
        
        R    = DLLMDirect.comp_R(iAoA)
        DLLMPost.run(F_list_names=['Lift'])

        self.__R_TL[:self.__N] = R[:]
        self.__R_TL[self.__N]  = DLLMPost.Lift- self.__target_Lift
        
        return self.__R_TL
    
    def comp_dpR_TL_dpW(self, W):
        DLLMDirect = self.get_DLLMDirect()
        DLLMPost   = self.get_DLLMPost()
        OC =  self.get_OC()
        
        iAoA = W[0:self.__N]
        AoA  = W[self.__N]
        OC.set_AoA_rad(AoA)
        
        # Init information
        DLLMDirect.comp_R(iAoA)
        dpR_dpiAoA  = DLLMDirect.comp_dpR_dpiAoA(iAoA)
        dpR_dpAoA   = DLLMDirect.comp_dpR_dpAoA()
        
        DLLMPost.run(F_list_names=['Lift'])
        dpLift_dpiAoA = DLLMPost.dpLift_dpiAoA
        dpLift_dpAoA  = DLLMPost.dpLift_dpAoA
      
        self.__dpR_TL_dpW[0:self.__N,0:self.__N] = dpR_dpiAoA[:,:]
        self.__dpR_TL_dpW[self.__N,0:self.__N]   = dpLift_dpiAoA[:]
        
        self.__dpR_TL_dpW[0:self.__N,self.__N]   = dpR_dpAoA[:]
        self.__dpR_TL_dpW[self.__N,self.__N]     = dpLift_dpAoA
        
        return self.__dpR_TL_dpW
    
    def get_R(self):
        return self.__R_TL
    
    def get_dpR_dpW(self):
        return self.__dpR_TL_dpW
    
    def get_dpR_dpchi(self):
        DLLMDirect = self.get_DLLMDirect()
        DLLMPost   = self.get_DLLMPost()
        dpR_dpchi    = DLLMDirect.get_dpR_dpchi()
        dpLift_dpchi = DLLMPost.dpLift_dpchi
        
        self.__dpR_TL_dpchi[:self.__N,:] = dpR_dpchi[:,:]
        self.__dpR_TL_dpchi[self.__N,:]  = dpLift_dpchi[:]
        
        return self.__dpR_TL_dpchi
    
    def get_dpF_list_dpW(self):
        DLLMPost   = self.get_DLLMPost()
        
        dpF_list_dpiAoA = DLLMPost.get_dpF_list_dpiAoA()
        dpF_list_dpAoA  = DLLMPost.get_dpF_list_dpAoA()
        
        dim = len(dpF_list_dpiAoA)
        
        self.__dpF_list_dpW = numpy.zeros((dim,self.__N+1))
        
        for i in xrange(dim):
            self.__dpF_list_dpW[i,:self.__N] = dpF_list_dpiAoA[i,:]
            self.__dpF_list_dpW[i,self.__N]  = dpF_list_dpAoA[i]
        
        return self.__dpF_list_dpW
    
    
    def run_direct(self):
        DLLMDirect = self.get_DLLMDirect()
#        W0= numpy.zeros(self.__N+1)
#        self.__NRPb.valid_jacobian(W0, iprint=True)
        self.__NRPb.solve()
        DLLMDirect.set_computed(True)
        DLLMDirect.write_gamma_to_file()
        if self.get_grad_active():
            DLLMDirect.comp_dpR_dpchi()