Line data Source code
1 : /* 2 : * Module.hpp 3 : * 4 : * Created on: 29 Nov 2019 5 : * Author(s): Jorn Reniers, Volkan Kumtepeli 6 : */ 7 : 8 : #pragma once 9 : 10 : #include "../StorageUnit.hpp" 11 : #include "../cooling/cooling.hpp" 12 : #include "../types/State.hpp" 13 : #include "../settings/settings.hpp" 14 : #include "../utility/utility.hpp" 15 : 16 : 17 : #include <vector> 18 : #include <cstdlib> 19 : #include <memory> 20 : #include <iostream> 21 : #include <span> 22 : 23 : 24 : namespace slide { 25 : struct ModuleThermalParam 26 : { 27 : double k_cell2cell{ 5 }; //!< conductive heat transfer coefficient for heat transfer betweenthe child SUs 28 : double A{ 0.0042 * 10 * settings::MODULE_NSUs_MAX }; //!< thermally active surface area of this module. The first number is the thermal active surface area of a cell 29 : double Qcontact{ 0 }; //!< heat energy generated in the contact resistances since the last time the thermal model was solved 30 : double time{ 0 }; //!< time since the last update of the thermal model [s] 31 : }; 32 : 33 : class Module : public StorageUnit 34 : { 35 : 36 : public: 37 : //!< connected child SUs 38 : using SU_t = Deep_ptr<StorageUnit>; // #TODO in future it should store directly storage unit itself. 39 : using SUs_t = std::vector<SU_t>; 40 : using SUs_span_t = std::span<SU_t>; 41 : using CoolSystem_t = Deep_ptr<CoolSystem>; 42 : 43 : protected: 44 : SUs_t SUs; 45 : std::vector<double> Rcontact; //!< array with the contact resistance for cell i 46 : 47 : //!< thermal model 48 : CoolSystem_t cool{ nullptr }; //!< cooling system of this module //!< make<CoolSystem>(settings::MODULE_NSUs_MAX, 1); 49 : ModuleThermalParam therm; 50 : 51 : //!< voltage 52 : size_t Ncells; //!< Number of cells this module contains. 53 : double Vmodule{ 0 }; //!< voltage of the module 54 : bool Vmodule_valid{ false }; //!< boolean indicating if stored the voltage of the module is valid 55 : bool par{ true }; //!< if true, some functions will be calculated parallel using multithreaded computing 56 : //!< data storage 57 : 58 : State<0, settings::data::N_CumulativeModule> st_module; 59 : std::vector<double> data; //!< Time data 60 : 61 : 62 : size_t calculateNcells() override 63 : { 64 : /* return the number of cells connected to this module 65 : * e.g. if this module has 3 child-modules, each with 2 cells. 66 : * then getNSUs = 3 but getNcells = 6 67 : */ 68 : //!< #TODO this function needs to call parent to update their number of cells if they are module. 69 : return Ncells = transform_sum(SUs, free::get_Ncells<SU_t>); 70 : } 71 : 72 : double thermalModel_cell(); 73 : double thermalModel_coupled(int Nneighbours, double Tneighbours[], double Kneighbours[], double Aneighb[], double tim); 74 : 75 : public: 76 : Module() : StorageUnit("Module") {} 77 2 : Module(std::string_view ID_) : StorageUnit(ID_) {} 78 : Module(std::string_view ID_, double Ti, bool print, bool pari, int Ncells, int coolControl, int cooltype); 79 : Module(std::string_view ID_, double Ti, bool print, bool pari, int Ncells, CoolSystem_t &&coolControlPtr, int cooltype); 80 : 81 : //!< common implementation for all base-modules 82 25486909 : size_t getNSUs() { return SUs.size(); } //!< note that these child-SUs can be modules themselves (or they can be cells) 83 18 : SUs_t &getSUs() { return SUs; } 84 : 85 : const auto &operator[](size_t i) const { return SUs[i]; } 86 : auto &operator[](size_t i) { return SUs[i]; } 87 : 88 : virtual Status checkVoltage(double &v, bool print) noexcept override; //!< get the voltage and check if it is valid 89 : double getVhigh() override; //!< return the voltage of the cell with the highest voltage 90 : double getVlow() override; //!< return the voltage of the cell with the lowest voltage 91 : void getStates(getStates_t &s) override; //!< returns one long array with the states: getStates-array of each cell followed by the states of the module (Tmod) 92 : // [s0 s1 s2 ... sn T], where s1 = cells[0].getStates() 93 : 94 : // int Vstatus 95 : 96 : virtual bool validStates(bool print = true) override; //!< check if a state-array is valid for this module (uses setStates) 97 : virtual Status setStates(setStates_t s, bool checkV = true, bool print = true) override; 98 : //!< Set the states of this module to the given one 99 : //!< note: setStates is the master function to check if states and cells are valid 100 : //!< if checkV=true, then also the cell and module voltages are checked 101 : //!< the other functions just call setStates to check validity 102 : 103 : //!< thermal model 104 : double T() override { return cool->T(); } //!< get the temperature of this module 105 : 106 : double getThermalSurface() override { return therm.A; }; 107 : double getCoolingLoad(); //!< return the energy required to run the entire coolingsystem of this module and all its children 108 : double thermalModel(int Nneighbours, double Tneighbours[], double Kneighbours[], double Aneighb[], double tim) override; 109 : 110 : virtual void setSUs(SUs_span_t c, bool checkCells = true, bool print = true); 111 : //!< Sets the cells of this module. Checks module-constraints 112 : //!< does not check if the states of cells are valid, nor the voltages of the cells and module 113 : //!< it only checks whether the cells are ok for this module (same current if series, same voltage if parallel) 114 : //!< note on virtual functions, see StorageUnit.hpp 115 : 116 1408305 : CoolSystem *getCoolSystem() { return cool.get(); } 117 : 118 11 : void setRcontact(std::span<double> Rc) //!< #TODO if ok. 119 : { 120 : /* 121 : * Set the contact resistance of each cell. 122 : * In parallel modules, this is the 'horizontal' resistance through which all currents of the cells 'behind it' goes. 123 : */ 124 11 : assert(Rc.size() == getNSUs()); 125 11 : Rcontact.resize(Rc.size()); 126 11 : std::copy(Rc.begin(), Rc.end(), Rcontact.begin()); 127 11 : Vmodule_valid = false; //!< we are changing the resistance, so the stored voltage is no longer valid 128 11 : } 129 : 130 : virtual Module *copy() override = 0; 131 : 132 : void storeData() override 133 : { 134 : for (const auto &SU : SUs) //!< Tell all connected cells to store their data 135 : SU->storeData(); 136 : 137 : //!< Store data for the coolsystem 138 : cool->storeData(getNcells()); 139 : 140 : if constexpr (settings::DATASTORE_MODULE >= settings::moduleDataStorageLevel::storeTimeData) //!< Store data of this module 141 : data.insert(data.end(), { st_module.Ah(), st_module.Wh(), st_module.time(), I(), V(), T() }); 142 : } 143 : 144 : void writeData(const std::string &prefix) override 145 : { 146 : for (const auto &SU : SUs) //!< Tell all connected cells to write their data 147 : SU->writeData(prefix); 148 : 149 : 150 : if constexpr (settings::DATASTORE_MODULE >= settings::moduleDataStorageLevel::storeTimeData) //!< Write data for this module 151 : { 152 : std::string name = prefix + "_" + getFullID() + "_ModuleData.csv"; //!< name of the file, start with the full hierarchy-ID to identify this cell 153 : 154 : //!< append the new data to the existing file 155 : std::ofstream file(name, std::ios_base::app); // #TODO if first time open + header, if not append. 156 : 157 : if (!file.is_open()) { 158 : std::cerr << "ERROR in Module::writeData, could not open file " << name << '\n'; 159 : throw 11; 160 : } 161 : 162 : free::write_data(file, data, 6); 163 : 164 : file.close(); 165 : } 166 : 167 : //!< Write data for the cooling system 168 : #if 0 //!< (DATASTORE_COOL > 0) 169 : cool->writeData(prefix + '_' + getFullID()); //!< append the ID to the prefix since the cooling system does not have the ID of this module 170 : #endif 171 : } 172 : 173 0 : void setBlockDegAndTherm(bool block) 174 : { 175 0 : for (auto &SU : SUs) 176 0 : SU->setBlockDegAndTherm(block); 177 : 178 0 : blockDegAndTherm = block; 179 0 : } 180 : 181 : /***************************************************************** 182 : * Set the temperature of the coolant in this module. 183 : * Note that it does NOT immediately change the temperatures of the child-SUs. 184 : * That is done by the thermal model over time 185 : *****************************************************************/ 186 : void setT(double Tnew) override { cool->setT(Tnew); } //!< set a module temperature 187 : 188 : /***************************************************************** 189 : * return the number of cells connected to this module 190 : * e.g. if this module has 3 child-modules, each with 2 cells. 191 : * then getNSUs = 3 but getNcells = 6 192 : *****************************************************************/ 193 : size_t getNcells() override { return Ncells; } 194 : 195 : //!< Return the temperature of the hottest element of the module. 196 : //!< Note that this will be the T of a cell, since child-modules will pass on 197 : //!< this function to their cells 198 : double getThotSpot() override //!< get the maximum temperature of the cells or the module 199 : { 200 : double Thot = cool->T(); 201 : for (const auto &SU : SUs) 202 : Thot = std::max(Thot, SU->getThotSpot()); 203 : 204 : return Thot; 205 : } 206 : }; 207 : } // namespace slide