예제 #1
0
파일: VLM.py 프로젝트: Nasrollah/SHARPy
def Run_Cpp_Solver_VLM(VMOPTS, VMINPUT, VMUNST=None, AELOPTS=None):

    # init grid
    if VMUNST == None:
        # Set up variables assuming no unsteady motion
        VMUNST = MyStruct()
        VMUNST.PsiA_G = np.array([0.0, 0.0, 0.0])
        VMUNST.VelA_G = np.array([0.0, 0.0, 0.0])
        VMUNST.OmegaA_G = np.array([0.0, 0.0, 0.0])
        VMUNST.OriginA_G = np.array([0.0, 0.0, 0.0])

    if AELOPTS == None:
        # Set up defaults for grid generation.
        AELOPTS = MyStruct()
        AELOPTS.ElasticAxis = 0.0

    # Initialise DerivedTypes for PyBeam initialization.
    XBOPTS = DerivedTypes.Xbopts()
    XBINPUT = DerivedTypes.Xbinput(2, VMOPTS.N.value, VMINPUT.b)
    # Create a dummy stiffness matrix to avoid errors.
    XBINPUT.BeamStiffness = np.eye(6, dtype=ct.c_double)
    # Use PyBeam to define reference beam (elastic axis).
    XBINPUT, XBOPTS, NumNodes_tot, XBELEM, PosIni, PsiIni,\
            XBNODE, NumDof = BeamInit.Static(XBINPUT, XBOPTS)
    # Delete unnecessary variables.
    del XBELEM, XBNODE, NumDof
    # Copy reference beam to current (deformed) variables.
    PosDefor = PosIni.copy(order='F')
    PsiDefor = PsiIni.copy(order='F')
    # Declare empty array for beam DoF rates.
    PosDotDef = np.zeros_like(PosDefor, ct.c_double, 'F')
    PsiDotDef = np.zeros_like(PsiDefor, ct.c_double, 'F')

    # Check the specified inputs from the PyAero have been properly applied.
    assert NumNodes_tot.value - 1 == VMOPTS.N.value, "Initialisation wrong"

    # Initialise section coordinates.
    Section = InitSection(VMOPTS, VMINPUT, AELOPTS.ElasticAxis)

    # Initialise origin and orientation of surface velocities in a-frame
    CGa = Psi2TransMat(VMUNST.PsiA_G)
    VelA_A = np.dot(CGa.T, VMUNST.VelA_G)
    OmegaA_A = np.dot(CGa.T, VMUNST.OmegaA_G)

    # Declare empty array for aerodynamic grid and velocities.
    Zeta = np.zeros((VMOPTS.M.value + 1, VMOPTS.N.value + 1, 3), ct.c_double,
                    'C')
    ZetaDot = np.zeros((VMOPTS.M.value + 1, VMOPTS.N.value + 1, 3),
                       ct.c_double, 'C')

    # Initialise aerodynamic grid and velocities.
    CoincidentGrid(PosDefor, PsiDefor, Section, VelA_A, OmegaA_A, PosDotDef,
                   PsiDotDef, XBINPUT, Zeta, ZetaDot, VMUNST.OriginA_G,
                   VMUNST.PsiA_G, VMINPUT.ctrlSurf)

    # init wake
    ZetaStar, GammaStar = InitSteadyWake(VMOPTS, VMINPUT, Zeta)

    # init external velocities
    Uext = InitSteadyExternalVels(VMOPTS, VMINPUT)

    # Solver variables.
    Gamma = np.zeros((VMOPTS.M.value, VMOPTS.N.value), ct.c_double, 'C')
    Forces = np.zeros((VMOPTS.M.value + 1, VMOPTS.N.value + 1, 3), ct.c_double,
                      'C')

    # Solve
    UVLMLib.Cpp_Solver_VLM(Zeta, ZetaDot, Uext, ZetaStar, VMOPTS, Forces,
                           Gamma, GammaStar)

    # Print tecplot file to check wake and grid etc
    Variables = ['X', 'Y', 'Z', 'Gamma']

    # write header

    Filename = Settings.OutputDir + Settings.OutputFileRoot + 'AeroGrid.dat'

    FileObject = PostProcess.WriteAeroTecHeader(Filename, 'Default', Variables)

    # write surface zone data
    PostProcess.WriteAeroTecZone(FileObject, 'Surface', Zeta, -1, 0, 0.0,
                                 Variables, False, Gamma)

    # write wake data
    PostProcess.WriteAeroTecZone(FileObject, 'Wake', ZetaStar, -1, 0, 0.0,
                                 Variables, False, GammaStar)

    # close file
    PostProcess.CloseAeroTecFile(FileObject)

    if Settings.WriteUVLMdebug == True:
        debugFile = Settings.OutputDir + 'gamma_1degBeta.dat'
        np.savetxt(debugFile, Gamma.flatten('C'))

    # post process to get coefficients
    return PostProcess.GetCoeffs(VMOPTS, Forces, VMINPUT, VMUNST.VelA_G)
예제 #2
0
파일: UVLM.py 프로젝트: cndaqiang/SHARPy
def Run_Cpp_Solver_UVLM(VMOPTS,
                        VMINPUT,
                        VMUNST,
                        AELOPTS,
                        vOmegaHist=None,
                        eta0=None,
                        numNodesElem=2,
                        delEtaHist=None):
    """@brief UVLM solver with prescribed inputs.
       @param vOmegaHist None, or np.array history of velocities of the A-frame, expressed in A-frame.
       @param eta0 None, or tuple containing reference disps, rots, and gamma.
       @param delEtaHist None, or tuple of np.array histories of underlying beam disps, rotations, vels, and rotvels in A-frame."""

    # Initialise DerivedTypes for PyBeam initialisation.
    XBOPTS = DerivedTypes.Xbopts()
    if numNodesElem == 2:
        beamElems = VMOPTS.N.value
    elif numNodesElem == 3:
        beamElems = int(VMOPTS.N.value / 2)
    else:
        raise ValueError('numNodesElem should be 2 or 3')

    XBINPUT = DerivedTypes.Xbinput(numNodesElem, beamElems, VMINPUT.b)
    # Create a dummy stiffness matrix to avoid errors.
    XBINPUT.BeamStiffness = np.eye(6, 6, 0, ct.c_double)
    # Use PyBeam to define reference beam (elastic axis).
    XBINPUT, XBOPTS, NumNodes_tot, XBELEM, PosIni, PsiIni,\
            XBNODE, NumDof = BeamInit.Static(XBINPUT, XBOPTS)
    # Delete unnecessary variables.
    del XBELEM, XBNODE, NumDof
    # Copy reference beam to current (deformed) variables.
    if eta0 is None:
        PosDefor = PosIni.copy(order='F')
        PsiDefor = PsiIni.copy(order='F')
    else:
        PosDefor = eta0[0]  #+delEtaHist[0][:,:,0]
        PsiDefor = eta0[1]  #+delEtaHist[1][:,:,:,0]

    if delEtaHist is None:
        # Declare empty array for beam DoF rates.
        PosDotDef = np.zeros_like(PosDefor, ct.c_double, 'F')
        PsiDotDef = np.zeros_like(PsiDefor, ct.c_double, 'F')
    else:
        PosDotDef = delEtaHist[2][:, :, 0]
        PsiDotDef = delEtaHist[3][:, :, :, 0]

    # Check the specified inputs from the PyAero have been properly applied.
    assert NumNodes_tot.value - 1 == VMOPTS.N.value, "Initialisation wrong"

    # Initialise section coordinates.
    Section = InitSection(VMOPTS, VMINPUT, AELOPTS.ElasticAxis)

    # Initialise origin and orientation of surface velocities in a-frame
    CGa = Psi2TransMat(VMUNST.PsiA_G)
    if vOmegaHist is None:
        VelA_A = np.dot(CGa.T, VMUNST.VelA_G)
        OmegaA_A = np.dot(CGa.T, VMUNST.OmegaA_G)
    else:
        VelA_A = np.dot(CGa.T, vOmegaHist[0, 1:4])
        OmegaA_A = np.dot(CGa.T, vOmegaHist[0, 4:7])

    # Declare empty array for aerodynamic grid and velocities.
    Zeta = np.zeros((VMOPTS.M.value + 1, VMOPTS.N.value + 1, 3), ct.c_double,
                    'C')
    ZetaDot = np.zeros((VMOPTS.M.value + 1, VMOPTS.N.value + 1, 3),
                       ct.c_double, 'C')

    # Initialise aerodynamic grid and velocities.
    CoincidentGrid(PosDefor, PsiDefor, Section, VelA_A, OmegaA_A, PosDotDef,
                   PsiDotDef, XBINPUT, Zeta, ZetaDot, VMUNST.OriginA_G,
                   VMUNST.PsiA_G, VMINPUT.ctrlSurf)

    # Initialise wake for unsteady solution.
    if vOmegaHist is None:
        velForWake = VMUNST.VelA_G
    else:
        velForWake = vOmegaHist[0, 1:4]

    ZetaStar, GammaStar = InitSteadyWake(VMOPTS, VMINPUT, Zeta, velForWake)

    # Initialise external velocities.
    Uext = InitSteadyExternalVels(VMOPTS, VMINPUT)

    # Declare empty solver variables.
    Forces = np.zeros_like(Zeta, ct.c_double, 'C')
    Gamma = np.zeros((VMOPTS.M.value, VMOPTS.N.value), ct.c_double, 'C')
    AIC = np.zeros(
        (VMOPTS.M.value * VMOPTS.N.value, VMOPTS.M.value * VMOPTS.N.value),
        ct.c_double, 'C')
    BIC = np.zeros(
        (VMOPTS.M.value * VMOPTS.N.value, VMOPTS.M.value * VMOPTS.N.value),
        ct.c_double, 'C')

    if type(eta0) is tuple:
        Gamma[:, :] = eta0[2]
        for j in range(VMOPTS.N.value):
            GammaStar[:, j] = Gamma[VMOPTS.M.value - 1, j]

    # Open tecplot file object."
    Variables = ['X', 'Y', 'Z', 'Gamma']
    Filename = Settings.OutputDir + Settings.OutputFileRoot + 'AeroGrid.dat'
    FileObject = PostProcess.WriteAeroTecHeader(Filename, 'Default', Variables)

    # Initialise vector of time steps.
    Time = np.arange(0.0, VMUNST.FinalTime, VMOPTS.DelTime.value)
    # Create Array for storing time and coefficient data.
    CoeffHistory = np.zeros((len(Time), 4))

    # Loop through time steps.
    for iTimeStep in range(len(Time)):

        # Set forces array to zero (+= operator used in C++ library).
        Forces[:, :, :] = 0.0

        if iTimeStep > 0:

            # Update geometry.
            if vOmegaHist is None:
                VMUNST.OriginA_G[:] += VMUNST.VelA_G[:] * VMOPTS.DelTime.value
                # TODO: update OmegaA_A, PsiA_A in pitching problem.
            else:
                VMUNST.OriginA_G[:] += vOmegaHist[iTimeStep,
                                                  1:4] * VMOPTS.DelTime.value
                VelA_A = vOmegaHist[iTimeStep, 1:4]
                # TODO: update OmegaA_A, PsiA_G in pitching problem.

            if type(eta0) is tuple:
                PosDefor = eta0[0]
                PsiDefor = eta0[1]

            if type(delEtaHist) is tuple:
                PosDefor = PosDefor + delEtaHist[0][:, :, iTimeStep]
                PsiDefor = PsiDefor + delEtaHist[1][:, :, :, iTimeStep]
                PosDotDef = delEtaHist[
                    2][:, :, iTimeStep]  #TODO: PosDefor seems to be correct!
                PsiDotDef = delEtaHist[3][:, :, :, iTimeStep]

            # Update control surface defintion.
            if VMINPUT.ctrlSurf is not None:
                VMINPUT.ctrlSurf.update(Time[iTimeStep])

            # Update aerodynamic surface.
            CoincidentGrid(PosDefor, PsiDefor, Section, VelA_A, OmegaA_A,
                           PosDotDef, PsiDotDef, XBINPUT, Zeta, ZetaDot,
                           VMUNST.OriginA_G, VMUNST.PsiA_G, VMINPUT.ctrlSurf)

            # Convect wake downstream.
            ZetaStar = np.roll(ZetaStar, 1, axis=0)
            GammaStar = np.roll(GammaStar, 1, axis=0)
            # Overwrite 1st row with with new trailing-edge position.
            ZetaStar[0, :] = Zeta[VMOPTS.M.value, :]
            # Overwrite Gamma with TE value from previous time step.
            GammaStar[0, :] = Gamma[VMOPTS.M.value - 1, :]

        # END if iTimeStep > 1

        # Calculate forces on aerodynamic grid.
        if iTimeStep == 0:
            sav = VMOPTS.NewAIC
            VMOPTS.NewAIC = ct.c_bool(True)

        UVLMLib.Cpp_Solver_VLM(Zeta, ZetaDot, Uext, ZetaStar, VMOPTS, Forces,
                               Gamma, GammaStar, AIC, BIC)

        if iTimeStep == 0:
            VMOPTS.NewAIC = sav
            del sav

        #print(PostProcess.GetCoeffs(VMOPTS, Forces, VMINPUT, VMUNST.VelA_G))

        CoeffHistory[iTimeStep, 0] = Time[iTimeStep]
        CoeffHistory[iTimeStep,
                     1:] = PostProcess.GetCoeffs(VMOPTS, Forces, VMINPUT,
                                                 VMUNST.VelA_G)

        # Write aerodynamic surface data as tecplot zone data.
        PostProcess.WriteAeroTecZone(FileObject, 'Surface', Zeta,\
                                     iTimeStep, len(Time),\
                                     Time[iTimeStep], Variables, False, Gamma)

        # Write wake data as tecplot zone data.
        PostProcess.WriteAeroTecZone(FileObject, 'Wake', ZetaStar,\
                                    iTimeStep, len(Time),\
                                    Time[iTimeStep], \
                                    Variables, False, GammaStar)

        # Rollup due to external velocities.
        ZetaStar[:, :] += VMINPUT.U_infty * VMOPTS.DelTime.value

    # END for iTimeStep

    # Close tecplot file object.
    PostProcess.CloseAeroTecFile(FileObject)

    # write geometry and circ dist. to file for matlab
    if iTimeStep == len(Time) - 1 and False:
        savemat('/home/rjs10/Desktop/uvlmOut.mat', {
            'zeta': Zeta.flatten('C'),
            'zetaW': ZetaStar.flatten('C'),
            'gamma': Gamma.flatten('C'),
            'gammaW': GammaStar.flatten('C')
        },
                False,
                oned_as='column')

    return CoeffHistory
예제 #3
0
def Run_Cpp_Solver_UVLM(VMOPTS, VMINPUT, VMUNST, AELOPTS):
    """@brief UVLM solver with prescribed inputs."""

    # Initialise DerivedTypes for PyBeam initialisation.
    XBOPTS = DerivedTypes.Xbopts()
    XBINPUT = DerivedTypes.Xbinput(2, VMOPTS.N.value, VMINPUT.b)
    # Create a dummy stiffness matrix to avoid errors.
    XBINPUT.BeamStiffness = np.eye(6, 6, 0, ct.c_double)
    # Use PyBeam to define reference beam (elastic axis).
    XBINPUT, XBOPTS, NumNodes_tot, XBELEM, PosIni, PsiIni,\
            XBNODE, NumDof = BeamInit.Static(XBINPUT, XBOPTS)
    # Delete unnecessary variables.
    del XBELEM, XBNODE, NumDof
    # Copy reference beam to current (deformed) variables.
    PosDefor = PosIni.copy(order='F')
    PsiDefor = PsiIni.copy(order='F')
    # Declare empty array for beam DoF rates.
    PosDotDef = np.zeros_like(PosDefor, ct.c_double, 'F')
    PsiDotDef = np.zeros_like(PsiDefor, ct.c_double, 'F')

    # Check the specified inputs from the PyAero have been properly applied.
    assert NumNodes_tot.value - 1 == VMOPTS.N.value, "Initialisation wrong"

    # Initialise section coordinates.
    Section = InitSection(VMOPTS, VMINPUT, AELOPTS.ElasticAxis)

    # Initialise origin and orientation of surface velocities in a-frame
    CGa = Psi2TransMat(VMUNST.PsiA_G)
    VelA_A = np.dot(CGa.T, VMUNST.VelA_G)
    OmegaA_A = np.dot(CGa.T, VMUNST.OmegaA_G)

    # Declare empty array for aerodynamic grid and velocities.
    Zeta = np.zeros((VMOPTS.M.value + 1, VMOPTS.N.value + 1, 3), ct.c_double,
                    'C')
    ZetaDot = np.zeros((VMOPTS.M.value + 1, VMOPTS.N.value + 1, 3),
                       ct.c_double, 'C')

    # Initialise aerodynamic grid and velocities.
    CoincidentGrid(PosDefor, PsiDefor, Section, VelA_A, OmegaA_A, PosDotDef,
                   PsiDotDef, XBINPUT, Zeta, ZetaDot, VMUNST.OriginA_G,
                   VMUNST.PsiA_G, VMINPUT.ctrlSurf)

    # Initialise wake for unsteady solution.
    ZetaStar, GammaStar = InitSteadyWake(VMOPTS, VMINPUT, Zeta, VMUNST.VelA_G)

    # Initialise external velocities.
    Uext = InitSteadyExternalVels(VMOPTS, VMINPUT)

    # Declare empty solver variables.
    Forces = np.zeros_like(Zeta, ct.c_double, 'C')
    Gamma = np.zeros((VMOPTS.M.value, VMOPTS.N.value), ct.c_double, 'C')
    AIC = np.zeros(
        (VMOPTS.M.value * VMOPTS.N.value, VMOPTS.M.value * VMOPTS.N.value),
        ct.c_double, 'C')
    BIC = np.zeros(
        (VMOPTS.M.value * VMOPTS.N.value, VMOPTS.M.value * VMOPTS.N.value),
        ct.c_double, 'C')

    # Open tecplot file object."
    Variables = ['X', 'Y', 'Z', 'Gamma']
    Filename = Settings.OutputDir + Settings.OutputFileRoot + 'AeroGrid.dat'
    FileObject = PostProcess.WriteAeroTecHeader(Filename, 'Default', Variables)

    # Initialise vector of time steps.
    Time = np.arange(0.0, VMUNST.FinalTime + VMUNST.DelTime, VMUNST.DelTime)
    # Create Array for storing time and coefficient data.
    CoeffHistory = np.zeros((len(Time), 4))

    # Loop through time steps.
    for iTimeStep in range(len(Time)):

        # Set forces array to zero (+= operator used in C++ library).
        Forces[:, :, :] = 0.0

        if iTimeStep > 0:

            # Update geometry.
            VMUNST.OriginA_G[:] += VMUNST.VelA_G[:] * VMUNST.DelTime
            # TODO: update OmegaA_A in pitching problem.

            # Update control surface defintion.
            if VMINPUT.ctrlSurf != None:
                VMINPUT.ctrlSurf.update(Time[iTimeStep])

            # Update aerodynamic surface.
            CoincidentGrid(PosDefor, PsiDefor, Section, VelA_A, OmegaA_A,
                           PosDotDef, PsiDotDef, XBINPUT, Zeta, ZetaDot,
                           VMUNST.OriginA_G, VMUNST.PsiA_G, VMINPUT.ctrlSurf)

            # Convect wake downstream.
            ZetaStar = np.roll(ZetaStar, 1, axis=0)
            GammaStar = np.roll(GammaStar, 1, axis=0)
            # Overwrite 1st row with with new trailing-edge position.
            ZetaStar[0, :] = Zeta[VMOPTS.M.value, :]
            # Overwrite Gamma with TE value from previous time step.
            GammaStar[0, :] = Gamma[VMOPTS.M.value - 1, :]

            # set NewAIC to false.
            if VMINPUT.ctrlSurf == False:
                VMOPTS.NewAIC = ct.c_bool(False)

        # END if iTimeStep > 1

        # Calculate forces on aerodynamic grid.
        UVLMLib.Cpp_Solver_VLM(Zeta, ZetaDot, Uext, ZetaStar, VMOPTS, Forces,
                               Gamma, GammaStar, AIC, BIC)

        #print(PostProcess.GetCoeffs(VMOPTS, Forces, VMINPUT, VMUNST.VelA_G))

        CoeffHistory[iTimeStep, 0] = Time[iTimeStep]
        CoeffHistory[iTimeStep,
                     1:] = PostProcess.GetCoeffs(VMOPTS, Forces, VMINPUT,
                                                 VMUNST.VelA_G)

        # Write aerodynamic surface data as tecplot zone data.
        PostProcess.WriteAeroTecZone(FileObject, 'Surface', Zeta,\
                                     iTimeStep, len(Time),\
                                     Time[iTimeStep], Variables, False, Gamma)

        # Write wake data as tecplot zone data.
        PostProcess.WriteAeroTecZone(FileObject, 'Wake', ZetaStar,\
                                    iTimeStep, len(Time),\
                                    Time[iTimeStep], \
                                    Variables, False, GammaStar)

        # Rollup due to external velocities.
        ZetaStar[:, :] += VMINPUT.U_infty * VMOPTS.DelTime.value

    # END for iTimeStep

    # Close tecplot file object.
    PostProcess.CloseAeroTecFile(FileObject)

    return CoeffHistory