Trying to do an fsolve via an anonymous function

4 visualizaciones (últimos 30 días)
Mat
Mat el 23 de Jun. de 2025
Comentada: Steven Lord el 24 de Jun. de 2025
I am trying to compute something from a set of nonlinear algebraic equations. I have a function I called initial which defines the set of nonlinear algebraic equations, I use a function initial.m as my function that I need to set as as f(x)=0. I wanted to try and see how fzero sorts this problem, I would normally code up Newton's method to do this.
The idea behind this is that I'm looking at a rod ofdensity rho_0, and I want to split it up into N equally heavy sections. The problem I have is to find how long those intervals are. I'm approximating the mass as 0.5*(rho_0(X(i))+rho_0(X(i+1)))*(X(i+1)-X(i)). It runs but it gives me zeros and bombs out.
Do I need to do back to coding up Newton's method?
  5 comentarios
Mat
Mat el 24 de Jun. de 2025
I've noticed that although matlab has a great deal of inbuilt functions, it is often easier and better to write your own functions for doing these things. It's often quicker in the long run.
Steven Lord
Steven Lord el 24 de Jun. de 2025
What leads you to believe that "It's often quicker in the long run." to write your own functions instead of using the ones included in MATLAB or other MathWorks products? Are you talking about development and maintenance time, running time, time spent learning how to use the function, or something else? I admit if you write your own function the "time spent learning how to use the function" is likely going to be small -- but how about the time spent relearning it when you try to use the code again in a month or two?
Generally, like in cases such as this one from about two weeks ago, attempting to replicate the full behavior of a built-in function can be tricky. There can be a lot of "devil in the details" cases that you may not think about. Granted, if all you need is a small piece of the functionality implementing that specific behavior may be quicker, but often problems (like gases and cats in boxes) tend to expand to fill more space than you expect.

Iniciar sesión para comentar.

Respuesta aceptada

Mat
Mat el 24 de Jun. de 2025
If you use the trapezium rule to approxumate the integral, then the problem for finding the co-ordinates just becomes a linear problem, and you can just invert a matrix.
  1 comentario
Steven Lord
Steven Lord el 24 de Jun. de 2025
you can just invert a matrix.
Please don't do that. If you need to solve a system of linear equations, use the backslash operator instead of inverting and multiplying.

Iniciar sesión para comentar.

Más respuestas (3)

Star Strider
Star Strider el 23 de Jun. de 2025
I exrtracted your code sections and attempted to run it.
You need to check the trapz integration. The call to it is correct, however you are giving it scalars, not vectors, and it cannot integrate scalars.
My analysis --
% ----- rho_0 -----
function y=rho_0(X,L)
z=0.5*exp(-(X-0.5*L).^2);
X
z
M=trapz(X,z)
y=z/M;
end%function
% ----- initial -----
function y=initial(X,N,dh,L)
%This function
y=zeros(N+1,1);
for i=1:N
i
X(i)
L
S1 = rho_0(X(i),L)
S2 = rho_0(X(i+1),L)
y(i)=0.5*(rho_0(X(i),L)+rho_0(X(i+1),L))-dh
end%for
X(1)=0;
end%function
% ----- new_idea -----
%This code is yet another attempt to solve the 1D sintering equations via a differnt approach.
%The incremental mass dh, will be held constant but the initial co-ordinates X, will be non-uniform.
%The initial co-ordinates are computed as a solution of an systen of non-linear algebraic equations.
clear; clc;
%initial length of rod
L=1;
%Amount of mass
M=1;
%Split the rod into N elements;
N=200;
X_0=linspace(0,L,N+1);
%set dh=constant
h=linspace(0,M,N+1);
dh=h(2);
%initial density as a function of X_0:
rho_start=rho_0(X_0,L);
X = 1×201
0 0.0050 0.0100 0.0150 0.0200 0.0250 0.0300 0.0350 0.0400 0.0450 0.0500 0.0550 0.0600 0.0650 0.0700 0.0750 0.0800 0.0850 0.0900 0.0950 0.1000 0.1050 0.1100 0.1150 0.1200 0.1250 0.1300 0.1350 0.1400 0.1450
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
z = 1×201
0.3894 0.3913 0.3933 0.3952 0.3971 0.3990 0.4009 0.4028 0.4046 0.4065 0.4083 0.4102 0.4120 0.4138 0.4156 0.4174 0.4191 0.4209 0.4226 0.4244 0.4261 0.4278 0.4295 0.4311 0.4328 0.4344 0.4360 0.4376 0.4392 0.4408
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
M = 0.4613
%Create an anonymous function from initial
disp("N = ")
N =
N
N = 200
disp("dh = ")
dh =
dh
dh = 0.0050
disp("L = ")
L =
L
L = 1
myfun = @(z) initial(z,N,dh,L);
%Get the initial non-uniform Lagrangian co-ordinates
% X=fzero(myfun,X_0);
X=fsolve(myfun,X_0)
i = 1
ans = 0
L = 1
X = 0
z = 0.3894
Error using matlab.internal.math.getdimarg
Dimension argument must be a positive integer scalar within indexing range.

Error in trapz>getDimArg (line 90)
dim = matlab.internal.math.getdimarg(dim);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error in trapz (line 44)
dim = min(ndims(y)+1, getDimArg(dim));
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error in solution>rho_0 (line 7)
M=trapz(X,z)
^^^^^^^^^^^^
Error in solution>initial (line 20)
S1 = rho_0(X(i),L)
^^^^^^^^^^^^^^^^^^
Error in solution>@(z)initial(z,N,dh,L) (line 61)
myfun = @(z) initial(z,N,dh,L);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error in fsolve (line 167)
fuser = feval(funfcn{3},x,varargin{:});
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Caused by:
Failure in initial objective function evaluation. FSOLVE cannot continue.
.
  2 comentarios
Mat
Mat el 24 de Jun. de 2025
trapz is fine. I'm simply computing the total mass given the initial density.
Star Strider
Star Strider el 24 de Jun. de 2025
Calling trapz with scalar arguments will produce no useful information.

Iniciar sesión para comentar.


John D'Errico
John D'Errico el 23 de Jun. de 2025
You say you want to use fzero. But you need to understand that fzero is a ONE variable solver. It CANNOT solve a multi-variable problem.
Do you need to use Newton's method? No, not at all. In fact, it is rarely ever a good idea to write your own rootfinding codes, certainly not if you are as unsure about the problem as your question seems to imply.
Your question is confusing however. You talk about a muti-variable prob;em, but then you state you are looking to identify points (in ONE dimension) along a rod. And I'd not even use a root finder for that. I'd use interp1, at least if I understand your question. You can visualize the integral of rho_0 as a monotonic function. Use cumtrapz to compute the cumulative integral.
Now interpolate a set of uniformly spaced points in cumulative rho.
  2 comentarios
Mat
Mat el 24 de Jun. de 2025
I find that coding up Newton's method is the only thing that works in most cases.
I thought fzero works for systems as well as single equations.
Stephen23
Stephen23 el 24 de Jun. de 2025
Editada: Stephen23 el 24 de Jun. de 2025
"I thought fzero works for systems as well as single equations."
The FZERO documentation states that the objective function "fun accepts a scalar x and returns a scalar fun(x)." In general a scalar cannot represent a system of equations without loss of information: FZERO is very unlikely to help with your system of equations.

Iniciar sesión para comentar.


Matt J
Matt J el 23 de Jun. de 2025
Editada: Matt J el 23 de Jun. de 2025
It doesn't look like you need an iterative solver at all. It appears that your rho0() function is just a reinvention of normcdf (perhaps with some unit scaling). The solution will therefore just be some appropriately scaled version of,
X=norminv( linspace(0,1,N), L/2) %closed-form solution
  2 comentarios
Mat
Mat el 24 de Jun. de 2025
This was simply an example, it would be any continuous function.
Matt J
Matt J el 24 de Jun. de 2025
The extension to arbitrary continuous functions is no big deal. You just compute its inverse CDF and proceed similarly.

Iniciar sesión para comentar.

Categorías

Más información sobre Numerical Integration and Differentiation en Help Center y File Exchange.

Etiquetas

Productos


Versión

R2024b

Community Treasure Hunt

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

Start Hunting!

Translated by