Getting the voltage
If the Cycler
asks the voltage of the Battery (e.g. to determine whether to stop charging), the Battery will pass on this request to the Module_s. In a series module, the voltage is the sum of the voltages of its children, so this module will ask the voltage of each Module_p, add them up, return them to the Battery, which in turn passes it on to the Cycler. When each Module_p calculates its voltage, it asks the voltages of the Cells of which it is made up, and takes the average. In Cell, there is a function to calculate the cell voltage as a function of the cell current, SoC, temperature, etc. This is illustrated graphically below, where blue arrows are invoking functions to ‘lower levels' while orange arrows are returning results to ‘higher levels'.
Time integration
Time integration for the electrical model follows a very similar pattern to the setCurrent-function. The Cycler
instructs the Battery to take N steps of dt seconds each. The Battery will first pass that command on to the Module_S.
When the Module_s
gets the command to take N steps of dt seconds, it passes this command on to each of the 10 parallel modules connected to it. Each of these Module_p will then pass it on to each of the the Cells connected to it. In the Cells, the diffusion PDE is integrated in time over dt seconds for N times. Then cells calculate the internal heat generation and degradation over the Ndt seconds (so the diffusion model is solved ever dt seconds, while the thermal and degradation models are only resolved every Ndt model).
Once all cells of a parallel module have finished their time integration, the code return to the time integration of the parallel module, which then redistributes the current of its cells to equalise their voltages. Note that this voltage equalisation is only done after N*dt seconds.
If all parallel modules have finished redistributing their currents, the code returns to the series module. The series module does not need to do anything, and returns back to the Battery time integration function. That function will now call the thermal model, which is explained in the next section and indicated by the green arrow in the graph.
The internal heat generation in cells is accumulated during time integration. However, cells cannot update their temperature because they don't know how much heat they will exchange with neighbours, or how much cooling they will get. So during time integration, they don't update their temperature.
Once all time integration is done, the code returns to the top level of the StorageUnit, in our case the Battery (but it could also be Module_s
, Module_p
or Cell
). The Battery then starts the computation of the thermal model (indicated in green in the figure below), which is a top-down calculation.
The concept is relatively straightforward: every level gets as inputs the temperatures and thermal resistances of all neighbouring elements (e.g. cooling from the higher level and heat exchange with neighbours from the same level). This function has the following steps
CoolSystem
of this module) and T of all our children.This same process goes on in the Battery
, Module_s
, and each of the Module_p
. Cells are a bit simpler because they don't have children. When a parallel module informs a cell of h and T of its two neighbouring cells and the T and h of the coolsystem, cells can compute their thermal balance (sum of internal heat generation, heat exchange with two neighbouring cells and with the parallel module). Cells return this new temperature to the parallel module, but only in step 3 of the parallel module, we will update the cell temperature to this new value. This is done because the parallel module needs to compute how much heat it exchanged with the Cell, so all temperatures must remain the same until we have finished this calculation.
Note that it is imperative that Cells or Modules don't update their own temperature after calculating the new value. Heat exchange is calculated by \(hA(T_1 – T_2)\). So e.g. the parent will give us \(T_2\) and we can calculate our own \(T_{\rm 1-new}\). But if we already set our temperature to this new value, then there will be an error in the code because at some later point in the flow of this function, the parent will compute the heat exchange with its children when it calculates its own new temperature. And this will now be \(hA(T_2 – T_{1_new})\). In other words, the child thinks the heat exchange is \(hA(T_1 – T_2)\), while the parent thinks it is \(hA(T_2 – T_{1_new})\). And this violates the conservation of energy law (heat given away by the parent must equal the heat exchange received by the child). Therefore, we cannot update T1 until after the parent has calculated its own temperature, i.e. in step 3.
The full flow of the program is therefore:
Module_s
will first compute the neighbours of every parallel module. To parallel module_i, the Module_s
will pass on the T of module i-1 and module i+1, as well as the T of the Module_s, the convective cooling constant of its CoolSystem and the conductive constant between adjacent Modules. `Module_p` will first compute the neighbours of every Cell. To Cell_i, the Module_p will pass on the T of `Cell` i-1 and `Cell` i+1, as well as the T of the `Module_p`, the convective cooling constant of its CoolSystem and the conductive constant between adjacent cells. A `Cell` knows how much heat had been generated internally (from the time integration). And we can compute the heat transfer with adjacent cells and the parallel modules (hAT1-T2), so we can calculate the new temperature of the cell based on the heat balance. We return this new temperature to our parallel module.
[repeat for each cell in the parallel module]
Once all the cells have told us their new temperature, the `Module_p` will first calculate its own temperature based on heat exchanged with the cells, and the `Module_s` and our neighbouring parallel modules [for which we got the parameters as input to this function]. Then we set the temperature of each Cell to the value they had reported to us And finally we return the new T of the `Module_p` to the `Module_s`
[repeat for each parallel module]
Module_s
will first calculate its own temperature based on heat exchanged with the parallel modules and the Battery [for which we got the parameters as input to this function].Module_s
to the Battery. Module_s
using the old Module_s
temperature (such that the Module_s
gets the same heat as we give away here). The Battery also adds up the heat generation from the Converter losses, and computes its new temperature.Module_s
to the value it had given usThe graph below illustrates this process. The four steps in the layers are coloured in blue, purple, red and yellow. Note that we have only displayed the flow for one parallel module and one cell in this module, although in reality it will be repeated for each cell in the parallel module, and each parallel module in the series module.
Data storage is completely analogous to setting the current. It is a simple top-down process where you first invoke storeData on the Battery
, which invokes it on the Module_s
, which invokes it on all parallel modules, which invoke it on each of their Cells.
The only difference is that if a Module
(or Battery
) has a CoolSystem
, it will also invoke storeData
on its Coolsystem