angle_rng=angle_rng)

# %% Classify the stability of fixed points

df_td_exp, df_ev_exp = eqns.tau_delta(df_equil_exp, Cl_fun, Cd_fun,
                                      Clprime_fun, Cdprime_fun)
df_td_spl, df_ev_spl = eqns.tau_delta(df_equil_spl,
                                      cl_fun,
                                      cd_fun,
                                      clprime_fun,
                                      cdprime_fun,
                                      angle_rng=angle_rng)

# %% Stability analysis for individual squirrels

df_nuni_exp, df_uni_exp, df_class_exp = eqns.classify_fp(df_td_exp)
df_nuni_spl, df_uni_spl, df_class_spl = eqns.classify_fp(df_td_spl)

possible_class = [
    'saddle point', 'unstable focus', 'unstable node', 'stable focus',
    'stable node'
]
bfbmap = [bmap[0], bmap[4], bmap[2], bmap[3], bmap[1]]

# %% Spline bifurcation plot for paper

rd = np.rad2deg

gam_high = angle_rng[0] - pitches  # closer to 0
gam_low = angle_rng[1] - pitches  # closer to 90
                      cdprime_fun_1,
                      angle_rng=arng)
nt_td_4, nt_ev_4 = td(nt_equil_4,
                      cl_fun_4,
                      cd_fun_4,
                      clprime_fun_4,
                      cdprime_fun_4,
                      angle_rng=arng)
nt_td, nt_ev = td(nt_equil,
                  cl_fun,
                  cd_fun,
                  clprime_fun,
                  cdprime_fun,
                  angle_rng=arngpt)

_, _, nt_Class_1 = eqns.classify_fp(nt_TD_1)
_, _, nt_Class_4 = eqns.classify_fp(nt_TD_4)
_, _, nt_Class = eqns.classify_fp(nt_TD)
_, _, nt_class_1 = eqns.classify_fp(nt_td_1)
_, _, nt_class_4 = eqns.classify_fp(nt_td_4)
_, _, nt_class = eqns.classify_fp(nt_td)

#possible_class = ['saddle point', 'unstable spiral', 'unstable node',
#                  'stable spiral', 'stable node']
#bfbmap = [bmap[0], bmap[4], bmap[2], bmap[3], bmap[1]]

possible_class = [
    'saddle point', 'unstable focus', 'stable focus', 'stable node'
]
bfbmap = [bmap[0], bmap[4], bmap[3], bmap[1]]
                                      angle_rng=angle_rng)

# %% Classify the stability of fixed points

ch_td_exp, ch_ev_exp = eqns.tau_delta(ch_equil_exp, Cl_fun, Cd_fun,
                                      Clprime_fun, Cdprime_fun)
ch_td_spl, ch_ev_spl = eqns.tau_delta(ch_equil_spl,
                                      cl_fun,
                                      cd_fun,
                                      clprime_fun,
                                      cdprime_fun,
                                      angle_rng=angle_rng)

# %% Stability analysis for individual squirrels

ch_nuni_exp, ch_uni_exp, ch_class_exp = eqns.classify_fp(ch_td_exp)
ch_nuni_spl, ch_uni_spl, ch_class_spl = eqns.classify_fp(ch_td_spl)

possible_class = [
    'saddle point', 'unstable focus', 'unstable node', 'stable focus',
    'stable node'
]
bfbmap = [bmap[0], bmap[4], bmap[2], bmap[3], bmap[1]]

# %% Spline bifurcation plot for paper

rd = np.rad2deg

gam_high = angle_rng[0] - pitches  # closer to 0
gam_low = angle_rng[1] - pitches  # closer to 90
                        Cdprime_fun_25,
                        angle_rng=arng)
so_td_10, so_ev_10 = td(so_equil_10,
                        cl_fun_10,
                        cd_fun_10,
                        clprime_fun_10,
                        cdprime_fun_10,
                        angle_rng=arng)
so_td_25, so_ev_25 = td(so_equil_25,
                        cl_fun_25,
                        cd_fun_25,
                        clprime_fun_25,
                        cdprime_fun_25,
                        angle_rng=arng)

_, _, so_Class_10 = eqns.classify_fp(so_TD_10)
_, _, so_Class_25 = eqns.classify_fp(so_TD_25)
_, _, so_class_10 = eqns.classify_fp(so_td_10)
_, _, so_class_25 = eqns.classify_fp(so_td_25)

possible_class = [
    'saddle point', 'unstable focus', 'unstable node', 'stable focus',
    'stable node'
]
bfbmap = [bmap[0], bmap[4], bmap[2], bmap[3], bmap[1]]

# %% Spline bifurcation plot (deg) for paper

rd = np.rad2deg

gam_high = arng[0] - pitches  # closer to 0
# %% Eigenvalue plot (Re vs. Re, Im vs. Im)

fig, ax = plt.subplots()
ax.plot(np.real(sq_ev_spl[:, 0]), np.real(sq_ev_spl[:, 1]), 'o', label=r'$Re$')
ax.plot(np.imag(sq_ev_spl[:, 0]), np.imag(sq_ev_spl[:, 1]), 'o', label=r'$Im$')
ax.set_xlabel(r'$\lambda_1$', fontsize=16)
ax.set_ylabel(r'$\lambda_2$', fontsize=16)
ax.legend(loc='best', frameon=False)
rcj(ax)
tl(fig)


# %% Stability analysis

sq_nuni_exp, sq_uni_exp, sq_class_exp = eqns.classify_fp(sq_td_exp)
sq_nuni_spl, sq_uni_spl, sq_class_spl = eqns.classify_fp(sq_td_spl)

possible_class = ['saddle point', 'unstable focus', 'unstable node',
                  'stable focus', 'stable node']
bfbmap = [bmap[0], bmap[4], bmap[2], bmap[3], bmap[1]]


# %% Spline bifurcation plot

fig, ax = plt.subplots()
for ii, fp_kind in enumerate(possible_class):
    idx = np.where(sq_class_spl == fp_kind)[0]
    if len(idx) > 0:
        ax.plot(sq_equil_spl[idx, 1], sq_equil_spl[idx, 0], 'o', ms=2,
                label=fp_kind, c=bfbmap[ii], mec=bfbmap[ii])
Example #6
0
def phase_plotter(afdict,
                  pitch,
                  lims,
                  arng,
                  tvec,
                  ngrid=201,
                  nseed=41,
                  nseed_skip=1,
                  quiver=False,
                  skip=10,
                  seed=False,
                  timer=False,
                  gamtest=None,
                  extrap=None,
                  traj=None,
                  seedloc=None,
                  fig=None,
                  ax=None,
                  acc_contour=True,
                  nullcline_x=False,
                  nullcline_z=False):

    # unpack the data
    cli, cdi, = afdict['cli'], afdict['cdi']
    clip, cdip = afdict['clip'], afdict['cdip']

    # upack axis limits
    vxlim, vzlim = lims

    from eqns import cart_eqns, cart_model

    if traj is None:
        traj = ps_traj_dp5

    VXorig, VZorig, VX, VZ, ALPHA = setup_grid(ngrid, vxlim, vzlim, pitch,
                                               arng)
    CL = cli(ALPHA.flatten()).reshape(ALPHA.shape)
    CD = cdi(ALPHA.flatten()).reshape(ALPHA.shape)
    dVX, dVZ = cart_eqns(VX, VZ, CL, CD)
    AMAG = np.hypot(dVX, dVZ)
    AX, AZ = dVX / AMAG, dVZ / AMAG

    # calculation the integral curves
    now = time.time()
    # vxs, vzs, VXs, VZs, als = setup_grid(nseed, vxlim, vzlim, pitch, arng)
    vxseed, vzseed = seed_locations(nseed, vxlim, vzlim, pitch, arng)
    vxseed, vzseed = vxseed[::nseed_skip], vzseed[::nseed_skip]

    if seedloc is not None:
        vxseed = np.r_[vxseed, seedloc[:, 0]]
        vzseed = np.r_[vzseed, seedloc[:, 1]]
    odeargs = (pitch, cli, cdi)
    solns = []
    for i in range(len(vxseed)):
        x0 = (0, 0, vxseed[i], vzseed[i])
        soln = traj(x0, tvec, odeargs, cart_model, arng, vxlim, vzlim)
        solns.append(soln)
    if timer:
        print('Elapsed time: {:.3f}'.format(time.time() - now))

    # equilibrium points
    if gamtest is not None:
        from eqns import pitch_bifurcation as pb
        from eqns import v_equil, vxvz_equil, tau_delta, classify_fp
        equil = pb([pitch], gamtest, cli, cdi, angle_rng=arng)
        thbar, gambar = equil.T
        vbar = v_equil(pitch + gambar, cli, cdi)
        vxbar, vzbar = vxvz_equil(vbar, gambar)

        td, ev = tau_delta(equil, cli, cdi, clip, cdip, arng)
        _, _, fp_class = classify_fp(td)

        possible_class = [
            'saddle point', 'unstable focus', 'unstable node', 'stable focus',
            'stable node'
        ]
        bfbmap = [bmap[0], bmap[4], bmap[2], bmap[3], bmap[1]]

    if fig is None or ax is None:
        fig, ax = plt.subplots(figsize=(5.5, 5.125))

    if quiver:
        ax.quiver(VX[::skip, ::skip],
                  VZ[::skip, ::skip],
                  AX[::skip, ::skip],
                  AZ[::skip, ::skip],
                  color='gray',
                  pivot='middle',
                  alpha=.8,
                  edgecolor='gray',
                  linewidths=0 * np.ones(VX[::skip, ::skip].size))

    for i in range(len(solns)):
        ax.plot(solns[i][:, 2],
                solns[i][:, 3],
                '-',
                ms=2.25,
                c='gray',
                alpha=.95,
                lw=.5)  # color=bmap[1])

    if seed:
        ax.plot(vxseed, vzseed, 'o', ms=2.5)

    if gamtest is not None:
        for ii, fp_kind in enumerate(possible_class):
            idx = np.where(fp_class == fp_kind)[0]
            if len(idx) == 0:
                continue

            # now globalize the phase space
            if fp_kind == 'saddle point':
                #  or fp_kind == 'stable node' or fp_kind == 'unstable node':
                tvec = np.linspace(tvec[0], 3 * tvec[-1], 6 * len(tvec))
                vxpt, vzpt = vxbar[idx], vzbar[idx]
                solns = []
                for i in range(len(vxpt)):
                    vxs, vzs = saddle_filler(vxpt[i], vzpt[i])
                    for vx0, vz0 in zip(vxs, vzs):
                        ic = (0, 0, vx0, vz0)
                        sn1 = traj(ic, tvec, odeargs, cart_model, arng, vxlim,
                                   vzlim)
                        sn2 = traj(ic, -tvec, odeargs, cart_model, arng, vxlim,
                                   vzlim)
                        solns.append(sn1)
                        solns.append(sn2)

                # plot the globalized saddles
                for i in range(len(solns)):
                    ax.plot(solns[i][:, 2], solns[i][:, 3], '-', c=bfbmap[ii])

            # plot the equilibrium point
            ax.plot(vxbar[idx],
                    vzbar[idx],
                    'o',
                    ms=7,
                    c=bfbmap[ii],
                    zorder=200)

    if acc_contour:
        ax.contourf(VX, VZ, AMAG, [0, .1], colors=[bmap[3]], alpha=.2)
        # ax.contourf(VX, VZ, dVZ, [0, .1], colors=[bmap[4]], alpha=.2)

    if extrap is not None and extrap[0] is not None:
        ax.contourf(VX,
                    VZ,
                    np.array(ALPHA < extrap[0]).astype(np.int), [.5, 1.5],
                    colors='gray',
                    alpha=.1)
    if extrap is not None and extrap[1] is not None:
        ax.contourf(VX,
                    VZ,
                    np.array(ALPHA > extrap[1]).astype(np.int), [.5, 1.5],
                    colors='gray',
                    alpha=.1)

    # plot the nullclines
    if nullcline_x:
        ax.contour(VX, VZ, dVX, [0], colors=[bmap[3]], alpha=1, zorder=100)
    if nullcline_z:
        ax.contour(VX, VZ, dVZ, [0], colors=[bmap[3]], alpha=1, zorder=100)

    ax.set_xlim(vxlim[0], vxlim[1])
    ax.set_ylim(vzlim[1], vzlim[0])

    ax.xaxis.set_label_position('top')
    ax.xaxis.tick_top()
    ax.set_xlabel(r"$\hat{v}_x$", fontsize=20)
    ax.set_ylabel(r"$\hat{v}_z    $", fontsize=20, rotation=0)
    ax.set_aspect('equal', adjustable='box')  # these need to be square
    ax.set_xticks([0, .25, .5, .75, 1, 1.25])
    ax.set_yticks([0, -.25, -.5, -.75, -1, -1.25])
    ax.set_xticklabels(['0', '', '', '', '', '1.25'])
    ax.set_yticklabels(['0', '', '', '', '', '-1.25'])
    [ttl.set_size(18) for ttl in ax.get_xticklabels()]
    [ttl.set_size(18) for ttl in ax.get_yticklabels()]
    rcj(ax, ['bottom', 'right'])
    tl(fig)

    return fig, ax
                                      angle_rng=sn_angle_rng)


# %% Classify the stability of fixed points

sn_td_exp, sn_ev_exp = eqns.tau_delta(sn_equil_exp, Cl_fun, Cd_fun,
                                      Clprime_fun, Cdprime_fun,
                                      angle_rng=sn_angle_rng)
sn_td_spl, sn_ev_spl = eqns.tau_delta(sn_equil_spl, cl_fun, cd_fun,
                                      clprime_fun, cdprime_fun,
                                      angle_rng=sn_angle_rng)


# %% Classification of fixed points

sn_nuni_exp, sn_uni_exp, sn_class_exp = eqns.classify_fp(sn_td_exp)
sn_nuni_spl, sn_uni_spl, sn_class_spl = eqns.classify_fp(sn_td_spl)

possible_class = ['saddle point', 'unstable focus', 'unstable node',
                  'stable focus', 'stable node']
bfbmap = [bmap[0], bmap[4], bmap[2], bmap[3], bmap[1]]


# %% Acceleration along terminal manifold when we have a saddle point

sad_idx = np.where(sn_class_spl == 'saddle point')[0]
sad_pitch, sad_gamma = sn_equil_spl[sad_idx].T

# we have some double saddle points below theta =2 deg; remove these
sad_idx = np.where(sad_pitch >= np.deg2rad(2))[0]
sad_pitch, sad_gamma = sad_pitch[sad_idx], sad_gamma[sad_idx]