Extract Stablitiy Diagram

Extract Stablitiy Diagram

Contents

function SD = extract_Stability_Diagram(obj,resModes, order, omRange, epsRange, parName, p0,varargin)
        

Extract Stability Diagram

This function extracts the stability diagram of the trivial fixed point of parametrically excited systems (also known as InceStrutt diagram) in a range of forcing frequency around the principal subharmonic 2:1 resonance using the reduced order model computed by the SSM. An appropriate SSM is constructed based on the resonant spectrum of system. Using continuation periodic orbits are detected and period doubling / saddle node bifurcations which appear at the boundaries of stable regions around these resonances are tracked and continued.

IC = EXTRACE_STABILITY_DIAGRAM(OBJ, RESMODES, ORDER, OMRANGE, EPSRANGE, PARNAME, P0, VARARGIN)

See also: COCO/EXTRACT_STABILITY_DIAGRAM

startStab = tic;
        

Parse input parameters

flag for bifurctaion type and plotting

if numel(varargin)==2
        SNflag = strcmp(varargin{1},'SN');
        PlotSD = varargin{2};
elseif numel(varargin)==1
    if islogical(varargin{1})
        PlotSD = varargin{1};
        SNflag = false;
    else
        PlotSD = true;
        SNflag = strcmp(varargin{1},'SN');
    end
else
    SNflag = false;
    PlotSD = true;
end

if SNflag
    bifType = 'SN';
else
    bifType = 'PD';
end
        

Compute Autonomous SSM

obj.choose_E(resModes);

% Initialise external forcing frequency
obj.System.Omega = p0(1);

% Compute SSM
[W, R] = obj.compute_whisker(order);
        

Reduced dynamics ODEfunction

Data for odefunction

if obj.FRCOptions.omDepNonAuto % Assume strong dependence of coefficients on Omega

    fdata   = struct('order', order,'R',R,'W',W);
    odefun    = @(t,x,p) ode_2DSSM_cartesian(t,x,p,fdata,obj);
    odefun_dx = @(t,x,p) ode_2DSSM_cartesian_DFDX(t,x,p,fdata,obj);
    odefun_dp = @(t,x,p) ode_2DSSM_cartesian_DFDP(t,x,p,fdata,obj);
else

    % Use a fixed ROM, computed for a single forcing frequency and use it
    % for the full frequency span

    % Compute Reduced dynamics and sensitivity coefficients
    obj.System.Omega = obj.FRCOptions.omDepNonAutoVal;

    fdata   = struct('order', order,'R',R,'S',S);
    odefun    = @(t,x,p) ode_2DSSM_cartesian_fixROM(t,x,p,fdata);
    odefun_dx = @(t,x,p) ode_2DSSM_cartesian_DFDX_fixROM(t,x,p,fdata);
    odefun_dp = @(t,x,p) ode_2DSSM_cartesian_DFDP_fixROM(t,x,p,fdata,obj.Options.contribNonAuto);
end

funcs  = {odefun,odefun_dx,odefun_dp};
        

Set up continuation problem

Initial conditions

switch bifType
    case 'PD'
        periodsRatio = 1;
    case 'SN'
        periodsRatio = 2;
end

T = periodsRatio *2*pi/p0(1); % Forcing period of initial condition


t0 = linspace(0,T,101);
x0 = zeros(101,2);

% Build Problem
prob = coco_prob();
prob = cocoSet(obj.contOptions, prob); %set default options
prob = coco_set(prob, 'ode', 'autonomous', false,'vectorized', false);

coll_args = [funcs, {t0, x0, {'om' 'eps' }, p0}];
prob = ode_isol2po(prob, '', coll_args{:});

% Fix period of response to forcing frequency to detect PD bifurcation
[data, uidx] = coco_get_func_data(prob, 'po.orb.coll', 'data', 'uidx');
maps = data.coll_seg.maps;
omData = struct();
omData.periodsRatio = periodsRatio;
prob = coco_add_func(prob, 'OmegaT', @OmegaT, @OmegaT_du, omData, 'zero',...
    'uidx', [uidx(maps.T_idx), uidx(maps.p_idx(1))]);
        

Continuation arguments

switch parName
    case 'freq'

        isomega = true;
        cont_args = { 1, { 'om', 'po.period' }, omRange };
        parRange = epsRange; %Range of 2nd continuation parameter
    case 'amp'
        isomega = false;
        cont_args = {1, {'eps', 'po.period'}, epsRange };
        parRange = omRange; %Range of 2nd continuation parameter
    otherwise
        error('Continuation parameter should be freq or amp');
end
        

Continuation

runid = 'ROM_detect_bif';
bd = coco(prob,runid,[],cont_args{:});
        

Continue Period Doubling branches

switch bifType
    case 'PD'
        labs = coco_bd_labs(bd, 'PD');
    case 'SN'
        labs = coco_bd_labs(bd, 'SN');
end
if obj.FRCOptions.branchSwitch
    if isempty(labs)
        sprintf('No bifurcations indicating a resonance tongue were detected');
        SD = [];
        return
    else
        epsilon = [];
        omega   = [];
        run_idx = 1;
        for lab = labs

            labid = sprintf('ROM_family_bif%d',run_idx ); % Id of this run along family of PD bifurcations
            fprintf('\n Run=''%s'': Continue bifurcations from point %d in run ''%s''.\n',labid, lab, runid);

            [omega_i,epsilon_i] = stab_diag(obj,parRange,lab,runid,labid,isomega,bifType, omData);
            omega   = [omega,omega_i];
            epsilon = [epsilon,epsilon_i];
            run_idx = run_idx+1;
        end
        SD.omega = omega;
        SD.epsilon = epsilon;
    end

    if PlotSD
        plot_Stability_Diagram(omega,epsilon,order);
    end

    SD.order = order;
    totalComputationTime = toc(startStab);
    disp(['Total time spent on Stability Diagram computation = ' datestr(datenum(0,0,0,0,0,totalComputationTime),'HH:MM:SS')])
else
    SD = [];
end
        
end
        
function[omega,epsilon] = stab_diag(obj,parRange,lab, runid,labid,isomega, bifType, omData)
% For continuation of PD bifurcation in omega and epsilon

% Build continuation problem
prob = coco_prob();
prob = cocoSet(obj.contOptions, prob); %set default options
switch bifType
    case 'PD'
        prob = ode_PD2PD(prob, '', runid, lab);
    case 'SN'
        prob = ode_SN2SN(prob, '', runid, lab);
end

% Fix period of response
[data, uidx] = coco_get_func_data(prob, 'po.orb.coll', 'data', 'uidx');
maps = data.coll_seg.maps;
prob = coco_add_func(prob, 'OmegaT', @OmegaT, @OmegaT_du, omData, 'zero',...
            'uidx', [uidx(maps.T_idx), uidx(maps.p_idx(1))]);


if isomega
    cont_args = {1, {'eps' 'om' 'po.period' }, parRange};
else
    cont_args = {1, {'om' 'po.period' 'eps' }, parRange};
end
bd_lab  = coco(prob, labid, [], cont_args{:});

% read out omega and epsilon values along period doubling bifurcation

omega = coco_bd_col(bd_lab, 'om');
epsilon = coco_bd_col(bd_lab, 'eps');
end
        
function [] = plot_Stability_Diagram(omega,epsilon,order)
figSD = gcf;
% Plot in terms of omega and epsilon
figure(figSD); hold on; grid off;
plot(omega,epsilon,'-','LineWidth',2,'color',[0.4940    0.1840    0.5560],'DisplayName',strcat('SSM-$$\mathcal{O}(',num2str(order),')$$'))
add_labels('$\Omega$','$\epsilon$')
add_legends(order);
%title('Stability of trivial fixed point')
%legend(strcat('SSM-$$\mathcal{O}(',num2str(order),')$$'),...
%        'Interpreter','latex','Location','best');
%legend boxon

end
        
function add_legends(order)
hl = legend('show','Location','best');
set(hl, 'Interpreter','latex')
legend boxon;
end


function add_labels(xlab,ylab)
xlabel(xlab,'Interpreter','latex');
ylabel(ylab,'Interpreter','latex');
set(gca,'FontSize',14);
grid on, axis tight; legend boxoff;
end

function [data, y] = OmegaT(prob, data, u) %#ok<INUSL>
y = u(1)*u(2)-2*pi*data.periodsRatio; % omega*T = 2*pi
end

function [data, J] = OmegaT_du(prob, data, u) %#ok<INUSL>
J = [u(2) u(1)];
end