我有一个类似的等式:
这里a,b,c,d,e,f,g,h是常数。我想改变k从.6到10与0.1间隔,并找到w。在MATLAB中有两种方法可以做到这一点。
一种方法是将此等式转换为形式的等式(某物)w ^ 8-(其他)w ^ 6 ....-(另外的东西)w ^ 0 = 0,然后使用命令MATLAB中的“根”(方法1)。
另一种方法是定义符号函数然后执行程序。当您使用此方法时,您可能不需要进一步简化表达式,您可以将其放在第一个表单中(方法2)。
两种方式都显示在下面的脚本中:
%%% defining values
clear; clc;
a=0.1500;
b=0.20;
c=0.52;
d=0.5;
e=6;
f=30;
g=18;
h=2;
%% Method 1: varying k using roots
tic
i=0;
for k=.6:.1:10
i=i+1;
t8=a;
t7=0;
t6=-(1+e+a*(c+g))*(k^2) ;
t5=0;
t4=(k^2*(b+f+(c*e+g)*k^2)-a*(d+h-c*g*k^4));
t3=0;
t2=k^2*(d*(e+a*g)+h+a*c*h-(c*f+b*g)*k^2);
t1=0;
t0=(a*d*h)-(d*f+b*h)*k^2;
q=[t8 t7 t6 t5 t4 t3 t2 t1 t0];
r(i,:)=roots(q);
end
krho1(:,1)=.6:.1:10;
r_real=real(r);
r_img=imag(r);
dat1=[krho1 r_real(:,1) r_real(:,2) r_real(:,3) r_real(:,4) r_real(:,5) r_real(:,6) r_real(:,7) r_real(:,8)];
fnameout=('stack_using_roots.dat');
fid1=fopen(fnameout,'w+');
fprintf(fid1,'krho\t RR1\t RR2\t RR3\t RR4\t RR5\t RR6\t RR7\t RR8\t \r');
fprintf(fid1,'%6.4f %7.10f %7.10f %7.10f %7.10f %7.10f %7.10f %7.10f %7.10f \n',dat1');
fclose(fid1);
plot(krho1, r_real(:,1),krho1, r_real(:,2),krho1, r_real(:,3),krho1, r_real(:,4),krho1, r_real(:,5),krho1, r_real(:,6),krho1, r_real(:,7),krho1, r_real(:,8))
toc
%% Method 2: varying k using solve
tic
syms w k
i=0;
for k=.6:.1:10
i=i+1;
first=a/k^2;
second=(w^2-b)/(w^4-k^2*c*w^2-d) ;
third=(e*w^2-f)/(w^4-k^2*g*w^2-h);
n(i,:)=double(solve(first-second-third, w));
end
krho1(:,1)=.6:.1:10;
r_real=real(n);
r_img=imag(n);
dat1=[krho1 r_real(:,1) r_real(:,2) r_real(:,3) r_real(:,4) r_real(:,5) r_real(:,6) r_real(:,7) r_real(:,8)];
fnameout=('stack_using_solve.dat');
fid1=fopen(fnameout,'w+');
fprintf(fid1,'krho\t RR1\t RR2\t RR3\t RR4\t RR5\t RR6\t RR7\t RR8\t \r');
fprintf(fid1,'%6.4f %7.10f %7.10f %7.10f %7.10f %7.10f %7.10f %7.10f %7.10f \n',dat1');
fclose(fid1);
figure;
plot(krho1, r_real(:,1),krho1, r_real(:,2),krho1, r_real(:,3),krho1, r_real(:,4),krho1, r_real(:,5),krho1, r_real(:,6),krho1, r_real(:,7),krho1, r_real(:,8))
toc
方法1使用root命令,方法2使用symbolic和solve。我的问题如下:
我用
运行了程序i)syms w和n(i,:)= double(求解(first-second-third == 0,w));
ii)syms w k和n(i,:)= double(求解(first-second-third == 0,w));
iii)syms w k和n(i,:)= double(求解(第一秒 - 第三,w));
在所有这3个案例中,结果似乎相同。那么我们必须定义为符号的东西是什么?我们何时使用并且不使用表达式'== 0'?
答案 0 :(得分:1)
几个。一些微不足道的速度改进将来自在循环之前定义变量。最大的瓶颈是solve
。不幸的是,如果事先不知道k
,就没有明显的解决方案来解决你的问题,因此没有明显的方法可以将solve
拉出for循环。
你的函数关于w = 0是对称的。因此,对于每个根r,在-r处有另一个根。每当你调用solve时,它会给你第一个,第二个,第三个然后第四个根,然后是相同的东西,但是这次根乘以 -1。
有时候解决选择取出-1作为一个共同因素。在这些情况下,它首先给你的根乘以-1,然后是正根。为什么它有时会取出-1,有时候不会,我不知道,但在你的情况下(因为你不关心想象的部分)你可以通过替换{{1与double(solve(first-second-third, w))
一起使用。根的顺序与方法1中的顺序不一样,但是你不会得到奇怪的切换行为。
sort(real(double(solve(first-second-third, w))))
与syms w k
相比没有什么区别,因为您将k重新定义为数值(0.6,0.7,...等)。只有syms w
需要具有象征性。
w
的{{3}}决定了如何指定等式。如果向下滚动到有关输入变量solve
的部分,则说明
如果
eqns
的任何元素是符号表达式(没有右侧),则solve将该元素等同为0.
这就是为什么将eqns
或first-second-third==0
写为first-second-third
的第一个输入没有区别。