tudoumama2018 2023-06-05 22:56 采纳率: 45.5%
浏览 63
已结题

matlab动态模态分解程序

%这是一个动态模态分解matlab程序,X和Y已知,对此数据进行分析,我想将随时间衰减很快,且振幅(能量)大的模态都减掉,应该怎么写程序?
(实在不好意思 修改了一下题目)

[Dd,b,Phi,Time_DMD,Energy] = DMD_CLASS(X,Y);
function [Dd,b,Phi,Time_DMD,Energy] = DMD_CLASS(X,Y)
%DMD分解函数
%输入:
%X,Y,DMD分解的数据矩阵。X是data(1,1:(end-1)),Y是data(:,2:end)。
%
%输出:
%Dd,特征根
%b,初始状态
%Phi,DMD分解的模态
%Time_DMD,DMD还原信号所用到的时间项
%Energy,每个模态对应的能量,从大到小排序

N=size(X,2);
%1 SVD分解
[U,S,V] = svd(X,'econ');%奇异值分解的精简分解
%删除奇异值约等于0的模态,防止计算发散
Sd = diag(S);
r = sum(Sd>1e-4);%可以将条件改成1e-6,1e-5等
U = U(:,1:r);
S = S(1:r,1:r);
V = V(:,1:r);
%2 求解矩阵A
A = U'*(Y*V/S);
%3 求矩阵A的特征值和特征向量
[Om,D] = eig(A);
Dd = diag(D);%求特征值转为向量形式
%4 求DMD模态
Phi = Y*V/S*Om;
%5 求解初始状态b
b = Phi\X(:,1);
%6 对模态进行排序
Q = Dd.^(0:N-1);%计算出范德蒙矩阵
Time_DMD = b.*Q;%旧版本matlab可以用右边形式替换Time_DMD=(b*ones(1,N)).*Q;

% %对信号初始振幅排序,速度快,输出能量可以近似用振幅平方代替
%[b,Ie] = sort(abs(b),'descend');
%Energy = abs(b).*abs(b);

%求出所有模态的信号,并计算能量。这是按照能量排序,和上面3行不一样。毕竟DMD模态的排序方法不唯一。
Energy = zeros( size(Phi,2) , 1 );
for k = 1 : size(Phi,2)
Uxt_DMD_k = real(Phi(:,k) * Time_DMD(k,:));
E_k = sum( sum( Uxt_DMD_k.^2 ) );
Energy(k) = E_k;
end
[Energy,Ie] = sort(Energy,'descend');%对每个模态的能量进行排序

%按顺序输出特征值、初始状态b、模态Phi
Dd = Dd(Ie);
b = b(Ie);
Phi = Phi(:,Ie);
Time_DMD = Time_DMD(Ie,:);
end

  • 写回答

9条回答 默认 最新

  • 全栈若城 Python领域新星创作者 2023-06-05 23:15
    关注
    获得1.80元问题酬金

    这是一个组合函数吧 , 你少给我东西了吧?

    评论
  • 虚白在敲代码 2023-06-06 11:17
    关注
    获得0.30元问题酬金

    要减去随时间衰减的模式,需要识别并删除衰减率为负或较小的模式。可以通过添加负或小衰减率检查来修改DMD_CLASS函数,并将这些模式设置为零。示例:

    function [Dd,b,Phi,Time_DMD,Energy] = DMD_CLASS(X,Y,delta)
    %DMD分解函数
    %输入:%X,Y,DMD分解的数据矩阵。X是data(1,1:(end-1)),Y是data(:,2:end)。%
    %delta, 阈值,用于判断需要保留的模态的衰减率,即如果模态的特征值小于delta,则该模态被认为衰减严重,需要被移除。
    %%输出:%Dd,特征根
    %b,初始状态
    %Phi,DMD分解的模态
    %Time_DMD,DMD还原信号所用到的时间项
    %Energy,每个模态对应的能量,从大到小排序
    
    N=size(X,2);
    
    %1 SVD分解
    [U,S,V] = svd(X,'econ');%奇异值分解的精简分解
    
    %删除奇异值约等于0的模态,防止计算发散
    Sd = diag(S);
    r = sum(Sd>1e-4);%可以将条件改成1e-6,1e-5等
    U = U(:,1:r);
    S = S(1:r,1:r);
    V = V(:,1:r);
    
    %2 求解矩阵A
    A = U'*(Y*V/S);
    
    %3 求矩阵A的特征值和特征向量
    [Om,D] = eig(A);
    Dd = diag(D);%求特征值转为向量形式
    
    %4 求DMD模态
    Phi = Y*V/S*Om;
    
    %5 求解初始状态
    bb = Phi\X(:,1);
    
    %6 对模态进行排序
    Q = Dd.^(0:N-1);%计算出范德蒙矩阵
    Time_DMD = b.*Q;%旧版本matlab可以用右边形式替换Time_DMD=(b*ones(1,N)).*Q;
    
    %对信号初始振幅排序,速度快,输出能量可以近似用振幅平方代替
    [b,Ie] = sort(abs(b),'descend');
    Energy = abs(b).*abs(b);%求出所有模态的信号,并计算能量。这是按照能量排序,和上面3行不一样。毕竟DMD模态的排序方法不唯一。
    % Energy = zeros( size(Phi,2) , 1 ); % use this if you want to compute energy using reconstructed signals
    for k = 1 : size(Phi,2)
        % skip modes with negative or small decay rates
        if abs(Dd(k)) < delta
            Phi(:,k) = 0;
            continue;
        end
        
        Uxt_DMD_k = real(Phi(:,k) * Time_DMD(k,:));
        % E_k = sum( sum( Uxt_DMD_k.^2 ) ); % use this if you want to compute energy using reconstructed signals
        Energy(k) = abs(Dd(k)); % set energy to decay rate
    end
    
    [Energy,Ie] = sort(Energy,'descend');%对每个模态的能量进行排序
    
    %按顺序输出特征值、初始状态b、模态Phi
    Dd = Dd(Ie);
    b = b(Ie);
    Phi = Phi(:,Ie);
    Time_DMD = Time_DMD(Ie,:);
    end
    

    该修改包括一个附加的输入参数“delta”,它设置了衰减率的阈值,低于该阈值应去除模式。在计算每个模式能量的循环中,对衰减率(“abs(Dd(k))<delta”)进行检查,如果它小于阈值,则将模式设置为零。

    要使用这个修改后的函数,只需用数据矩阵“X”、“Y”和所需的衰减率阈值“delta”来调用它。输出将与原始的“DMD_CLASS”函数相同,只是衰减过快的模式已被删除。

    评论
  • 鱼弦 全栈领域创作新星创作者 2023-06-06 13:53
    关注
    获得1.80元问题酬金

    可以这样做,借鉴一下这个:https://zhuanlan.zhihu.com/p/635043276

    评论
  • GIS工具开发 2023-06-12 11:35
    关注
    获得1.80元问题酬金

    参考代码

    
    function [Dd,b,Phi,Time_DMD,Energy] = DMD_CLASS(X,Y, energy_thresh)
    
    N = size(X,2);
    
    [U,S,V] = svd(X,'econ');
    
    Sd = diag(S);
    r = sum(Sd>1e-4);
    U = U(:,1:r);
    S = S(1:r,1:r);
    V = V(:,1:r);
    
    A = U'*(Y*V/S);
    
    [Om,D] = eig(A);
    Dd = diag(D);
    
    Phi = Y*V/S*Om;
    
    b = Phi\X(:,1);
    
    Q = Dd.^(0:N-1);
    Time_DMD = b.*Q;
    
    Energy = zeros(size(Phi,2), 1);
    for k = 1:size(Phi,2)
        Uxt_DMD_k = real(Phi(:,k) * Time_DMD(k,:));
        %计算模态在最后一个时间步长的振幅大小
        b(k) = Uxt_DMD_k(end);
        %计算模态的能量
        E_k = sum(sum(Uxt_DMD_k.^2));
        Energy(k) = E_k;
    end
    
    %找到能量小于阈值的模态并删除
    energy_pct = (Energy ./ sum(Energy)) * 100;
    mode_inds_to_keep = find(energy_pct >= energy_thresh);
    Dd = Dd(mode_inds_to_keep);
    Phi = Phi(:,mode_inds_to_keep);
    b = b(mode_inds_to_keep);
    Time_DMD = Time_DMD(mode_inds_to_keep,:);
    
    %按照能量大小对模态排序
    [Energy, sort_inds] = sort(Energy, 'descend');
    Dd = Dd(sort_inds);
    Phi = Phi(:,sort_inds);
    b = b(sort_inds);
    Time_DMD = Time_DMD(sort_inds,:);
    
    end
    
    评论
  • yy64ll826 2023-06-12 16:33
    关注
    获得1.80元问题酬金

    可以参考下

    %DMD实验2
    clear
    close all
    
    x=0:0.01:5;m=length(x);
    t=0:0.1:5;N=length(t);
    Fs=1/(t(2)-t(1));
    [X,T]=meshgrid(x,t);
    
    %信号
    U_tx=1.2*exp(-0.5*T).*sin(2*pi*(X+0*T))+0.8*exp(0.3*T).*sin(2*pi*(3*X+4*T));
    %p的格式为时间*空间的矩阵
    U_xt=U_tx';
    Up=pinv(U_xt(:,1:50));%求解X的伪逆
    %求解矩阵A
    A=U_xt(:,2:51)*Up;
    
    [V,D] = eig(A);
    D=diag(D);
    [~,ind] = sort(abs(D),'descend');
    D=D(ind);V=V(:,ind);
    D_abs=abs(D);
    Dd=D./D_abs;
    %频率
    f=Fs*angle(Dd)./(2*pi);
    
    %图1,绘制特征根图谱
    figure(1)
    scatter(real(Dd(100:-1:1)),imag(Dd(100:-1:1)),30,-abs(D(100:-1:1)),'filled')
    axis equal
    box on
    
    %图2,绘制频率和衰减图
    figure(2)
    wa=log(D)*Fs;%利用特征根计算衰减率
    scatter(real(wa),imag(wa)/2/pi,30,-D_abs,'filled')
    xlabel('衰减率σ');ylabel('频率w')
    ylim([-6,6]);xlim([-1,1])
    hold on
    plot([0,0],ylim,'b--')
    plot(xlim,[0,0],'b--')
    box on
    
    
    
    评论
  • CSDN-Ada助手 CSDN-AI 官方账号 2023-06-12 17:18
    关注
    获得4.50元问题酬金

    D模态对应的能量较小,随时间衰减快,可以通过计算每个DMD模态对应的能量,然后去掉能量较高的模态来减少振幅较高的数据。代码中的变量Energy就是每个模态对应的能量,可以通过对能量从大到小排序,确定需要去掉的模态数目,将这些模态对应的数据从原始数据中剔除即可。

    具体实现代码如下:

    Energy = sort(abs((diag(S)V')b).^2/(prod(abs(Sd))trace(YY')),'descend'); %计算所有模态对应的能量,从大到小排序 total_energy = sum(Energy); %计算所有模态对应的总能量 energy_ratio = cumsum(Energy)/total_energy; %计算累计能量贡献率 mode_num = find(energy_ratio>=0.95,1); %确定需要去掉的模态数目 modes_to_remove = 1:mode_num; %需要去掉的模态 keep_modes = mode_num+1:length(Energy); %需要保留的模态 DMD_modes(:,modes_to_remove) = []; %剔除需要去掉的模态 DMD_modes_energy = Energy(keep_modes); %保留的模态对应的能量

    评论
  • MR_Bone 2023-06-07 10:57
    关注

    根据您提供的MATLAB代码,您想要对给定的数据进行动态模态分解,并减去随时间衰减的模态。以下是编写程序的步骤:

    1. 调用函数:调用DMD_CLASS函数,并传入数据矩阵X和Y。
    2. SVD分解:对数据矩阵X进行奇异值分解(SVD),得到矩阵U、S和V。根据奇异值的大小,选择一个阈值(例如1e-4),确定需要保留的奇异值个数r,并截取U、S和V的前r列。
    3. 计算矩阵A:根据公式 A = U'_(Y_V/S),计算矩阵A。
    4. 求解特征值和特征向量:对矩阵A进行特征值分解,得到特征值D和特征向量Om。
    5. 计算DMD模态:根据公式 Phi = Y_V/S_Om,计算DMD模态矩阵Phi。
    6. 求解初始状态b:根据公式 b = Phi\X(:,1),求解初始状态b。
    7. 对模态进行排序:计算范德蒙矩阵Q和Time_DMD,然后根据能量排序。
    8. 输出结果:输出特征根Dd、初始状态b、DMD模态Phi、DMD还原信号所用的时间项Time_DMD以及每个模态对应的能量Energy。

    根据您的需求,如果您想将随时间衰减的模态减掉,可以在计算DMD还原信号时,根据需要减去衰减较快的模态。

    注意:以上步骤是根据您提供的代码进行理解和解释的,确保数据矩阵X和Y的格式正确,并适用于您的具体问题。

    评论
  • 是小韩呀 2023-06-12 16:27
    关注
    获得1.50元问题酬金

    根据你的描述,你希望将随时间衰减很快且振幅(能量)大的模态减掉。你可以在函数 DMD_CLASS 中的最后几行进行修改,按照以下步骤编写程序:

    将以下两行代码注释掉,因为你不再需要按初始振幅排序和计算能量:

    
    % [b,Ie] = sort(abs(b),'descend');
    % Energy = abs(b).*abs(b);
    
    

    将以下代码取消注释,以按照能量排序模态:

    [Energy,Ie] = sort(Energy,'descend'); % 对每个模态的能量进行排序
    
    
    

    修改模态的输出,只保留衰减较慢且能量较小的模态:

    Dd = Dd(Ie);
    b = b(Ie);
    Phi = Phi(:,Ie);
    Time_DMD = Time_DMD(Ie,:);
    
    
    

    通过这些修改,模态将按照能量从大到小排序,并且你可以选择保留衰减较慢且能量较小的模态。你可以根据需要修改代码,例如只保留能量占总能量一定比例的模态。

    评论
  • HiSiri666666 Java领域优质创作者 2023-06-07 12:48
    关注

    对于动态模态分解(DMD)程序,可以通过对DMD模态的能量进行排序,然后选择能量较大的模态进行保留,而将能量较小的模态进行截断。这样可以达到减掉随时间衰减很快、且振幅(能量)小的模态的效果。

    具体实现步骤如下:

    1. 运行DMD程序,得到DMD模态和对应的能量:
      [Phi,omega,lambda,b,X_dmd,S] = DMD(X,Y,r);
      其中, Phi 是DMD模态, omega 是DMD模态的频率, lambda 是DMD模态的特征值, b 是DMD重构系数, X_dmd 是DMD重构结果, S 是DMD模态的能量。
    2. 对能量进行排序:
      [sorted_S, index] = sort(S, 'descend');
      这里使用 sort 函数将能量从大到小进行排序,并返回排序后的能量和对应的索引。
    3. 选择能量较大的模态进行保留:
      k = 10; % 选择前10个能量较大的模态
      Phi_k = Phi(:, index(1:k));
      omega_k = omega(index(1:k));
      lambda_k = lambda(index(1:k));
      b_k = b(index(1:k));
      这里选择前10个能量较大的模态进行保留,可以根据实际情况进行调整。
    4. 对DMD进行重构:
      X_dmd_k = Phi_k * diag(b_k) * exp(omega_k * t);
      这里只使用了保留的模态进行重构,得到新的重构结果 X_dmd_k 。

    完整的代码如下:

    % 运行DMD程序,得到DMD模态和对应的能量
    [Phi,omega,lambda,b,X_dmd,S] = DMD(X,Y,r);
     % 对能量进行排序
    [sorted_S, index] = sort(S, 'descend');
     % 选择前10个能量较大的模态进行保留
    k = 10;
    Phi_k = Phi(:, index(1:k));
    omega_k = omega(index(1:k));
    lambda_k = lambda(index(1:k));
    b_k = b(index(1:k));
     % 对DMD进行重构
    X_dmd_k = Phi_k * diag(b_k) * exp(omega_k * t);
    
    
    评论

报告相同问题?

问题事件

  • 系统已结题 6月13日
  • 赞助了问题酬金15元 6月7日
  • 修改了问题 6月7日
  • 创建了问题 6月5日

悬赏问题

  • ¥15 定义了函数,但是无法根据函数定义触发器
  • ¥20 5变量卡诺图化简得出与非门电路图
  • ¥20 位置依赖的碱基序列独热编码
  • ¥15 Python爬取交通拥堵指数数据
  • ¥15 使用vba抓取重定向网页问题
  • ¥20 付费需求测试程序(细谈)。
  • ¥15 为什么这段c++代码会报这么多语法错误?
  • ¥20 如何利用C语言实现用最小二乘法选配两个经验公式
  • ¥50 vue-codemirror如何对指定行 指定位置的 字符进行背景颜色或者字体颜色的修改?
  • ¥30 遇到一个的问题,请教各位