LCOV - code coverage report
Current view: top level - src/utility - free_functions.hpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 57 75 76.0 %
Date: 2023-04-08 04:19:02 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /*
       2             :  * free_functions.cpp
       3             :  *
       4             :  * Free functions to help to write everything shorter.
       5             :  *
       6             :  *  Created on: 05 Apr 2022
       7             :  *   Author(s): Jorn Reniers, Volkan Kumtepeli
       8             :  */
       9             : 
      10             : #pragma once
      11             : 
      12             : #include "../settings/settings.hpp"
      13             : #include "../types/Status.hpp"
      14             : 
      15             : #include <fstream>
      16             : #include <string>
      17             : #include <numeric>
      18             : #include <vector>
      19             : #include <fstream>
      20             : #include <iostream>
      21             : 
      22             : namespace slide::free {
      23             : 
      24             : template <typename Tsu>
      25      186051 : inline Status setVoltage_iterative(Tsu *su, double Vset)
      26             : {
      27             :   // New redistributeCurrent without PI control:
      28             :   //!< get cell voltages
      29      186051 :   constexpr int maxIteration = 50;
      30      186051 :   double Ia{ su->I() };
      31             : 
      32      479892 :   for (int iter{ 0 }; iter < maxIteration; iter++) {
      33      479892 :     const auto Va = su->V();
      34      479892 :     if (std::abs(Vset - Va) < 1e-6)
      35      186051 :       return Status::Success;
      36             : 
      37      293841 :     const auto Ib = (Vset > Va) ? Ia - 0.01 * su->Cap() : Ia + 0.01 * su->Cap();
      38      293841 :     su->setCurrent(Ib);
      39      293841 :     const auto Vb = su->V();
      40             : 
      41      293841 :     const double slope = (Ia - Ib) / (Va - Vb);
      42      293841 :     Ia = Ib - (Vb - Vset) * slope; //!< False-Position method.
      43      293841 :     su->setCurrent(Ia);
      44             :   }
      45             : 
      46           0 :   return Status::RedistributeCurrent_failed; // #TODO change to setVoltage failed.
      47             : }
      48             : 
      49          10 : inline void write_data(std::ofstream &file, std::vector<double> &data, size_t N = 1)
      50             : {
      51     5648100 :   for (size_t i{}; i < data.size(); i++) {
      52     5648090 :     if (i % N == 0) {
      53      806870 :       if (i != 0)
      54      806860 :         file << '\n';
      55             :     } else
      56     4841220 :       file << ',';
      57             : 
      58     5648090 :     file << data[i];
      59             :   }
      60             : 
      61          10 :   data.clear(); //!< reset the index to 0 since we can overwrite the stored data
      62          10 : }
      63             : 
      64             : template <typename T>
      65             : size_t get_Ncells(T const &SU)
      66             : {
      67             :   /*  return the number of cells connected to this module
      68             :    *    e.g. if this module has 3 child-modules, each with 2 cells.
      69             :    *    then getNSUs = 3 but getNcells = 6
      70             :    */
      71             :   return SU->getNcells();
      72             : }
      73             : 
      74             : template <typename T>
      75             : auto get_V(T const &SU) { return SU.V(); }
      76             : 
      77             : template <typename T>
      78             : auto get_T(T const &SU) { return SU->T(); }
      79             : 
      80             : 
      81             : template <typename T>
      82             : auto get_Vmin(const T &SU) { return SU->Vmin(); }
      83             : 
      84             : template <typename T>
      85             : auto get_VMIN(const T &SU) { return SU->VMIN(); }
      86             : 
      87             : template <typename T>
      88             : auto get_Vmax(const T &SU) { return SU->Vmax(); }
      89             : 
      90             : template <typename T>
      91             : auto get_VMAX(const T &SU) { return SU->VMAX(); }
      92             : 
      93             : template <typename T>
      94             : auto get_Cap(const T &SU) { return SU->Cap(); }
      95             : 
      96             : template <typename T>
      97             : auto get_OCV(const T &SU) { return SU->getOCV(); }
      98             : 
      99             : template <typename T>
     100             : auto get_I(const T &SU) { return SU->I(); }
     101             : 
     102             : 
     103             : template <bool Print = settings::printBool::printCrit>
     104          35 : auto inline check_SOC(double SOCnew, double SOC_min = 0, double SOC_max = 1)
     105             : {
     106          35 :   if (SOCnew < SOC_min || SOCnew > SOC_max) //!< check that the input argument is valid
     107             :   {
     108             :     if constexpr (Print)
     109           0 :       std::cerr << "ERROR in some Cell, illegal input value of SOC: "
     110           0 :                 << SOCnew << " while the minimum is " << SOC_min
     111           0 :                 << " and maximum is " << SOC_max << ".\n";
     112           0 :     return false;
     113             :   }
     114          35 :   return true;
     115             : }
     116             : 
     117             : template <bool Print = settings::printBool::printCrit>
     118          10 : auto inline check_Cell_states(auto &su, bool checkV)
     119             : {
     120          10 :   if (!su.validStates(Print)) //!< check if valid state
     121             :   {
     122             :     if constexpr (Print)
     123           0 :       std::cerr << "ERROR in " << su.getID() << "::setStates, illegal State.\n"; //!< #TODO here add some type id.
     124             : 
     125           0 :     return Status::Invalid_states;
     126             :   }
     127             : 
     128             :   //!< check the voltage if desired
     129          10 :   if (checkV) {
     130             :     double v;
     131          10 :     return su.checkVoltage(v, Print); //!< get the voltage Does not throw anymore!
     132             :   }
     133             : 
     134           0 :   return Status::Success;
     135             : }
     136             : 
     137             : template <bool Print = true>
     138    11961170 : auto inline check_voltage(double &v, auto &su) //!< Check voltage.
     139             : {
     140             :   /*
     141             :    * -2         V < VMIN                             discharging and outside safety range, cycling should be halted asap to avoid numerical errors
     142             :    * -1 VMIN <= V < Vmin          discharging and outside range of cell, but not yet safety limit
     143             :    * 0  Vmin <= V <= Vmax                 valid range
     144             :    * 1  Vmax < V <= VMAX          charging and ...
     145             :    * 2  VMAX < V                             charging and ...
     146             :    *
     147             :    * note: allow a small margin on Vmin and Vmax for when we are doing a CV phase
     148             :    * then occasionally, V can be slightly above or below Vlimit
     149             :    */
     150             : 
     151    11961170 :   constexpr bool printCrit = (settings::printBool::printCrit) && Print;       //!< print if the (global) verbose-setting is above the threshold
     152    11961170 :   constexpr bool printNonCrit = (settings::printBool::printNonCrit) && Print; //!< print if the (global) verbose-setting is above the threshold
     153             : 
     154             :   try {
     155    11961170 :     v = su.V();
     156           0 :   } catch (int) {
     157           0 :     std::cout << "We could not calculate voltage!!!\n";
     158           0 :     return Status::V_not_calculated;
     159             :   }
     160             : 
     161    11961170 :   if (v <= 0) {
     162             :     if (printCrit)
     163           2 :       std::cout << "Error in Cell::setStates when getting the voltage, which is "
     164           2 :                 << v << " restoring the old states.\n";
     165             : 
     166           2 :     return Status::V_not_calculated;
     167             :   }
     168             : 
     169             :   //!< lower limits
     170    11961168 :   if (v > (su.Vmin() - settings::MODULE_P_V_ABSTOL) && v < (su.Vmax() + settings::MODULE_P_V_ABSTOL)) {
     171    11920672 :     return Status::Success;                       //!< Just to put this here, probably first if will be executed most of the time.
     172       40496 :   } else if (v < su.VMIN() && su.isDischarging()) // #Check we dont actually look at the is discharging
     173             :   {
     174             :     if (printCrit)
     175           0 :       std::cout << "The voltage of cell " << su.getFullID() << " is " << v
     176           0 :                 << "V which is below its safety limit of "
     177           0 :                 << su.VMIN() << ", cell temperature = " << K_to_Celsius(su.T())
     178           0 :                 << " centigrade and I = " << su.I() << '\n';
     179             : 
     180           0 :     return Status::VMIN_violation;
     181       40496 :   } else if (v > su.VMAX() && su.isCharging()) //!< upper limits
     182             :   {
     183             :     if (printCrit)
     184         244 :       std::cout << "The voltage of cell " << su.getFullID() << " is " << v
     185         122 :                 << "V which is above its safety limit of "
     186         122 :                 << su.VMAX() << ", cell temperature = " << K_to_Celsius(su.T())
     187         122 :                 << " centigrade and I = " << su.I() << '\n';
     188             : 
     189         122 :     return Status::VMAX_violation;
     190       40374 :   } else if (v < (su.Vmin() - settings::MODULE_P_V_ABSTOL) && su.isDischarging()) {
     191             :     if (printNonCrit)
     192             :       std::cout << "The voltage of cell " << su.getFullID() << " is " << v
     193             :                 << "V which is below its minimum voltage of "
     194             :                 << su.Vmin() << ", cell temperature = " << K_to_Celsius(su.T())
     195             :                 << " centigrade and I = " << su.I() << '\n';
     196             : 
     197        7205 :     return Status::Vmin_violation;
     198       33169 :   } else if (v > (su.Vmax() + settings::MODULE_P_V_ABSTOL) && su.isCharging()) //!< #TODO
     199             :   {
     200             :     if (printNonCrit)
     201             :       std::cout << "The voltage of cell " << su.getFullID() << " is " << v
     202             :                 << "V which is above its maximum voltage of "
     203             :                 << su.Vmax() << ", cell temperature = " << K_to_Celsius(su.T())
     204             :                 << " centigrade and I = " << su.I() << '\n';
     205             : 
     206         912 :     return Status::Vmax_violation;
     207             :   }
     208             : 
     209       32257 :   return Status::Success; //!< #TODO should we also send Vmin/Vmax violations even we are not charging/discharging?
     210             : }
     211             : 
     212             : template <bool Print = settings::printBool::printCrit>
     213             : auto inline check_safety(double vi, auto &cyc)
     214             : {
     215             :   const auto SafetyVmin = cyc.getSafetyVmin(); //!< #TODO this requires some calculations!
     216             :   const auto SafetyVmax = cyc.getSafetyVmax();
     217             : 
     218             :   if (vi < SafetyVmin) //!< #TODO this requires some calculations!
     219             :   {
     220             :     if constexpr (Print)
     221             :       std::cout << "Error in Cycler::??, the voltage of " << vi
     222             :                 << " V is smaller than the minimum safety voltage of the cycler of "
     223             :                 << SafetyVmin << " V." << '\n';
     224             : 
     225             :     return Status::VMINsafety_violation;
     226             :   } else if (vi > SafetyVmax) //!< #TODO this requires some calculations!
     227             :   {
     228             :     if constexpr (Print)
     229             :       std::cout << "Error in Cycler::??, the voltage of " << vi
     230             :                 << " V is larger than the maximum safety voltage of the cycler of "
     231             :                 << SafetyVmax << " V." << '\n';
     232             :     return Status::VMAXsafety_violation;
     233             :   }
     234             : 
     235             :   return Status::SafeVoltage;
     236             : }
     237             : 
     238             : template <bool Print = true>
     239             : auto inline check_current(bool checkV, auto &su) //!< Check voltage.
     240             : {
     241             : 
     242             :   //!< TBC
     243             : }
     244             : 
     245          10 : inline std::ofstream openFile(auto &SU, const auto &folder, const std::string &prefix, const std::string &suffix)
     246             : {
     247          20 :   const auto name = PathVar::results / (prefix + "_" + SU.getFullID() + "_" + suffix);
     248             : 
     249             :   //  std::string name = getName(cell, prefix); //!< name of the file
     250          10 :   std::ofstream file(name, std::ios_base::app); // #TODO app-> initially open then append.
     251             : 
     252          10 :   if (!file.is_open()) {
     253             :     std::cerr << "ERROR in Cell::writeData, could not open file "
     254           0 :               << name << '\n';
     255           0 :     throw 11;
     256             :   }
     257             : 
     258          20 :   return file;
     259          10 : }
     260             : 
     261             : } // namespace slide::free

Generated by: LCOV version 1.14