Double-Checked Sizes but Still Get 'Index Exceeds Matrix Dimensions' Error

Hello,
I had a post yesterday talking about the error I keep getting, and thought I understood the issue enough to fix it.
However, I keep getting the same error, mainly in line 71 (denoted below).
A, B, and C are all the same size (1x4). I know BB is larger, but that is my text issue to tackle.
For now, I'm struggling to figure this one out. I attached my code below:
%Given Parameters
a = 10;
b = 1E-4;
d = 400000;
e = 2E-3;
TH = 2000;
TC = 400;
hH = 900;
hL = 1100;
L = .10;
IL = 5;
DX = L/(IL-1);
T(1)=200;
T(2) = (b*T(1)^2+(hH*DX+a)*T(1)-hH*DX*TH)/(a+b*T(1));
T(IL)=50;
T(IL-1)=(b*T(IL)^2+(hL*DX+a)*T(IL)-hL*DX*TC)/(a+b*T(IL));
%Define For-Loop to determine all temperatures based off of initial guesses
for i=3:(IL-2)
T(i)= ((e-(2*a)/(DX^2))*T(i-1)-((2*b)/(DX^2))*T(i-1)^2+...
(1/DX^2-b/(2*DX))*T(i-2)+(b/DX^2)*T(i-1)*T(i-1)+d)/...
(1/DX^2+b/(2*DX)+(b/DX^2)*T(i-1));
end
%Define First and Last Row of Matrix for the BC
% at i=1:
dFi_dTi(1) = (-2*b*T(1))/(DX)-a/DX-hH+(b*T(2))/DX;
dFi_dTip1(1) = (b*T(1))/(DX)+a/DX;
% at i = IL
dFi_dTim1(IL) = (-b*T(IL))/(DX)-a/DX;
dFi_dTi(IL) = (2*b*T(IL))/(DX)+a/DX+hL+(b*T(IL-1))/DX;
for i=2:(IL-1)
dFi_dTim1(i) = a/DX^2-b/(2*DX)+(b*T(i))/(DX^2);
dFi_dTi(i) = e-(2*a)/(DX^2)+(b*T(i+1))/...
(DX^2)+(b*T(i-1))/(DX^2)-(4*b*T(i))/(DX^2);
dFi_dTip1(i) = a/DX^2+b/(2*DX)+(b*T(i))/(DX^2);
end
%Matrix Stuff for Thomas Algorithm
%Matrix Parameters
A(i) = dFi_dTi(i);
B(i) = dFi_dTip1(i);
C(i) = dFi_dTim1(i);
BB = 1:DX:IL;
B(1)=B(1)/A(1);
for i=2:IL
A(i)=A(i)-C(i)*B(i-1); %***LINE 71****
B(i)=B(i)/A(i);
end
BB(1)=BB(1)/A(1);
for i=2:IL
BB(i)=(BB(i)-C(i)*BB(i-1))/A(i);
end
NMI=IL-1;
for i=1:NMI
ii=IL-1;
BB(ii)=BB(ii)-B(ii)*BB(ii+1);
end
I believe all function/variables that rely on i all run from 1 to IL, so I'm not sure how the sizes are mismatched, specifically in line 71, where I keep getting the error.
Any help is appreciated, thank you. If there's more detail or information I can give please ask.

 Accepted Answer

for i=2:(IL-1)
dFi_dTim1(i) = a/DX^2-b/(2*DX)+(b*T(i))/(DX^2);
C has not been defined up to that point, and that particular for loop does not define it. However, that particular for loop defines i, and is going to leave i set to the last value assigned to it, so after that loop i = IL-1
A(i) = dFi_dTi(i);
B(i) = dFi_dTip1(i);
C(i) = dFi_dTim1(i);
Those statements all use whatever value happens to be in i, so as indicated above, the value i = IL-1 . Before those statements, A, B, C do not exist; after those statements, A, B, C will be length IL-1 with positions 1:IL-2 being 0.
B(1)=B(1)/A(1);
0 divided by 0 since A and B are initialized to 0 except for position IL-1
for i=2:IL
A(i)=A(i)-C(i)*B(i-1); %***LINE 71****
B(i)=B(i)/A(i);
end
Eventually you get to i = IL. But you only created A and C up to IL-1 so A(i) and C(i) will be out of range when i becomes IL.

6 Comments

Thank you for your response. I do have a question though. I understand what you are saying, about how the 'for loop' is defining i, and since it ends at i=IL-1, then that is the value that i goes to now.
But what about when I define T such that T(IL)=50?
Is it because since the 'for loop' comes after that definition, it overwrites it?
Sorry if that's a dumb question, but I'm not understanding what happenss to T(IL) then, or by the same token, any variable defined at IL.
No, that is fine, but you do not do the same for A, B, or C.
I think I see, thank you.
I guess to me it makes sense that if everything calls back on something else, as long as the first thing runs from 1 to IL, then everything that follows will also have the same range.
But what you're saying is that each terms itself must be defined at the desired range, similar to what T has.
"Here's four pieces of paper. I want you to take five pieces of paper and add one to the number written on each, writing in the new number."
What happens when you try to do page five, when you were only given four pages?
P = zeros(1,4);
for K = 1 : 5; P(K) = P(K) + 1; end %but P(5) does not exist
"Here's five pieces of paper. I want you to take five pieces of paper and add one to the number written on each, writing in the new number."
What happens when you find out that one of the five has not already had a number written to it, so there is nothing there to read?
P = cell(1,5); P(1:4) = {7};
for K = 1 : 5; P{K} = P{K} + 1; end %but P{5} is empty
"Here's five pieces of paper. I wrote zero to each of the five, and then I wrote 7 to the fourth of them. I want you to take five pieces of paper and divide 14 by the number on the paper and write the result to the paper."
What happens when you try to take 14 divided by the 0's that appear on all except the 4th page?
P = zeros(1,5); P(4) = 7;
for K = 1 : 5; P(K) = 14/P(K); end %division by zero
When you are working on a vector, you have a few possibilities:
  • You can initialize all of it at the beginning to a constant such as nan or inf (or perhaps 0) Then you can loop and be careful to never read from a location before you write a new value at the location. For example, when you are at location K, reading P(K), then you write to P(K+1) before you read from that location (next loop iteration)
  • You can initialize all of it at the beginning to a relevant constant such as 0. Then you can loop and be careful in your calculations that if you read from a location before you write a new value at the location, that it is meaningful to do so (e.g., checking to see if it was written to yet), or that your choose your constant to not affect the calculation. For example sum(P(K:end)) is fine if the spaces not written to yet are all 0.
  • You can grow the vector, being careful not to read from a location before it exists. For example, when you are at location K, reading P(K), then you write to P(K+1) before you read from that location (next loop iteration). The difference compared to the first option is that it is more expensive to keep growing the vector step by step, and sometimes the code needs to know what the final size will be before it can do the calculations correctly
Your code was initializing T to a proper length, but was constructing A, B, and C by writing to somewhere near the end of the final size without writing to the elements at the beginning of the vector. You then had problems because you were counting on the elements at the beginning of the vector to have a meaningful value when they were just the 0 you get from writing past the end of an array; and you had the problem that you did not write A, or C long enough to be able to read the last element. You should probably not have been reading the last element before you wrote something specific to it.
For example, perhaps your code should be along the lines of
for i=1:IL-1
A(i+1)=A(i)-C(i)*B(i); %***LINE 71****
B(i+1)=B(i)/A(i+1);
end
Thank you for the analogy, likening it to the paper examples helped with the explanation in my opinion.
I'll be sure to utilize this for my script as well as for future programs I write.
I appreciate your help.

Sign in to comment.

More Answers (0)

Categories

Products

Release

R2017a

Community Treasure Hunt

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

Start Hunting!