![]() |
SLIDE
3.0.0
A simulator for lithium-ion battery pack degradation
|
Slide namespace contains all the types, classes, and functions for the simulation framework. More...
Namespaces | |
namespace | benchmarks |
namespace | debug |
namespace | free |
namespace | paperCode |
namespace | param |
namespace | PhyConst |
namespace | policy |
namespace | settings |
< Non-user related settings, please do not change! | |
namespace | tests |
namespace | tol |
namespace | util |
Classes | |
class | ArrayVec |
struct | BasicData |
class | Battery |
struct | BatteryData |
class | card_prod |
class | Cell |
Abstract Class representing a single battery cell. More... | |
class | Cell_ECM |
class | Cell_KokamNMC |
class | Cell_LGChemNMC |
class | Cell_SPM |
struct | CellCommonHist |
struct | CellData |
struct | CellDataStorage |
struct | CellDataStorage< settings::cellDataStorageLevel::storeHistogramData > |
< Store as histogram. More... | |
struct | CellDataStorage< settings::cellDataStorageLevel::storeTimeData > |
struct | CellDataWriter |
struct | CellLimits |
struct | Clock |
class | Converter |
class | CoolSystem |
class | CoolSystem_HVAC |
struct | CoolSystem_HVACCumulative |
struct | CoolSystem_HVACData |
struct | CoolSystem_HVACHist |
struct | CoolSystem_HVACInst |
< #TODO -> in future try to combine. More... | |
class | CoolSystem_open |
struct | CoolSystemCumulative |
struct | CoolSystemData |
struct | CoolSystemHist |
Data storage. More... | |
struct | CoolSystemInst |
< Instantenous data. More... | |
class | Cycler |
struct | DataStore |
class | Deep_ptr |
struct | DEG_ID |
DEG_ID structure handles the identifications of which degradation model(s) to use. More... | |
class | DynamicMatrix |
struct | Empty |
class | FixedData |
class | FixedDataIter |
struct | GammaDensityFunctor |
struct | GetHistograms |
< #TODO how do we remove these helper functions in constexpr? More... | |
class | Histogram |
class | Interval |
struct | MCMC_Input |
struct | MCMC_Record |
struct | MCMCSettings |
struct | Model_SPM |
class | Module |
class | Module_p |
class | Module_s |
struct | ModuleThermalParam |
struct | OCVcurves |
struct | OCVparam |
struct | Prior |
class | Procedure |
struct | ProcedureThroughputData |
class | PtrInterval |
< std::span is same size. It is now postponed. More... | |
class | SmallVector |
struct | State |
struct | State_ECM |
State_ECM template class for holding the states of the ECM model. More... | |
class | State_SPM |
< #TODO how can we make this so it takes 29=N_states from enum? More... | |
class | StateStorage |
class | StorageUnit |
class | VecStates |
class | XYdata |
struct | XYplain |
struct Data More... | |
Typedefs | |
using | Cell_Bucket = Cell_ECM< 0 > |
using | State_Bucket = State_ECM< 0 > |
Bucket Cell with no RC pairs. More... | |
using | CoolSystemInst_t = std::vector< CoolSystemInst > |
using | CoolSystemHist_t = CoolSystemHist |
using | CoolSystemData_t = std::conditional_t< settings::DATASTORE_COOL==1, CoolSystemHist_t, std::conditional_t< settings::DATASTORE_COOL==2, CoolSystemInst_t, Empty > > |
using | CoolSystem_HVACHist_t = CoolSystem_HVACHist |
using | CoolSystem_HVACInst_t = std::vector< CoolSystem_HVACInst > |
using | CoolSystem_HVACData_t = std::conditional_t< settings::DATASTORE_COOL==1, CoolSystem_HVACHist_t, std::conditional_t< settings::DATASTORE_COOL==2, CoolSystem_HVACInst_t, Empty > > |
using | LL_Result = std::array< double, 5 > |
using | ThroughputData = State< 0, 3 > |
template<typename T , size_t ROW, size_t COL> | |
using | Matrix = std::array< std::array< T, COL >, ROW > |
See source: http://cpptruths.blogspot.com/2011/10/multi-dimensional-arrays-in-c11.html. More... | |
using | XYdata_ff = XYdata< FixedData< double >, FixedData< double > > |
using | XYdata_fv = XYdata< FixedData< double >, std::vector< double > > |
using | XYdata_vv = XYdata< std::vector< double >, std::vector< double > > |
using | XYdata_ss = XYdata< std::span< double >, std::span< double > > |
Enumerations | |
enum | cellType { KokamNMC = 0 , LGChemNMC = 1 , UserCell = 2 } |
enum class | HistogramType { slidepack = 0 , equidistant = 1 } |
enum class | Status : int_fast8_t { ReachedCurrentLimit = -6 , ReachedVoltageLimit , ReachedTimeLimit , ReachedSmallCurrent , Invalid_Vset , SafeVoltage , Success , Vmin_violation , Vmax_violation , VMIN_violation , VMAX_violation , VMINsafety_violation , VMAXsafety_violation , V_not_calculated , SOC_limits_violation , Invalid_states , Invalid_SUs , ParallelUnit_failed , RedistributeCurrent_failed , timeStep_CC_failed , setVoltage_not_defined , Unknown_problem = 127 , Critical = VMIN_violation , NotSafe = VMINsafety_violation } |
Functions | |
void | validState (State_SPM &s, State_SPM &s_ini) |
< State related functions More... | |
Deep_ptr< StorageUnit > | makeBattery (bool balance, bool capSpread, bool RcellSpread, bool degrateSpread, bool contactR, int coolControl) |
Deep_ptr< StorageUnit > | makeBattery2 (bool balance, bool capSpread, bool RcellSpread, bool degrateSpread, bool contactR, int coolControl) |
Deep_ptr< StorageUnit > | makeBattery_EPFL_smaller (bool capSpread, bool RcellSpread, bool degrateSpread, bool contactR, int coolControl, std::string IDadditions, double RM) |
Deep_ptr< StorageUnit > | makeBattery_EPFL (bool capSpread, bool RcellSpread, bool degrateSpread, bool contactR, int coolControl, std::string IDadditions, double RM) |
Deep_ptr< StorageUnit > | makeBattery_Test (bool capSpread, bool RcellSpread, bool degrateSpread, bool contactR, int coolControl, std::string IDadditions, double RM) |
Deep_ptr< StorageUnit > | makeBattery_TestParallel (bool capSpread, bool RcellSpread, bool degrateSpread, bool contactR, int coolControl, std::string IDadditions, double RM) |
template<size_t N> | |
auto | S_update (slide::Matrix< double, N, N > &S, std::array< double, N > w, double alpha, double n) |
template<typename ThetaType , typename PriorType , typename CostType , typename SettingsType > | |
auto | LL (const ThetaType &theta_cand, PriorType &prior, const CostType &costFun, const size_t Nobservations, const SettingsType &mcmcSettings) |
bool | CCCV_fit (Cell_SPM c1, double Crate, double Ccut, double Tref, double Dp, double Dn, double kp, double kn, double R, const struct OCVparam &ocvfit, const struct slide::Model_SPM &M, slide::XYdata_vv &Vsim, slide::XYdata_vv &Tsim) |
void | CCCV (double Crate, double Ccut, double Tref, double Dp, double Dn, double kp, double kn, double R, const struct OCVparam &ocvfit, const struct Model_SPM *M, slide::XYdata_vv &Vsim, slide::XYdata_vv &Tsim) |
void | fitDiffusionAndRate (int hierarchy, int ir, double R, slide::FixedData< double > Dp_space, slide::FixedData< double > Dn_space, slide::FixedData< double > kp_space, slide::FixedData< double > kn_space, std::vector< slide::XYdata_vv > &Vdata_all, double weights[], double Crates[], double Ccuts[], double Tref, const struct OCVparam &ocvfit, double *err, std::array< double, 5 > &par) |
void | hierarchicalCharacterisationFit (int hmax, slide::FixedData< double > r_space, slide::FixedData< double > Dp_space, slide::FixedData< double > Dn_space, slide::FixedData< double > kp_space, slide::FixedData< double > kn_space, std::vector< slide::XYdata_vv > &Vdata_all, double weights[], double Crates[], double Ccuts[], double Tref, const struct OCVparam &ocvfit, double *err, std::array< double, 5 > &par) |
void | estimateCharacterisation () |
void | writeCharacterisationParam (int h, const std::array< double, 5 > &par, double err) |
void | CCCV (double Crate, double Ccut, double Tref, double Dp, double Dn, double kp, double kn, double R, const struct OCVparam &ocvfit, const struct slide::Model_SPM &M, slide::XYdata_vv &Vsim, slide::XYdata_vv &Tsim) |
bool | validOCV (bool checkRange, slide::XYdata_vv &data) |
auto | discharge_noexcept (const slide::XYdata_vv &OCVp, const slide::XYdata_vv &OCVn, double cap, const double AMp, const double AMn, const double cmaxp, const double cmaxn, double sp, double sn, double Vend, slide::XYdata_vv &OCV, slide::XYdata_vv &OCVanode, slide::XYdata_vv &OCVcathode, double fp[], double fn[]) |
auto | discharge_noexcept (const slide::XYdata_vv &OCVp, const slide::XYdata_vv &OCVn, double cap, const double AMp, const double AMn, const double cmaxp, const double cmaxn, double sp, double sn, double Vend, slide::XYdata_vv &OCV, double fp[], double fn[]) |
void | discharge (const slide::XYdata_vv &OCVp, const slide::XYdata_vv &OCVn, double cap, const double AMp, const double AMn, const double cmaxp, const double cmaxn, double sp, double sn, double Vend, slide::XYdata_vv &OCV, slide::XYdata_vv &OCVanode, slide::XYdata_vv &OCVcathode, double fp[], double fn[]) |
void | readOCVinput (const std::string &namepos, const std::string &nameneg, const std::string &namecell, slide::XYdata_vv &OCVp, slide::XYdata_vv &OCVn, slide::XYdata_vv &OCVcell) |
double | calculateError (bool bound, slide::XYdata_vv &OCVcell, slide::XYdata_vv &OCVsim) |
auto | cost_OCV (const slide::XYdata_vv &OCVp, const slide::XYdata_vv &OCVn, const double AMp, const double AMn, double sp, double sn, const double cmaxp, const double cmaxn, const slide::XYdata_vv &OCVcell) |
void | fitAMnAndStartingPoints (int hierarchy, int ap, double AMp, slide::FixedData< double > AMn_space, slide::FixedData< double > sp_space, slide::FixedData< double > sn_space, double cmaxp, double cmaxn, double *err, std::array< double, 4 > &par, slide::XYdata_vv &OCVp, slide::XYdata_vv &OCVn, slide::XYdata_vv &OCVcell) |
auto | hierarchicalOCVfit (int hmax, slide::FixedData< double > AMp_space, slide::FixedData< double > AMn_space, slide::FixedData< double > sp_space, slide::FixedData< double > sn_space, std::string namepos, std::string nameneg, std::string namecell, double cmaxp, double cmaxn) |
void | estimateOCVparameters () |
void | writeOCVParam (int h, const std::array< double, 4 > &par) |
void | fitAMnAndStartingPoints (int hierarchy, int ap, slide::FixedData< double > AMn_space, slide::FixedData< double > sp_space, slide::FixedData< double > sn_space, double cmaxp, double cmaxn, double *err, std::array< double, 4 > &par, std::array< int, 4 > &parindex, slide::XYdata_vv &OCVp, slide::XYdata_vv &OCVn, slide::XYdata_vv &OCVcell) |
void | visit_SUs (StorageUnit *su, auto &&fn) |
template<typename T , typename... Args> | |
auto | make_SU (Args &&...args) |
void | writeData (std::ofstream &file, std::span< Histogram<> > histograms) |
void | writeVarAndStates (std::ofstream &file, auto &cell) |
template<settings::cellDataStorageLevel N> | |
void | writeDataImpl (std::ofstream &file, auto &cell, auto &dataStorage) |
template<typename T , typename... Args> | |
Deep_ptr< T > | make_Deep_ptr (Args &&...args) |
template<typename T , typename... Args> | |
Deep_ptr< T > | make (Args &&...args) |
Makes storage units. More... | |
template<typename Tdata > | |
std::ostream & | operator<< (std::ostream &os, const DynamicMatrix< Tdata > &M) |
template<typename T , bool extrapolation = true> | |
int | distance (const FixedDataIter< T, extrapolation > &a, const FixedDataIter< T, extrapolation > &b) |
std::ostream & | operator<< (std::ostream &ofs, const Histogram<> &hist) |
template<size_t N, size_t M = N> | |
auto | eye (double k=1.0) |
template<size_t N, size_t M = N> | |
auto | zeros () |
template<int N, int M = N> | |
auto | ones (double k=1.0) |
template<int N> | |
void | cholUpdate (slide::Matrix< double, N, N > &L, std::array< double, N > x, bool isDowndate=false) |
const char * | getStatusMessage (Status status) |
bool | isStatusSuccessful (Status status) |
bool | isStatusFailed (Status status) |
bool | isStatusOK (Status status) |
bool | isStatusBad (Status status) |
bool | isStatusWarning (Status status) |
Not successful but voltage is in limits. More... | |
bool | isStatusSafe (Status status) |
bool | isLimitsReached (Status status) |
bool | isStatusVoltageLimitsViolated (Status status) |
bool | isCCLimitReached (Status status) |
bool | isCVLimitReached (Status status) |
bool | isCurrentLimitReached (Status status) |
bool | isVoltageLimitReached (Status status) |
template<typename Tx > | |
bool | check_is_fixed (Tx &xdat) |
template<typename Tpath > | |
void | loadCSV_2col (Tpath &&name, slide::XYdata_vv &data, int n=0) |
template<typename T , size_t N> | |
auto | arrSum (const std::array< T, N > &a1, const std::array< T, N > &a2, double b1, double b2) |
template<typename T , size_t N> | |
auto | operator+= (std::array< T, N > &c, const std::array< T, N > &b) |
template<typename T , size_t N> | |
auto | operator+ (const std::array< T, N > &a, const std::array< T, N > &b) |
template<typename T , size_t N> | |
auto | operator-= (std::array< T, N > &c, const std::array< T, N > &b) |
template<typename T , size_t N> | |
auto | operator- (const std::array< T, N > &a, const std::array< T, N > &b) |
template<typename Tx , typename Ty > | |
auto | linInt_noexcept (bool bound, Tx &xdat, Ty &ydat, int nin, double x, bool is_fixed=false) |
template<typename Tx , typename Ty > | |
double | linInt (bool verbose, bool bound, Tx &xdat, Ty &ydat, int nin, double x, bool is_fixed=false) |
template<typename Tpath > | |
std::string | getFileContents (const Tpath &name) |
auto | getFile (std::string name) |
template<typename Tpath , typename T , size_t ROW, size_t COL> | |
void | loadCSV_mat (const Tpath &name, Matrix< T, ROW, COL > &x) |
template<typename Tpath , typename T , size_t ROW> | |
void | loadCSV_1col (const Tpath &name, std::array< T, ROW > &x) |
void | ignoreBOM (std::ifstream &in) |
template<typename Tpath , typename Tx , typename Ty > | |
void | loadCSV_2col (const Tpath &name, Tx &x, Ty &y, int n=0) |
template<typename Tpath , typename Tx > | |
void | loadCSV_Ncol (const Tpath &name, DynamicMatrix< Tx > &x, int n=0) |
template<typename Tpath > | |
void | loadCSV_2col (const Tpath &name, std::span< double > &x, std::span< double > &y, int n=0) |
template<typename Tfun > | |
void | run (Tfun task_indv, int i_end, unsigned int numMaxParallelWorkers=settings::numMaxParallelWorkers) |
auto | transform_sum (const auto &SUs, auto &function) |
auto | transform_max (const auto &SUs, auto &function) |
auto | transform_min (const auto &SUs, auto &function) |
auto | transform_mean (const auto &SUs, auto &function) |
template<int N, typename T > | |
double | norm_sq (const T &x) |
< Takes vector or array: More... | |
template<int N, typename T > | |
double | norm (const T &x) |
< Takes vector or array: More... | |
std::ostream & | operator<< (std::ostream &ofs, const Clock &clk) |
constexpr auto | operator""_kA (long double d) |
kiloAmperes More... | |
constexpr auto | operator""_A (long double d) |
Amperes. More... | |
constexpr auto | operator""_mA (long double d) |
miliAmperes More... | |
constexpr auto | operator""_uA (long double d) |
microAmperes More... | |
constexpr auto | operator""_kV (long double d) |
kiloVolts More... | |
constexpr auto | operator""_V (long double d) |
Volts. More... | |
constexpr auto | operator""_mV (long double d) |
miliVolts More... | |
constexpr auto | operator""_uV (long double d) |
microVolts More... | |
constexpr double | C_to_Kelvin (auto Celsius) |
constexpr double | K_to_Celsius (auto Kelvin) |
constexpr double | operator""_degC (long double d) |
degrees Celsius More... | |
constexpr double | operator""_K (long double d) |
Kelvins. More... | |
constexpr double | operator""_degC (unsigned long long d) |
degrees Celsius More... | |
constexpr double | operator""_K (unsigned long long d) |
Kelvins. More... | |
constexpr auto | abs_sqrt (auto x) |
constexpr auto | sqr (auto x) |
constexpr auto | cube (auto x) |
template<typename T > | |
void | output_printer (const std::vector< T > &vec, const auto &save_path) |
std::vector< double > | linstep (double x_min, double x_step, int Nstep) |
std::vector< double > | logstep (double x_min, double x_step, int Nstep) |
FixedData< double > | linspace_fix (double x1, double x2, int N) |
template<size_t N> | |
constexpr std::array< double, N > | linspace (double x1, double x2) |
FixedData< double > | range_fix (double x_min, double x_max, double x_step) |
FixedData< double > | linstep_fix (double x_min, double x_step, int Nstep) |
FixedData< double > | logstep_fix (double x_min, double x_step, int Nstep) |
std::vector< double > | linspace (double x1, double x2, int N) |
Variables | |
constexpr CellLimits | defaultCellLimits |
constexpr double | TIME_INF = 20 * 365 * 24 * 3600 |
Slide namespace contains all the types, classes, and functions for the simulation framework.
< Include other util files.
< -> for memcpy
< common implementation for all base-modules
< class that represents the state of a cell, the state is the collection of all time-varying conditions of the battery defines a struct with the values for the matrices used in the spatial discretisation of the diffusion PDE
using slide::Cell_Bucket = typedef Cell_ECM<0> |
using slide::CoolSystem_HVACData_t = typedef std::conditional_t<settings::DATASTORE_COOL == 1, CoolSystem_HVACHist_t, std::conditional_t<settings::DATASTORE_COOL == 2, CoolSystem_HVACInst_t, Empty> > |
using slide::CoolSystem_HVACHist_t = typedef CoolSystem_HVACHist |
using slide::CoolSystem_HVACInst_t = typedef std::vector<CoolSystem_HVACInst> |
using slide::CoolSystemData_t = typedef std::conditional_t<settings::DATASTORE_COOL == 1, CoolSystemHist_t, std::conditional_t<settings::DATASTORE_COOL == 2, CoolSystemInst_t, Empty> > |
using slide::CoolSystemHist_t = typedef CoolSystemHist |
using slide::CoolSystemInst_t = typedef std::vector<CoolSystemInst> |
using slide::LL_Result = typedef std::array<double, 5> |
struct LL_Result { double LLout{0}, LLout1{0}, LLout2{0}, P{}, err_sqr{}; };
using slide::Matrix = typedef std::array<std::array<T, COL>, ROW> |
using slide::State_Bucket = typedef State_ECM<0> |
Bucket Cell with no RC pairs.
using slide::ThroughputData = typedef State<0, 3> |
using slide::XYdata_ff = typedef XYdata<FixedData<double>, FixedData<double> > |
using slide::XYdata_fv = typedef XYdata<FixedData<double>, std::vector<double> > |
using slide::XYdata_ss = typedef XYdata<std::span<double>, std::span<double> > |
using slide::XYdata_vv = typedef XYdata<std::vector<double>, std::vector<double> > |
enum slide::cellType |
|
strong |
|
strong |
|
inlineconstexpr |
auto slide::arrSum | ( | const std::array< T, N > & | a1, |
const std::array< T, N > & | a2, | ||
double | b1, | ||
double | b2 | ||
) |
|
inlineconstexpr |
double slide::calculateError | ( | bool | bound, |
slide::XYdata_vv & | OCVcell, | ||
slide::XYdata_vv & | OCVsim | ||
) |
< root mean square error
< loop through all data points
< Get the simulated OCV at the discharged charge of this point on the measured OCV curve of the cell
< if status is not 0 then the simulated voltage is already set to 0;
< Calculate the error
< sum ( (Vcell[i] - Vsim[i])^2, i=0..ncell )
void slide::CCCV | ( | double | Crate, |
double | Ccut, | ||
double | Tref, | ||
double | Dp, | ||
double | Dn, | ||
double | kp, | ||
double | kn, | ||
double | R, | ||
const struct OCVparam & | ocvfit, | ||
const struct Model_SPM * | M, | ||
slide::XYdata_vv & | Vsim, | ||
slide::XYdata_vv & | Tsim | ||
) |
< *********************************************************** 1 variables ***********************************************************************
< integer deciding how verbose the simulation should be The higher the number, the more output there is. Recommended value is 1, only use higher value for debugging From 4 (and above) there will be too much info printed to follow what is going on, but this might be useful for debugging to find where the error is and why it is happening 0 almost no messages are printed, only in case of critical errors related to illegal parameters 1 error messages are printed in case of critical errors which might crash the simulation 2 all error messages are printed, whether the simulation can recover from the errors or not 3 on top of the output from 2, a message is printed every time a function in the CyclerOld and BasicCycler is started and terminated 4 on top of the output from 3, the high-level flow of the program in the CyclerOld is printed (e.g. 'we are going to discharge the cell') 5 on top of the output from 4, the low-level flow of the program in the BasicCycler is printed (e.g. 'in time step 101, the voltage is 3.65V') 6 on top of the output from 5, we also print details of the nonlinear search for the current needed to do a CV phase 7 on top of the output from 6, a message is printed every time a function in the Cell is started and terminated
< Make a cell of the sub-class Cell_SPM. This sub-class defines some extra functions to change its parameters
< Check all parameters are positive
< Set the characterisation parameters of the cell to the ones given as input to this function
< c1.setVlimits(ocvfit.Vmax, ocvfit.Vmin); #TODO
< set the temperature of the cell to the given value
< set the environmental temperature to the given value
< time steps
< time step for cycling [s]
< current step for ramping, indicating how fast the current can change per 'ramp time step', [A s-1]
< time step for ramping [s] the current can change at Istep/tstep, so currently 0.1A per 1 ms.
< variables
< initial state of the cell, used to recover after an error
< initial current of the cell, used to recover after an error
< Crate for the cutoff current when bringing the cell to the initial state (i.e. charge the cell first before you simulate the CCCV discharge)
< voltage at which the CCCV cycle should end (i.e. the minimum voltage if you are simulating a discharge)
< don't account for degradation while doing the cycles
< identification std::string for the CyclerOld
< time interval at which cycling data has to be recorded [s] <0 means no folder is created and no data is stored 0 means no data is recorded but a folder is still created for later use >0 means data is recorded approximately every so many seconds
< Make the CyclerOld
< feedback variables we don't need
< *********************************************************** 2 (dis)charge ***********************************************************************
< We are going to start trying to simulate the (dis)charge with a normal time step (for time integration and ramping) But smaller diffusion constants lead to decreased numerical stability and other discretiation errors Therefore, these normal time steps might leads to errors in the code So instead, there are loops which iteratively decrease the time steps to check if that solves the error.
< boolean to indicate whether we have completed the discharge
< loop to decrease the integration time step (dt)
< Set the ramping time steps to their normal value
< current step for ramping
< time step for ramping
< loop to decrease the time steps for ramping
< Try to simulate the (dis)charge
< restore the original battery state in case an error occurred earlier in the loop
< don't collect cycling data during the charging
< Bring the cell to the correct soc before simulating the (dis)charge
< simulate a discharge
< first fully charge the cell to the maximum voltage at 1C
< simulate a charge
< first fully discharge the cell to the minimum voltage at 1C
< collect cycling data of every time step
< If we get here, no errors were thrown and we can leave the loop
< indicate we have finished the simulation
< leave the loops
< std::cout << "Throw test: " << 79 << '
';
< An error occurred while simulating the (dis)charge
< reduce the ramping parameters by a factor of 10 now we are still in the loop which decreases the ramping time steps ('final' is still false), so you will try again and the original battery state will be restored at the start of the loop, so the illegal battery state will be 'forgotten'
< if we haven't finished the cycle, try again with a smaller time step
< now we are still in the loop which decreases the time step, so you will try again and the original battery state will be restored at the start of the loop, so the illegal battery state will be 'forgotten'
< *********************************************************** 3 output ***********************************************************************
< Throw an error if the simulation wasn't successful. This happens if 'finished' is still false or if ahi == 0 i.e. no charge could be discharged
< Get the cell voltage from the simulated (dis)charge from the CyclerOld
void slide::CCCV | ( | double | Crate, |
double | Ccut, | ||
double | Tref, | ||
double | Dp, | ||
double | Dn, | ||
double | kp, | ||
double | kn, | ||
double | R, | ||
const struct OCVparam & | ocvfit, | ||
const struct slide::Model_SPM & | M, | ||
slide::XYdata_vv & | Vsim, | ||
slide::XYdata_vv & | Tsim | ||
) |
bool slide::CCCV_fit | ( | Cell_SPM | c1, |
double | Crate, | ||
double | Ccut, | ||
double | Tref, | ||
double | Dp, | ||
double | Dn, | ||
double | kp, | ||
double | kn, | ||
double | R, | ||
const struct OCVparam & | ocvfit, | ||
const struct slide::Model_SPM & | M, | ||
slide::XYdata_vv & | Vsim, | ||
slide::XYdata_vv & | Tsim | ||
) |
< *********************************************************** 1 variables ***********************************************************************
< integer deciding how verbose the simulation should be The higher the number, the more output there is. Recommended value is 1, only use higher value for debugging From 4 (and above) there will be too much info printed to follow what is going on, but this might be useful for debugging to find where the error is and why it is happening 0 almost no messages are printed, only in case of critical errors related to illegal parameters 1 error messages are printed in case of critical errors which might crash the simulation 2 all error messages are printed, whether the simulation can recover from the errors or not 3 on top of the output from 2, a message is printed every time a function in the CyclerOld and BasicCycler is started and terminated 4 on top of the output from 3, the high-level flow of the program in the CyclerOld is printed (e.g. 'we are going to discharge the cell') 5 on top of the output from 4, the low-level flow of the program in the BasicCycler is printed (e.g. 'in time step 101, the voltage is 3.65V') 6 on top of the output from 5, we also print details of the nonlinear search for the current needed to do a CV phase 7 on top of the output from 6, a message is printed every time a function in the Cell is started and terminated
< Check all parameters are positive
< time steps
< time step for cycling [s]
< current step for ramping, indicating how fast the current can change per 'ramp time step', [A s-1]
< time step for ramping [s] the current can change at Istep/tstep, so currently 0.1A per 1 ms.
< variables
< initial state of the cell, used to recover after an error
< Crate for the cutoff current when bringing the cell to the initial state (i.e. charge the cell first before you simulate the CCCV discharge)
< voltage at which the CCCV cycle should end (i.e. the minimum voltage if you are simulating a discharge)
< don't account for degradation while doing the cycles
< identification std::string for the CyclerOld
< time interval at which cycling data has to be recorded [s] <0 means no folder is created and no data is stored 0 means no data is recorded but a folder is still created for later use >0 means data is recorded approximately every so many seconds
< Make the CyclerOld
< feedback variables we don't need
< *********************************************************** 2 (dis)charge ***********************************************************************
< We are going to start trying to simulate the (dis)charge with a normal time step (for time integration and ramping) But smaller diffusion constants lead to decreased numerical stability and other discretiation errors Therefore, these normal time steps might leads to errors in the code So instead, there are loops which iteratively decrease the time steps to check if that solves the error.
< boolean to indicate whether we have completed the discharge
< loop to decrease the integration time step (dt)
< Set the ramping time steps to their normal value
< current step for ramping
< time step for ramping
< loop to decrease the time steps for ramping
< Try to simulate the (dis)charge
< restore the original battery state in case an error occurred earlier in the loop
< Does not throw.
< c1.setRamping(Istep, tstep); //!< Does not throw.
< don't collect cycling data during the charging //!< Does not throw. (anymore)
< Bring the cell to the correct soc before simulating the (dis)charge
< simulate a discharge
< first fully charge the cell to the maximum voltage at 1C
< simulate a charge
< first fully discharge the cell to the minimum voltage at 1C
< collect cycling data of every time step
< If we get here, no errors were thrown and we can leave the loop
< indicate we have finished the simulation
< leave the loops
< std::cout << "Throw test: " << 78 << '
'; An error occurred while simulating the (dis)charge #TODO -> we throw here very much.
< now we are still in the loop which decreases the ramping time steps ('final' is still false), so you will try again and the original battery state will be restored at the start of the loop, so the illegal battery state will be 'forgotten'
< if we haven't finished the cycle, try again with a smaller time step
< now we are still in the loop which decreases the time step, so you will try again
< and the original battery state will be restored at the start of the loop, so the illegal battery state will be 'forgotten'
< *********************************************************** 3 output ***********************************************************************
< the simulation wasn't successful. This happens if 'finished' is still false or if ahi == 0 i.e. no charge could be discharged
< Get the cell voltage from the simulated (dis)charge from the CyclerOld
< Simulation was successful.
bool slide::check_is_fixed | ( | Tx & | xdat | ) |
< Tolerance.
xdat | Checks if steps are fixed length. #TODO should not be here. |
void slide::cholUpdate | ( | slide::Matrix< double, N, N > & | L, |
std::array< double, N > | x, | ||
bool | isDowndate = false |
||
) |
< In-place rank-one update for Cholesky
auto slide::cost_OCV | ( | const slide::XYdata_vv & | OCVp, |
const slide::XYdata_vv & | OCVn, | ||
const double | AMp, | ||
const double | AMn, | ||
double | sp, | ||
double | sn, | ||
const double | cmaxp, | ||
const double | cmaxn, | ||
const slide::XYdata_vv & | OCVcell | ||
) |
< Variables
< number of electrons involved in the reaction
< discharged charge up to now
< check the surface concentration is within the allowed limits when doing linear interpolation.
< boolean to check if we have reached the end voltage
< square error
< Simulation OCV.
< Original equations: Ah += I * dt / 3600; -> I*dt = dAs sp += I * dt / (n * F) / AMp / cmaxp; sn -= I * dt / (n * F) / AMn / cmaxn;
< Ah need to be added to reach cell's Ah.
< Ah += I * dt / 3600; I*dt = dAs, Amper seconds
< #TODO: convert to interp
< OCV = OCV_cathode - OCV_anode, cell voltage in this time step
< Calculate the error
< sum ( (Vcell[i] - Vsim[i])^2, i=0..ncell )
|
inlineconstexpr |
void slide::discharge | ( | const slide::XYdata_vv & | OCVp, |
const slide::XYdata_vv & | OCVn, | ||
double | cap, | ||
const double | AMp, | ||
const double | AMn, | ||
const double | cmaxp, | ||
const double | cmaxn, | ||
double | sp, | ||
double | sn, | ||
double | Vend, | ||
slide::XYdata_vv & | OCV, | ||
slide::XYdata_vv & | OCVanode, | ||
slide::XYdata_vv & | OCVcathode, | ||
double | fp[], | ||
double | fn[] | ||
) |
< *********************************************************** 1 variables ***********************************************************************
< It can only throw due to IntLin therefore, its error code it 1.
auto slide::discharge_noexcept | ( | const slide::XYdata_vv & | OCVp, |
const slide::XYdata_vv & | OCVn, | ||
double | cap, | ||
const double | AMp, | ||
const double | AMn, | ||
const double | cmaxp, | ||
const double | cmaxn, | ||
double | sp, | ||
double | sn, | ||
double | Vend, | ||
slide::XYdata_vv & | OCV, | ||
double | fp[], | ||
double | fn[] | ||
) |
< *********************************************************** 1 variables ***********************************************************************
< Variables
< number of electrons involved in the reaction
< discharged charge up to now
< magnitude of the discharge current [A]
< time step to use in the simulation [s]
< check the surface concentration is within the allowed limits when doing linear interpolation.
< boolean to check if we have reached the end voltage
< If we store a data point for every time step, the output arrays will be very long. Therefore, store only one value every 'nstore' time steps
< store one data point every 100 time steps
< Store the lithium fractions at the start (=100% SOC)
< *********************************************************** 2 discharge & measure voltage ***********************************************************************
< OCV = OCV_cathode - OCV_anode, cell voltage in this time step
< discharge charge
< open circuit voltage
< //!< *********************************************************** 3 output parameters ***********************************************************************
< Store the lithium fractions at the end (= 0% SOC)
< Then the lithium fractions at 50% SOC are the average between the fractions at 100% and 0% This is true because SOC is defined based on charge throughput, which is directly (linearly) linked with the lithium concentration
auto slide::discharge_noexcept | ( | const slide::XYdata_vv & | OCVp, |
const slide::XYdata_vv & | OCVn, | ||
double | cap, | ||
const double | AMp, | ||
const double | AMn, | ||
const double | cmaxp, | ||
const double | cmaxn, | ||
double | sp, | ||
double | sn, | ||
double | Vend, | ||
slide::XYdata_vv & | OCV, | ||
slide::XYdata_vv & | OCVanode, | ||
slide::XYdata_vv & | OCVcathode, | ||
double | fp[], | ||
double | fn[] | ||
) |
< *********************************************************** 1 variables ***********************************************************************
< Variables
< number of electrons involved in the reaction
< discharged charge up to now
< magnitude of the discharge current [A]
< time step to use in the simulation [s]
< check the surface concentration is within the allowed limits when doing linear interpolation.
< boolean to check if we have reached the end voltage
< If we store a data point for every time step, the output arrays will be very long. Therefore, store only one value every 'nstore' time steps
< store one data point every 100 time steps
< OCV = OCV_cathode - OCV_anode, cell voltage in this time step
< discharge charge
< open circuit voltage
< anode lithium fraction
< anode potential
< cathode lithium fraction
< cathode potential
< if (sp_n != 1 && sn_n != 1) std::cout << "V = " << V << " ocvpi = " << ocvpi << " ocvni = " << ocvni << " sp = " << sp << " sn = " << sn << '
';
< Store the lithium fractions at the start (=100% SOC)
< *********************************************************** 2 discharge & measure voltage *********************************************************************** std::cout << "===========================\n";
< *********************************************************** 3 output parameters ***********************************************************************
< Store the lithium fractions at the end (= 0% SOC)
< Then the lithium fractions at 50% SOC are the average between the fractions at 100% and 0% This is true because SOC is defined based on charge throughput, which is directly (linearly) linked with the lithium concentration
< Flag is never false.
int slide::distance | ( | const FixedDataIter< T, extrapolation > & | a, |
const FixedDataIter< T, extrapolation > & | b | ||
) |
void slide::estimateCharacterisation | ( | ) |
< *********************************************************** 1 USER INPUT ***********************************************************************
< Specify the characterisation tests for which data is available
< Temperature at which the characterisation should be done [K]
< Name of the files with the voltage curve from the cell
< C rates of the CC phases for each voltage curve, <0 for charge, >0 for discharge
< C rates of the current threshold for the CV phases [A], > 0 a very high value (above the Crate of the CC) will avoid there is a CV phase at all, so there is only a CC phase
< array with the weight that should be attributed to each individual CCCV curve when calculating the overall error no restrictions are imposed, but it is recommended that all weights sum up to 1 if a weight is set to 0, that curve is ignored. If a weight is negative, the error for that curve will be maximised so this is not recommended.
< number of data sets for CCCV (dis)charges
< names of output files
< name of the output csv file in which the optimal parameters will be written
< prefix appended before the name of the output data files with the simulations for the best fit each file will have 3 columns: charge throughput, voltage and temperature
< Specify the OCV parameters (calculated by determineOCV::estimateOCVparameters)
< electrode surface
< volume fraction of active material in the cathode
< volume fraction of active material in the anode
< thickness of the cathode
< thickness of the anode
< lithium fraction in the cathode at 50% soC
< lithium fraction in the anode at 50% SOC
< maximum lithium concentration in the cathode [mol m-3]
< maximum lithium concentration in the anode [mol m-3]
< the capacity of the cell [Ah]
< maximum voltage of the cell [V]
< minimum voltage of the cell [V]
< name of the CSV file with the cathode OCV curve
< name of the CSV file with the anode OCV curve
< number of points in the cathode OCV curve
< number of points in the anode OCV curve
< ****************************************** 2 define the search space for fitting parameters ***********************************************************************
< define the search space for the characterisation parameters at reference temperature
< if true, the steps in the first level are logarithmically, i.e. D = Dmin * Dstep^i if false, the steps are linearly, i.e. D = Dmin + i*Dstep steps in the later search levels are always linearly
< if true, the steps in the first level are logarithmically, i.e. k = kmin * kstep^i if false, the steps are linearly, i.e. k = kmin + i*kstep steps in the later search levels are always linearly
< lowest value/step size/Nsteps in the search space for Dp [m s-1]
< lowest value/step size/Nsteps in the search space for Dn [m s-1]
< lowest value/step size/Nsteps in the search space for kp [m s-1]
< lowest value/step size/Nsteps in the search space for kn [m s-1]
< lowest value/step size/Nsteps in the search space for Rdc [Ohm]
< Read the measured voltage profiles
< the first column has to start at 0, but not end at 1
< loop to read the voltage profile of each cycle
< read the csv file with the voltage profile
< check the data is in the correct format
< boolean indicating if the data is in the correct format
< Call the hierarchical search algorithm, which does the fitting
< number of hierarchical levels to use. Increasing this number will improve the accuracy, but take longer to calculate
< error in the best fit
< parameters giving the lowest error [R Dp Dn kp kn]
< ***************************************************** 4 write outputs ***********************************************************************
< Print the best fit, and write in a CSV file
< write the parameters in a csv file
< Simulate the voltage curves at the best fit
< structure with the matrices for the spatial discretisation for the solid diffusion PDE #TODO possible duplication somewhere of below code.
< time step to be used for the simulation
< length of the arrays to store the simulation results. (for a 0.5 C rate CC phase, *10 for the CV phase and safety margin)
< arrays to store the simulation results #TODO
< loop through all CCCV experiments
< write the simulated voltages in a csv file
< the combined error of all CCCV experiments for this combination of Dp, Dn, kp and kn
< the error for this CCCV cycle
< append the errors in the file with the parameter values
< loop through all CCCV experiments
< Simulate this CCCV experiment
< calculate the error (function defined in determineOCV.cpp)
< Write on which cycles this fit is based
< then note down the settings used to get this fit
< the search space
void slide::estimateOCVparameters | ( | ) |
< *********************************************************** 1 USER INPUT ***********************************************************************
< input parameters
< name of the file with the OCV curve of the cathode
< number of data points on the cathode OCV curve
< name of the file with the OCV curve of the anode
< number of data points on the anode OCV curve
< name of the file with the OCV curve of the cell
< number of data points on the cell OCV curve
< maximum li-concentration in the cathode [mol m-3]
< maximum li-concentration in the anode [mol m-3]
< names of the output files
< name of the output file in which the parameters of the best fit will be written
< name of the output file in which the OCV curve with the best parameters will be written
< Read the OCV curves
< std::cout << "Throw test: " << 81 << '
';
< stop calculating because we can't do anything
< We can play with 4 parameters: AMp the amount of active material on the positive electrode AMn the amount of active material on the negative electrode sp the starting point on the positive electrode OCV curve sn the starting point on the negative electrode OCV curve
< estimate the amount of active material needed to reach the cell capacity:
< number of electrons involved in the reaction
< capacity of the cell [Ah] (the discharge Ah at the last point on the OCV curve)
< the total charge in an electrode in Ah is given by; n * F * cmax * AM / 3600
< //!< Define the search space for the amount of active material on each electrode
< take steps of 5% of the guessed active material
< the maximum amount of active material is 5 times the guessed amount
< the minimum amount of active material is 0, actually should not be zero since it is a divisor.
< Define the search space for the initial lithium fractions at each electrode
< From 0 to 1 lithium fraction 5% increase of the lithium fraction
< Define the search space for the amount of active material on each electrode
< From 0 to 5x of guessed active material with 10% steps.
< ***************************************************** 3 Fit the parameters ***********************************************************************
< Call the hierarchical search algorithm, which does the fitting
< number of levels in the hierarchy to consider.
< parameters of the best fit and lowest error.
< ***************************************************** 4 write outputs ***********************************************************************
< Print the best fit
< write the parameters in a csv file
< Simulate the best-fit OCV curve
< minimum voltage of the OCV curve
< array for the simulated OCV curve and voltage of each electrode
< size hint for the array to store the simulated OCV curve
< reserve some size.
< arrays to store the lithium fractions at 100%, 50% and 0% SOC
< Write this best-fit OCV curve in a csv file so the user can check it using the matlab script readEstimateOCV.m
< From the 4 fitted values, we need to determine the following parameters, needed by the single particle model implemented in Cell elec_surf the geometric surface area of the electrode thickp the thickness of the cathode thickn the thickness of the anode ep the volume fraction of active material on the cathode en the volume fraction of active material on the anode cinip the initial lithium fraction for the cathode cinin the initial lithium fraction for the anode
< Assume the volume fractions are 50% and the electrode surface is 0.0982 m2. Then we can calculate the thickness of the electrodes to give the desired amount of active material, which is given by: AM = elec_surf * thick * e
< Append these parameters in the csv file where we had written the fitted parameters
< then note down the settings used to get this fit
< the search space
auto slide::eye | ( | double | k = 1.0 | ) |
void slide::fitAMnAndStartingPoints | ( | int | hierarchy, |
int | ap, | ||
double | AMp, | ||
slide::FixedData< double > | AMn_space, | ||
slide::FixedData< double > | sp_space, | ||
slide::FixedData< double > | sn_space, | ||
double | cmaxp, | ||
double | cmaxn, | ||
double * | err, | ||
std::array< double, 4 > & | par, | ||
slide::XYdata_vv & | OCVp, | ||
slide::XYdata_vv & | OCVn, | ||
slide::XYdata_vv & | OCVcell | ||
) |
< *********************************************************** 1 variables ***********************************************************************
< variables
< lowest error encountered so far
< *********************************************************** 2 loop through the search space ***********************************************************************
< loop for the search space of AMn
< loop through the search space of sp / avoid that the starting points go out of range (the lithium fraction has to be between 0 and 1)
< loop through the search space of sn / avoid that the starting points go out of range (the lithium fraction has to be between 0 and 1)
< Simulate the OCV curve with these parameters and calculate the error between the simulated and measured OCV curve
< calculates total squared error.
< Store the minimum error & parameters leading to this error
< check if the error of this combination is lower than the best fit so far
< RMSE error.
void slide::fitAMnAndStartingPoints | ( | int | hierarchy, |
int | ap, | ||
slide::FixedData< double > | AMn_space, | ||
slide::FixedData< double > | sp_space, | ||
slide::FixedData< double > | sn_space, | ||
double | cmaxp, | ||
double | cmaxn, | ||
double * | err, | ||
std::array< double, 4 > & | par, | ||
std::array< int, 4 > & | parindex, | ||
slide::XYdata_vv & | OCVp, | ||
slide::XYdata_vv & | OCVn, | ||
slide::XYdata_vv & | OCVcell | ||
) |
void slide::fitDiffusionAndRate | ( | int | hierarchy, |
int | ir, | ||
double | R, | ||
slide::FixedData< double > | Dp_space, | ||
slide::FixedData< double > | Dn_space, | ||
slide::FixedData< double > | kp_space, | ||
slide::FixedData< double > | kn_space, | ||
std::vector< slide::XYdata_vv > & | Vdata_all, | ||
double | weights[], | ||
double | Crates[], | ||
double | Ccuts[], | ||
double | Tref, | ||
const struct OCVparam & | ocvfit, | ||
double * | err, | ||
std::array< double, 5 > & | par | ||
) |
< *********************************************************** 1 variables ***********************************************************************
< Variables auto M = Model_SPM::makeModel(); //!< structure with the matrices for the spatial discretisation for the solid diffusion PDE constexpr double dt = 2; //!< time step to be used for the simulation
< arrays to store the simulation results #TODO -> static thread_local
< lowest error encountered so far
< ************************************************ Create an initial cell. ************************************************
< Set the characterisation parameters of the cell to the ones given as input to this function
< cell_init.setVlimits(ocvfit.Vmax, ocvfit.Vmin); #TODO set Vlimits?
< set the temperature of the cell to the given value
< set the environmental temperature to the given value
< identification std::string for the CyclerOld
< time interval at which cycling data has to be recorded [s]
< CyclerOld cycler(cell_init, ID, verbose, timeCycleData); //!< Make the CyclerOld
< *********************************************************** 2 loop through the search space ***********************************************************************
< scan the search space for Dp
< scan the search space for Dn
< scan the search space for kp
< scan the search space for kn
< Calculate the error for this set of parameters
< initialise the combined error of all CCCV experiments for this combination of Dp, Dn, kp and kn to 0
< loop through all CCCV cycles
< Simulate this CCCV experiment
< calculate the error of this CCCV cycle with the given parameters
< calculate the total (weighted) error
< if flag is false, an error occured while simulating. This means the parameters were infeasible. High cost.
< Store the minimum error
< check if the error of this combination is better than the best fit so far
< return the lowest error
|
inline |
std::string slide::getFileContents | ( | const Tpath & | name | ) |
< For more info see: https://insanecoding.blogspot.com/2011/11/how-to-read-in-file-in-c.html
< check if we could open the file
|
inline |
void slide::hierarchicalCharacterisationFit | ( | int | hmax, |
slide::FixedData< double > | r_space, | ||
slide::FixedData< double > | Dp_space, | ||
slide::FixedData< double > | Dn_space, | ||
slide::FixedData< double > | kp_space, | ||
slide::FixedData< double > | kn_space, | ||
std::vector< slide::XYdata_vv > & | Vdata_all, | ||
double | weights[], | ||
double | Crates[], | ||
double | Ccuts[], | ||
double | Tref, | ||
const struct OCVparam & | ocvfit, | ||
double * | err, | ||
std::array< double, 5 > & | par | ||
) |
< variables
< array of parameters [R Dp Dn kp kn] giving the lowest error for that resistance
< Loop for each level in the search
< print the search space of this level
< Calculate the best fit in this level
< Print the best fit, and write in a CSV file
< Update the search space suppose the optimal value for a parameter p was in the search space at index i then the new search space has as minimum value the value of p at i-1 and as maximum the value of p at i+1
< only the first search level is logarithmic, afterwards the search has linear steps
< Make the output parameters
auto slide::hierarchicalOCVfit | ( | int | hmax, |
slide::FixedData< double > | AMp_space, | ||
slide::FixedData< double > | AMn_space, | ||
slide::FixedData< double > | sp_space, | ||
slide::FixedData< double > | sn_space, | ||
std::string | namepos, | ||
std::string | nameneg, | ||
std::string | namecell, | ||
double | cmaxp, | ||
double | cmaxn | ||
) |
< parameters [AMp AMn sp sn] giving the lowest error for that amount of cathode active material
< Optimal parameters.
< lowest error.
< Temp vectors
< Loop for each level in the search
< print the search space of this level
< amount of cathode active material for each
< Loop through the search space of AMp
< Make the output parameters
< Print the best fit, and write in a CSV file
< Calculate the best fit in this level Update the search space
< the best fit parameters in this level of the hierarchy
< min to limit it to 1<.
< max to limit it to >0
< Return parameters and error.
|
inline |
< Ignore byte order mark (BOM) at the beginning
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
Not successful but voltage is in limits.
|
inline |
|
inlineconstexpr |
double slide::linInt | ( | bool | verbose, |
bool | bound, | ||
Tx & | xdat, | ||
Ty & | ydat, | ||
int | nin, | ||
double | x, | ||
bool | is_fixed = false |
||
) |
auto slide::linInt_noexcept | ( | bool | bound, |
Tx & | xdat, | ||
Ty & | ydat, | ||
int | nin, | ||
double | x, | ||
bool | is_fixed = false |
||
) |
< Some programs depend on 0.0 initial condition when status != 0, do not change.
< Set the status as inverse of bound. So that first two branches of if are invalid if bound is true.
< check that x is within the limits of the data points
< if x is below the minimum value, return the y value of the first data point
< if x is above the maximum value, return the y value of the last data point
< scan the data points
< For fixed step no need to iterate:
< binary search algorithm: i_low will be the first index which compares greater than x; const auto it = std::find_if(std::begin(xdat), std::begin(xdat) + nin, [x](double element) { return (x < element); }); -> Linear search if needed.
< then that point is the point 'to the right' of x
< while the previous point is the point 'to the left' of x
|
constexpr |
|
inline |
|
inline |
< FixedData<int> range(int stop); #TODO -> FixedData is not good since it has function FixedData<int> range(int start, int stop, int step = 1);
std::vector< double > slide::linstep | ( | double | x_min, |
double | x_step, | ||
int | Nstep | ||
) |
|
inline |
auto slide::LL | ( | const ThetaType & | theta_cand, |
PriorType & | prior, | ||
const CostType & | costFun, | ||
const size_t | Nobservations, | ||
const SettingsType & | mcmcSettings | ||
) |
< std::pair(P, flag);
< std::pair(LLout, true);
void slide::loadCSV_1col | ( | const Tpath & | name, |
std::array< T, ROW > & | x | ||
) |
< read data from a CSV file with one column
void slide::loadCSV_2col | ( | const Tpath & | name, |
std::span< double > & | x, | ||
std::span< double > & | y, | ||
int | n = 0 |
||
) |
< #TODO -> for some reason it does not take XYdataMap[name] directly.
void slide::loadCSV_2col | ( | const Tpath & | name, |
Tx & | x, | ||
Ty & | y, | ||
int | n = 0 |
||
) |
< check if we could open the file
< Sometimes pre-allocated vectors are passed; therefore, cleared to be able to use push_back.
< Read file.
< It must be a std::array, then just read without clear.
< Read file.
void slide::loadCSV_2col | ( | Tpath && | name, |
slide::XYdata_vv & | data, | ||
int | n = 0 |
||
) |
< slide::XYdata_vv overload.
void slide::loadCSV_mat | ( | const Tpath & | name, |
Matrix< T, ROW, COL > & | x | ||
) |
< * Reads a matrix CSV file with multiple columns.
< check if we could open the file
< Ignore byte order mark (BOM) at the beginning
< read all but the last column
< Read number and comma
< Read only number since there is no comma.
void slide::loadCSV_Ncol | ( | const Tpath & | name, |
DynamicMatrix< Tx > & | x, | ||
int | n = 0 |
||
) |
< check if we could open the file
< Sometimes pre-allocated vectors are passed; therefore, cleared to be able to use push_back.
< Read file.
std::vector< double > slide::logstep | ( | double | x_min, |
double | x_step, | ||
int | Nstep | ||
) |
|
inline |
Deep_ptr< T > slide::make | ( | Args &&... | args | ) |
Makes storage units.
T | |
...Args |
...args |
Deep_ptr< T > slide::make_Deep_ptr | ( | Args &&... | args | ) |
auto slide::make_SU | ( | Args &&... | args | ) |
Deep_ptr< StorageUnit > slide::makeBattery | ( | bool | balance, |
bool | capSpread, | ||
bool | RcellSpread, | ||
bool | degrateSpread, | ||
bool | contactR, | ||
int | coolControl | ||
) |
< String prefix for the names of the results to indicate the settings of the simulation
< Cell-to-cell variations, numbers based on paper from Trish, Jorge (results of screening over 200 prestine lithium-ion cells
< normal distribution with mean 1 and std 0.4%
< normal distribution with mean 1 and std 2.5%
< normal distribution with mean 1 and std 10%
< factors with the relative change in resistance and capacity of the cells
< contact resistances
< contact R for parallel connection
< contact R for series connection
< use a 1mOhm resistance. Value from paper Taheri et al, 2011, Investigating electrical contact resistance losses in lithium-ion battery assemblies for hybrid and electric vehicles j Power sources, 2011 pouch cell of 5*the capacity -> 5* larger currents -> divide R by 5 or the resistive Vdrop becomes huge this can be a large resistance since they are in parallel, so Rtot reduces with each branch
< this must be a much smaller resistance 15s20s means we have 15*20 contactR in series. so if Rc_s = 0.01, then the total R is 3 ohm so the resistive voltage drop means cells immediately go outside their voltage limit todo: unrealistically large values, see EPFL battery Paper schimpe has values of 0.1 mOhm = 10^-4 Rumpf has 9 * 10^-4
< Kinetic SEI + porosity + Dai LAM
< Make the battery
< number of cells in modules
< number of modules in strings
< number of strings in battery
< array with strings in one battery
< array with modules in one string
< array with cells in one module
< arrays with the contact resistances for the different levels (3 = lowest level)
< loop for strings in battery
< loop for modules in string
< loop for cells in modules
< in series module, so every cell has a resistance of Rc
< print warning messages, single-threaded
< in series module, so every cell has a resistance of Rc
< in parallel module, every horizontal branch has the same value of Rc
< multithreaded parallel module
< make the battery
< 20 * 15 cells in series -> 20*15*3.68V = 1,104V 9 strings in parallel -> 9*Ah = 115.699Ah
Deep_ptr< StorageUnit > slide::makeBattery2 | ( | bool | balance, |
bool | capSpread, | ||
bool | RcellSpread, | ||
bool | degrateSpread, | ||
bool | contactR, | ||
int | coolControl | ||
) |
< String prefix for the names of the results to indicate the settings_str of the simulation
< Cell-to-cell variations
< unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
< normal distribution with mean 1 and std 0.4%
< normal distribution with mean 1 and std 2.5%
< normal distribution with mean 1 and std 10% factors with the relative change in resistance and capacity of the cells
< contact resistances
< contact R for parallel connection
< contact R for series connection
< use a 1mOhm resistance. Value from paper Taheri et al, 2011, Investigating electrical contact resistance losses in lithium-ion battery assemblies for hybrid and electric vehicles j Power sources, 2011 pouch cell of 5*the capacity -> 5* larger currents -> divide R by 5 or the resistive Vdrop becomes huge
< this must be a much smaller resistance 15s20s means we have 15*20 contactR in series. so if Rc_s = 0.01, then the total R is 3 ohm so the resistive voltage drop means cells immediately go outside their voltage limit todo: unrealistically large values see make EFFL battery
< Kinetic SEI + porosity + Dai/Laresgoiti LAM
< Make the battery
< number of cells in (parallel) modules
< number of modules in (s) strings
< number of strings in (s) battery
< array with strings in one battery
< array with modules in one string
< array with cells in one module
< arrays with the contact resistances for the different levels (3 = lowest level)
< loop for strings in battery
< loop for modules in string
< loop for cells in modules
< in parallel module, all branches have same R
< print warning messages, single-threaded
< in series module, so every cell has a resistance of Rc
< single-threaded
< in parallel module, every horizontal branch has the same value of Rc
< multithreaded series module
< make the battery
< 20 * 15 cells in series -> 20*15*3.68V = 1,104V 9 strings in parallel -> 9*3Ah = 27Ah
Deep_ptr< StorageUnit > slide::makeBattery_EPFL | ( | bool | capSpread, |
bool | RcellSpread, | ||
bool | degrateSpread, | ||
bool | contactR, | ||
int | coolControl, | ||
std::string | IDadditions, | ||
double | RM | ||
) |
< String prefix for the names of the results to indicate the settings of the simulation
< Cell-to-cell variations
< unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
< normal distribution with mean 1 and std 0.4%
< normal distribution with mean 1 and std 2.5%
< normal distribution with mean 1 and std 10% factors with the relative change in resistance and capacity of the cells
< contact resistances
< contact R for parallel connection or cells
< contact R for series connections of cells
< contact R for parallel connection of racks
< contact R for series connection of modules
< use a 0.1 mOhm resistance. Value from paper Schimpe
< use a 0.1 mOhm resistance. Value from paper Schimpe
< this must be a much smaller resistance
< this must be a much smaller resistance
< Kinetic SEI + porosity + Dai/Laresgoiti LAM
< Make the battery
< number of cells in parallel in a module [lowest level]
< number of cells in series in a module
< number of modules in (s) racks
< number of strings in (p) battery
< array with racks in one battery
< array with modules in one rack
< array with cells in series in one module
< array with cells in parallel in one module
< arrays with the contact resistances for the different levels (3 = lowest level)
< loop for strings in battery
< loop for modules in string
< loop for cells in series in modules
< loop for cells in parallel in modules
< in parallel module, all branches have same R
< put the cells in parallel to the lowest-level module
< print warning messages, single-threaded, pass through coolsystem
< in series module, so every cell has a resistance of Rc
< assemble the cells in series for the
< single-threaded, conventional coolsystem
< assemble the modules in series for a rack
< single-threaded, pass through coolsystem
< Assemble the racks in the battery compartment (bc)
< multithreaded parallel module, pass through coolsystem
< make the battery
< battery, gets HVAC coolsystem
< 20 * 15 cells in series -> 20*15*3.68V = 1,104V 9 strings in parallel -> 9*3Ah = 27Ah
Deep_ptr< StorageUnit > slide::makeBattery_EPFL_smaller | ( | bool | capSpread, |
bool | RcellSpread, | ||
bool | degrateSpread, | ||
bool | contactR, | ||
int | coolControl, | ||
std::string | IDadditions, | ||
double | RM | ||
) |
< String prefix for the names of the results to indicate the settings of the simulation
< Cell-to-cell variations
< unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
< normal distribution with mean 1 and std 0.4%
< normal distribution with mean 1 and std 2.5%
< normal distribution with mean 1 and std 10% factors with the relative change in resistance and capacity of the cells
< contact resistances
< contact R for parallel connection or cells
< contact R for series connections of cells
< contact R for parallel connection of racks
< contact R for series connection of modules
< use a 0.1 mOhm resistance. Value from paper Schimpe
< use a 0.1 mOhm resistance. Value from paper Schimpe
< this must be a much smaller resistance
< this must be a much smaller resistance
< Kinetic SEI + porosity + Dai/Laresgoiti LAM
< Make the battery
< number of cells in parallel in a module [lowest level]
< number of cells in series in a module
< number of modules in (s) racks
< number of strings in (p) battery
< array with racks in one battery
< array with modules in one rack
< array with cells in series in one module
< array with cells in parallel in one module
< arrays with the contact resistances for the different levels (3 = lowest level)
< loop for strings in battery
< loop for modules in string
< loop for cells in series in modules
< loop for cells in parallel in modules
< in parallel module, all branches have same R
< put the cells in parallel to the lowest-level module
< print warning messages, single-threaded, pass through coolsystem
< in series module, so every cell has a resistance of Rc
< assemble the cells in series for the
< single-threaded, conventional coolsystem
< assemble the modules in series for a rack
< single-threaded, pass through coolsystem
< Assemble the racks in the battery compartment (bc)
< multithreaded parallel module, pass through coolsystem
< make the battery
< battery, gets HVAC coolsystem
< 20 * 15 cells in series -> 20*15*3.68V = 1,104V 9 strings in parallel -> 9*3Ah = 27Ah
Deep_ptr< StorageUnit > slide::makeBattery_Test | ( | bool | capSpread, |
bool | RcellSpread, | ||
bool | degrateSpread, | ||
bool | contactR, | ||
int | coolControl, | ||
std::string | IDadditions, | ||
double | RM | ||
) |
< String prefix for the names of the results to indicate the settings of the simulation
< Cell-to-cell variations
< unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
< normal distribution with mean 1 and std 0.4%
< normal distribution with mean 1 and std 2.5%
< normal distribution with mean 1 and std 10% factors with the relative change in resistance and capacity of the cells
< contact resistances
< contact R for parallel connection or cells
< contact R for series connections of cells
< contact R for parallel connection of racks
< contact R for series connection of modules
< use a 0.1 mOhm resistance. Value from paper Schimpe
< use a 0.1 mOhm resistance. Value from paper Schimpe
< this must be a much smaller resistance
< this must be a much smaller resistance
< Kinetic SEI + porosity + Dai/Laresgoiti LAM
< Make the battery
< number of cells in parallel in a module [lowest level]
< number of cells in series in a module
< number of modules in (s) racks
< number of strings in (p) battery
< array with racks in one battery
< array with modules in one rack
< array with cells in series in one module
< array with cells in parallel in one module
< arrays with the contact resistances for the different levels (3 = lowest level)
< loop for strings in battery
< loop for modules in string
< loop for cells in series in modules
< loop for cells in parallel in modules
< in parallel module, all branches have same R
< put the cells in parallel to the lowest-level module
< print warning messages, single-threaded, pass through coolsystem
< in series module, so every cell has a resistance of Rc
< assemble the cells in series for the
< single-threaded, conventional coolsystem
< assemble the modules in series for a rack
< single-threaded, pass through coolsystem
< Assemble the racks in the battery compartment (bc)
< multithreaded parallel module, pass through coolsystem
< make the battery
< battery, gets HVAC coolsystem
< 20 * 15 cells in series -> 20*15*3.68V = 1,104V 9 strings in parallel -> 9*3Ah = 27Ah
Deep_ptr< StorageUnit > slide::makeBattery_TestParallel | ( | bool | capSpread, |
bool | RcellSpread, | ||
bool | degrateSpread, | ||
bool | contactR, | ||
int | coolControl, | ||
std::string | IDadditions, | ||
double | RM | ||
) |
< String prefix for the names of the results to indicate the settings of the simulation
< Cell-to-cell variations
< unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
< normal distribution with mean 1 and std 0.4%
< normal distribution with mean 1 and std 2.5%
< normal distribution with mean 1 and std 10% factors with the relative change in resistance and capacity of the cells
< contact resistances
< contact R for parallel connection or cells
< contact R for series connections of cells
< contact R for parallel connection of racks
< contact R for series connection of modules
< use a 0.1 mOhm resistance. Value from paper Schimpe
< use a 0.1 mOhm resistance. Value from paper Schimpe
< this must be a much smaller resistance
< this must be a much smaller resistance
< Kinetic SEI + porosity + Dai/Laresgoiti LAM
< Make the battery
< number of cells in parallel in a module [lowest level]
< number of cells in series in a module
< number of modules in (s) racks
< number of strings in (p) battery
< array with racks in one battery
< array with modules in one rack
< array with cells in series in one module
< array with cells in parallel in one module
< arrays with the contact resistances for the different levels (3 = lowest level)
< loop for cells in parallel in modules
< in parallel module, all branches have same R
< put the cells in parallel to the lowest-level module
< print warning messages, single-threaded, pass through coolsystem
< for (size_t ip = 0; ip < nracks; ip++) { //!< loop for strings in battery for (size_t is = 0; is < nmodules; is++) { //!< loop for modules in string for (size_t ics = 0; ics < ncs; ics++) { //!< loop for cells in series in modules for (size_t icp = 0; icp < ncp; icp++) { //!< loop for cells in parallel in modules if (capSpread) capf = distribution_c(generator); if (RcellSpread) Rf = distribution_r(generator); if (degrateSpread) { degf = distribution_d(generator); degflam = distribution_d(generator); } CinpM[icp] = make<Cell_SPM>("cell" + std::to_string(icp), deg, capf, Rf, degf, degflam); Rc4[icp] = Rc_p_cells; //!< in parallel module, all branches have same R } //!< loop to make cells connected in parallel in modules
< //!< put the cells in parallel to the lowest-level module auto mip = make<Module_p>("p" + std::to_string(ics), T_ENV, true, false, ncp, coolControl, 2); //!< print warning messages, single-threaded, pass through coolsystem
< mip->setSUs(CinpM, checkCells, true); mip->setRcontact(Rc4); CinsM[ics] = std::move(mip); Rc3[ics] = Rc_s_cells; //!< in series module, so every cell has a resistance of Rc } //!< loop to make the parallel-connected cells which goes in series to make one module
< //!< assemble the cells in series for the auto modulei = make<Module_s>("s" + std::to_string(is), T_ENV, true, false, ncp * ncs, coolControl, 0); //!< single-threaded, conventional coolsystem modulei->setSUs(CinsM, checkCells, true); modulei->setRcontact(Rc3); MinR[is] = std::move(modulei); Rc2[is] = Rc_s;
< } //!< loop to make the modules for one rack
< //!< assemble the modules in series for a rack auto racki = make<Module_s>("s" + std::to_string(ip), T_ENV, true, false, ncp * ncs * nmodules, coolControl, 2); //!< single-threaded, pass through coolsystem racki->setSUs(MinR, checkCells, true); racki->setRcontact(Rc2); RinB[ip] = std::move(racki); Rc1[ip] = Rc_p;
< } //!< loop to make the racks
< //!< Assemble the racks in the battery compartment (bc) auto bc = make<Module_p>("p", T_ENV, true, true, ncp * ncs * nmodules * nracks, coolControl, 2); //!< multithreaded parallel module, pass through coolsystem bc->setSUs(RinB, checkCells, true); bc->setRcontact(Rc1);
< make the battery
< battery, gets HVAC coolsystem
< 20 * 15 cells in series -> 20*15*3.68V = 1,104V 9 strings in parallel -> 9*3Ah = 27Ah
double slide::norm | ( | const T & | x | ) |
< Takes vector or array:
double slide::norm_sq | ( | const T & | x | ) |
< Takes vector or array:
< Infinite norm
< 0 norm
< This should not happen.
auto slide::ones | ( | double | k = 1.0 | ) |
|
inlineconstexpr |
Amperes.
|
inlineconstexpr |
degrees Celsius
|
inlineconstexpr |
degrees Celsius
|
inlineconstexpr |
Kelvins.
|
inlineconstexpr |
Kelvins.
|
inlineconstexpr |
kiloAmperes
|
inlineconstexpr |
kiloVolts
|
inlineconstexpr |
miliAmperes
|
inlineconstexpr |
miliVolts
|
inlineconstexpr |
microAmperes
|
inlineconstexpr |
microVolts
|
inlineconstexpr |
Volts.
auto slide::operator+ | ( | const std::array< T, N > & | a, |
const std::array< T, N > & | b | ||
) |
auto slide::operator+= | ( | std::array< T, N > & | c, |
const std::array< T, N > & | b | ||
) |
auto slide::operator- | ( | const std::array< T, N > & | a, |
const std::array< T, N > & | b | ||
) |
auto slide::operator-= | ( | std::array< T, N > & | c, |
const std::array< T, N > & | b | ||
) |
|
inline |
|
inline |
std::ostream & slide::operator<< | ( | std::ostream & | os, |
const DynamicMatrix< Tdata > & | M | ||
) |
M | #TODO in future this should be const. |
void slide::output_printer | ( | const std::vector< T > & | vec, |
const auto & | save_path | ||
) |
|
inline |
void slide::readOCVinput | ( | const std::string & | namepos, |
const std::string & | nameneg, | ||
const std::string & | namecell, | ||
slide::XYdata_vv & | OCVp, | ||
slide::XYdata_vv & | OCVn, | ||
slide::XYdata_vv & | OCVcell | ||
) |
< std::cout << "Throw test: " << 80 << '
';
< check the cathode OCV curve. The first column must go from 0-1
< check the anode OCV curve. The first column must go from 0-1
< check the cell OCV curve. The first column must start at 0 but can end anywhere
void slide::run | ( | Tfun | task_indv, |
int | i_end, | ||
unsigned int | numMaxParallelWorkers = settings::numMaxParallelWorkers |
||
) |
< indices for the threads
< Multi threaded simul:
auto slide::S_update | ( | slide::Matrix< double, N, N > & | S, |
std::array< double, N > | w, | ||
double | alpha, | ||
double | n | ||
) |
< a parameter determining the speed of adaptation of the proposal density covariance matrix.
< S_new;
|
inlineconstexpr |
auto slide::transform_max | ( | const auto & | SUs, |
auto & | function | ||
) |
auto slide::transform_mean | ( | const auto & | SUs, |
auto & | function | ||
) |
auto slide::transform_min | ( | const auto & | SUs, |
auto & | function | ||
) |
auto slide::transform_sum | ( | const auto & | SUs, |
auto & | function | ||
) |
bool slide::validOCV | ( | bool | checkRange, |
slide::XYdata_vv & | data | ||
) |
< Check if the range of the first column is valid
< boolean to indicate of the first column has the correct range
< check the first column has the correct range, from 0 to 1
< allow a small error of e-5
< check the first column has the correct starting point, 0
< boolean to indicate if this row has a decreasing value in the 1st column
< boolean to indicate if there are decreasing values in the 1st column
< boolean to indicate if there is an unrealistic value in the 2nd column
< check for increasing values
< print an error message
< we have found a decreasing value
< print an error message
< we have found an unrealistic value
< the range must be correct and we cannot have any decreasing or unrealistic values
|
inline |
< visits storage units and applies function fn function should be void as of now.
< if SU is a battery, recursively call this function on the module with the cells
< If su is a module, recursively call this function on its children
void slide::writeCharacterisationParam | ( | int | h, |
const std::array< double, 5 > & | par, | ||
double | err | ||
) |
< Print the best fit, and write in a CSV file
< write the parameters and the magnitude of the error
|
inline |
void slide::writeDataImpl | ( | std::ofstream & | file, |
auto & | cell, | ||
auto & | dataStorage | ||
) |
< else write nothing.
void slide::writeOCVParam | ( | int | h, |
const std::array< double, 4 > & | par | ||
) |
< Print the best fit, and write in a CSV file
< write the parameters
|
inline |
auto slide::zeros | ( | ) |
|
inlineconstexpr |
|
constexpr |