Consider the following matlab code fragment:
g = #(x, t)x.*0;
u_explizit = explizit_Euler(20, 800, 1, 1, zeros(21,1), g, [1;2], 0, 0.1);
figure
surf(u_explizit);
shading flat;
title('Aufgabe 2 - Explizit Euler');
u_implizit = implizit_Euler(20, 800, 1, 1, zeros(21,1), g, [1;2], 0, 0.1);
Both functions explizit_Euler and implizit_Euler start with the same commands (here shown for explizit_Euler:
function [u] = explizit_Euler(n, nt, T, kappa, u0, f, b, gN, gD)
tau = T/nt;
[A, z] = prepare_system(n, f, b, gN, gD);
z = z';
...
end
The function prepare_system looks like this:
function [ A, z] = prepare_system(n, f, b, gN, gD)
%PREPARE_MATRIX_SYSTEM Prepares A_h and solution vector f_h
h = 1/n;
z = f((0:n)./n);
...
end
The call of prepare_system from within explizit_Euler works just fine. However, the call from within implizit_Euler delivers an error message and I just can't figure out why:
Subscript indices must either be real positive integers or logicals.
Error in implizit_Euler (line 5)
z = f((0:n)./n);
It seems that matlab thinks f is a vector, and thus it can't access f(0), which makes sense if f was a vector. But f is a function handle! And how come the exact same code works fine in an earlier code from within explizit_Euler?
I missplaced the parameters in the signature of implizit_Euler (!) - sorry, guys!
Related
So I have three seperate function in MATLAB where each have its designated purpose.
The first one calculates the partial derivative
The second finds the roots for a system of two equations and two variables.
The third is supposed to find the critical point.
I have tried doing everything separately and it worked. However when I do this through my CriticalPoint function it just keeps running(it says "busy" in the lower left corner).
I have tried solving this manually. Meaning that I've used each function as intended, saved the values in my workspace and used for the next function.
The only thing different is how I treated my partials.
I have a function which takes evaluates the partial derivative at a point [x,y].
derivative = Pderiv(f, a, b, i)
%The i denotes if the partial derivative is take with respect to x or y
%where if i == 1, then it means that partial derivative is with respect to
%x and if i == 2 then it is with respect to y
The thing I did differently was that I found the partial derivative for f(x,y) manually using pen and paper.
I.e
df/dx and df/dy (these are partials, sorry for not using the proper symbol)
And then I inserted it into my function:
[x0,y0] = MyNewton(f, g, a, b)
Where df/dx is the argument for "f" and df/dy is the argument for "g".
This gives me the correct x & y values when df/dx=df/dy=0.
What I want to have it do is for a given function f(x,y)
I want to find the partial derivative where the input values are still represented by x and y.
I was told by my teacher that the following expression:
g=#(x,y)NPderiv(f,x,y,1);
would be sufficent. Is it though? Since it works when I do it manually but the program runs forever when I define my function g as above.
I'm not sure if it is relevant but here is my code for the partial derivative:
function derivative = NPderiv(f, a, b, i)
h = 0.0000001;
fn=zeros(1,2);
if i == 1
fn(i) = (f(a+h,b)-f(a,b))/h;
elseif i==2
fn(i) = (f(a,b+h)-f(a,b))/h;
end
derivative = fn(i);
end
function for my critical point function:
function [x,y] = CriticalPoint(f, a, b)
g=#(x,y)NPderiv(f,x,y,1); %partial derivative for f(x,y) with respect to x
z=#(x,y)NPderiv(f,x,y,2);%partial derivative for f(x,y) with respect to y
[x,y]=MyNewton(g,z,a,b);
end
MyNewton function:
function [x0,y0] = MyNewton(f, g, a, b)
y0 = b;
x0 = a;
tol = 1e-18;
resf = tol + 1;
resg = tol + 1;
while resf > tol && resg > tol
dfdx = NPderiv(f, x0, y0, 1);
dfdy = NPderiv(f, x0, y0, 2);
dgdx = NPderiv(g, x0, y0, 1);
dgdy = NPderiv(g, x0, y0, 2);
jf1 = [f(x0,y0) dfdy; ...
g(x0,y0) dgdy];
jg1 = [dfdx f(x0,y0); ...
dgdx g(x0,y0)];
j2 = [dfdx dfdy; ...
dgdx dgdy];
jx = det(jf1)./det(j2);
jy = det(jg1)./det(j2);
x0 = x0 - jx;
y0 = y0 - jy;
resf = abs(f(x0,y0));
resg = abs(g(x0,y0));
end
end
This is my first attempt to write anything in matlab, so please, be patient.
I am trying to evaluate the solution of the following ODE: w'' + N(w, w') = f(t) with the Cauchy conditions w(0) = w'(0) = 0. Here N is a given nonlinear function, f is a given source. I also need the function
where G is the solution of the following ODE:
where G(0) = G'(0) =0, s is a constant, and
My try is as follows: I define N, f, w and G:
k = 1000;
N = #(g1,g2) g1^2 + sin(g2);
f = #(t) 0.5 * (1 + tanh(k * t));
t = linspace(0, 10, 100);
w = nonlinearnonhom(N, f);
G = nonlinearGreen(N);
This part is ok. I can plot both w and G: both seems to be correct. Now, I want to evaluate wG. For that purpose, I use the direct and inverse Laplace transforms as follows:
wG = ilaplace(laplace(G, t, s) * laplace(f, t, s), s, t);
but is says
Undefined function 'laplace' for input arguments of type 'double'.
Error in main (line 13)
wG = ilaplace(laplace(G, t, s) * laplace(f, t, s), s, t);
Now, I am not sure if this definition of wG is correct at all and if there are not any other definitions.
Appendix: nonlinearGreen(N) is defined as follows:
function G = nonlinearGreen(N)
eps = .0001;
del = #(t)[1/(eps * pi) * exp( -t^2/eps^2)];
eqGreen = #(t, g)[g(2); - N(g(1),g(2)) + del(t)];
tspan = [0, 100];
Cc = [0, 0];
solGreen = ode45(eqGreen, tspan, Cc);
t = linspace(0, 10, 1000);
G = deval(solGreen, t, 1);
end
and nonlinearnonhom is defined as follows:
function w = nonlinearnonhom(N, f)
eqnonhom = #(t, g)[g(2); - N(g(1),g(2)) + f(t)];
tspan = [0, 100];
Cc = [0, 0];
solnonhom = ode45(eqnonhom, tspan, Cc);
t = linspace(0, 10, 100);
w = deval(solnonhom, t, 1);
end
You keep mixing different kind of types and it's not a good idea. I suggest you keep with symbolic all the way if you want to use the laplace function. When you define N and f with #(arobase) as function handles and not symbolic expressions as you might want to do. I suggest you have a look at symbolic documentation and rewrite your functions as symbolic.
Then, the error message is pretty clear.
Undefined function 'laplace' for input arguments of type 'double'.
Error in main (line 13)
wG = ilaplace(laplace(G, t, s) * laplace(f, t, s), s, t);
It means that the function laplace can't have arguments of type double.
The problem is that your t is a vector of double. Another mistake is that s is not defined in your code.
According to Matlab documentation of laplace, all arguments are of type symbolic.
You can try to manually specify symbolic s and t.
% t = linspace(0, 10, 100); % This is wrong
syms s t
wG = ilaplace(laplace(G, t, s) * laplace(f, t, s), s, t);
I have no error after that.
I am trying to get the volume under a profile by using Octave. I have built a simple model for this:
function F1 = f_x(x)
F1 = x-1;
endfunction
function F2 = f_y(y)
F2 = y;
endfunction
function F3 = f_z(z)
F3 = z;
endfunction
f_xyz = inline('f_x(x).*f_y(y).*f_z(z);', 'x', 'y', 'z');
Volume = triplequad(f_xyz,0,3,0,3,0,4)
x = 1:1:2;
y = 1:1:2;
z = 1:1:2;
f_plot=f_x(x).*f_y(y).*f_z(z)';
%Lines for plotting the 3D plot
tx = linspace (0, 3, numel(x))';
ty = linspace (0, 3, numel(y))';
[xx, yy] = meshgrid (tx, ty);
tz = f_plot;
mesh (tx, ty, tz);
which gives a plot that looks like in the picture below:
I am using the triplequad function (which works also on Matlab) to get the volume under that profile, but it doesn't look like it works. The function return a volume of 54 units, which is not really true. Calculating the volume of a parallelepiped using the full dimensions gives 36 units (3 x 3 x 4), which proves that it calculates it wrongly. The questions is... what am I doing wrong here? Why doesn't "triplequad" give the right volume?
I think you might be misunderstanding the dimensionality of your problem. You're dealing with a 4D function:
f = #(x, y, z) (x-1).*y.*z;
You have a value returned by f (i.e. the dependent variable) determined by a set of 3 independent variables, thus a 4D function. You have to talk in terms of hypervolume instead of volume in this case, since volume is a 3D measurement. The triplequad function will evaluate a triple integral of f over a given set of ranges for the independent variables, giving you the hypervolume:
>> triplequad(f, 0, 3, 0, 3, 0, 4) % Integrate over 0 <= x <= 3, 0 <= y <= 3, 0 <= z <= 4
ans =
53.999999999999986 % Just shy of 54
Your visualization of a 3D surface doesn't make any sense, and is leading you astray in thinking that the result is wrong.
NOTE 1: In MATLAB, the function triplequad appears slated for deprecation in a future release, so you should use integral3 instead. It also appears to give more accurate results:
>> integral3(f, 0, 3, 0, 3, 0, 4)
ans =
54
NOTE 2: In regards to your comment, the function f(x,y,z) = 1 is constant and has no dependence on x, y, or z. A triple integral over this function is the equivalent of computing the volume of the area over which you're integrating (3*3*4 = 36) multiplied by the constant function value (which is just 1 in this case). You can confirm it like so:
>> f = #(x, y, z) ones(size(x));
>> triplequad(f, 0, 3, 0, 3, 0, 4)
ans =
36
EDIT: Regarding your follow-up problem, I actually get an error when trying to run that example in R2016b, so I'm not sure how you got it to work (although the resulting value is correct):
>> V = triplequad(h_xxyy,0,3,0,3,0,15)
Error using inline/subsref (line 14)
Too many inputs to inline function.
The problem is that triplequad is used to perform triple integrals over functions of 3 variables, but your function only has 2 inputs (x and y). When calculating the volume under a function of 2 variables, you only need to integrate over those 2 variables, so you should be using the MATLAB function integral2 instead (or dblquad in Octave):
>> f = #(x, y) x.^2.*sqrt(y);
>> V = integral2(f, 0, 3, 0, 3)
V =
31.176914536244894
Note that f has no z-dependence, so f(x, y) is constant with respect to z (i.e. for a given x and y, it always returns the same value regardless of z). As a result, if you were to perform a third integration over the z dimension it would be the same as multiplying the result by the integration range:
>> V*15
ans =
467.6537 % Same result you got from triplequad
'x' is specified as #(x), but error message keeps coming up.
<i> function F = drawCFRPgraph0726(X, y, E, I, A, G, r, c, m)
t(1) = pi/2+0.0000001;
i = 1;
while t(i)<pi
disp(t(i));
for k = 1:500
L(k) = 0.000001*k;
dvdx(x) = #(x) ((x/3-L(k)/2)(c*L(k)*m/(c+r)-x(t(i)-y-pi/2))/(x-L(k))+x* (L(k)/2-x/3)(c*L(k)*m/(c+r)-x(t(i)-y-pi/2))/(x-L(k))^2+x(c*L(k)*m/(c+r)-x(t(i)-y-pi/2))/(3*(x-L(k)))+x*(y-t(i)+pi/2)*(x/3-L(k)/2)/(x-L)+x*t(i)-x*y-pi*x/2)/L(k);
d2vdx2(x) = #(x) ((-2*x/3+L(k))*(c*L(k)*m/(c+r)-x*(t(i)-y-pi/2))/(x-L(k))^2+x*(2*x/3-L(k))*(c*L(k)*m/(c+r)-x(t(i)-y-pi/2))/(x-L(k))^3-2*x*(c*L(k)*m/(c+r)-x*(t(i)-y-pi/2))/(3(x-L(k))^2)+2*(c*L(k)*m/(c+r)-x*(t(i)-y-pi/2))/(3*(x-L(k)))+(y-t(i)+pi/2)*(2*x/3-L(k))/(x-L(k))+x*(-2*x/3+L(k))*(y-t(i)+pi/2)/(x-L(k))^2+2*x*(y-t(i)+1.5708)/(3*(x-L(k)))+t(i)-y-pi/2)^2/L(k)^2;
A(k) = quad(dvdx(x), 0, L(k));
B(k) = quad(dv2dx2(x), 0, L(k));</i>
you are wrongly defining the anonymous function.
To define them properly you should:
dvdx = #(x) ((x/3-L(k)/2)(c*L(k)*m/(c+r)-x(t(i)-y-pi/2))/(x-L(k))+x* (L(k)/2-x/3)(c*L(k)*m/(c+r)-x(t(i)-y-pi/2))/(x-L(k))^2+x(c*L(k)*m/(c+r)-x(t(i)-y-pi/2))/(3*(x-L(k)))+x*(y-t(i)+pi/2)*(x/3-L(k)/2)/(x-L)+x*t(i)-x*y-pi*x/2)/L(k);
This means: now dvdx is a function that takes 1 argument (#(x)) and evaluates it with the following equation ((x/2-L(k) .... But x is not defined outside, the same way X, y, E, I, A, G, r, c, m are not defined outside, just inside the function.
The first input of quad is a function, and the function is not dvdx(x) but just dvdx
I have the following homework question:
Apply linear least squares with the two models S1(A, B, C) = Ax^2 + Bx
+ C and S2(A, B, C, D) = Ax^3 + Bx^2 + Cx + D to the data set (0, 4), (1, −1), (2, 6), (3, 1), (4, −4), (5, −9). Solve in MATLAB using
lspoly. Report the values of the parameters A, B, C and D clearly, and
produce a plot showing the data and both fitting curves.
I am working with the following function in MATLAB:
Function 1
function y = horner(a,c)
n=length(a)-1;
y=a(n+1);
for k = n:-1:1
y = a(k)+ c*y;
end
Function 2
function C = lspoly(x,y,M)
n = length(x);
F = zeros(n,M+1);
for k = 1:M+1
F(:,k) = x'.^(k-1);
end
A = F'*F;
B = F'*y';
C = A\B;
And this is the code I wrote for the problem:
clc
clear all
close all
x = [0, 1, 2, 3, 4, 5];
y = [4, -1, 6, 1, -4, -9];
C = lspoly(x,y,2); % finds the parameters
xx = 0:0.01:5;
yy = zeros(1, length(xx));
for i=1:length(xx)
yy(i) = horner(C,xx(i));
end
CC = lspoly(x,y,3); % finds the parameters
xxx = 0:0.1:5;
yyy = zeros(1, length(xxx));
for i=1:length(xxx)
yyy(i) = horner(CC,xxx(i));
end
figure(1)
plot(x, y, 'o', xx, yy, 'r-', xxx, yyy, 'b-')
I am encountering some issues with this code. When I try to run the program, I get the following error:
In an assignment A(I) = B, the number of elements in B and I must be
the same.
Error in HW7_1 (line 14) yy(i) = horner(C,xx(i));
I can't really wrap my head around what exactly I need to do to fix this issue. I tried breaking down my program piece by piece to determine results at different spots in the code, but so far nothing of note has been found.
Can someone help me fix this error?
It works just fine for me in Octave 3.8. The only thing I can think of is there a built-in function called horner in MATLAB (part of the Symbolic Math Toolbox), so maybe your code is calling that function instead of yours. Maybe try renaming it to something different, like my_horner or similar.