Programmatically find fzero of two RCL functions

2 次查看(过去 30 天)
How do I fix my code to programmatically find the fzero of two functions? I had to hand-code the functions funcVL and funcVR from model fit coefficients. I want to do that programmatically, then find fzero (intersection point) of the two function curves. Need some help here. Thank you
% find intersection (frequency) of two RCL functions
load RCL_vars.mat % creates 3 vectors, f, VL, VR from data
% function calls
createFitVL(f, VL)
createFitVR(f, VR)
% find intersection point, f
x = f;
funcVL = @ (x) -3.948*exp(-0.658*x)+3.898;
funcVR = @ (x) 3.856*exp(0.2436*x)+0.2436;
%use fzero with the function: @(x) funcVL(x) - funcVR(x).
soltn = fzero(@(x) funcVR(x)- funcVL(x), [0, 10])
%%
function [fitresult, gof] = createFitVL(f, VL)
%CREATEFIT(F,VL)
% Create a fit.
%
% Data for 'untitled fit 1' fit:
% X Input: f
% Y Output: VL
% Output:
% fitresult : a fit object representing the fit.
% gof : structure with goodness-of fit info.
%
% See also FIT, CFIT, SFIT.
% Auto-generated by MATLAB on 26-Feb-2025 15:57:28
%% Fit: 'untitled fit 1'.
[xData, yData] = prepareCurveData( f, VL );
% Set up fittype and options.
ft = fittype( 'a*exp(-b*x)+c', 'independent', 'x', 'dependent', 'y' );
opts = fitoptions( 'Method', 'NonlinearLeastSquares' );
opts.Display = 'Off';
opts.StartPoint = [0.317099480060861 0.950222048838355 0.0344460805029088];
% Fit model to data.
[fitresult, gof] = fit( xData, yData, ft, opts );
% Plot fit with data.
figure( 'Name', 'untitled fit 1' );
h = plot( fitresult, xData, yData );
legend( h, 'VL vs. f', 'untitled fit 1', 'Location', 'NorthEast', 'Interpreter', 'none' );
% Label axes
xlabel( 'f', 'Interpreter', 'none' );
ylabel( 'VL', 'Interpreter', 'none' );
grid on
end
%
hold on
%% Fit: 'untitled fit 1'.
function [fitresult, gof] = createFitVR(f, VR)
[xData, yData] = prepareCurveData( f, VR );
% Set up fittype and options.
ft = fittype( 'a*exp(-b*x)+c', 'independent', 'x', 'dependent', 'y' );
opts = fitoptions( 'Method', 'NonlinearLeastSquares' );
opts.Display = 'Off';
opts.StartPoint = [0.257508254123736 0.840717255983663 0.254282178971531];
% Fit model to data.
[fitresult, gof] = fit( xData, yData, ft, opts );
% Plot fit with data.
figure( 'Name', 'untitled fit 1' );
h = plot( fitresult, xData, yData );
legend( h, 'VR vs. f', 'untitled fit 1', 'Location', 'NorthEast', 'Interpreter', 'none' );
% Label axes
xlabel( 'f', 'Interpreter', 'none' );
ylabel( 'VR', 'Interpreter', 'none' );
grid on
end

采纳的回答

Star Strider
Star Strider 2025-2-27
It seems that the curves don’t intersect.
The ‘funcVR’ function never crosses zero, although the ‘funcVL’ function does —
funcVL = @ (x) -3.948*exp(-0.658*x)+3.898;
funcVR = @ (x) 3.856*exp(0.2436*x)+0.2436;
xs = fzero(@(x) funcVL(x)-funcVR(x), randn)
Exiting fzero: aborting search for an interval containing a sign change because NaN or Inf function value encountered during search. (Function value at -1203.79 is -Inf.) Check function or try again with a different starting value.
xs = NaN
xv = linspace(-1E+2, 1E+2, 1E3);
yL = funcVL(xv);
yR = funcVR(xv);
ixx = find(diff(sign(yL-yR)))
ixx = 1x0 empty double row vector
Zpts = [fzero(funcVR, 0.5) fzero(funcVL, 0.5)]
Exiting fzero: aborting search for an interval containing a sign change because NaN or Inf function value encountered during search. (Function value at 3707.78 is Inf.) Check function or try again with a different starting value.
Zpts = 1×2
NaN 0.0194
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
figure
plot(xv, yR, DisplayName='funcVR')
hold on
plot(xv, yL, DisplayName='funcVL')
plot(Zpts(2), 0, 'mp', DisplayName=sprintf('funcVL(%.4f) = 0',Zpts(2)))
hold off
grid
legend(Location='best')
xlim([-100 100])
ylim([-5 5])
.
  5 个评论
Steven Lord
Steven Lord 2025-2-27
Yes, and from the presence of this line in your createFitVL local function it seems you've already used it.
% Auto-generated by MATLAB on 26-Feb-2025 15:57:28
See this page in the documentation for Curve Fitting Toolbox.
Or if you don't want to generate code, rather than manually creating the anonymous function yourself you can use the fitresult output argument (created by the fit function) from the local functions directly in the anonymous function you pass to the zero finder. Let's make two fits to the census data included in MATLAB:
load census
fitobj1 = fit(cdate, pop, 'poly1')
fitobj1 =
Linear model Poly1: fitobj1(x) = p1*x + p2 Coefficients (with 95% confidence bounds): p1 = 1.216 (1.045, 1.387) p2 = -2212 (-2535, -1889)
fitobj2 = fit(cdate, pop, 'poly2')
fitobj2 =
Linear model Poly2: fitobj2(x) = p1*x^2 + p2*x + p3 Coefficients (with 95% confidence bounds): p1 = 0.006541 (0.006124, 0.006958) p2 = -23.51 (-25.09, -21.93) p3 = 2.113e+04 (1.964e+04, 2.262e+04)
We can see from a plot of the two fits that they do cross.
plot(fitobj1)
hold on
plot(fitobj2)
Let's computing one of the crossing points using a starting guess of 1900. Here I'm directly evaluating the two fits inside crossingFcn.
crossingFcn = @(x) fitobj1(x)-fitobj2(x);
format longg
crossingValue = fzero(crossingFcn, 1900)
crossingValue =
1950.55300708195
Let's show the crossing point fzero found for this starting point. I made the circle a bit bigger and gave it a descriptive name for the legend.
figure
plot(fitobj1);
hold on
plot(fitobj2);
plot(crossingValue, fitobj1(crossingValue), 'ko', ...
MarkerSize = 10, DisplayName = "Crossing point")
A different starting point could give the other crossing.
crossingValue = fzero(crossingFcn, 1800)
crossingValue =
1829.44699291805
Star Strider
Star Strider 2025-2-27
If I understand correcttly what you want to do, it is relatively straightforward to get the function intersections.
This gives the single intersection at (1.8292,2.7132)
funcVL = @ (x) -3.948*exp(-0.658*x)+3.898;
funcVR = @ (x) 3.856*exp(-0.2436*x)+0.2436;
xv = linspace(-2E+1, 1.5E+1, 1E3);
yL = funcVL(xv);
yR = funcVR(xv);
ixx = find(diff(sign(yL-yR)));
idxrng = max(1,ixx-1) : min(numel(xv),ixx+1);
xisx = interp1(yR(idxrng)-yL(idxrng), xv(idxrng), 0)
xisx = 1.8292
yisx = interp1(xv(idxrng), yR(idxrng), xisx)
yisx = 2.7132
ydif = yR - yL;
funcD = @(x) funcVR(x)-funcVL(x);
[xmin,fv] = fminsearch(@(x)norm(funcD(x)), randn)
xmin = 1.8292
fv = 4.5517e-05
[xmin,fv] = fzero(@(x)funcD(x), randn)
xmin = 1.8292
fv = 4.4409e-16
figure
plot(xv, yR, DisplayName='funcVR')
hold on
plot(xv, yL, DisplayName='funcVL')
% plot(xv, ydif, DisplayName='funcVR-funcVL', LineWidth=3)
plot(xisx, yisx, 'rs', DisplayName='Intersection')
hold off
grid
legend(Location='best')
xlim([-5 10])
ylim([-1 5])
text(xisx,yisx,sprintf(' \\leftarrow (%.6f, %.6f)',xisx,yisx), Horiz='left', Vert='middle')
This appears to provide a reasonable answer for the intersection.
.

请先登录,再进行评论。

更多回答(0 个)

类别

Help CenterFile Exchange 中查找有关 Get Started with Curve Fitting Toolbox 的更多信息

产品


版本

R2024b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by