LCOV - code coverage report
Current view: top level - src/cells/Cell_SPM - Cell_SPM.hpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 4 4 100.0 %
Date: 2023-04-08 04:19:02 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Cell_SPM.hpp
       3             :  *
       4             :  * Header file for the parent Class for all Cells.
       5             :  *
       6             :  * It also defines a number of structs:
       7             :  *              DEG_ID          settings about which degradation models should be used for the simulations
       8             :  *              SEIparam        fitting parameters of the various models for SEI growth
       9             :  *              CSparam         fitting parameters of the various models for crach growth on the surface of the electrodes
      10             :  *              LAMparam        fitting parameters of the various models for loss of active material
      11             :  *              PLparam         fitting parameters of the various models for lithium plating
      12             :  *
      13             :  * Copyright (c) 2019, The Chancellor, Masters and Scholars of the University
      14             :  * of Oxford, VITO nv, and the 'Slide' Developers.
      15             :  * See the licence file LICENCE.txt for more information.
      16             :  */
      17             : 
      18             : #pragma once
      19             : 
      20             : #include "State_SPM.hpp" //!< class that represents the state of a cell, the state is the collection of all time-varying conditions of the battery
      21             : #include "Model_SPM.hpp" //!< defines a struct with the values for the matrices used in the spatial discretisation of the diffusion PDE
      22             : #include "param/param_SPM.hpp"
      23             : #include "../Cell.hpp"
      24             : #include "../../utility/utility.hpp"   // Do not remove they are required in cpp files.
      25             : #include "../../settings/settings.hpp" // Do not remove they are required in cpp files.
      26             : #include "../../types/OCVcurves.hpp"
      27             : 
      28             : #include <vector>
      29             : #include <array>
      30             : #include <iostream>
      31             : #include <memory>
      32             : 
      33             : namespace slide {
      34             : 
      35             : //!< State related functions
      36             : void validState(State_SPM &s, State_SPM &s_ini);
      37             : 
      38             : class Cell_SPM : public Cell
      39             : {
      40             : public:
      41             :   DEG_ID deg_id; //!< structure with the identification of which degradation model(s) to use #TODO may be protected.
      42             :   using sigma_type = std::array<double, settings::nch + 2>;
      43             : 
      44             : protected:                 //!< protected such that child classes can access the class variables
      45             :   State_SPM st{}, s_ini{}; //!< the battery current/initial state, grouping all parameter which change over the battery's lifetime (see State_SPM.hpp)
      46             : 
      47             :   //!< Battery model constants
      48             :   double Cmaxpos{ 51385 }; //!< maximum lithium concentration in the cathode [mol m-3]  value for NMC
      49             :   double Cmaxneg{ 30555 }; //!< maximum lithium concentration in the anode [mol m-3] value for C
      50             :   double C_elec{ 1000 };   //!< Li- concentration in electrolyte [mol m-3] standard concentration of 1 molar
      51             : 
      52             :   double n{ 1 }; //!< number of electrons involved in the main reaction [-] #TODO if really constant?
      53             : 
      54             :   //!< parameters of the main li-insertion reaction
      55             :   double kp{ 5e-11 };      //!< rate constant of main reaction at positive electrode at reference temperature
      56             :   double kp_T{ 58000 };    //!< activation energy for the Arrhenius relation of kp
      57             :   double kn{ 1.7640e-11 }; //!< rate constant of main reaction at negative electrode at reference temperature
      58             :   double kn_T{ 20000 };    //!< activation energy for the Arrhenius relation of kn
      59             :   //!< The diffusion constants at reference temperature are part of State because they can change over the battery's lifetime
      60             :   double Dp_T{ 29000 };         //!< activation energy for the Arrhenius relation of Dp
      61             :   double Dn_T{ 35000.0 / 5.0 }; //!< activation energy for the Arrhenius relation of Dn
      62             : 
      63             :   //!< Thermal model parameters
      64             :   double Therm_Qgen{};             //!< total heat generation since the last update [J]
      65             :   double Therm_Qgentot{};          //!< variable for unit testing, total heat generation since the beginning of this cell's life [J]
      66             :   double Therm_time{};             //!< time since the last update of the thermal model
      67             :   double T_env{ settings::T_ENV }; //!< environment temperature [K]
      68             :   double T_ref{ 25.0_degC };       //!< reference temperature [K]
      69             : 
      70             :   //!< Qch: 90 gives very good cooling, as if there is a fan pointed at the cell. values of 30-60 are representative for a cell on a shelf without forced cooling
      71             :   //!< 40 is representative for a cell on a shelf without forced cooling
      72             :   double Qch{ 45 };   //!< convective heat transfer coefficient per volume [W K-1 m-3]
      73             :   double rho{ 1626 }; //!< density of the battery
      74             :   double Cp{ 750 };   //!< thermal capacity of the battery #TODO = units missing.
      75             : 
      76             :   //!< Geometric parameters
      77             :   param::Geometry_SPM geo{};
      78             :   //!< other geometric parameters are part of State because they can change over the battery's lifetime
      79             : 
      80             :   param::StressParam sparam{ param::def::StressParam_Kokam }; //!< Stress parameters.
      81             : 
      82             :   //!< Constants and parameters for the SEI growth model //!< #TODO if we can make these static and speed gain.
      83             :   double rsei{ 2037.4 * 50 }; //!< specific resistance times real surface area of the SEI film [Ohm m] ? #TODO if unit is correct. aging fit.
      84             :   double nsei{ 1 };           //!< number of electrons involved in the SEI reaction [-]
      85             :   double alphasei{ 1 };       //!< charge transfer coefficient of the SEI reaction [-]
      86             :   double OCVsei{ 0.4 };       //!< equilibrium potential of the SEI side reaction [V]
      87             :   double rhosei{ 100e3 };     //!< partial molar volume of the SEI layer [m3 mol-1]
      88             :   double c_elec0{ 4.541e-3 }; //!< bulk concentration of the electrolyte molecule participating in the SEI growth (e.g. EC) [mol m-3]
      89             :   double Vmain{ 13 };         //!< partial molar volume of the main reaction, see Ashwin et al, 2016
      90             :   double Vsei{ 64.39 };       //!< partial molar volume of the SEI side reaction, see Ashwin et al., 2016
      91             : 
      92             :   param::SEIparam sei_p{ param::def::SEIparam_Kokam }; //!< structure with the fitting parameters of the different SEI growth models
      93             : 
      94             :   //!< surface crack parameters & constants
      95             :   param::CSparam csparam{}; //!< structure with the fitting parameters of the different crack growth models
      96             : 
      97             :   //!< LAM parameters & constants
      98             :   double OCVnmc{ 4.1 };                                //!< equilibrium potential of the NMC dissolution side reaction [V]
      99             :   param::LAMparam lam_p{ param::def::LAMparam_Kokam }; //!< structure with the fitting parameters of the different LAM models
     100             : 
     101             :   //!< Li-plating parameters & constants //!< #TODO if we can make these static and speed gain.
     102             :   double npl{ 1 };      //!< number of electrons involved in the plating reaction [-]
     103             :   double alphapl{ 1 };  //!< charge transfer constant for the plating reaction [-]
     104             :   double OCVpl{ 0 };    //!< OCV of the plating reaction [V]
     105             :   double rhopl{ 10e6 }; //!< density of the plated lithium layer
     106             :   param::PLparam pl_p;  //!< structure with the fitting parameters of the different plating models
     107             : 
     108             :   //!< Matrices for spatial discretisation of the solid diffusion model
     109             :   Model_SPM *M{ Model_SPM::makeModel() };
     110             : 
     111             :   //!< OCV curves
     112             :   OCVcurves OCV_curves;
     113             : 
     114             :   bool Vcell_valid{ false };
     115             : 
     116             :   //!< Functions
     117             :   std::pair<double, double> calcSurfaceConcentration(double jp, double jn, double Dpt, double Dnt);
     118             :   std::pair<double, double> calcOverPotential(double cps, double cns, double i_app); //!< Should not throw normally, except divide by zero?
     119             : 
     120             :   inline double calcArrheniusCoeff() { return (1 / T_ref - 1 / st.T()) / PhyConst::Rg; } //!< Calculates Arrhenius coefficient.
     121             : 
     122             :   std::array<double, 2> calcDiffConstant(); //!< Calculate the diffusion constant at the battery temperature using an Arrhenius relation
     123             :   std::array<double, 3> calcMolarFlux();    //!< Calculate molar flux
     124             : 
     125             :   //!< void setStates(State_SPM &&states);                                                                                     //!< set the cell's states to the states in the array
     126             : 
     127             :   //!< degradation models
     128             :   void SEI(double OCVnt, double etan, double *isei, double *den);                                                                             //!< calculate the effect of SEI growth
     129             :   void CS(double OCVnt, double etan, double *isei_multiplyer, double *dCS, double *dDn);                                                      //!< calculate the effect of surface crack growth
     130             :   void LAM(bool critical, double zp_surf, double etap, double *dthickp, double *dthickn, double *dap, double *dan, double *dep, double *den); //!< calculate the effect of LAM
     131             :   double LiPlating(double OCVnt, double etan);
     132             : 
     133             :   //!< state space model
     134             :   void dState_diffusion(bool print, State_SPM &d_state);   //!< just diffusion PDE
     135             :   void dState_thermal(bool print, double &dQgen);          //!< calculate the heat generation
     136             :   void dState_degradation(bool print, State_SPM &d_state); //!< calculate the effect of lithium plating
     137             :   void dState_all(bool print, State_SPM &d_state);         //!< individual functions are combined in one function to gain speed.
     138             : 
     139             :   //!< thermal model
     140             :   double thermalModel_cell();
     141             :   double thermalModel_coupled(int Nneighb, double Tneighb[], double Kneighb[], double Aneighb[], double tim);
     142             : 
     143             :   //!< cell to cell variations // #TODO why do we store variations?
     144             :   double var_cap{ 1 };    //!< relative factor increasing the capacity of the cell
     145             :   double var_R{ 1 };      //!< relative factor increasing the DC resistance
     146             :   double var_degSEI{ 1 }; //!< relative factor to speed up or slow down the rate of SEI growth
     147             :   double var_degLAM{ 1 }; //!< relative factor to speed up or slow down the rate of LAM
     148             : 
     149             : public:
     150             :   //!< Constructor
     151             :   Cell_SPM(OCVcurves OCV_curves_) : OCV_curves(OCV_curves_) {}
     152             :   Cell_SPM(std::string IDi, const DEG_ID &degid, double capf, double resf, double degfsei, double degflam);
     153             : 
     154             :   Cell_SPM(); //!< Default constructor.
     155             : 
     156             :   Cell_SPM(Model_SPM *M_ptr) : M(M_ptr) {}
     157             : 
     158             :   //!< getters
     159           8 :   double T() noexcept override { return st.T(); }   //!< returns the uniform battery temperature in [K]
     160             :   double getTenv() const noexcept { return T_env; } //!< get the environmental temperature [K]
     161             : 
     162             :   Status setCurrent(double Inew, bool checkV = true, bool print = true) override;
     163             :   Status setSOC(double SOCnew, bool checkV = true, bool print = true) override;
     164             : 
     165           2 :   auto &getStateObj() { return st; }
     166             :   auto setStateObj(State_SPM &st_new)
     167             :   {
     168             :     st = st_new;
     169             :     Vcell_valid = false;
     170             :   }
     171             : 
     172             :   std::array<double, 4> getVariations() const noexcept override { return { var_cap, var_R, var_degSEI, var_degLAM }; } // #TODO : deprecated will be deleted.
     173             : 
     174             :   void getTemperatures(double *Tenv, double *Tref) noexcept //!< get the environmental and reference temperature
     175             :   {
     176             :     /*
     177             :      * Function to get the environmental and reference temperatures
     178             :      * OUT
     179             :      * Tenv     environmental temperature [K]
     180             :      * Tref     reference temperature [K] at which cell parameters are measured
     181             :      */
     182             :     *Tenv = T_env;
     183             :     *Tref = T_ref;
     184             :   }
     185             : 
     186             :   //!< thermal model
     187             :   double getThermalSurface() override;
     188             :   double thermalModel(int Nneighb, double Tneighb[], double Kneighb[], double Aneighb[], double tim) override;
     189             :   double thermal_getTotalHeat(); //!< function for unit testing
     190             : 
     191             :   //!< double getR() noexcept //!< get the total cell DC resistance
     192             :   //!< {
     193             :   //!<       /*
     194             :   //!<        * Return the total cell DC resistance [Ohm]
     195             :   //!<        * The total cell resistance is the sum of the resistance of the electrodes and the SEI layer
     196             :   //!<        * the resistance of the electrodes increases due to loss of active material (LAM)
     197             :   //!<        * the resistance of the SEI layer increases as the layer becomes thicker
     198             :   //!<        * it is assumed the plated lithium does not add resistance
     199             :   //!<        */
     200             :   //!<       return (rsei * st.delta() + st.getR(elec_surf));
     201             :   //!< }
     202             : 
     203             :   double getRdc() noexcept; //!< calculate the resistance from every component
     204             :   double getRtot() override { return getRdc(); }
     205             : 
     206             :   double getAnodeSurface() noexcept { return st.an() * st.thickn() * geo.elec_surf; } //!< get the anode pure surface area (without cracks) product of the effective surface area (an) with the electrode volume
     207             : 
     208          44 :   double I() const override { return st.I(); } //!< get the cell current [A]  positive for discharging
     209             :   double V() override;
     210             : 
     211             :   bool getCSurf(double &cps, double &cns, bool print);                                                                           //!< get the surface concentrations
     212             :   void getC(double cp[], double cn[]) noexcept;                                                                                  //!< get the concentrations at all nodes
     213             :   int getVoltage(bool print, double *V, double *OCVp, double *OCVn, double *etap, double *etan, double *Rdrop, double *Temp);    //!< get the cell's voltage
     214             :   int getVoltage_ne(bool print, double *V, double *OCVp, double *OCVn, double *etap, double *etan, double *Rdrop, double *Temp); //!< get the cell's voltage noexcept
     215             : 
     216             :   void getDaiStress(double *sigma_p, double *sigma_n, sigma_type &sigma_r_p, sigma_type &sigma_r_n, sigma_type &sigma_t_p, sigma_type &sigma_t_n, sigma_type &sigma_h_p, sigma_type &sigma_h_n) noexcept; //!< get the stresses at all nodes according to Dai's stress model
     217             :   void updateDaiStress() noexcept;                                                                                                                                                                        //!< updated the stored stress values for Dai's stress model
     218             :   void getLaresgoitiStress(bool print, double *sigma_n);                                                                                                                                                  //!< get the stresses at all nodes according to Laresgoiti's stress model
     219             :   void updateLaresgoitiStress(bool print);                                                                                                                                                                //!< update the stored stress values for Laresgoiti's stress model
     220             : 
     221             :   //!< setters
     222             :   //!< void setVlimits(double VMAX, double VMIN); //!< set the voltage limits of the cell
     223             :   void setT(double T) override; //!< set the cell's temperature
     224             :   void setTenv(double Tenv);    //!< set the environmental temperature
     225             :   //!< void setStates(const State_SPM &si, double I);              //!< set the cell's states to the states in the State object and the cell current to the given value
     226             :   void setC(double cp0, double cn0); //!< set the concentrations to the given (uniform) concentration
     227             :   //!< void setCurrent(bool critical, bool check, double I); //!< set the cell's current to the specified value -> From old slide.
     228             :   void peekVoltage(double I); //!< Peeks voltage for state for given I
     229             : 
     230             :   //!< State related functions
     231             : 
     232             :   //!< void validState()
     233             :   //!< {
     234             :   //!<       slide::validState(st, s_ini);
     235             :   //!< }
     236             :   ThroughputData getThroughputs() override { return { st.time(), st.Ah(), st.Wh() }; }
     237             : 
     238             :   void overwriteCharacterisationStates(double Dpi, double Dni, double ri)
     239             :   {
     240             :     //!< Overwrite both current and initial states.
     241             :     st.overwriteCharacterisationStates(Dpi, Dni, ri);
     242             :     s_ini.overwriteCharacterisationStates(Dpi, Dni, ri);
     243             :   }
     244             : 
     245             :   void overwriteGeometricStates(double thickpi, double thickni, double epi, double eni, double api, double ani)
     246             :   {
     247             :     //!< Overwrite both current and initial states.
     248             :     st.overwriteGeometricStates(thickpi, thickni, epi, eni, api, ani);
     249             :     s_ini.overwriteGeometricStates(thickpi, thickni, epi, eni, api, ani);
     250             :   }
     251             : 
     252             :   //!< time integration
     253             :   //!< void integratorStep(bool print, double dti, bool blockDegradation); //!< step forward in time using specified numerical integrator
     254             : 
     255             :   //!< void ETI_electr(bool print, double I, double dti, bool blockDegradation, bool pos); //!< step forward with only one electrode using forward Euler time integration
     256             : 
     257             :   //!< Base integrators:
     258             : 
     259             :   //!< State_SPM::states_type Int_FWEuler(bool print, double dti, bool blockDegradation); //!< Forward euler integrator.
     260             :   //!< State_SPM::states_type Int_RK4(bool print, double dti, bool blockDegradation);           //!< Runge-Kutta 4 integrator.
     261             : 
     262             :   //!< Calculate the time derivatives of the states at the actual cell current (state-space model)
     263             :   State_SPM::states_type dState(bool print, State_SPM &d_state);
     264             : 
     265             :   //!< Utility
     266             :   void checkModelparam(); //!< check if the inputs to the MATLAB code are the same as the ones here in the C++ code
     267             : 
     268             :   //!< --- slide-pack functions --- //
     269             : 
     270             :   void getStates(getStates_t s) override { s.insert(s.end(), st.begin(), st.end()); } //!< returns the states of the cell collectively.
     271             :   std::span<double> viewStates() override { return std::span<double>(st.begin(), st.end()); }
     272             :   double getOCV() override;
     273             :   Status setStates(setStates_t sSpan, bool checkV, bool print) override;
     274             :   bool validStates(bool print = true) override;
     275           7 :   inline double SOC() override { return st.SOC(); }
     276             :   void timeStep_CC(double dt, int steps = 1) override;
     277             : 
     278             :   Cell_SPM *copy() override { return new Cell_SPM(*this); }
     279             :   //!< Obsolete functions (do not use):
     280             :   void ETI(bool print, double dti, bool blockDegradation); //!< step forward in time using forward Eurler time integration
     281             : 
     282             :   //!< Functions for fitting:
     283             :   void setOCVcurve(const std::string &namepos, const std::string &nameneg);                                         //!< sets the OCV curve of the cell to the given value
     284             :   void setInitialConcentration(double cmaxp, double cmaxn, double lifracp, double lifracn);                         //!< sets the initial concentration
     285             :   void setGeometricParameters(double capnom, double elec_surf, double ep, double en, double thickp, double thickn); //!< sets the geometric parameters related to the amount of active material
     286             :   //!< void setRamping(double Istep, double tstep);                                                                                                                                    //!< sets the ramping parameters
     287             : 
     288             :   void setCharacterisationParam(double Dp, double Dn, double kp, double kn, double Rdc); //!< sets the parameters related to the characterisation of the cell
     289             : };
     290             : } // namespace slide

Generated by: LCOV version 1.14