I performed a surface fit of some data in Matlab using the fit function.
To be more specific:
func_trim= fit( [hopper_volume, water_ballast_volume], trim, 'poly55');
It returned a multi-variable polynomial:
Linear model Poly55:
func_trim(x,y) = p00 + p10*x + p01*y + p20*x^2 + p11*x*y + p02*y^2 + p30*x^3
+ p21*x^2*y + p12*x*y^2 + p03*y^3 + p40*x^4 + p31*x^3*y
+ p22*x^2*y^2 + p13*x*y^3 + p04*y^4 + p50*x^5 + p41*x^4*y
+ p32*x^3*y^2 + p23*x^2*y^3 + p14*x*y^4 + p05*y^5
Coefficients (with 95% confidence bounds):
p00 = -4.742 (-4.745, -4.74)
p10 = 5.068e-05 (4.969e-05, 5.167e-05)
p01 = 0.001447 (0.001436, 0.001459)
p20 = -3.565e-09 (-3.731e-09, -3.399e-09)
p11 = -6.534e-08 (-6.7e-08, -6.369e-08)
p02 = -1.6e-07 (-1.815e-07, -1.385e-07)
p30 = 5.919e-13 (5.795e-13, 6.043e-13)
p21 = 4.683e-12 (4.552e-12, 4.815e-12)
p12 = 1.129e-11 (9.908e-12, 1.267e-11)
p03 = 1.471e-10 (1.282e-10, 1.659e-10)
p40 = -2.017e-17 (-2.059e-17, -1.975e-17)
p31 = -1.562e-16 (-1.611e-16, -1.513e-16)
p22 = -6.93e-16 (-7.444e-16, -6.417e-16)
p13 = -9.909e-16 (-1.551e-15, -4.308e-16)
p04 = -6.751e-14 (-7.516e-14, -5.986e-14)
p50 = 2.446e-22 (2.392e-22, 2.5e-22)
p41 = 2.186e-21 (2.118e-21, 2.254e-21)
p32 = 1.321e-20 (1.243e-20, 1.4e-20)
p23 = 3.805e-20 (2.969e-20, 4.642e-20)
p14 = 2.262e-20 (-6.978e-20, 1.15e-19)
p05 = 1.059e-17 (9.424e-18, 1.175e-17)
I now want to use this object in the simulink environment.
One option would be to explicitly define this in simulink by just hard-coding it in. However I don't prefer this because the coefficients might change (quite frequently) over time and I would have to repeat this every time.
So in short. Are there any more elegant ways to use this object straight in simulink?
The easiest thing to do is to wrap the fit object into a function handle and then call that from an Interpreted MATLAB function block.
To create the function handle:
>> myFunc = #(u)feval(func_trim,u);
Then with the Interpreted MATLAB function block you'll need to
Mux the x and y signals together, then feed the combined signal into the block.
Use "myFunc(u)" - without the double quotes - as the name of the function to call.
The above is not the fastest approach from an execution pespective, nor will it allow for code generation, but it is by far the easiest/quickest to get something up an running.
Related
I want to plot the Lorentz system (s=10, r=28, b=8/3) for a start condition which should give 0 since it's a start condition in the plane spanned by v1 and v2 and trough the critical point (0,0,0) (equation of the plane : -x + (-9- \sqrt(1201))/56 * y = 0) When I use the Runge-Kutta method to plot the solution with as start conditions ((-9-sqrt(1201))/56,1,10) my graph doesn't converge to 0 and I don't know why.
[X,Y,Z,T] = Runge(T0,(-9-sqrt(1201))/56,1,10,h,1000);
plot(T,X);
plot(T,Y);
plot(T,Z);
I expect a solution in which the lines in the plots go to 0. But I get some random function which goes up and down all the time.
Could this be caused by approximations?
Thanks in advance
This is the function Runge
function [X,Y,Z,T] = Runge(t0,x0,y0,z0,h,n)
X=[x0];
Y=[y0];
Z=[z0];
T=[t0];
k1x = 0;
k1y = 0;
k1z = 0;
k2x=0;
k2y=0;
k2z=0;
k3x=0;
k3y=0;
k3z=0;
k4x=0;
k4y=0;
k4z=0;
for k = 1:n
T(k+1)= T(k) +h;
k1x = F(X(k),Y(k),Z(k));
k1y = G(X(k),Y(k),Z(k));
k1z = H(X(k),Y(k),Z(k));
k2x = F(X(k)+h/2*k1x,Y(k) + h/2*k1y, Z(k) + h/2*k1z);
k2y= G(X(k)+h/2*k1x,Y(k) + h/2*k1y, Z(k) + h/2*k1z);
k2z= H(X(k)+h/2*k1x,Y(k) + h/2*k1y, Z(k) + h/2*k1z);
k3x= F(X(k)+h/2*k2x,Y(k)+h/2*k2y,Z(k) + h/2*k2z);
k3y=G(X(k)+h/2*k2x,Y(k)+h/2*k2y,Z(k) + h/2*k2z);
k3z=H(X(k)+h/2*k2x,Y(k)+h/2*k2y,Z(k) + h/2*k2z);
k4x= F(X(k)+h*k3x,Y(k)+h*k3y,Z(k)+h*k3z);
k4y=G(X(k)+h*k3x,Y(k)+h*k3y,Z(k)+h*k3z);
k4z=H(X(k)+h*k3x,Y(k)+h*k3y,Z(k)+h*k3z);
X(k+1) = X(k) + h/6 * (k1x + 2*k2x + 2*k3x + k4x);
Y(k+1) = Y(k) + h/6 * (k1y + 2*k2y + 2*k3y + k4y);
Z(k+1) = Z(k) + h/6 * (k1z + 2*k2z + 2*k3z + k4z);
end
end
There is no such plane for the non-linear system
Why do you think this plane is invariant?
In the system
F=#(x,y,z) sigma*(y-x);
G=#(x,y,z) x*(rho-z)-y;
H=#(x,y,z) x*y-beta*z;
no non-trivial linear combination of the first two equations is independent of z, which would be required to get an invariant expression in only x and y.
The invariant sub-spaces of the linearization are close to the stable and unstable manifolds, but they are not identical to them. So if you are on some invariant subspace of the linearization, you are in fact some distance away from any curved sub-manifolds related to the non-linear system, and numerical as well as exact solutions will move towards the chaotic attractor.
The Lorentz system is chaotic
Apart from that your observation is correct that floating point errors accumulate to drive the numerical solution away from the exact solution and any properties of it.
I fit some data with high order polynomials as such:
ft = fittype('poly9');
[f,gof] = fit(x,y,ft);
and then turn this into a function:
func = #(x) f.p1*x.^9 + f.p2*x.^8 + f.p3*x.^7 + f.p4*x.^6 + f.p5*x.^5 + f.p6*x.^4 + f.p7*x.^3 + f.p8*x.^2 + f.p9*x + f.p10;
I therefore write out the function by hand. The problem is, this is very prone to typos. Is there a way to create a function automatically from a fit?
You don't need to write the function, you can simply use the object f from the output of fit:
y_model = f(x);
where y_model is the result of input x.
I am building (my first...) MatLab program, it needs to differentiate an equations symbolically and then use this solution many many times (with different numeric inputs).
I do not want it to recalculate the symbolic differentiation every time it needs to put in a new set of numeric values. This would probably greatly add to the time taken to run this program (which - given its nature, a numeric optimiser, will probably already be hours).
My question is how can I structure my program such that it will not recalculate the symbolic differentiation?
The class in question is:
function [ result ] = GradOmega(numX, numY, numZ, numMu)
syms x y z mu
omega = 0.5*(x^2+y^2+z^2) + (1-mu)/((x+mu)^2+y^2+z^2)^0.5 + mu/((x+mu-1)^2+y^2+z^2)^0.5;
symGradient = gradient(omega);
%//Substitute the given numeric values back into the funtion
result = subs(symGradient, {x,y,z,mu}, {numX, numY, numZ, numMu});
end
I know that I could just symbolically calculate the derivative and then copy-paste it into the code e.g.
gradX = x + ((2*mu + 2*x)*(mu - 1))/(2*((mu + x)^2 + y^2 + z^2)^(3/2)) - (mu*(2*mu + 2*x - 2))/(2*((mu + x - 1)^2 + y^2 + z^2)^(3/2));
gradY = y - (mu*y)/((mu + x - 1)^2 + y^2 + z^2)^(3/2) + (y*(mu - 1))/((mu + x)^2 + y^2 + z^2)^(3/2);
gradZ = z - (mu*z)/((mu + x - 1)^2 + y^2 + z^2)^(3/2) + (z*(mu - 1))/((mu + x)^2 + y^2 + z^2)^(3/2);
But then my code is a bit cryptic, which is a problem in a shared project.
There is a related query here: http://uk.mathworks.com/matlabcentral/answers/53542-oop-how-to-avoid-recalculation-on-dependent-properties-i-hope-a-mathwork-developer-could-give-me-a
But I'm afraid I couldn't follow the code.
Also I am much more familiar with Java and Python, if that helps explain anything.
You could wrap your function into some kind of Function-Factory, which does not return numerical results, but a function that can be evaluated:
(I had to replace the call syms with sym('mu'), because for some reason it kept calling a mutools function in line omega = .... I did also change the call to gradient to make sure the arguments are in correct order, and mu will be treated as constant.)
function GradOmega = GradOmegaFactory()
x = sym('x');
y = sym('y');
z = sym('z');
mu = sym('mu');
omega = 0.5*(x^2+y^2+z^2) + (1-mu)/((x+mu)^2+y^2+z^2)^0.5 + mu/((x+mu-1)^2+y^2+z^2)^0.5;
symGradient = gradient(omega,{'x','y','z'});
GradOmega = matlabFunction(symGradient, 'vars', {'x','y','z','mu'});
end
Then you would call it via:
GradOmega = GradOmegaFactory();
result1 = GradOmega(numX1, numY1, numZ1, numMu1);
result2 = GradOmega(numX2, numY2, numZ2, numMu2);
result3 = GradOmega(numX3, numY3, numZ3, numMu3);
...
Even better:
You could go even more fancy and use a wrapper function GradOmega which builds such a function inside and makes it persistent, to get the same interface you had with your initial approach. The first time you call the function GradOmega the symbolic expression is evaluated, but on each consecutive call you will only have to evaluate the generated function handle, which means it should be nearly as fast as if you hard-coded it.
function result = GradOmega(numX, numY, numZ, numMu)
persistent numericalGradOmega;
if isempty(numericalGradOmega)
numericalGradOmega = GradOmegaFactory();
end
result = numericalGradOmega(numX, numY, numZ, numMu);
end
Use this like you would use your original version
result = GradOmega(numX, numY, numZ, numMu);
Just copy and paste both functions into a single GradOmega.m file. (GradOmega should be the first function in the file.)
Another tip: You can even evaluate this function using vectors. Instead of calling GradOmega(1,2,3,4) and GradOmega(5,6,7,8) afterwards, you can save the time overhead via the call GradOmega([1,5], [2,6], [3,7], [4,8]) using row vectors.
Yet another tip: To clean up your code even more, you could also put the first lines into a separate symOmega.m file.
function omega = symOmega()
x = sym('x');
y = sym('y');
z = sym('z');
mu = sym('mu');
omega = 0.5*(x^2+y^2+z^2) + (1-mu)/((x+mu)^2+y^2+z^2)^0.5 + mu/((x+mu-1)^2+y^2+z^2)^0.5;
This way you don't have to have a copy of this symbolic expression in every file you use it. This can be beneficial if you also want to evaluate Omega itself, as you then can make use of the same Factory-approach listed in this answer. You would end up with the following files: symOmega.m, Omega.m and GradOmega.m, where only the file symOmega.m has the actual mathematical formula and the other two files make use of symOmega.m.
I have a series of experimental kinetic data in a form of Concentration = f(time), namely:
L(time) = f0(time)
A(time) = f1(time)
B(time) = f2(time)
C(time) = f3(time)
D(time) = f4(time)
P(time) = f5(time)
A(time) + ... + P(Time) = known value
I have a model represented as a system of differential equations:
dL/dt = -k_tot*MR3*(L)^2, where k_tot = k_LA + k_LB + k_LC + k_LD
dMR3/dt = -k_tot*MR3*L
dP/dt = k_AP*A + k_BP*B + k_CP*C + k_DP*D
dA/dt = 2*k_LA*MR3*(L)^2 - k_AP*A
dB/dt = 2*k_LB*MR3*(L)^2 - k_BP*B
dC/dt = 2*k_LC*MR3*(L)^2 - k_CP*C
dD/dt = 2*k_LA*MR3*(L)^2 - k_DP*D
I would like to use ODE model (ode45) in order to:
find/estimate the k_XY (k_LA, k_LB, ..., k_AP etc)
curve-fit the calculated data with the experimental ones.
The idea is to set up the ODE-based function, which would allow to fit a specified data for a specified diff.equation within the given system of equations.
Could someone help with the example of Matlab code, please?
Thanks much in advance!
Is there any way to extract data out of cfit or sfit object? I want to extract matrix of fitted values out of sfit object without accessing to every element of fit (very slow in 240x320 ). Problem is equivalent to extraction of vector out of cfit object. Is there a method defined over this object, or something similar?
Please, post a code!
thanks, Nikola
You can access an element of an sfit object with sfit.element. For example:
sf = fit([x,y],z,'poly23');
sf
Linear model Poly23:
sf(x,y) = p00 + p10*x + p01*y + p20*x^2 + p11*x*y + p02*y^2 + p21*x^2*y
+ p12*x*y^2 + p03*y^3
Coefficients (with 95% confidence bounds):
p00 = 1.118 (0.9149, 1.321)
p10 = -0.0002941 (-0.000502, -8.623e-05)
p01 = 1.533 (0.7032, 2.364)
p20 = -1.966e-08 (-7.084e-08, 3.152e-08)
p11 = 0.0003427 (-0.0001009, 0.0007863)
p02 = -6.951 (-8.421, -5.481)
p21 = 9.563e-08 (6.276e-09, 1.85e-07)
p12 = -0.0004401 (-0.0007082, -0.0001721)
p03 = 4.999 (4.082, 5.917)
To get one element of sf:
sf.p03
ans =
4.9994