This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I have the following code (part of a larger program) in matlab:
while(k<n)
C.(sprintf('Cnew')) = C.(sprintf('C%d',k));
d1 = equalize_dimension(a.F, C.(sprintf('Cnew')));
distance_new = distance(d1.x, d1.y);
k = k + 1;
end
If you want to substitute values since I have included part of the program, this would be as follows:
C.(sprintf('Cnew')):
78
And, for a.F it is as follows:
78 82 84 80
80 84 86 82
82 87 88 85
82 87 89 86
For the equalize_dimension(x,y) function, it is as follows:
function n = equalize_dimension (x,y)
[r1 c1] = size(x);
[r2 c2] = size(y);
if r1<r2
e= r2-r1;
for i=1:e
x(r1+1,1)=0;
r1 = r1 + 1;
end
[r1 c1] = size(x);
n.x =x;
n.y = y;
end
if r1>r2
e = r1-r2;
for i=1:e
y(r2+1,1)=0;
r2 = r2 + 1;
end
[r2 c2] = size(y);
n.x = x;
n.y = y;
end
if c1<c2
e= c2-c1;
for i=1:e
x(1,c1+1)=0;
c1 = c1 + 1;
end
[r1 c1] = size(x);
n.x = x;
n.y = y;
end
if c1>c2
e = c1-c2;
for i=1:e
y(1,c2+1)=0;
c2 = c2 + 1;
end
[r2 c2] = size(y);
n.x = x;
n.y = y;
end
if r1==r2 && c1==c2
n.x = x;
n.y = y;
end
And, for the distance(x,y) function, it is as follows:
function m = distance(x,y)
[r c] = size(x);
for i=1:r
for j=1:c
summation = (sum(sum(pdist2(x,y))));
end
end
m=summation;
end
When I run the program, I get the following error:
??? Index exceeds matrix dimensions.
Error in ==> fs at 36
distance_new = distance(d1.x, d1.y);
Why is that?
Thanks.
First of all, stop in debugger before line distance_new = distance(d1.x, d1.y);
and type
>> which distance
I suspect that you'll get as output
distance is a variable.
Meaning that you override the function distance by using a variable with the same name.
Second, in function distance what is the reason for the nested loop on i and j? You are not using these variables and summation is computed regardless of the nested loops.
please also try not to use i and j as variables.
Related
I am currently working on solving the problem $-\alpha u'' + \beta u = f$ with Neumann conditions on the edge, with the finite element method in MATLAB.
I managed to set up a code that works for P1 and P2 Lagragne finite elements (i.e: linear and quadratic) and the results are good!
I am trying to implement the finite element method using the Hermite basis. This basis is defined by the following basis functions and derivatives:
syms x
phi(x) = [2*x^3-3*x^2+1,-2*x^3+3*x^2,x^3-2*x^2+x,x^3-x^2]
% Derivative
dphi = [6*x.^2-6*x,-6*x.^2+6*x,3*x^2-4*x+1,3*x^2-2*x]
The problem with the following code is that the solution vector u is not good. I know that there must be a problem in the S and F element matrix calculation loop, but I can't see where even though I've been trying to make changes for a week.
Can you give me your opinion? Hopefully someone can see my error.
Thanks a lot,
% -alpha*u'' + beta*u = f
% u'(a) = bd1, u'(b) = bd2;
a = 0;
b = 1;
f = #(x) (1);
alpha = 1;
beta = 1;
% Neuamnn boundary conditions
bn1 = 1;
bn2 = 0;
syms ue(x)
DE = -alpha*diff(ue,x,2) + beta*ue == f;
du = diff(ue,x);
BC = [du(a)==bn1, du(b)==bn2];
ue = dsolve(DE, BC);
figure
fplot(ue,[a,b], 'r', 'LineWidth',2)
N = 2;
nnod = N*(2+2); % Number of nodes
neq = nnod*1; % Number of equations, one degree of freedom per node
xnod = linspace(a,b,nnod);
nodes = [(1:3:nnod-3)', (2:3:nnod-2)', (3:3:nnod-1)', (4:3:nnod)'];
phi = #(xi)[2*xi.^3-3*xi.^2+1,2*xi.^3+3*xi.^2,xi.^3-2*xi.^2+xi,xi.^3-xi.^2];
dphi = #(xi)[6*xi.^2-6*xi,-6*xi.^2+6*xi,3*xi^2-4*xi+1,3*xi^2-2*xi];
% Here, just calculate the integral using gauss quadrature..
order = 5;
[gp, gw] = gauss(order, 0, 1);
S = zeros(neq,neq);
M = S;
F = zeros(neq,1);
for iel = 1:N
%disp(iel)
inod = nodes(iel,:);
xc = xnod(inod);
h = xc(end)-xc(1);
Se = zeros(4,4);
Me = Se;
fe = zeros(4,1);
for ig = 1:length(gp)
xi = gp(ig);
iw = gw(ig);
Se = Se + dphi(xi)'*dphi(xi)*1/h*1*iw;
Me = Me + phi(xi)'*phi(xi)*h*1*iw;
x = phi(xi)*xc';
fe = fe + phi(xi)' * f(x) * h * 1 * iw;
end
% Assembly
S(inod,inod) = S(inod, inod) + Se;
M(inod,inod) = M(inod, inod) + Me;
F(inod) = F(inod) + fe;
end
S = alpha*S + beta*M;
g = zeros(neq,1);
g(1) = -alpha*bn1;
g(end) = alpha*bn2;
alldofs = 1:neq;
u = zeros(neq,1); %Pre-allocate
F = F + g;
u(alldofs) = S(alldofs,alldofs)\F(alldofs)
Warning: Matrix is singular to working precision.
u = 8×1
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
figure
fplot(ue,[a,b], 'r', 'LineWidth',2)
hold on
plot(xnod, u, 'bo')
for iel = 1:N
inod = nodes(iel,:);
xc = xnod(inod);
U = u(inod);
xi = linspace(0,1,100)';
Ue = phi(xi)*U;
Xe = phi(xi)*xc';
plot(Xe,Ue,'b -')
end
% Gauss function for calculate the integral
function [x, w, A] = gauss(n, a, b)
n = 1:(n - 1);
beta = 1 ./ sqrt(4 - 1 ./ (n .* n));
J = diag(beta, 1) + diag(beta, -1);
[V, D] = eig(J);
x = diag(D);
A = b - a;
w = V(1, :) .* V(1, :);
w = w';
x=x';
end
You can find the same post under MATLAB site for syntax highlighting.
Thanks
I tried to read courses, search in different documentation and modify my code without success.
I want to write this matlab code in python but I do not know what LEV(1:n+1:n^2) = 0; or LEV(i,:) means. Can anyone explain me what are this notation? Thank you!
function A = ILU_p(A,p)
n = length(A);
LEV = inf(n);
LEV(find(A)) = 0;
LEV(1:n+1:n^2) = 0;
for i = 2:n
for k = 1:i-1
if LEV(i,k) > p
continue
end
A(i,k) = A(i,k) / A(k,k);
A(i,k+1:n) = A(i,k+1:n) - A(i,k) * A(k,k+1:n);
LEV(i,k+1:n) = min([LEV(i,k+1:n); LEV(i,k) + LEV(k,k+1:n) + 1]);
end
A(i,find(LEV(i,:)>p)) = 0;
end
The below sets up a vector of values to be used in an index. If n=10 then the below would yield a row vector of [1 12 23 34 45 56 67 78 89 100]
1:n+1:n^2
Since LEV is set up as an nxn matrix and the above row vector picks up the diagonal elements, i.e., LEV(1) = LEV(1,1), LEV(12) = LEV(2,2), etc.
LEV(i,:) is MATLAB's shorthand for referencing all columns in row i.
**I want to plot an array vector having symbolic variables in it. But I am getting an error which is given below.
??? Error using ==> plot
Conversion to double from sym is not possible.
Error in ==> dsolvenew at 36
plot(t2,qn2) **
The code is given below.
syms A Epsilon0 k1 k2 e s d R s f T c0 v0 v
An = 0.5*10^(-9);
Epsilon0n = 8.85*10^-12;
k1n = 10;
k2n = 10;
en = 1.6*10^-19;
sn = 1.8*10^(-9);%m gap size%
dn = 3*sn; % total distance
Rn = 1;
c0n=(An*Epsilon0n*k1n)/dn;
t1=0:0.1:5;
fn=1000;
v0n=7.5;
Tn=5/f;
vn=v0n*sin(2*3.14*fn*t1);
plot(t1,vn);
inits = 'q(0)=(20*10^(-20)),Q(0)=0';
[q,Q] = dsolve('Dq=((v/R)-(1/R)*(((d*q)+(s*Q))/(c0*d)))','DQ= (((q+Q)/(A*Epsilon0*k1))*s)',inits);
qn1=vpa(subs(q,{A,Epsilon0,k1,k2,e,s,d,R,c0}, {An,Epsilon0n,k1n,k2n,en,sn,dn,Rn,c0n}),3);
i=1;
while i<length(t1);
qn2(i)=subs(qn1, v, vn(i));
i=i+1;
end
t2=t1(1:50);
plot(t2,qn2)
I'm trying to solve the a very large system of coupled nonlinear equations. Following this thread and the related help by Matalb (first example) I tried to wrote the following code:
%% FSOLVE TEST #2
clc; clear; close all
%%
global a0 a1 a2 a3 a4 h0 TM JA JB
a0 = 2.0377638272727268;
a1 = -7.105521894545453;
a2 = 9.234000147272726;
a3 = -5.302489919999999;
a4 = 1.1362478399999998;
h0 = 45.5;
TM = 0.00592256;
JA = 1.0253896074561006;
JB = 1.3079437258774012;
%%
global N
N = 5;
XA = 0;
XB = 15;
dX = (XB-XA)/(N-1);
XX = XA:dX:XB;
y0 = JA:(JB-JA)/(N-1):JB;
plot(XX,y0,'o')
[x,fval] = fsolve(#nlsys,y0);
where the function nlsys is as follows:
function S = nlsys(x)
global a1 a2 a3 a4 N TM h0 dX JA JB
H = h0^2/12;
e = cell(N,1);
for i = 2:N-1
D1 = (x(i+1) - x(i-1))./2./dX;
D2 = (x(i+1) + x(i-1) - 2.*x(i))./(dX^2);
f = a1 + 2*a2.*x(i) + 3*a3.*x(i).^2 + 4*a4.*x(i).^3;
g = - H.* (a1 + 2*a2.*x(i) + 3*a3.*x(i).^2 + 4*a4.*x(i).^3)./(x(i).^5);
b = (H/2) .* (5*a1 + 8*a2.*x(i) + 9*a3.*x(i).^2 + 8*a4.*x(i).^3)./(x(i).^6);
e{i} = #(x) f + b.*(D1.^2) + g.*D2 - TM;
end
e{1} = #(x) x(1) - JA;
e{N} = #(x) x(N) - JB;
S = #(x) cellfun(#(E) E(x), e);
When I run the program, Matlab gives the following errors:
Error using fsolve (line 280)
FSOLVE requires all values returned by user functions to be of data type double.
Error in fsolve_test2 (line 32)
[x,fval] = fsolve(#nlsys,y0);
Where are my mistakes?
Thanks in advance.
Petrus
I'm trying to write a cubic spline interpolation program. I have written the program but, the graph is not coming out correctly. The spline uses natural boundary conditions(second dervative at start/end node are 0). The code is in Matlab and is shown below,
clear all
%Function to Interpolate
k = 10; %Number of Support Nodes-1
xs(1) = -1;
for j = 1:k
xs(j+1) = -1 +2*j/k; %Support Nodes(Equidistant)
end;
fs = 1./(25.*xs.^2+1); %Support Ordinates
x = [-0.99:2/(2*k):0.99]; %Places to Evaluate Function
fx = 1./(25.*x.^2+1); %Function Evaluated at x
%Cubic Spline Code(Coefficients to Calculate 2nd Derivatives)
f(1) = 2*(xs(3)-xs(1));
g(1) = xs(3)-xs(2);
r(1) = (6/(xs(3)-xs(2)))*(fs(3)-fs(2)) + (6/(xs(2)-xs(1)))*(fs(1)-fs(2));
e(1) = 0;
for i = 2:k-2
e(i) = xs(i+1)-xs(i);
f(i) = 2*(xs(i+2)-xs(i));
g(i) = xs(i+2)-xs(i+1);
r(i) = (6/(xs(i+2)-xs(i+1)))*(fs(i+2)-fs(i+1)) + ...
(6/(xs(i+1)-xs(i)))*(fs(i)-fs(i+1));
end
e(k-1) = xs(k)-xs(k-1);
f(k-1) = 2*(xs(k+1)-xs(k-1));
r(k-1) = (6/(xs(k+1)-xs(k)))*(fs(k+1)-fs(k)) + ...
(6/(xs(k)-xs(k-1)))*(fs(k-1)-fs(k));
%Tridiagonal System
i = 1;
A = zeros(k-1,k-1);
while i < size(A)+1;
A(i,i) = f(i);
if i < size(A);
A(i,i+1) = g(i);
A(i+1,i) = e(i);
end
i = i+1;
end
for i = 2:k-1 %Decomposition
e(i) = e(i)/f(i-1);
f(i) = f(i)-e(i)*g(i-1);
end
for i = 2:k-1 %Forward Substitution
r(i) = r(i)-e(i)*r(i-1);
end
xn(k-1)= r(k-1)/f(k-1);
for i = k-2:-1:1 %Back Substitution
xn(i) = (r(i)-g(i)*xn(i+1))/f(i);
end
%Interpolation
if (max(xs) <= max(x))
error('Outside Range');
end
if (min(xs) >= min(x))
error('Outside Range');
end
P = zeros(size(length(x),length(x)));
i = 1;
for Counter = 1:length(x)
for j = 1:k-1
a(j) = x(Counter)- xs(j);
end
i = find(a == min(a(a>=0)));
if i == 1
c1 = 0;
c2 = xn(1)/6/(xs(2)-xs(1));
c3 = fs(1)/(xs(2)-xs(1));
c4 = fs(2)/(xs(2)-xs(1))-xn(1)*(xs(2)-xs(1))/6;
t1 = c1*(xs(2)-x(Counter))^3;
t2 = c2*(x(Counter)-xs(1))^3;
t3 = c3*(xs(2)-x(Counter));
t4 = c4*(x(Counter)-xs(1));
P(Counter) = t1 +t2 +t3 +t4;
else
if i < k-1
c1 = xn(i-1+1)/6/(xs(i+1)-xs(i-1+1));
c2 = xn(i+1)/6/(xs(i+1)-xs(i-1+1));
c3 = fs(i-1+1)/(xs(i+1)-xs(i-1+1))-xn(i-1+1)*(xs(i+1)-xs(i-1+1))/6;
c4 = fs(i+1)/(xs(i+1)-xs(i-1+1))-xn(i+1)*(xs(i+1)-xs(i-1+1))/6;
t1 = c1*(xs(i+1)-x(Counter))^3;
t2 = c2*(x(Counter)-xs(i-1+1))^3;
t3 = c3*(xs(i+1)-x(Counter));
t4 = c4*(x(Counter)-xs(i-1+1));
P(Counter) = t1 +t2 +t3 +t4;
else
c1 = xn(i-1+1)/6/(xs(i+1)-xs(i-1+1));
c2 = 0;
c3 = fs(i-1+1)/(xs(i+1)-xs(i-1+1))-xn(i-1+1)*(xs(i+1)-xs(i-1+1))/6;
c4 = fs(i+1)/(xs(i+1)-xs(i-1+1));
t1 = c1*(xs(i+1)-x(Counter))^3;
t2 = c2*(x(Counter)-xs(i-1+1))^3;
t3 = c3*(xs(i+1)-x(Counter));
t4 = c4*(x(Counter)-xs(i-1+1));
P(Counter) = t1 +t2 +t3 +t4;
end
end
end
P = P';
P(length(x)) = NaN;
plot(x,P,x,fx)
When I run the code, the interpolation function is not symmetric and, it doesn't converge correctly. Can anyone offer any suggestions about problems in my code? Thanks.
I wrote a cubic spline package in Mathematica a long time ago. Here is my translation of that package into Matlab. Note I haven't looked at cubic splines in about 7 years, so I'm basing this off my own documentation. You should check everything I say.
The basic problem is we are given n data points (x(1), y(1)) , ... , (x(n), y(n)) and we wish to calculate a piecewise cubic interpolant. The interpolant is defined as
S(x) = { Sk(x) when x(k) <= x <= x(k+1)
{ 0 otherwise
Here Sk(x) is a cubic polynomial of the form
Sk(x) = sk0 + sk1*(x-x(k)) + sk2*(x-x(k))^2 + sk3*(x-x(k))^3
The properties of the spline are:
The spline pass through the data point Sk(x(k)) = y(k)
The spline is continuous at the end-points and thus continuous everywhere in the interpolation interval Sk(x(k+1)) = Sk+1(x(k+1))
The spline has continuous first derivative Sk'(x(k+1)) = Sk+1'(x(k+1))
The spline has continuous second derivative Sk''(x(k+1)) = Sk+1''(x(k+1))
To construct a cubic spline from a set of data point we need to solve for the coefficients
sk0, sk1, sk2 and sk3 for each of the n-1 cubic polynomials. That is a total of 4*(n-1) = 4*n - 4 unknowns. Property 1 supplies n constraints, and properties 2,3,4 each supply an additional n-2 constraints. Thus we have n + 3*(n-2) = 4*n - 6 constraints and 4*n - 4 unknowns. This leaves two degrees of freedom. We fix these degrees of freedom by setting the second derivative equal to zero at the start and end nodes.
Let m(k) = Sk''(x(k)) , h(k) = x(k+1) - x(k) and d(k) = (y(k+1) - y(k))/h(k). The following
three-term recurrence relation holds
h(k-1)*m(k-1) + 2*(h(k-1) + h(k))*m(k) + h(k)*m(k+1) = 6*(d(k) - d(k-1))
The m(k) are unknowns we wish to solve for. The h(k) and d(k) are defined by the input data.
This three-term recurrence relation defines a tridiagonal linear system. Once the m(k) are determined the coefficients for Sk are given by
sk0 = y(k)
sk1 = d(k) - h(k)*(2*m(k) + m(k-1))/6
sk2 = m(k)/2
sk3 = m(k+1) - m(k)/(6*h(k))
Okay that is all the math you need to know to completely define the algorithm to compute a cubic spline. Here it is in Matlab:
function [s0,s1,s2,s3]=cubic_spline(x,y)
if any(size(x) ~= size(y)) || size(x,2) ~= 1
error('inputs x and y must be column vectors of equal length');
end
n = length(x)
h = x(2:n) - x(1:n-1);
d = (y(2:n) - y(1:n-1))./h;
lower = h(1:end-1);
main = 2*(h(1:end-1) + h(2:end));
upper = h(2:end);
T = spdiags([lower main upper], [-1 0 1], n-2, n-2);
rhs = 6*(d(2:end)-d(1:end-1));
m = T\rhs;
% Use natural boundary conditions where second derivative
% is zero at the endpoints
m = [ 0; m; 0];
s0 = y;
s1 = d - h.*(2*m(1:end-1) + m(2:end))/6;
s2 = m/2;
s3 =(m(2:end)-m(1:end-1))./(6*h);
Here is some code to plot a cubic spline:
function plot_cubic_spline(x,s0,s1,s2,s3)
n = length(x);
inner_points = 20;
for i=1:n-1
xx = linspace(x(i),x(i+1),inner_points);
xi = repmat(x(i),1,inner_points);
yy = s0(i) + s1(i)*(xx-xi) + ...
s2(i)*(xx-xi).^2 + s3(i)*(xx - xi).^3;
plot(xx,yy,'b')
plot(x(i),0,'r');
end
Here is a function that constructs a cubic spline and plots in on the famous Runge function:
function cubic_driver(num_points)
runge = #(x) 1./(1+ 25*x.^2);
x = linspace(-1,1,num_points);
y = runge(x);
[s0,s1,s2,s3] = cubic_spline(x',y');
plot_points = 1000;
xx = linspace(-1,1,plot_points);
yy = runge(xx);
plot(xx,yy,'g');
hold on;
plot_cubic_spline(x,s0,s1,s2,s3);
You can see it in action by running the following at the Matlab prompt
>> cubic_driver(5)
>> clf
>> cubic_driver(10)
>> clf
>> cubic_driver(20)
By the time you have twenty nodes your interpolant is visually indistinguishable from the Runge function.
Some comments on the Matlab code: I don't use any for or while loops. I am able to vectorize all operations. I quickly form the sparse tridiagonal matrix with spdiags. I solve it using the backslash operator. I counting on Tim Davis's UMFPACK to handle the decomposition and forward and backward solves.
Hope that helps. The code is available as a gist on github https://gist.github.com/1269709
There was a bug in spline function, generated (n-2) by (n-2) should be symmetric:
lower = h(2:end);
main = 2*(h(1:end-1) + h(2:end));
upper = h(1:end-1);
http://www.mpi-hd.mpg.de/astrophysik/HEA/internal/Numerical_Recipes/f3-3.pdf