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