Possible workaround for non-integer indices

29 visualizzazioni (ultimi 30 giorni)
Tom Oud
Tom Oud il 11 Giu 2019
Risposto: James Browne il 12 Giu 2019
For an assignment for uni, I have to create a RK4 population simulation. This I what I have so far:
close all
clear
alpha = 10^-3;
gamma = 6e-3;
c = 3;
a = 2;
Dt = 0.5;
lambda = sqrt(-6);
y1(1) = 600;
y2(1) = 1000;
t = 1:Dt:6;
k11 = zeros(1,11);
k12 = zeros(1,11);
k21 = zeros(1,11);
k22 = zeros(1,11);
k31 = zeros(1,11);
k32 = zeros(1,11);
k41 = zeros(1,11);
k42 = zeros(1,11);
for i = 1:10
k11(i) = Dt*dy1(i,y1,y2);
k12(i) = Dt*dy2(i,y1,y2);
k21(i) = Dt*(dy1(i,y1 + 0.5*k11(i),y2 + 0.5*k12(i)) + 0.5*k11(i));
k22(i) = Dt*(dy2(i,y1 + 0.5*k11(i),y2 + 0.5*k12(i)) + 0.5*k12(i));
k31(i) = Dt*(dy1(i,y1 + 0.5*k21(i),y2 + 0.5*k22(i)) + 0.5*k21(i));
k32(i) = Dt*(dy2(i,y1 + 0.5*k21(i),y2 + 0.5*k22(i)) + 0.5*k22(i));
k41(i) = Dt*(dy1(i,y1 + k31(i),y2 + k32(i)) + k31(i));
k42(i) = Dt*(dy2(i,y1 + k31(i),y2 + k32(i)) + k32(i));
y1(i+1) = y1(i) + (1/6)*(k11(i) + 2*k21(i) + 2*k31(i) + k41(i));
y2(i+1) = y2(i) + (1/6)*(k12(i) + 2*k22(i) + 2*k32(i) + k42(i));
end
dy1, dy2, and W are seperate functions.
The only thing that needs to be changed is the input in the dy1 and dy2.
Ideally, I would just fill in i + 0.5*i, which would give the right answer, howerver matlab doesn't allow this. Is there an easy way to achieve the same effect without changing the entire code?
  5 Commenti
Pieter-Bas Draijer
Pieter-Bas Draijer il 11 Giu 2019
Modificato: Pieter-Bas Draijer il 11 Giu 2019
Hi Bob,
I'm working together with Tom. The W and dy2 are also depended on i (see downbelow). But this doesn't cause the problem. The problem appears when we want to try to use a non real positive integers or logicals in i such as 1.5 and 1.75 instead of 1, 2, 3 etc. Is there a way in which we can work with this kind of numbers in our code above?
w:
function f = W(t)
f = [];
if 0 <= t && t < (3/12)
f = 0;
end
if (3/12) <= t && t <= (8/12)
f = 1;
end
if (8/12) < t && t < 1
f = 0;
end
if 1 <= t && t < 1+(3/12)
f = 0;
end
if 1+(3/12) <= t && t <= 1+(8/12)
f = 1;
end
if 1+(8/12) < t && t < 2
f = 0;
end
if 2 <= t && t < 2+(3/12)
f = 0;
end
if 2+(3/12) <= t && t <= 2+(8/12)
f = 1;
end
if 2+(8/12) < t && t < 3
f = 0;
end
if 3 <= t && t < 3+(3/12)
f = 0;
end
if 3+(3/12) <= t && t <= 3+(8/12)
f = 1;
end
if 3+(8/12) < t && t < 4
f = 0;
end
if 4 <= t && t < 4+(3/12)
f = 0;
end
if 4+(3/12) <= t && t <= 4+(8/12)
f = 1;
end
if 4+(8/12) < t && t < 5
f = 0;
end
if 5 <= t && t < 5+(3/12)
f = 0;
end
if 5+(3/12) <= t && t <= 5+(8/12)
f = 1;
end
if 5+(8/12) < t && t < 6
f = 0;
end
if 6 <= t && t < 6+(3/12)
f = 0;
end
if 6+(3/12) <= t && t <= 6+(8/12)
f = 1;
end
if 6+(8/12) < t && t < 7
f = 0;
end
if 7 <= t && t < 7+(3/12)
f = 0;
end
if 7+(3/12) <= t && t <= 7+(8/12)
f = 1;
end
if 7+(8/12) < t && t < 8
f = 0;
end
if 8 <= t && t < 8+(3/12)
f = 0;
end
if 8+(3/12) <= t && t <= 8+(8/12)
f = 1;
end
if 8+(8/12) < t && t < 9
f = 0;
end
if 9 <= t && t < 9+(3/12)
f = 0;
end
if 9+(3/12) <= t && t <= 9+(8/12)
f = 1;
end
if 9+(8/12) < t && t < 10
f = 0;
end
if 10 <= t && t < 10+(3/12)
f = 0;
end
if 10+(3/12) <= t && t <= 10+(8/12)
f = 1;
end
if 10+(8/12) < t && t < 11
f = 0;
end
if 11 <= t && t < 11+(3/12)
f = 0;
end
if 11+(3/12) <= t && t <= 11+(8/12)
f = 1;
end
if 11+(8/12) < t && t < 12
f = 0;
end
if 12 <= t && t < 12+(3/12)
f = 0;
end
if 12+(3/12) <= t && t <= 12+(8/12)
f = 1;
end
if 12+(8/12) < t && t < 13
f = 0;
end
end
dy2
function h = dy2(i,y1,y2)
alpha = 10^-3;
gamma = 6e-3;
c = 3;
a = 2;
%y2 = a/alpha;
%y1 = c/gamma;
Dt = 0.5;
lambda = sqrt(-6);
y1(1) = 600;
y2(1) = 1000;
h = (-c + gamma.*y1(i)).*y2(i);
end
Rik
Rik il 11 Giu 2019
You are calling y1 (and y2) not as a function, but as an array. You need to make sure they are functions. The frequent use of the letter d makes me think you want to treat them as differential equations. Can you explain your reasoning of what you're trying to achieve?
I would also suggest rewriting your w function. I would suggest making an nx3 array with the upper bounds, lower bounds and value for f. That way it is harder to make a typo, easier to edit, easier to understand, and likely easier to speed up.

Accedi per commentare.

Risposte (1)

James Browne
James Browne il 12 Giu 2019
Greetings,
I thik, at least your problem with using the iterator variable to generate a complex number is that you are using "i" as the iterator and also trying to use "i" in the complex number as the imaginary component.
There are two solutions to this specific problem:
1) Use a different iterator variable such as k and then generate your complex number(s) with something like:
n = k + 0.5*i;
2) You can also use "j" to define the imaginary component of a complex number, so if you have defined "i" as an iterater variable already, you can create a complex number with something like:
n = i + 0.5*j
One last note too, I often write scripts where the iterator variable ("i", in your case) cannot be used directly in part of an equation. Using the iterator to determine a logical value or take on a non-integer number from a sequence are examples of this issue.
The solution is to generate an object in which the desired values are stored and then use the iterator to access them. This opens up the possabilities of using the iterator beyond modifying a number in an equation. The following are some examples of the concept that I am referring to.
animals = {'Cats','Dogs','Hampsters'};
isCool = {true,false,false};
reasons = {'They just are','They smell bad and bark all the time','They smell bad'};
n = length(animals);
for i = 1:n
if(isCool{i})
message = strcat(animals{i},' are cool because',reasons{i},'\n');
fprintf(message)
end
if(~isCool{i})
message = strcat(animals{i},' are not cool because',reasons{i},'\n');
fprintf(message)
end
end
The example above shows how you can use the iterator variable to invoke strings and logical values inside of a loop, which you would not otherwise be able to do by using the iterator value directly.
nWaves = 3;
omegas = zeros(1,nWaves);
for i = 1:nWaves
omegas(i) = i +1.75*i;
end
n = length(omegas);
duration = 4;
dt = 0.01;
t = 0:dt:duration;
for i = 1:n
y = sin(omegas(i)*t);
plot(t,y)
hold on
end
hold off
xlabel('Time (seconds)')
ylabel('Amplitude')
title('A Really Messy Figure')
In the above example, you can see that the iterator is used to invoke non-integer values for angular velocities in the second for loop. Additionally, in the first for loop, you can see that the equation for omegas(i) looks like it should generate a complex number but it does not because the variable "i" was defined in the previous line as a vector containing integer values so it will no longer generate a complex number when used in an equation.
Hope this helps~

Categorie

Scopri di più su Data Type Identification in Help Center e File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by