Five dimensional matrix manipulation - matlab

I have made the following changes to the code but still get the "Index exceeds matrix dimensions" error on the line where the "if statement" is called and I am for looping the "h" starting from 2:25. I still have net figured out how I can use an element from the previous dimension in the current dimension equation expression
number_of_days = 3;
number_of_hours = 24*number_of_days;
number_panels = 1:5;
for idx_number_panels = 1:length(number_panels) % range of PV panel units examined
for number_turbines = 0:1 % range of wind turbine units examined
for number_batteries = 1:2 % range of battery units examined
for h=2:25 %# hours
battery_capacity(:,:,:,1,1) = max_battery_capacity*number_batteries;
for d = 1:number_of_days %# which day
n = h + 24*(d-1);
if (max_battery_capacity*number_batteries) - (battery_capacity(idx_number_panels, number_turbines+1 ,number_batteries, h-1,d)*number_batteries) >0
storage_availability(idx_number_panels, number_turbines+1 ,number_batteries, h,d) = (max_battery_capacity*number_batteries) - (battery_capacity(idx_number_panels, number_turbines+1 ,number_batteries, h-1,d)) ;
else
storage_availability(idx_number_panels, number_turbines+1 ,number_batteries, h,d) = 0;
end

Let's look at this just by hours.
for h = 1:24
battery_capacity(1) = initial_battery_capacity*number_batteries
if hourly_total_RES(h) > hourly_annual_demand(n), % battery charging
battery_capacity(h) = battery_capacity(h-1);
else
battery_capacity(h) = battery_capacity(h-1);
end
end
First off, the both sides of the if statement are the same as written. I assume that your actual code does some sort of work with the previous data. If not, that's a problem.
It also might make the code a little easier to think about if you switch the order of the day and hour loops. To me, looking through all the hours of one day at a time makes better sense than looking at the first hour of each day, then the second hour of each day...
As for the indexing, one definite error is that you index battery_capacity(h-1) on the first iteration of the loop. That is, when h is 1, you define battery_capacity(1) and then try to look at battery_capacity(0), which is probably what's throwing the error.
To fix this, you could check to see if h == 1, but I think a more elegant way would be to loop through h = 2:24 and set battery_capacity(1) before entering that loop. See if this code works:
for d = 1:number_of_days
battery_capacity(1) = initial_battery_capacity*number_batteries
for h = 2:24
if hourly_total_RES(h) > hourly_annual_demand(n), % battery charging
battery_capacity(h) = battery_capacity(h-1);
else
battery_capacity(h) = battery_capacity(h-1);
end
end
end

From what I understand, the last two dimensions store the hour and day respectively. So to set the value for first day at hour=1 (I assume this means midnight start of day):
battery_capacity(:,:,:,1,1) = 2; %# 2kWh
This will set the value 2 for all "panels" and all "turbines" and all "batteries".
I assume you have the matrix already pre-allocated somewhere in your code.
For what its worth, I think you have a typo where you first mention battery_capacity in the code (there is a missing h parameter)

Related

How to break loop if number repeats -Matlab

I recognized this is a quite hard problem for me. I asked this problem on official Matlab side but no-one could help me either so maybe someone of you can come up with an outstanding approach.
In detail my Problem consist of:
N = 100 %some number
G = 21 %random guess < N
for x = 1:N;
a = mod(G^x,N);
end
Now I want the calculation of a to stop, if a number repeats.
For example: a = 1, 2, 3, 1 -break
Seems simple but I just can't handle it right after many tries.
For instance I've put:
for x = 1:N
a = mod(G^x,N);
b = unique(a);
if a ~= b
break
end
end
but doesn't seem to work bc. it's not element wise I guess.
This approach keeps a running log of the past Results and uses the ismember() function to check if the current value of a has been previously seen.
clc;
N = 100; %some number
G = 21; %random guess < N
Results = NaN(1,N);
for x = 1:N
a = mod(G^x,N);
disp(a);
if ismember(a,Results)
disp("-break");
break
end
Results(x) = a;
end
Ran using MATLAB R2019b

How to increase time by 1s and replace old DT_i with the new one

I'm trying to calculate the DT value from a model I set up on Sim4Life. Firstly, i'd like to say that I am a complete beginner and I am trying to understand how programming works in general.
Now, I have a function with some constants and two variables, the one being time Dt (starting from 1 sec to 900 secs) and the other being the initial DT_i value. I want to calculate the increase of temperature for every second and create a loop that replaces the DT_i value with the DT_1_i value and also calculates the increased temperature DT_i_1. The function looks like this: DT_1_i=DT_i+Dt.
I know it is a very simple problem but I couldn't work my way through other similar questions. Any help would be appreciated.
Temperature variation:
You need initial temperature variation , I used 0
T(i+1) stands for Next temperature variation
T(i) stands for present temperature variation
i stands for time step, dt
Read through comment in my code
Time
Use for loop to set the time for i = 1 : 900 %Temperature increase end
i =1:900 just means
first run use time = 1s,
second run time = 1+1 = 2
so on till 900
The code is as follow
% Initial Temperature variation is set to zero, unless you have some data
d = 1.3;
c = 3.7;
S_i = 3*10^3;
t_reg = 900;
%Time
t = 1:900;
% Length oftime to help me know the size of the variable needed to
% initialize
l = length(t);
% Initialize variable that used to store DT it helps speed up
% comutation
% Initial Temperature variation is set to zero, unless you have some data
DT = zeros(1, l);
for i = 1:900
% the value of i represent dt, first run i = 1, dt = 1, second run
% i = 2 and dt = 2 so on
if i == 900
%do nothing already reached the last index 900, i+1 = 901 will be
%out of range
else
DT(i+1) = DT(i) + (i./t_reg).*(d.*sqrt(c*S_i)-DT(i+1));
end
end

How to setup equation that involves a sum from x=1 to infinity and loops?

I am getting confused on how to properly set up this equation. To find a value of V(i,j). The end result would be plotting V over time. I understand that there needs to be loops to allow this equation to work, however I am lost when it comes to setting it up. Basically I am trying to take the sum from n=1 to infinity of (1-(-1)^n)/(n^4 *pi^4)*sin((n*pi*c*j)/L)*sin((n*pi*i)/L)
I originally thought that I should make it a while loop to increment n by 1 until I reach say 10 or so just to get an idea of what the output would look like. All of the variables were unknown and values were added again to see what the plot would look like.
I have down another code where the equation is just dependent on i and j. However with this n term, I am thrown off. Any advice would be great as to setting up the equation. Thank you.
L=10;
x=linspace(0,L,30);
t1= 50;
X=30;
p=1
c=t1/1000;
V=zeros(X,t1);
V(1,:)=0;
V(30,:)=0;
R=((4*p*L^3)/c);
n=1;
t=1:50;
while n < 10
for i=1:31
for j=1:50
V(i,j)=R*sum((1-(-1)^n)/(n^4 *pi^4)*sin((n*pi*c*j)/L)*sin((n*pi*i)/L));
end
end
n=n+1;
end
figure(1)
plot(V(i,j),t)
Various ways of doing so:
1) Computing the sum up to one Nmax in one shot:
Nmax = 30;
Vijn = #(i,j,n) R*((1-(-1)^n)/(n^4 *pi^4)*sin((n*pi*c*j)/L)*sin((n*pi*i)/L));
i = 1:31;
j = 1:50;
n = 1:Nmax;
[I,J,N] = ndgrid(i,j,n);
V = arrayfun(Vijn,I,J,N);
Vc = cumsum(V,3);
% now Vc(:,:,k) is sum_n=1^{k+1} V(i,j,n)
figure(1);clf;imagesc(Vc(:,:,end));
2) Looping indefinitely
n = 1;
V = 0;
i = 1:31;
j = 1:50;
[I,J] = meshgrid(i,j);
while true
V = V + R*((1-(-1)^n)/(n^4 *pi^4)*sin((n*pi*c*J)/L).*sin((n*pi*I)/L));
n = n + 1;
figure(1);clf;
imagesc(V);
title(sprintf('N = %d',n))
drawnow;
pause(0.25);
end
Note that in your example you won't need many terms, since:
Every second term is zero (for even n, the term 1-(-1)^n is zero).
The terms decay with 1/n^4. In norms: n=1 contributes ~2e4, n=3 contributes ~4e2, n=5 contributes 5e1, n=7 contributes ~14, etc. Visually, there is a small difference between n=1 and n=1+n=3 but barely a noticeable one for n=1+n=3+n=5.
Given that so few terms are needed, the first approach is probably the better one. Also, skip the even indices, as you don't need them.

How can I rearrange a list of numbers so that every N numbers is nonrepeating?

So I have a list of 190 numbers ranging from 1:19 (each number is repeated 10 times) that I need to sample 10 at a time. Within each sample of 10, I don't want the numbers to repeat, I tried incorporating a while loop, but computation time was way too long. So far I'm at the point where I can generate the numbers and see if there are repetitions within each subset. Any ideas?
N=[];
for i=1:10
N=[N randperm(19)];
end
B=[];
for j=1:10
if length(unique(N(j*10-9:j*10)))<10
B=[B 1];
end
end
sum(B)
Below is an updated version of the code. this might be a little more clear in showing what I want. (19 targets taken 10 at a time without repetition until all 19 targets have been repeated 10 times)
nTargs = 19;
pairs = nchoosek(1:nTargs, 10);
nPairs = size(pairs, 1);
order = randperm(nPairs);
values=randsample(order,19);
targs=pairs(values,:);
Alltargs=false;
while ~Alltargs
targs=pairs(randsample(order,19),:);
B=[];
for i=1:19
G=length(find(targs==i))==10;
B=[B G];
end
if sum(B)==19
Alltargs=true;
end
end
Here are some very simple steps to do this, basically you just shuffle the vector once, and then you grab the last 10 unique values:
v = repmat(1:19,1,10);
v = v(randperm(numel(v)));
[a idx]=unique(v);
result = unique(v);
v(idx)=[];
The algorithm should be fairly efficient, if you want to do the next 10, just run the last part again and combine the results into a totalResult
You want to sample the numbers 1:19 randomly in blocks of 10 without repetitions. The Matlab function 'randsample' has an optional 'replacement' argument which you can set to 'false' if you do not want repetitions. For example:
N = [];
replacement = false;
for i = 1:19
N = [N randsample(19,10,replacement)];
end
This generates a 19 x 10 matrix of random integers in the range [1,..,19] without repetitions within each column.
Edit: Here is a solution that addresses the requirement that each of the integers [1,..,19] occurs exactly 10 times, in addition to no repetition within each column / sample:
nRange = 19; nRep = 10;
valueRep = true; % true while there are repetitions
nLoops = 0; % count the number of iterations
while valueRep
l = zeros(1,nRep);
v = [];
for m = 1:nRep
v = [v, randperm(nRange,nRange)];
end
m1 = reshape(v,nRep,nRange);
for n = 1:nRep
l(n) = length(unique(m1(:,n)));
end
if all(l == nRep)
valueRep = false;
end
nLoops = nLoops + 1;
end
result = m1;
For the parameters in the question it takes about 300 iterations to find a result.
I think you should approach this constructively.
It's easy to initially find a 19 groups that fulfill your conditions just by rearranging the series 1:19: series1 = repmat(1:19,1,10); and rearranged= reshape(series1,10,19)
then shuffle the values
I would select two random columns copy them and switch the values at two random positions
then make a test if it fulfills your condition - like: test = #(x) numel(unique(x))==10 - if yes replace your columns
just keep shuffling till your time runs out or you are happy
of course you might come up with more efficient shuffling or testing
I was given another solution through the MATLAB forum that works pretty well (Credit to Niklas Nylen over on the MATLAB forum). Computation time is pretty low too. It basically shuffles the numbers until there are no repetitions within every 10 values. Thanks all for your help.
y = repmat(1:19,1,10);
% Run enough iterations to get the output random enough, I selected 100000
for ii = 1:100000
% Select random index
index = randi(length(y)-1);
% Check if it is allowed to switch places
if y(index)~=y(min(index+10, length(y))) && y(index+1)~=y(max(1,index-9))
% Make the switch
yTmp = y(index);
y(index)=y(index+1);
y(index+1)=yTmp;
end
end

matlab brute force indexing

Hi I am working with the brute force method to examine possible combinations of "panels" and "turbines"
My code is
for number_panels = 0:5
for number_turbines = 0:10
for n = 1:24 % number of hours per day
deficit(n) = Demand(n) - (PV_supply(n)*number_panels) -...
(WT_supply(n)*number_turbines);% hourly power deficit
if deficit(n)<0
deficit(n) = 0;
end
The problem I have above is that I haven't yet figured the correct indexing of this code.
What I am trying to do is find the "deficit" for the "number_panels" , "number_turbines" and "n". As it stands I can only find the "deficit" for the last for loop.
How can I code so that I can have the option to access the nth row (or sets of "n" i.e 1-24) and also for the "number_panels" "number_turbines" option?
thanks - in order to find the sum of each deficit(n) value and thus have the respective total deficit of the 24 hour period I have done the following which seems to me to be able to do what I am asking but I am getting incorrect answers:
daily_deficit(number_panels + 1, number_turbines + 1) =...
sum(deficit(number_panels + 1, number_turbines + 1,n)) –
function calcDeficit.m:
File Edit Options Buffers Tools ObjC Help
function deficit = calcDeficit (Demand, PV_supply, WT_supply)
% initialize the size (good practice)
deficit = zeros(6,11,24);
for number_panels = 0:5
for number_turbines = 0:10
for n = 1:24 % number of hours per day
deficit(number_panels+1,number_turbines+1,:) = Demand(n) - (PV_supply(n)*number_panels) -...
(WT_supply(n)*number_turbines);% hourly power deficit
if deficit(n)<0
deficit(n) = 0;
end
end
end
end
return
example call:
Demand=randn(24,1); PV_supply=randn(24,1); WT_supply=randn(24,1); test(Demand,PV_supply,WT_supply)
You access Demand by
Demand(panels+1,number_turbines+1,hour)
Your problem is that you're storing the deficit result as a function only of the value n, the number of hours per day. In your inner loop around n, you keep replacing the values each time through your outer loops, so at the end of the run, you only have the value for n = 1:24 at number_panels = 5 and number_turbines = 10.
Try this:
deficit(number_panels+1, number_turbines+1, n) = ...
That way at the end, you can check any combination given the three indices. I've added a value of 1 to number_panels and number_turbines because MATLAB uses 1-based indexes. To get your results for a specific number of panels or turbines, make sure to add 1 when checking.
Specifically, for 3 panels and 4 turbines at hour 5 in the day:
disp(deficit(3+1, 4+1, 5))
EDIT: Added 1 to the values of number_panels and number_turbines to avoid 0-indexing.