Exemplo n.º 1
0
def biot_panel_fast(zetaC, ZetaPanel, gamma=1.0):
    """
    Induced velocity over point ZetaC of a panel of vertices coordinates
    ZetaPanel and circulaiton gamma, where:
        ZetaPanel.shape=(4,3)=[vertex local number, (x,y,z) component]
    """

    Cfact = cfact_biot * gamma
    q = np.zeros((3, ))

    R_list = zetaC - ZetaPanel
    Runit_list = [R_list[ii] / algebra.norm3d(R_list[ii]) for ii in svec]

    for aa, bb in LoopPanel:

        RAB = ZetaPanel[bb, :] - ZetaPanel[aa, :]  # segment vector
        Vcr = algebra.cross3(R_list[aa], R_list[bb])
        vcr2 = np.dot(Vcr, Vcr)
        if vcr2 < (VORTEX_RADIUS_SQ * algebra.normsq3d(RAB)):
            continue

        q += ((Cfact / vcr2) *
              np.dot(RAB, Runit_list[aa] - Runit_list[bb])) * Vcr

    return q
Exemplo n.º 2
0
def eval_seg_comp_loop(DerP, DerA, DerB, ZetaP, ZetaA, ZetaB, gamma_seg,
                       vortex_radius):
    """
    Derivative of induced velocity Q w.r.t. collocation and segment coordinates
    in format:
        [ (x,y,z) of Q, (x,y,z) of Zeta ]
    Warning: function optimised for performance. Variables are scaled during the
    execution.
    """

    vortex_radius_sq = vortex_radius * vortex_radius
    Cfact = cfact_biot * gamma_seg

    RA = ZetaP - ZetaA
    RB = ZetaP - ZetaB
    RAB = ZetaB - ZetaA
    Vcr = algebra.cross3(RA, RB)
    vcr2 = np.dot(Vcr, Vcr)

    # numerical radious
    if vcr2 < (vortex_radius_sq * algebra.normsq3d(RAB)):
        return

    ### other constants
    ra1, rb1 = algebra.norm3d(RA), algebra.norm3d(RB)
    rainv = 1. / ra1
    rbinv = 1. / rb1
    Tv = RA * rainv - RB * rbinv
    dotprod = np.dot(RAB, Tv)

    ### --------------------------------------------- cross-product derivatives
    # lower triangular part only
    vcr2inv = 1. / vcr2
    vcr4inv = vcr2inv * vcr2inv
    diag_fact = Cfact * vcr2inv * dotprod
    off_fact = -2. * Cfact * vcr4inv * dotprod
    Dvcross = [[diag_fact + off_fact * Vcr[0]**2],
               [off_fact * Vcr[0] * Vcr[1], diag_fact + off_fact * Vcr[1]**2],
               [
                   off_fact * Vcr[0] * Vcr[2], off_fact * Vcr[1] * Vcr[2],
                   diag_fact + off_fact * Vcr[2]**2
               ]]

    ### ------------------------------------------ difference terms derivatives
    Vsc = Vcr * vcr2inv * Cfact
    Ddiff = np.array([RAB * Vsc[0], RAB * Vsc[1], RAB * Vsc[2]])
    dQ_dRAB = np.array([Tv * Vsc[0], Tv * Vsc[1], Tv * Vsc[2]])

    ### ---------------------------------------------- Final assembly (crucial)
    # ps: calling Dvcross_by_skew3d does not slow down execution.

    dQ_dRA = Dvcross_by_skew3d(Dvcross, -RB) \
             + np.dot(Ddiff, der_runit(RA, rainv, -rainv ** 3))
    dQ_dRB = Dvcross_by_skew3d(Dvcross, RA) \
             - np.dot(Ddiff, der_runit(RB, rbinv, -rbinv ** 3))

    DerP += dQ_dRA + dQ_dRB  # w.r.t. P
    DerA -= dQ_dRAB + dQ_dRA  # w.r.t. A
    DerB += dQ_dRAB - dQ_dRB  # w.r.t. B
Exemplo n.º 3
0
def biot_segment(zetaP, zetaA, zetaB, gamma=1.0):
    """
    Induced velocity of segment A_>B of circulation gamma over point P.
    """

    # differences
    ra = zetaP - zetaA
    rb = zetaP - zetaB
    rab = zetaB - zetaA
    ra_norm, rb_norm = algebra.norm3d(ra), algebra.norm3d(rb)
    vcross = algebra.cross3(ra, rb)
    vcross_sq = np.dot(vcross, vcross)

    # numerical radius
    if vcross_sq < (VORTEX_RADIUS_SQ * algebra.normsq3d(rab)):
        return np.zeros((3, ))

    q = ((cfact_biot * gamma / vcross_sq) * \
         (np.dot(rab, ra) / ra_norm - np.dot(rab, rb) / rb_norm)) * vcross

    return q
Exemplo n.º 4
0
def eval_panel_fast_coll(zetaP, ZetaPanel, vortex_radius, gamma_pan=1.0):
    """
    Computes derivatives of induced velocity w.r.t. coordinates of target point,
    zetaP, coordinates. Returns two elements:
        - DerP: derivative of induced velocity w.r.t. ZetaP, with:
            DerP.shape=(3,3) : DerC[ Uind_{x,y,z}, ZetaC_{x,y,z} ]

    The function is based on eval_panel_fast, but does not perform operations
    required to compute the derivatives w.r.t. the panel coordinates.
    """

    vortex_radius_sq = vortex_radius * vortex_radius
    DerP = np.zeros((3, 3))

    ### ---------------------------------------------- Compute common variables
    # these are constants or variables depending only on vertices and P coords
    Cfact = cfact_biot * gamma_pan

    # distance vertex ii-th from P
    R_list = zetaP - ZetaPanel
    r1_list = [algebra.norm3d(R_list[ii]) for ii in svec]
    r1inv_list = [1. / r1_list[ii] for ii in svec]
    Runit_list = [R_list[ii] * r1inv_list[ii] for ii in svec]
    Der_runit_list = [
        der_runit(R_list[ii], r1inv_list[ii], -r1inv_list[ii]**3)
        for ii in svec
    ]

    ### ------------------------------------------------- Loop through segments
    for aa, bb in LoopPanel:

        RAB = ZetaPanel[bb, :] - ZetaPanel[aa, :]  # segment vector
        Vcr = algebra.cross3(R_list[aa], R_list[bb])
        vcr2 = np.dot(Vcr, Vcr)

        if vcr2 < (vortex_radius_sq * algebra.normsq3d(RAB)):
            continue

        Tv = Runit_list[aa] - Runit_list[bb]
        dotprod = np.dot(RAB, Tv)

        ### ----------------------------------------- cross-product derivatives
        # lower triangular part only
        vcr2inv = 1. / vcr2
        vcr4inv = vcr2inv * vcr2inv
        diag_fact = Cfact * vcr2inv * dotprod
        off_fact = -2. * Cfact * vcr4inv * dotprod
        Dvcross = [[diag_fact + off_fact * Vcr[0]**2],
                   [
                       off_fact * Vcr[0] * Vcr[1],
                       diag_fact + off_fact * Vcr[1]**2
                   ],
                   [
                       off_fact * Vcr[0] * Vcr[2], off_fact * Vcr[1] * Vcr[2],
                       diag_fact + off_fact * Vcr[2]**2
                   ]]

        ### ---------------------------------------- difference term derivative
        Vsc = Vcr * vcr2inv * Cfact
        Ddiff = np.array([RAB * Vsc[0], RAB * Vsc[1], RAB * Vsc[2]])

        ### ------------------------------------------ Final assembly (crucial)

        # dQ_dRA=Dvcross_by_skew3d(Dvcross,-R_list[bb])\
        # 									 +np.dot(Ddiff, Der_runit_list[aa] )
        # dQ_dRB=Dvcross_by_skew3d(Dvcross, R_list[aa])\
        # 									 -np.dot(Ddiff, Der_runit_list[bb] )

        DerP += Dvcross_by_skew3d(Dvcross, RAB) + \
                +np.dot(Ddiff, Der_runit_list[aa] - Der_runit_list[bb])

    return DerP
Exemplo n.º 5
0
def eval_panel_fast(zetaP, ZetaPanel, vortex_radius, gamma_pan=1.0):
    """
    Computes derivatives of induced velocity w.r.t. coordinates of target point,
    zetaP, and panel coordinates. Returns two elements:
        - DerP: derivative of induced velocity w.r.t. ZetaP, with:
            DerP.shape=(3,3) : DerC[ Uind_{x,y,z}, ZetaC_{x,y,z} ]
        - DerVertices: derivative of induced velocity wrt panel vertices, with:
            DerVertices.shape=(4,3,3) :
            DerVertices[ vertex number {0,1,2,3},  Uind_{x,y,z}, ZetaC_{x,y,z} ]

    The function is based on eval_panel_comp, but minimises operationsby
    recycling variables.
    """

    vortex_radius_sq = vortex_radius * vortex_radius
    DerP = np.zeros((3, 3))
    DerVertices = np.zeros((4, 3, 3))

    ### ---------------------------------------------- Compute common variables
    # these are constants or variables depending only on vertices and P coords
    Cfact = cfact_biot * gamma_pan

    # distance vertex ii-th from P
    R_list = zetaP - ZetaPanel
    r1_list = [algebra.norm3d(R_list[ii]) for ii in svec]
    r1inv_list = [1. / r1_list[ii] for ii in svec]
    Runit_list = [R_list[ii] * r1inv_list[ii] for ii in svec]
    Der_runit_list = [
        der_runit(R_list[ii], r1inv_list[ii], -r1inv_list[ii]**3)
        for ii in svec
    ]

    ### ------------------------------------------------- Loop through segments
    for aa, bb in LoopPanel:

        RAB = ZetaPanel[bb, :] - ZetaPanel[aa, :]  # segment vector
        Vcr = algebra.cross3(R_list[aa], R_list[bb])
        vcr2 = np.dot(Vcr, Vcr)

        if vcr2 < (vortex_radius_sq * algebra.normsq3d(RAB)):
            continue

        Tv = Runit_list[aa] - Runit_list[bb]
        dotprod = np.dot(RAB, Tv)

        ### ----------------------------------------- cross-product derivatives
        # lower triangular part only
        vcr2inv = 1. / vcr2
        vcr4inv = vcr2inv * vcr2inv
        diag_fact = Cfact * vcr2inv * dotprod
        off_fact = -2. * Cfact * vcr4inv * dotprod
        Dvcross = [[diag_fact + off_fact * Vcr[0]**2],
                   [
                       off_fact * Vcr[0] * Vcr[1],
                       diag_fact + off_fact * Vcr[1]**2
                   ],
                   [
                       off_fact * Vcr[0] * Vcr[2], off_fact * Vcr[1] * Vcr[2],
                       diag_fact + off_fact * Vcr[2]**2
                   ]]

        ### ---------------------------------------- difference term derivative
        Vsc = Vcr * vcr2inv * Cfact
        Ddiff = np.array([RAB * Vsc[0], RAB * Vsc[1], RAB * Vsc[2]])

        ### ---------------------------------------------------- RAB derivative
        dQ_dRAB = np.array([Tv * Vsc[0], Tv * Vsc[1], Tv * Vsc[2]])

        ### ------------------------------------------ Final assembly (crucial)

        dQ_dRA = Dvcross_by_skew3d(Dvcross, -R_list[bb]) \
                 + np.dot(Ddiff, Der_runit_list[aa])
        dQ_dRB = Dvcross_by_skew3d(Dvcross, R_list[aa]) \
                 - np.dot(Ddiff, Der_runit_list[bb])

        DerP += dQ_dRA + dQ_dRB  # w.r.t. P
        DerVertices[aa, :, :] -= dQ_dRAB + dQ_dRA  # w.r.t. A
        DerVertices[bb, :, :] += dQ_dRAB - dQ_dRB  # w.r.t. B

    # ### collocation point only
    # DerP +=Dvcross_by_skew3d(Dvcross,RA-RB)+np.dot(Ddiff,
    # 		  der_runit(RA,rainv,minus_rainv3)-der_runit(RB,rbinv,minus_rbinv3))

    return DerP, DerVertices