ich suche nach einem geeigneten solver in matlab, um eine diskrete
impedanzkurve mit einer impedanzfunktion zu approximieren und deren
parameter zu bestimmen.
dabei bin ich auf "lsqcurvefit" gestossen, jedoch bin ich mir nicht
sicher, ob ich den solver richtig anwende bzw. ob der überhaupt für
solche funktionen zulässig ist, da mir keine richtigen ergebnisse
rauskommen. allein an den startwerten kann es nicht liegen, da es selbst
bei genauen angaben nicht konvergiert..
zuerst eine kurve, die genau durch die selbe funktion geplottet wurde.
in weiterer folge wäre eine kurve mit streuverhalten angebracht, um die
least square methode zu testen.
hat mir jemand tipps?
hier der matlab code:
clc
clear all
close all
R = 0.5;
C = 2e-11;
L = 5e-07;
optimoptions(@lsqcurvefit,'TolFun',1e-8,'MaxFunEvals', 1000, 'MaxIter',
1000, 'TolX', 1e-8);
fr = logspace(1,9,200);
w = 2*pi.*fr;
s = j*w;
Z = (R+s.*L)./(s.*R*C+(s.^2).*L.*C+1);
%x(1) = R; x(2) = L; x(3) = C
figure(1)
subplot(2,1,1)
loglog(fr,abs(Z))
hold
subplot(2,1,2)
semilogx(fr, angle(Z)*180/pi)
hold
X = fr;
Y = abs(Z);
F = @(x,X)(x(1)+j.*X.*x(2))./(j.*X.*x(1)*x(3)+(j.*X.^2).*x(2)*x(3)+1);
x0 = [1 0.0001 0.001];
[x,resnorm] = lsqcurvefit(F,x0,X,Y)
R = real(x(1))
L = real(x(2))
C = real(x(3))
Z = (R+s.*L)./(s.*R*C+(s.^2).*L.*C+1);
figure(1)
subplot(2,1,1)
loglog(fr,abs(Z),'.r')
subplot(2,1,2)
semilogx(fr, angle(Z)*180/pi,'.r')
Ein weites Feld.
Ich habe mal meinen Code angehängt, der nutzt fminsearch. Das geht mit
Deinem Z erstma so lala, er macht schon was.
Punkte:
- Z ist sehr spitz (ungedämpft), das mögen die nichtlinearen Fitter
nicht so
- Du hast ja eigentlich nur zwei Parameter, Resonanzfrequenz und
Dämpfung, es ist beser, das Problem in diesen beiden Parametern zu
formulieren
- Die gesuchten Parameter dürfen sich nicht in Größenordnungen
untescheiden, immer schön in der Nähe von 1 bleiben, ich habe C und L
entsprechend normiert
- lsqcurvefit kenne ich nicht, mache das seit jeher mit fminsearch, das
ist frickelig, kann aber gehen ;-)
- Function-handle verstehe ich nicht, bin ich zu blöd, die Paramter bei
Deinem Function-handle Aufruf waren auch buggy, das muss wahrscheinlich
lsqcurvefit(F,x0,s,Z) heißen. Ich mache das immer mit ner separaten
Function, fun1, fummelig aber geht, siehe Code.
Nichtlinearen Fit habe ich nur als schwierig kennengelernt, kann man
Woche um Woche fummeln ohne was zu erreichen, gerade wenn man mehr als
drei Parameter hat.
Cheers
Detlef
clc
clear all
close all
R = 0.5;
C = 2e-11;
L = 5e-07;
%optimoptions(@lsqcurvefit,...
% 'TolFun',1e-8,'MaxFunEvals', 1000, 'MaxIter', 1000, 'TolX', 1e-8);
fr = logspace(1,9,200);
w = 2*pi.*fr;
s = j*w;
Z = (R+s.*L)./(s.*R*C+(s.^2).*L.*C+1);
%x(1) = R; x(2) = L; x(3) = C
save z.mat s Z
figure(1)
subplot(2,1,1)
loglog(fr,abs(Z))
hold
subplot(2,1,2)
semilogx(fr, angle(Z)*180/pi)
hold
X = fr;
Y = abs(Z);
F = @(x,X)(x(1)+j.*X.*x(2))./(j.*X.*x(1)*x(3)+(j.*X.^2).*x(2)*x(3)+1);
x0 = [ 1 2.5 5];
%[x,resnorm] = lsqcurvefit(F,x0,s,Z)
ee=fminsearch('fun1',x0)
return
function [erg]= fun1(x);
C=x(2)*1e-11;
L =x(3)*1e-07;
R= x(1);
load z.mat;
ZZ = (R+s.*L)./(s.*R*C+(s.^2).*L.*C+1);
erg=sum(abs(Z-ZZ));
return