# Battery charge simulation not clipping properly as it iterates

My code for simulating a batterylevel-state throughout a year in 15min-steps doesn't work.

There is a certain list-inputs which simulates the charge state and the batterylevel-state, additionally maximum capacity and minimum capacity(because of discharge-depth) and L as start charging state

maxk=10;
mink=2;
L=5;
chargelevel= {-0.1,-0.1,-0.2, ...(more than 35000 other positive/negative values)...,-0.2,-0.1};
batterylevel=Table[L, {n, 0, 35040}]


which is used by

For[i = 1, i < 35040, i++,
Which[mink <= (batterylevel[[i - 1]] + chargelevel[[i]]) <= maxk,
batterylevel[[i]] = (batterylevel[[i - 1]] + chargelevel[[i]]),
batterylevel[[i]] <= mink, batterylevel[[i - 1]] = mink,
batterylevel[[i]] >= maxk, batterylevel[[i - 1]] = maxk
];];
ListPlot[batterylevel]


batterylevel

The function should be working like this: The loop defines that i is running over the whole thing 35040 times and the batterylevel from step i-1 should be summed up with the chargelevel from step i. If the charge state reaches or falls below 2kWh, it should stay at mink=2kWh and don't add negative chargelevel-rates anymore and go on with looping until there is a positive chargelevel, then it should add chargerates again and load the battery until maxk=10kWh and then stop again at 10kWh and go on with looping. When it reaches negative states, it should discharge again until 2 and so on.

So far i successfully modeled this thing in excel and it worked flawlessly. The crazy thing is that it worked yesterday after trying it a few times and it matched with the result in excel.

Today since i loaded the same notebook (!) it doesn't give me the same output anymore because according to the batterylevel-output it discharges till or below 2 (since it's more likely to reach mink=2 first) and then it starts at L=5 again, adding or substracting the rates according to the chargelevel. The same happens when reaching maxk=10, it just jumps back to L=5. It doesn't jump with the chargelevel-list though.

According to PlotList it looks like this, where you can clearly see that it jumps back:

I even tried to rewrite the loop with while and the conditional with If and Switch, where i get the same result (although If is made like the one in Excel).

Can somebody help me out with this please?

Your code shows you are somewhat confused about the indices. Here is some code that is more Mathematica idiomatic and which makes keeping the indices straight much easier. I am running the simulation with a 24 hour step to cut down the data plotted. Should work just a well with your time step.

maxk = 10;
mink = 2;
steps = 365;
batterylevel = ConstantArray[0, steps];
batterylevel[[1]] = 5;

SeedRandom[7]; chargelevel = RandomReal[{-.75, .75}, steps];

Do[Module[{next},
next = batterylevel[[i - 1]] + chargelevel[[i]];
Which[
mink < next < maxk, batterylevel[[i]] = next,
next <= mink, batterylevel[[i]] = mink,
next >= maxk, batterylevel[[i]] = maxk]],
{i, 2, steps}];

ListPlot[batterylevel]


You can see the clipping at 2 and 10 is now handled correctly.

### Update 1

Using the built-in Mathematica function Clip, your simulation can be reduced to

Do[
batterylevel[[i]] = Clip[batterylevel[[i - 1]] + chargelevel[[i]], {mink, maxk}],
{i, 2, steps}]


### Update 2

As you become more experienced with Mathematica, you will come to appreciate that your simulation can be expressed even more concisely. In Mathematica there is no need to create a batterylevel array.

SeedRandom[7];
With[{maxk = 10, mink = 2, initk = 5, steps = 365},
Module[{chargelevel},
chargelevel = RandomReal[{-.75, .75}, steps];
ListPlot[FoldList[Clip[#1 + #2, {mink, maxk}] &, initk, chargelevel]]]]


The plot produced by this code is exactly the same as the one shown above.

• Also worth pointing out that Which is an expression that returns a value, so you could do batterylevel[[i]] = Which[mink < next < maxk, next, next <= mink, mink, next >= maxk, maxk] if you didn't know about Clip`. – Rahul Jan 21 '16 at 1:28