diff --git a/CHANGELOG b/CHANGELOG index 8ce7d32c626f55b0c9e9a4c5238a437e6fb560f0..3bbfd1270263f97ca62af28a69d3ec2ca46a8dcf 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ +Version 2.24.1 +=========== +- Fix S-functions build for windows +- Fix observer output for individual twoports in the aging S-function + Version 2.24.0 =========== - Expression object can rescale parameters and output value diff --git a/CMakeLists.txt b/CMakeLists.txt index 635f6c0d6755c5781f9accbdadd7c64935124084..78cb9095297c2a1ee3a3a4cb6975798237669b3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/") cmake_policy(SET CMP0009 NEW) set(ISEAFrameVERSION_MAJOR 2) set(ISEAFrameVERSION_MINOR 24) -set(ISEAFramePATCH_LEVEL 0) +set(ISEAFramePATCH_LEVEL 1) set(ISEAFrameNAME "misc") set(ISEAFrameVERSION "${ISEAFrameVERSION_MAJOR}.${ISEAFrameVERSION_MINOR}.${ISEAFramePATCH_LEVEL}" diff --git a/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Electrical/SampleOutput_0_0.mat b/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Electrical/SampleOutput_0_0.mat index f3639c61df847a68f1cbb8518c86afd9bc3292e1..2f309fcf9a0db1c1e1ba1abcc8f92a8181588b60 100644 Binary files a/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Electrical/SampleOutput_0_0.mat and b/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Electrical/SampleOutput_0_0.mat differ diff --git a/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Electrical/SampleOutput_1_0.mat b/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Electrical/SampleOutput_1_0.mat index f2ec3c7c0fb622832b4a1f5e675de2e35d146c3c..64e7528286c3338ba1623dc5573b9d763878fab8 100644 Binary files a/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Electrical/SampleOutput_1_0.mat and b/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Electrical/SampleOutput_1_0.mat differ diff --git a/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Electrical/SampleOutput_2_0.mat b/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Electrical/SampleOutput_2_0.mat index 2e223f1a7433959e30ecb34d99cd7d36a9ea123d..41cae63104371aaad48176806dadd88f6ddee6f1 100644 Binary files a/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Electrical/SampleOutput_2_0.mat and b/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Electrical/SampleOutput_2_0.mat differ diff --git a/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Electrical/SampleOutput_3_0.mat b/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Electrical/SampleOutput_3_0.mat index 1eb9edd8a7420e3e675c4f8a8248285d99fcebf0..dedaf1ba03475fb318439247ffc60eaa5f7d7d3f 100644 Binary files a/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Electrical/SampleOutput_3_0.mat and b/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Electrical/SampleOutput_3_0.mat differ diff --git a/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Electrical/SampleOutput_4_0.mat b/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Electrical/SampleOutput_4_0.mat index 03cf3b09c83255fc1b68df4787bf87639b03d1ad..c59ce060144d54454f4322a0259ed75e4a117779 100644 Binary files a/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Electrical/SampleOutput_4_0.mat and b/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Electrical/SampleOutput_4_0.mat differ diff --git a/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Thermal/Patch_Temperatures_0_0.mat b/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Thermal/Patch_Temperatures_0_0.mat index 1b40637655940db7a90d5428f5d7cc0578ab3118..93eb46cfa84b150c018678ff0075ea5faa7536d1 100644 Binary files a/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Thermal/Patch_Temperatures_0_0.mat and b/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Thermal/Patch_Temperatures_0_0.mat differ diff --git a/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Thermal/Patch_Temperatures_1_0.mat b/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Thermal/Patch_Temperatures_1_0.mat index 12e40f32eb01cc8261cce4a3e073b606e4f74dd6..f06cbcd79a2c64382435975aaa2059986c26befb 100644 Binary files a/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Thermal/Patch_Temperatures_1_0.mat and b/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Thermal/Patch_Temperatures_1_0.mat differ diff --git a/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Thermal/Patch_Temperatures_2_0.mat b/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Thermal/Patch_Temperatures_2_0.mat index 5e907b5b6f257c2a2de33d48e32d351a0c41a03b..20e62caaaa367c23e8c7dd4664b6ad25b5f47ba8 100644 Binary files a/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Thermal/Patch_Temperatures_2_0.mat and b/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Thermal/Patch_Temperatures_2_0.mat differ diff --git a/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Thermal/Patch_Temperatures_3_0.mat b/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Thermal/Patch_Temperatures_3_0.mat index 64c976834236a90b096339545eb07a0eed53d6a4..0d80fb98d08085d8ada31d2cf037693904c916cd 100644 Binary files a/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Thermal/Patch_Temperatures_3_0.mat and b/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Thermal/Patch_Temperatures_3_0.mat differ diff --git a/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Thermal/Patch_Temperatures_4_0.mat b/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Thermal/Patch_Temperatures_4_0.mat index 5801a6879cef9e62ca1baf500ba3b4f4496d2a3a..7b5eea88a5abd67738f5df77934c1ee051ef8134 100644 Binary files a/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Thermal/Patch_Temperatures_4_0.mat and b/scenariotest/standalone_test/i3Cell_aging/reference/MatlabFilter/Thermal/Patch_Temperatures_4_0.mat differ diff --git a/src/aging/aging_simulation.cpp b/src/aging/aging_simulation.cpp index 033fc83977e1a7db49e8af53c89dcb47f77c9154..df4d74314b4f8bf2eb96869acb2a0ef2e4d5ad36 100644 --- a/src/aging/aging_simulation.cpp +++ b/src/aging/aging_simulation.cpp @@ -1,115 +1,7 @@ #include "aging_simulation.h" -#include "../electrical/electrical_simulation.h" -#include "../factory/factorybuilder_for_aging.h" -#include "../factory/observer/createObserver.h" -#include "../thermal/thermal_simulation.h" #ifdef BUILD_AGING_SIMULATION -namespace simulation -{ - -template < typename Matrix, typename T, bool filterTypeChoice > -AgingSimulation< Matrix, T, filterTypeChoice >::AgingSimulation( - const boost::shared_ptr< xmlparser::XmlParameter > &rootXmlNode, - boost::shared_ptr< simulation::ElectricalSimulation< Matrix, T, filterTypeChoice > > electricalSimulation, - boost::shared_ptr< simulation::ThermalSimulation< Matrix, T, filterTypeChoice > > thermalSimulation, - const std::vector< boost::shared_ptr< electrical::TwoPort< Matrix > > > & /*cells*/, double agingStepTime, - factory::FactoryBuilderForAging< Matrix, T > *factoryBuilder, const std::string &uuid ) - : mTime( 0.0 ) - , mElectricalSimulation( electricalSimulation ) - , mThermalSimulation( thermalSimulation ) - , mAgingStepTime( agingStepTime ) - , mCycleLength( electricalSimulation->mSimulationDuration ) - , mLastAgingDataTime( 0.0 ) - , mCollectAgingData( true ) -{ - mCellAgingTwoPorts = factoryBuilder->mAgingTwoPortFactory->GetObjectsOfClass( "CellElement" ); - mAgingTwoPorts.reserve( factoryBuilder->mAgingTwoPortFactory->GetNumberOfObjects() ); - for ( const auto &cellAgingTp : mCellAgingTwoPorts ) - { - mAgingTwoPorts.push_back( cellAgingTp ); - for ( const auto &child : cellAgingTp->GetChildren() ) - { - mAgingTwoPorts.push_back( child ); - } - } - - mAgingObserver = - CreateAgingObserver< std::vector< boost::shared_ptr< aging::AgingTwoPort< Matrix > > >, Matrix, filterTypeChoice >( - mAgingTwoPorts, rootXmlNode.get(), uuid ); -} - -template < typename Matrix, typename T, bool filterTypeChoice > -void AgingSimulation< Matrix, T, filterTypeChoice >::CollectCellAgingData() -{ - if ( !mCollectAgingData ) - return; - - double timestep = mTime - mLastAgingDataTime; - for ( auto &agingTwoPort : mCellAgingTwoPorts ) - { - agingTwoPort->CollectData( timestep ); - } - mLastAgingDataTime = mTime; -} - -template < typename Matrix, typename T, bool filterTypeChoice > -void AgingSimulation< Matrix, T, filterTypeChoice >::ResetToPointInTime( double time ) -{ - for ( auto &agingTwoPort : mCellAgingTwoPorts ) - { - agingTwoPort->ResetToPointInTime( time ); - } -} - -template < typename Matrix, typename T, bool filterTypeChoice > -void AgingSimulation< Matrix, T, filterTypeChoice >::CalculateAging( double timestep, bool scaleToAgingStep ) -{ - double scaleFactor = 1.0; - if ( scaleToAgingStep ) - scaleFactor = mAgingStepTime * 3600 * 24 / timestep; - - for ( auto &agingTwoPort : mCellAgingTwoPorts ) - { - agingTwoPort->CalculateAging( timestep, scaleFactor ); - } -} - -template < typename Matrix, typename T, bool filterTypeChoice > -void AgingSimulation< Matrix, T, filterTypeChoice >::CalculateAging( double timestep, double scaleFactor ) -{ - for ( auto &agingTwoPort : mCellAgingTwoPorts ) - { - agingTwoPort->CalculateAging( timestep, scaleFactor ); - } -} - -template < typename Matrix, typename T, bool filterTypeChoice > -void AgingSimulation< Matrix, T, filterTypeChoice >::ResetThElStates() -{ - mElectricalSimulation->ResetSystemStates(); - mElectricalSimulation->ResetSocStates(); - mElectricalSimulation->UpdateSystemValues(); - mThermalSimulation->ResetThermalElementTemperatures(); - mThermalSimulation->UpdateAllThermalStatesTemperatures(); -} - -template < typename Matrix, typename T, bool filterTypeChoice > -void AgingSimulation< Matrix, T, filterTypeChoice >::SetCollectAgingData( bool collectAgingData ) -{ - mCollectAgingData = collectAgingData; - if ( mCollectAgingData ) - mLastAgingDataTime = mTime; -} - -template < typename Matrix, typename T, bool filterTypeChoice > -double AgingSimulation< Matrix, T, filterTypeChoice >::GetAgingStepTime() const -{ - return mAgingStepTime; -} -} // namespace simulation - template class simulation::AgingSimulation< myMatrixType, double, true >; template class simulation::AgingSimulation< myMatrixType, double, false >; #endif diff --git a/src/aging/aging_simulation.h b/src/aging/aging_simulation.h index 8b7dd35f41eecd618de739f6c7cb86718f301411..ebdf31553773c6aebd01dcec6ecf08c25fcc822d 100644 --- a/src/aging/aging_simulation.h +++ b/src/aging/aging_simulation.h @@ -3,9 +3,14 @@ #ifdef BUILD_AGING_SIMULATION +#include "../electrical/electrical_simulation.h" #include "../electrical/twoport.h" +#include "../factory/factorybuilder_for_aging.h" +#include "../factory/observer/createObserver.h" +#include "../thermal/thermal_simulation.h" #include "../xmlparser/tinyxml2/xmlparameterimpl.h" #include "../xmlparser/tinyxml2/xmlparserimpl.h" + #include <boost/shared_ptr.hpp> namespace aging @@ -75,6 +80,106 @@ class AgingSimulation bool mCollectAgingData; }; +template < typename Matrix, typename T, bool filterTypeChoice > +AgingSimulation< Matrix, T, filterTypeChoice >::AgingSimulation( + const boost::shared_ptr< xmlparser::XmlParameter > &rootXmlNode, + boost::shared_ptr< simulation::ElectricalSimulation< Matrix, T, filterTypeChoice > > electricalSimulation, + boost::shared_ptr< simulation::ThermalSimulation< Matrix, T, filterTypeChoice > > thermalSimulation, + const std::vector< boost::shared_ptr< electrical::TwoPort< Matrix > > > & /*cells*/, double agingStepTime, + factory::FactoryBuilderForAging< Matrix, T > *factoryBuilder, const std::string &uuid ) + : mTime( 0.0 ) + , mElectricalSimulation( electricalSimulation ) + , mThermalSimulation( thermalSimulation ) + , mAgingStepTime( agingStepTime ) + , mCycleLength( electricalSimulation->mSimulationDuration ) + , mLastAgingDataTime( 0.0 ) + , mCollectAgingData( true ) +{ + mCellAgingTwoPorts = factoryBuilder->mAgingTwoPortFactory->GetObjectsOfClass( "CellElement" ); + mAgingTwoPorts.reserve( factoryBuilder->mAgingTwoPortFactory->GetNumberOfObjects() ); + for ( const auto &cellAgingTp : mCellAgingTwoPorts ) + { + mAgingTwoPorts.push_back( cellAgingTp ); + for ( const auto &child : cellAgingTp->GetChildren() ) + { + mAgingTwoPorts.push_back( child ); + } + } + + mAgingObserver = + CreateAgingObserver< std::vector< boost::shared_ptr< aging::AgingTwoPort< Matrix > > >, Matrix, filterTypeChoice >( + mAgingTwoPorts, rootXmlNode.get(), uuid ); +} + +template < typename Matrix, typename T, bool filterTypeChoice > +void AgingSimulation< Matrix, T, filterTypeChoice >::CollectCellAgingData() +{ + if ( !mCollectAgingData ) + return; + + double timestep = mTime - mLastAgingDataTime; + for ( auto &agingTwoPort : mCellAgingTwoPorts ) + { + agingTwoPort->CollectData( timestep ); + } + mLastAgingDataTime = mTime; +} + +template < typename Matrix, typename T, bool filterTypeChoice > +void AgingSimulation< Matrix, T, filterTypeChoice >::ResetToPointInTime( double time ) +{ + for ( auto &agingTwoPort : mCellAgingTwoPorts ) + { + agingTwoPort->ResetToPointInTime( time ); + } +} + +template < typename Matrix, typename T, bool filterTypeChoice > +void AgingSimulation< Matrix, T, filterTypeChoice >::CalculateAging( double timestep, bool scaleToAgingStep ) +{ + double scaleFactor = 1.0; + if ( scaleToAgingStep ) + scaleFactor = mAgingStepTime * 3600 * 24 / timestep; + + for ( auto &agingTwoPort : mCellAgingTwoPorts ) + { + agingTwoPort->CalculateAging( timestep, scaleFactor ); + } +} + +template < typename Matrix, typename T, bool filterTypeChoice > +void AgingSimulation< Matrix, T, filterTypeChoice >::CalculateAging( double timestep, double scaleFactor ) +{ + for ( auto &agingTwoPort : mCellAgingTwoPorts ) + { + agingTwoPort->CalculateAging( timestep, scaleFactor ); + } +} + +template < typename Matrix, typename T, bool filterTypeChoice > +void AgingSimulation< Matrix, T, filterTypeChoice >::ResetThElStates() +{ + mElectricalSimulation->ResetSystemStates(); + mElectricalSimulation->ResetSocStates(); + mElectricalSimulation->UpdateSystemValues(); + mThermalSimulation->ResetThermalElementTemperatures(); + mThermalSimulation->UpdateAllThermalStatesTemperatures(); +} + +template < typename Matrix, typename T, bool filterTypeChoice > +void AgingSimulation< Matrix, T, filterTypeChoice >::SetCollectAgingData( bool collectAgingData ) +{ + mCollectAgingData = collectAgingData; + if ( mCollectAgingData ) + mLastAgingDataTime = mTime; +} + +template < typename Matrix, typename T, bool filterTypeChoice > +double AgingSimulation< Matrix, T, filterTypeChoice >::GetAgingStepTime() const +{ + return mAgingStepTime; +} + } // namespace simulation #endif #endif diff --git a/src/cinterface/CMakeLists.txt b/src/cinterface/CMakeLists.txt index 15b91a68725f1356f7382c5f0e3a698c867ea8cd..523aad301265ba1f8e0e54f8511d0e437b147e4b 100644 --- a/src/cinterface/CMakeLists.txt +++ b/src/cinterface/CMakeLists.txt @@ -3,6 +3,6 @@ file(GLOB_RECURSE SOURCEFILES *.cpp) find_package(MATIO REQUIRED) add_library(cinterface ${SOURCEFILES}) -target_link_libraries(cinterface PUBLIC ISEAFrameNumeric matio::matio) +target_link_libraries(cinterface PUBLIC ISEAFrameNumeric) target_compile_definitions(cinterface PUBLIC ${COMMON_DEFINITIONS} - ${NUMERIC_DEFINITIONS}) + ${NUMERIC_DEFINITIONS}) diff --git a/src/cinterface/cinterface_ThEl_Aging.cpp b/src/cinterface/cinterface_ThEl_Aging.cpp index 040a271b3f4c7d102026d5ca65e16ea7b0b55314..437850b11f40e8e6cbe34b02ed35072da809dcff 100644 --- a/src/cinterface/cinterface_ThEl_Aging.cpp +++ b/src/cinterface/cinterface_ThEl_Aging.cpp @@ -86,21 +86,40 @@ extern "C" { PointerStructure_ThEl_Aging *pointerStructure = (PointerStructure_ThEl_Aging *)*pointerStructureAddress; - std::vector< boost::shared_ptr< electrical::TwoPort< myUnit > > > outputTwoports; - const auto &agingTwoports = pointerStructure->mAgingSimulation->mAgingTwoPorts; - outputTwoports.reserve( agingTwoports.size() ); - for ( const auto &twoport : agingTwoports ) + size_t numberOfCellelements = pointerStructure->mElectricalSimulation->mCellElements.size(); + const auto &observedTwoports = pointerStructure->mElectricalSimulation->mObserver->GetObservedTwoPorts(); + if ( observedTwoports.size() > numberOfCellelements ) { - outputTwoports.push_back( twoport->GetTwoPort() ); + // Reorder the observed twoports so that all elements inside one cell end up in the same row in the output + // matrix. The vector is interpreted as a column-major matrix with the number of rows equal to the number of cells + std::vector< boost::shared_ptr< electrical::TwoPort< myMatrixType > > > twoportVector( observedTwoports.size(), nullptr ); + size_t outputRows = numberOfCellelements; + size_t outputColumns = std::ceil( (double)observedTwoports.size() / outputRows ); + // first column has all the cellements, so they can just be copied + for ( size_t i = 0; i < numberOfCellelements; ++i ) + { + twoportVector[i] = observedTwoports[i]; + } + for ( size_t i = numberOfCellelements; i < observedTwoports.size(); ++i ) + { + size_t row = ( i - numberOfCellelements ) / ( outputColumns - 1 ); + size_t column = ( i - numberOfCellelements ) % ( outputColumns - 1 ) + 1; + twoportVector[column * outputRows + row] = observedTwoports[i]; + } + pointerStructure->mElectricalSimulation->mObserver = + CreateTwoPortObserver< std::vector< boost::shared_ptr< electrical::TwoPort< myUnit > > >, myUnit, false >( + &twoportVector, 0, voltageOutputVec, currentOutputVec, powerOutputVec, socOutputVec, socSurfaceOutputVec ); + } + else + { + pointerStructure->mElectricalSimulation->mObserver = + CreateTwoPortObserver< std::vector< boost::shared_ptr< electrical::TwoPort< myUnit > > >, myUnit, false >( + &observedTwoports, 0, voltageOutputVec, currentOutputVec, powerOutputVec, socOutputVec, socSurfaceOutputVec ); } - - pointerStructure->mElectricalSimulation->mObserver = - CreateTwoPortObserver< std::vector< boost::shared_ptr< electrical::TwoPort< myUnit > > >, myUnit, false >( - &outputTwoports, 0, voltageOutputVec, currentOutputVec, powerOutputVec, socOutputVec, socSurfaceOutputVec ); } void GetRealSizes_ThEl_Aging( const char *configStr, const size_t *pointerStructureAddress, size_t *stateSize, - size_t *numberOfCells, size_t *probeSize, size_t *agingTwoportSize ) + size_t *numberOfCells, size_t *probeSize, size_t *agingTwoportSize, size_t *observerSize ) { xmlparser::tinyxml2::XmlParserImpl parser; parser.ReadFromMem( configStr ); @@ -114,6 +133,7 @@ extern "C" PointerStructure_ThEl_Aging *pointerStructure = (PointerStructure_ThEl_Aging *)*pointerStructureAddress; electricalStateSize = pointerStructure->mElectricalSimulation->mStateSystemGroup.GetStateCount(); *agingTwoportSize = pointerStructure->mAgingSimulation->mAgingTwoPorts.size(); + *observerSize = pointerStructure->mElectricalSimulation->mObserver->GetObservedTwoPorts().size(); } else { @@ -126,6 +146,7 @@ extern "C" nullptr, {}, 0, &factoryBuilder ) ); electricalStateSize = pointerStructure.mElectricalSimulation->mStateSystemGroup.GetStateCount(); *agingTwoportSize = pointerStructure.mAgingSimulation->mAgingTwoPorts.size(); + *observerSize = pointerStructure.mElectricalSimulation->mObserver->GetObservedTwoPorts().size(); } if ( stateSize ) *stateSize = themalStateSize + electricalStateSize; diff --git a/src/cinterface/cinterface_ThEl_Aging.h b/src/cinterface/cinterface_ThEl_Aging.h index 30257a6b572f52b7d09a9f4cf4b7be9e8472ba68..748137f8dcd283aa77b42cb63f051398e9c86d8e 100644 --- a/src/cinterface/cinterface_ThEl_Aging.h +++ b/src/cinterface/cinterface_ThEl_Aging.h @@ -22,7 +22,7 @@ extern "C" real_T *powerOutputVec, real_T *socOutputVec, real_T *socSurfaceOutputVec ); void GetRealSizes_ThEl_Aging( const char *configStr, const size_t *pointerStructureAddress, size_t *stateSize, - size_t *numberOfCells, size_t *probeSize, size_t *agingTwoportSize ); + size_t *numberOfCells, size_t *probeSize, size_t *agingTwoportSize, size_t *realObserverSize ); /// Apply the aging input to the cells void SetAging_ThEl_Aging( const size_t *pointerStructureAddress, const real_T *capFactors, const real_T *resFactors, diff --git a/src/electrical/electrical_simulation.cpp b/src/electrical/electrical_simulation.cpp index 5e9101b069c826d2b11feff36d54600688dfe84e..9e9d821a3f3ff252f98fa84402c86cbd07cc74cf 100644 --- a/src/electrical/electrical_simulation.cpp +++ b/src/electrical/electrical_simulation.cpp @@ -1,368 +1,5 @@ -#include "electrical_simulation.h" -#include "../misc/matrixInclude.h" - -namespace simulation -{ - -template < typename Matrix, typename T, bool filterTypeChoice > -ElectricalSimulation< Matrix, T, filterTypeChoice >::ElectricalSimulation( - const boost::shared_ptr< xmlparser::XmlParameter > &rootXmlNode, T maxSimulationStepDuration, T simulationDuration, - double socStopCriterion, std::vector< boost::shared_ptr< ::electrical::TwoPort< Matrix > > > *cells, - factory::FactoryBuilder< Matrix, T > *factoryBuilder, const std::string &uuid ) - : mTime( 0.0 ) - , mDeltaTime( maxSimulationStepDuration ) - , mSimulationDuration( simulationDuration ) - , mLastUnconstrainedDeltaTime( maxSimulationStepDuration ) - , mMaxSimulationStepDuration( maxSimulationStepDuration ) - , mStepStartTime( 0.0 ) - , mSocStopCriterion( socStopCriterion ) - , mPowerStopCriterion( 0.0 ) - , mNumberOfSteps( 0 ) -{ - // if no FactoryBuilder is passed, create a local one in this scope - boost::scoped_ptr< factory::FactoryBuilder< Matrix, T > > scopedFactoryBuilder; - if ( !factoryBuilder ) - { - scopedFactoryBuilder.reset( new factory::FactoryBuilder< Matrix, T >() ); - factoryBuilder = scopedFactoryBuilder.get(); - } - - factory::Factory< state::State, factory::ArgumentTypeState > *stateFactory = factoryBuilder->BuildStateFactory(); - factory::Factory< object::Object< double >, factory::ArgumentTypeObject< double > > *objectFactory = - factoryBuilder->BuildObjectFactory(); - factory::Factory< electrical::TwoPort< Matrix >, factory::ArgumentTypeElectrical > *electricalFactory = - factoryBuilder->BuildElectricalFactory(); - - // Create electrical system - mRootTwoPort = electricalFactory->CreateInstance( rootXmlNode->GetElementChild( "RootElement" ) ); -#ifdef _SYMBOLIC_ - mRootTwoPort->SetID( 0 ); - size_t iDCounter = 1; - - std::vector< boost::shared_ptr< electrical::TwoPort< Matrix > > > electricalElements; - electricalFactory->GetObjects( electricalElements ); - for ( size_t i = 0; i < electricalElements.size(); ++i ) - if ( electricalElements.at( i ).get() != mRootTwoPort.get() ) - electricalElements.at( i )->SetID( iDCounter++ ); - - try - { - BOOST_FOREACH ( boost::shared_ptr< electrical::TwoPort< Matrix > > &elem, electricalFactory->GetObjectsOfClass( "WarburgCotanh" ) ) - { - SerialTwoPort< Matrix > *serialTwoPort = dynamic_cast< SerialTwoPort< Matrix > * >( elem.get() ); - for ( size_t i = 0; i < serialTwoPort->size(); ++i ) - serialTwoPort->at( i )->SetID( iDCounter++ ); - } - } - catch ( ... ) - { - } - try - { - BOOST_FOREACH ( boost::shared_ptr< electrical::TwoPort< Matrix > > &elem, electricalFactory->GetObjectsOfClass( "WarburgTanh" ) ) - { - SerialTwoPort< Matrix > *serialTwoPort = dynamic_cast< SerialTwoPort< Matrix > * >( elem.get() ); - for ( size_t i = 0; i < serialTwoPort->size(); ++i ) - serialTwoPort->at( i )->SetID( iDCounter++ ); - } - } - catch ( ... ) - { - } - try - { - BOOST_FOREACH ( boost::shared_ptr< electrical::TwoPort< Matrix > > &elem, electricalFactory->GetObjectsOfClass( "Rmphn" ) ) - { - SerialTwoPort< Matrix > *serialTwoPort = dynamic_cast< SerialTwoPort< Matrix > * >( elem.get() ); - for ( size_t i = 0; i < serialTwoPort->size(); ++i ) - serialTwoPort->at( i )->SetID( iDCounter++ ); - } - } - catch ( ... ) - { - } - for ( size_t i = 0; i < this->mStateSystemGroup.GetStateCount(); ++i ) - this->mStateSystemGroup.mStateVector.coeffRef( i, 0 ) = ScalarUnit( misc::StrCont( "State" ) + misc::StrCont( i + 1 ) ); - -#endif - mNumberOfObjects = objectFactory->GetNumberOfObjects(); - mRootTwoPort->SetSystem( &mStateSystemGroup ); - mStateSystemGroup.Initialize(); -#ifndef _SYMBOLIC_ - mRootTwoPort->SetInitialCurrent( 0.0 ); -#else - mRootTwoPort->SetInitialCurrent( ScalarUnit( "InputCurrent" ) ); -#endif - mRootTwoPort->UpdateStateSystemGroup(); - mEqSystem = boost::make_shared< systm::DifferentialAlgebraicSystem< Matrix > >( &mStateSystemGroup ); - - // Store thermal states, SoC states and cell elements from electrical state factory - mThermalStates.reserve( stateFactory->GetObjectsOfClass( "ThermalState" ).size() ); - BOOST_FOREACH ( const boost::shared_ptr< state::State > &thermalStateFromFactory, stateFactory->GetObjectsOfClass( "ThermalState" ) ) - mThermalStates.push_back( boost::static_pointer_cast< state::ThermalState< double >, state::State >( thermalStateFromFactory ) ); - - const size_t numberOfSocObject = stateFactory->GetObjectsOfClass( "Soc" ).size(); - mSocStates.reserve( numberOfSocObject ); - mSavedSocValues.resize( numberOfSocObject ); - mSavedSocOffsets.resize( numberOfSocObject ); - - BOOST_FOREACH ( const boost::shared_ptr< state::State > &socStateFromFactory, - stateFactory->GetObjectsOfClass( "Soc" ) ) - mSocStates.push_back( boost::static_pointer_cast< state::Soc, state::State >( socStateFromFactory ) ); - - mCellElements.reserve( electricalFactory->GetObjectsOfClass( "CellElement" ).size() ); - BOOST_FOREACH ( const boost::shared_ptr< ::electrical::TwoPort< Matrix > > &twoPortFromFactory, - electricalFactory->GetObjectsOfClass( "CellElement" ) ) - { - if ( twoPortFromFactory->IsCellelement() ) - mCellElements.push_back( - boost::static_pointer_cast< ::electrical::Cellelement< Matrix >, ::electrical::TwoPort< Matrix > >( twoPortFromFactory ) ); - else - { - ::electrical::ParallelTwoPort< Matrix > *cellFromFactory = - static_cast< ::electrical::ParallelTwoPort< Matrix > * >( twoPortFromFactory.get() ); - for ( size_t i = 0; i < cellFromFactory->GetParallelChildren(); ++i ) - mCellElements.push_back( - boost::static_pointer_cast< ::electrical::Cellelement< Matrix > >( cellFromFactory->shared_at( i ) ) ); - } - } - - // Evaluate Options node - boost::shared_ptr< xmlparser::XmlParameter > optionsNode = rootXmlNode->GetElementChild( "Options" ); - - // SocStopCriterion - if ( optionsNode->HasElementDirectChild( "SocStopCriterionInPercent" ) ) - { - mSocStopCriterion = optionsNode->GetElementDoubleValue( "SocStopCriterionInPercent" ); - if ( mSocStopCriterion <= 0.0 ) - ErrorFunction< std::runtime_error >( __FUNCTION__, __LINE__, __FILE__, "SocStopCriterionInPercentNegative" ); - } - - // Give out cells if wanted - if ( cells ) - *cells = electricalFactory->GetObjectsOfClass( "Cellelement" ); - - if ( cells ) - { - mObserver = CreateTwoPortObserver< std::vector< boost::shared_ptr< ::electrical::TwoPort< Matrix > > >, Matrix, filterTypeChoice >( - cells, rootXmlNode.get(), 0, 0, 0, 0, 0, mRootTwoPort, uuid ); - } - else - { - mObserver = CreateTwoPortObserver< std::vector< boost::shared_ptr< electrical::TwoPort< Matrix > > >, Matrix, filterTypeChoice >( - 0, rootXmlNode.get(), 0, 0, 0, 0, 0, mRootTwoPort, uuid ); - } -} - -template < typename Matrix, typename T, bool filterTypeChoice > -void ElectricalSimulation< Matrix, T, filterTypeChoice >::UpdateSystem() -{ - // Current must be set before this function - mRootTwoPort->UpdateStateSystemGroup(); - mEqSystem->PrepareEquationSystem(); -} - -template < typename Matrix, typename T, bool filterTypeChoice > -void ElectricalSimulation< Matrix, T, filterTypeChoice >::UpdateSystemValues() -{ - mRootTwoPort->CalculateStateDependentValues(); -#if defined( _ARMADILLO_ ) && defined( SPARSE_MATRIX_FORMAT ) - mStateSystemGroup.ResetSystem(); -#endif -} - -template < typename Matrix, typename T, bool filterTypeChoice > -bool ElectricalSimulation< Matrix, T, filterTypeChoice >::CheckLoopConditionAndSetDeltaTime( T currentChangeTime ) -{ - if ( mTime < mStepStartTime + mMaxSimulationStepDuration && mTime < currentChangeTime ) - { - mLastUnconstrainedDeltaTime = mDeltaTime; - mDeltaTime = std::min( currentChangeTime - mTime, mLastUnconstrainedDeltaTime ); - mDeltaTime = std::min( mStepStartTime + mMaxSimulationStepDuration - mTime, mDeltaTime ); - return true; - } - - return false; -} - -template < typename Matrix, typename T, bool filterTypeChoice > -bool ElectricalSimulation< Matrix, T, filterTypeChoice >::CheckIfSimulationTimeHasEnded() -{ - return mTime >= mSimulationDuration; -} - -template < typename Matrix, typename T, bool filterTypeChoice > -T ElectricalSimulation< Matrix, T, filterTypeChoice >::GetCurrentSimulationStepTime() const -{ - return mTime - mStepStartTime; -} - -template < typename Matrix, typename T, bool filterTypeChoice > -void ElectricalSimulation< Matrix, T, filterTypeChoice >::FinshStep() -{ -} - -template < typename Matrix, typename T, bool filterTypeChoice > -void ElectricalSimulation< Matrix, T, filterTypeChoice >::UpdateAllThermalStatesPowerDissipation() -{ - BOOST_FOREACH ( boost::shared_ptr< electrical::Cellelement< Matrix > > &elem, mCellElements ) - elem->UpdateThermalStatePowerDissipation( mTime ); -} - -template < typename Matrix, typename T, bool filterTypeChoice > -void ElectricalSimulation< Matrix, T, filterTypeChoice >::UpdateAllThermalStatesPowerDissipationWithoutTime() -{ - BOOST_FOREACH ( boost::shared_ptr< electrical::Cellelement< Matrix > > &elem, mCellElements ) - elem->UpdateThermalStatePowerDissipation(); -} - -template < typename Matrix, typename T, bool filterTypeChoice > -void ElectricalSimulation< Matrix, T, filterTypeChoice >::ResetAllThermalStatesPowerDissipation() -{ - BOOST_FOREACH ( boost::shared_ptr< electrical::Cellelement< Matrix > > &elem, mCellElements ) - elem->ResetThermalStatePowerDissipation(); -} - -template < typename Matrix, typename T, bool filterTypeChoice > -void ElectricalSimulation< Matrix, T, filterTypeChoice >::StartNewTimeStep() -{ - ResetAllThermalStatesPowerDissipation(); - mStepStartTime = mTime; - mNumberOfSteps = 0; - SaveStatesForLaterReset(); -#ifndef _SYMBOLIC_ - mInitialPowerValue = mRootTwoPort->GetCurrentValue() * mRootTwoPort->GetVoltageValue(); -#endif -} - -template < typename Matrix, typename T, bool filterTypeChoice > -bool ElectricalSimulation< Matrix, T, filterTypeChoice >::IsStopCriterionFulfilled() const -{ - bool isStop = false; - for ( size_t i = 0; i < mSocStates.size(); ++i ) - { - if ( fabs( mSocValuesSteps[0][i] - mSocStates[i]->GetValue() ) > mSocStopCriterion ) - { - isStop = true; - break; - } - } - -#ifndef _SYMBOLIC_ - if ( mPowerStopCriterion > 0.0 ) - { - double power = mRootTwoPort->GetCurrentValue() * mRootTwoPort->GetVoltageValue(); - double powerDeviation = ( std::abs( mInitialPowerValue - power ) / mInitialPowerValue ) - 1; - if ( powerDeviation > mPowerStopCriterion ) - isStop = true; - } -#endif - - return isStop; -} - -template < typename Matrix, typename T, bool filterTypeChoice > -void ElectricalSimulation< Matrix, T, filterTypeChoice >::SaveStatesForLaterReset() -{ - if ( mTimeSteps.size() == mNumberOfSteps ) - mTimeSteps.resize( mNumberOfSteps + 1 ); - if ( mStatesSteps.size() == mNumberOfSteps ) - mStatesSteps.resize( mNumberOfSteps + 1 ); - if ( mSocValuesSteps.size() == mNumberOfSteps ) - { - mSocValuesSteps.resize( mNumberOfSteps + 1 ); - mSocValuesSteps[mNumberOfSteps].resize( mSocStates.size() ); - } - - mTimeSteps[mNumberOfSteps] = mTime; - mStatesSteps[mNumberOfSteps] = mStateSystemGroup.mStateVector; - for ( size_t i = 0; i < mSocStates.size(); ++i ) - mSocValuesSteps[mNumberOfSteps][i] = mSocStates[i]->GetValue(); - - mNumberOfSteps++; -} - -template < typename Matrix, typename T, bool filterTypeChoice > -void ElectricalSimulation< Matrix, T, filterTypeChoice >::ResetStatesToPointOfTime( T time ) -{ - if ( time <= mTimeSteps[0] || time > mTimeSteps[mNumberOfSteps - 1] || mNumberOfSteps < 2 ) - ErrorFunction< std::runtime_error >( __FUNCTION__, __LINE__, __FILE__, - "errorResetStatesToPointOfTimeExecution" ); - if ( time == mTimeSteps[mNumberOfSteps - 1] ) // No need to reset if thermal stop criterion is triggered after - // full step time time has been simulated - return; - - // Get index, which is the index for the vectors mStateSystemGroup and mSocValuesSteps before time - size_t index = 0; - for ( size_t i = 1; i < mNumberOfSteps; ++i ) - if ( mTimeSteps[i] > time ) - { - index = i - 1; - break; - } - - // Calculate factor1 and factor2, which are used to scale linearly between the point of time for index and (index+1) - const T deltaTime = mTimeSteps[index + 1] - mTimeSteps[index]; - const T factor1 = ( mTimeSteps[index + 1] - time ) / deltaTime; - const T factor2 = ( time - mTimeSteps[index] ) / deltaTime; - - // Reset time, states and SoCs - mTime = time; - mStateSystemGroup.mStateVector = mStatesSteps[index] * factor1 + mStatesSteps[index] * factor2; - for ( size_t i = 0; i < mSocStates.size(); ++i ) - { - const T newSocValue = mSocValuesSteps[index][i] * factor1 + mSocValuesSteps[index + 1][i] * factor2; - const T deltaCapacityASec = - ( newSocValue - mSocValuesSteps[mNumberOfSteps - 1][i] ) / 100.0 * mSocStates[i]->GetActualCapacity(); - mSocStates[i]->SetStoredEnergy< state::SocSetFormat::DELTA >( deltaCapacityASec ); - } - UpdateSystemValues(); - UpdateSystem(); - - BOOST_FOREACH ( boost::shared_ptr< state::ThermalState< double > > &thermalState, mThermalStates ) - thermalState->ResetPowerDissipationToTime( time ); -} - -template < typename Matrix, typename T, bool filterTypeChoice > -void ElectricalSimulation< Matrix, T, filterTypeChoice >::SaveCapacityForLaterReset() -{ - for ( size_t i = 0; i < mSocStates.size(); ++i ) - { - mSavedSocValues[i] = mSocStates[i]->template GetValue< state::SocGetFormat::AS >(); - mSavedSocOffsets[i] = mSocStates[i]->template GetOffset< state::SocGetFormat::AS >(); - } -} - -template < typename Matrix, typename T, bool filterTypeChoice > -void ElectricalSimulation< Matrix, T, filterTypeChoice >::LoadCapacityForLaterReset() -{ - for ( size_t i = 0; i < mSocStates.size(); ++i ) - { - mSocStates[i]->template SetOffset< state::SocSetFormat::ABSOLUT >( mSavedSocOffsets[i] ); - mSocStates[i]->template SetStoredEnergy< state::SocSetFormat::ABSOLUT >( mSavedSocValues[i] ); - } -} - -template < typename Matrix, typename T, bool filterTypeChoice > -void ElectricalSimulation< Matrix, T, filterTypeChoice >::ResetSocStates() -{ - for ( size_t i = 0; i < mCellElements.size(); ++i ) - mCellElements[i]->ResetSocValue(); -} - -template < typename Matrix, typename T, bool filterTypeChoice > -void ElectricalSimulation< Matrix, T, filterTypeChoice >::ResetSystemStates() -{ - mStateSystemGroup.ResetStates(); -} - -template < typename Matrix, typename T, bool filterTypeChoice > -void ElectricalSimulation< Matrix, T, filterTypeChoice >::SetPowerStopCriterion( T maximumDeviation ) -{ - mPowerStopCriterion = maximumDeviation / 100; -} - -} // namespace simulation - -template class simulation::ElectricalSimulation< myMatrixType, double, true >; +#include "electrical_simulation.h" +#include "../misc/matrixInclude.h" + +template class simulation::ElectricalSimulation< myMatrixType, double, true >; template class simulation::ElectricalSimulation< myMatrixType, double, false >; \ No newline at end of file diff --git a/src/electrical/electrical_simulation.h b/src/electrical/electrical_simulation.h index 879dd01e86e688e556e965b1c942a92f1a8b1fd1..34737a78e4bd7ac75ee5d8d62b05ee2c7664d870 100644 --- a/src/electrical/electrical_simulation.h +++ b/src/electrical/electrical_simulation.h @@ -8,12 +8,15 @@ #include "../system/dae_sys.h" +#include "../electrical/electrical_simulation.h" #include "../exceptions/error_proto.h" +#include "../factory/factorybuilder_for_aging.h" #include "../factory/observer/createObserver.h" #include "../observer/filter/csvfilter.h" #include "../observer/filter/filter.h" #include "../observer/observer.h" #include "../observer/observerException.h" +#include "../thermal/thermal_simulation.h" namespace thermal { @@ -117,5 +120,368 @@ class ElectricalSimulation T mInitialPowerValue; }; +template < typename Matrix, typename T, bool filterTypeChoice > +ElectricalSimulation< Matrix, T, filterTypeChoice >::ElectricalSimulation( + const boost::shared_ptr< xmlparser::XmlParameter > &rootXmlNode, T maxSimulationStepDuration, T simulationDuration, + double socStopCriterion, std::vector< boost::shared_ptr< ::electrical::TwoPort< Matrix > > > *cells, + factory::FactoryBuilder< Matrix, T > *factoryBuilder, const std::string &uuid ) + : mTime( 0.0 ) + , mDeltaTime( maxSimulationStepDuration ) + , mSimulationDuration( simulationDuration ) + , mLastUnconstrainedDeltaTime( maxSimulationStepDuration ) + , mMaxSimulationStepDuration( maxSimulationStepDuration ) + , mStepStartTime( 0.0 ) + , mSocStopCriterion( socStopCriterion ) + , mPowerStopCriterion( 0.0 ) + , mNumberOfSteps( 0 ) +{ + // if no FactoryBuilder is passed, create a local one in this scope + boost::scoped_ptr< factory::FactoryBuilder< Matrix, T > > scopedFactoryBuilder; + if ( !factoryBuilder ) + { + scopedFactoryBuilder.reset( new factory::FactoryBuilder< Matrix, T >() ); + factoryBuilder = scopedFactoryBuilder.get(); + } + + factory::Factory< state::State, factory::ArgumentTypeState > *stateFactory = factoryBuilder->BuildStateFactory(); + factory::Factory< object::Object< double >, factory::ArgumentTypeObject< double > > *objectFactory = + factoryBuilder->BuildObjectFactory(); + factory::Factory< electrical::TwoPort< Matrix >, factory::ArgumentTypeElectrical > *electricalFactory = + factoryBuilder->BuildElectricalFactory(); + + // Evaluate Options node + boost::shared_ptr< xmlparser::XmlParameter > optionsNode = rootXmlNode->GetElementChild( "Options" ); + bool observeAllElectricalElements = false; + if ( optionsNode->HasElementDirectChild( "ObserveAllElectricalElements" ) ) + observeAllElectricalElements = optionsNode->GetElementBoolValue( "ObserveAllElectricalElements" ); + + factory::ArgumentTypeElectrical factoryArg; + factoryArg.mMakeAllECMElementsObservable = observeAllElectricalElements; + mRootTwoPort = electricalFactory->CreateInstance( rootXmlNode->GetElementChild( "RootElement" ), &factoryArg ); + + if ( cells ) + { + *cells = electricalFactory->GetObjectsOfClass( "Cellelement" ); + std::vector< boost::shared_ptr< electrical::TwoPort< Matrix > > > observableTwoports = *cells; + FindObservableTwoports( observableTwoports, mRootTwoPort ); + mObserver = CreateTwoPortObserver< std::vector< boost::shared_ptr< ::electrical::TwoPort< Matrix > > >, Matrix, filterTypeChoice >( + &observableTwoports, rootXmlNode.get(), 0, 0, 0, 0, 0, mRootTwoPort, uuid ); + } + else + { + mObserver = CreateTwoPortObserver< std::vector< boost::shared_ptr< electrical::TwoPort< Matrix > > >, Matrix, filterTypeChoice >( + 0, rootXmlNode.get(), 0, 0, 0, 0, 0, mRootTwoPort, uuid ); + } + + // Create electrical system +#ifdef _SYMBOLIC_ + mRootTwoPort->SetID( 0 ); + size_t iDCounter = 1; + + std::vector< boost::shared_ptr< electrical::TwoPort< Matrix > > > electricalElements; + electricalFactory->GetObjects( electricalElements ); + for ( size_t i = 0; i < electricalElements.size(); ++i ) + if ( electricalElements.at( i ).get() != mRootTwoPort.get() ) + electricalElements.at( i )->SetID( iDCounter++ ); + + try + { + BOOST_FOREACH ( boost::shared_ptr< electrical::TwoPort< Matrix > > &elem, electricalFactory->GetObjectsOfClass( "WarburgCotanh" ) ) + { + SerialTwoPort< Matrix > *serialTwoPort = dynamic_cast< SerialTwoPort< Matrix > * >( elem.get() ); + for ( size_t i = 0; i < serialTwoPort->size(); ++i ) + serialTwoPort->at( i )->SetID( iDCounter++ ); + } + } + catch ( ... ) + { + } + try + { + BOOST_FOREACH ( boost::shared_ptr< electrical::TwoPort< Matrix > > &elem, electricalFactory->GetObjectsOfClass( "WarburgTanh" ) ) + { + SerialTwoPort< Matrix > *serialTwoPort = dynamic_cast< SerialTwoPort< Matrix > * >( elem.get() ); + for ( size_t i = 0; i < serialTwoPort->size(); ++i ) + serialTwoPort->at( i )->SetID( iDCounter++ ); + } + } + catch ( ... ) + { + } + try + { + BOOST_FOREACH ( boost::shared_ptr< electrical::TwoPort< Matrix > > &elem, electricalFactory->GetObjectsOfClass( "Rmphn" ) ) + { + SerialTwoPort< Matrix > *serialTwoPort = dynamic_cast< SerialTwoPort< Matrix > * >( elem.get() ); + for ( size_t i = 0; i < serialTwoPort->size(); ++i ) + serialTwoPort->at( i )->SetID( iDCounter++ ); + } + } + catch ( ... ) + { + } + for ( size_t i = 0; i < this->mStateSystemGroup.GetStateCount(); ++i ) + this->mStateSystemGroup.mStateVector.coeffRef( i, 0 ) = ScalarUnit( misc::StrCont( "State" ) + misc::StrCont( i + 1 ) ); + +#endif + mNumberOfObjects = objectFactory->GetNumberOfObjects(); + mRootTwoPort->SetSystem( &mStateSystemGroup ); + mStateSystemGroup.Initialize(); +#ifndef _SYMBOLIC_ + mRootTwoPort->SetInitialCurrent( 0.0 ); +#else + mRootTwoPort->SetInitialCurrent( ScalarUnit( "InputCurrent" ) ); +#endif + mRootTwoPort->UpdateStateSystemGroup(); + mEqSystem = boost::make_shared< systm::DifferentialAlgebraicSystem< Matrix > >( &mStateSystemGroup ); + + // Store thermal states, SoC states and cell elements from electrical state factory + mThermalStates.reserve( stateFactory->GetObjectsOfClass( "ThermalState" ).size() ); + BOOST_FOREACH ( const boost::shared_ptr< state::State > &thermalStateFromFactory, stateFactory->GetObjectsOfClass( "ThermalState" ) ) + mThermalStates.push_back( boost::static_pointer_cast< state::ThermalState< double >, state::State >( thermalStateFromFactory ) ); + + const size_t numberOfSocObject = stateFactory->GetObjectsOfClass( "Soc" ).size(); + mSocStates.reserve( numberOfSocObject ); + mSavedSocValues.resize( numberOfSocObject ); + mSavedSocOffsets.resize( numberOfSocObject ); + + BOOST_FOREACH ( const boost::shared_ptr< state::State > &socStateFromFactory, + stateFactory->GetObjectsOfClass( "Soc" ) ) + mSocStates.push_back( boost::static_pointer_cast< state::Soc, state::State >( socStateFromFactory ) ); + + mCellElements.reserve( electricalFactory->GetObjectsOfClass( "CellElement" ).size() ); + BOOST_FOREACH ( const boost::shared_ptr< ::electrical::TwoPort< Matrix > > &twoPortFromFactory, + electricalFactory->GetObjectsOfClass( "CellElement" ) ) + { + if ( twoPortFromFactory->IsCellelement() ) + mCellElements.push_back( + boost::static_pointer_cast< ::electrical::Cellelement< Matrix >, ::electrical::TwoPort< Matrix > >( twoPortFromFactory ) ); + else + { + ::electrical::ParallelTwoPort< Matrix > *cellFromFactory = + static_cast< ::electrical::ParallelTwoPort< Matrix > * >( twoPortFromFactory.get() ); + for ( size_t i = 0; i < cellFromFactory->GetParallelChildren(); ++i ) + mCellElements.push_back( + boost::static_pointer_cast< ::electrical::Cellelement< Matrix > >( cellFromFactory->shared_at( i ) ) ); + } + } + + // SocStopCriterion + if ( optionsNode->HasElementDirectChild( "SocStopCriterionInPercent" ) ) + { + mSocStopCriterion = optionsNode->GetElementDoubleValue( "SocStopCriterionInPercent" ); + if ( mSocStopCriterion <= 0.0 ) + ErrorFunction< std::runtime_error >( __FUNCTION__, __LINE__, __FILE__, "SocStopCriterionInPercentNegative" ); + } +} + +template < typename Matrix, typename T, bool filterTypeChoice > +void ElectricalSimulation< Matrix, T, filterTypeChoice >::UpdateSystem() +{ + // Current must be set before this function + mRootTwoPort->UpdateStateSystemGroup(); + mEqSystem->PrepareEquationSystem(); +} + +template < typename Matrix, typename T, bool filterTypeChoice > +void ElectricalSimulation< Matrix, T, filterTypeChoice >::UpdateSystemValues() +{ + mRootTwoPort->CalculateStateDependentValues(); +#if defined( _ARMADILLO_ ) && defined( SPARSE_MATRIX_FORMAT ) + mStateSystemGroup.ResetSystem(); +#endif +} + +template < typename Matrix, typename T, bool filterTypeChoice > +bool ElectricalSimulation< Matrix, T, filterTypeChoice >::CheckLoopConditionAndSetDeltaTime( T currentChangeTime ) +{ + if ( mTime < mStepStartTime + mMaxSimulationStepDuration && mTime < currentChangeTime ) + { + mLastUnconstrainedDeltaTime = mDeltaTime; + mDeltaTime = std::min( currentChangeTime - mTime, mLastUnconstrainedDeltaTime ); + mDeltaTime = std::min( mStepStartTime + mMaxSimulationStepDuration - mTime, mDeltaTime ); + return true; + } + + return false; +} + +template < typename Matrix, typename T, bool filterTypeChoice > +bool ElectricalSimulation< Matrix, T, filterTypeChoice >::CheckIfSimulationTimeHasEnded() +{ + return mTime >= mSimulationDuration; +} + +template < typename Matrix, typename T, bool filterTypeChoice > +T ElectricalSimulation< Matrix, T, filterTypeChoice >::GetCurrentSimulationStepTime() const +{ + return mTime - mStepStartTime; +} + +template < typename Matrix, typename T, bool filterTypeChoice > +void ElectricalSimulation< Matrix, T, filterTypeChoice >::FinshStep() +{ +} + +template < typename Matrix, typename T, bool filterTypeChoice > +void ElectricalSimulation< Matrix, T, filterTypeChoice >::UpdateAllThermalStatesPowerDissipation() +{ + BOOST_FOREACH ( boost::shared_ptr< electrical::Cellelement< Matrix > > &elem, mCellElements ) + elem->UpdateThermalStatePowerDissipation( mTime ); +} + +template < typename Matrix, typename T, bool filterTypeChoice > +void ElectricalSimulation< Matrix, T, filterTypeChoice >::UpdateAllThermalStatesPowerDissipationWithoutTime() +{ + BOOST_FOREACH ( boost::shared_ptr< electrical::Cellelement< Matrix > > &elem, mCellElements ) + elem->UpdateThermalStatePowerDissipation(); +} + +template < typename Matrix, typename T, bool filterTypeChoice > +void ElectricalSimulation< Matrix, T, filterTypeChoice >::ResetAllThermalStatesPowerDissipation() +{ + BOOST_FOREACH ( boost::shared_ptr< electrical::Cellelement< Matrix > > &elem, mCellElements ) + elem->ResetThermalStatePowerDissipation(); +} + +template < typename Matrix, typename T, bool filterTypeChoice > +void ElectricalSimulation< Matrix, T, filterTypeChoice >::StartNewTimeStep() +{ + ResetAllThermalStatesPowerDissipation(); + mStepStartTime = mTime; + mNumberOfSteps = 0; + SaveStatesForLaterReset(); +#ifndef _SYMBOLIC_ + mInitialPowerValue = mRootTwoPort->GetCurrentValue() * mRootTwoPort->GetVoltageValue(); +#endif +} + +template < typename Matrix, typename T, bool filterTypeChoice > +bool ElectricalSimulation< Matrix, T, filterTypeChoice >::IsStopCriterionFulfilled() const +{ + bool isStop = false; + for ( size_t i = 0; i < mSocStates.size(); ++i ) + { + if ( fabs( mSocValuesSteps[0][i] - mSocStates[i]->GetValue() ) > mSocStopCriterion ) + { + isStop = true; + break; + } + } + +#ifndef _SYMBOLIC_ + if ( mPowerStopCriterion > 0.0 ) + { + double power = mRootTwoPort->GetCurrentValue() * mRootTwoPort->GetVoltageValue(); + double powerDeviation = ( std::abs( mInitialPowerValue - power ) / mInitialPowerValue ) - 1; + if ( powerDeviation > mPowerStopCriterion ) + isStop = true; + } +#endif + + return isStop; +} + +template < typename Matrix, typename T, bool filterTypeChoice > +void ElectricalSimulation< Matrix, T, filterTypeChoice >::SaveStatesForLaterReset() +{ + if ( mTimeSteps.size() == mNumberOfSteps ) + mTimeSteps.resize( mNumberOfSteps + 1 ); + if ( mStatesSteps.size() == mNumberOfSteps ) + mStatesSteps.resize( mNumberOfSteps + 1 ); + if ( mSocValuesSteps.size() == mNumberOfSteps ) + { + mSocValuesSteps.resize( mNumberOfSteps + 1 ); + mSocValuesSteps[mNumberOfSteps].resize( mSocStates.size() ); + } + + mTimeSteps[mNumberOfSteps] = mTime; + mStatesSteps[mNumberOfSteps] = mStateSystemGroup.mStateVector; + for ( size_t i = 0; i < mSocStates.size(); ++i ) + mSocValuesSteps[mNumberOfSteps][i] = mSocStates[i]->GetValue(); + + mNumberOfSteps++; +} + +template < typename Matrix, typename T, bool filterTypeChoice > +void ElectricalSimulation< Matrix, T, filterTypeChoice >::ResetStatesToPointOfTime( T time ) +{ + if ( time <= mTimeSteps[0] || time > mTimeSteps[mNumberOfSteps - 1] || mNumberOfSteps < 2 ) + ErrorFunction< std::runtime_error >( __FUNCTION__, __LINE__, __FILE__, + "errorResetStatesToPointOfTimeExecution" ); + if ( time == mTimeSteps[mNumberOfSteps - 1] ) // No need to reset if thermal stop criterion is triggered after + // full step time time has been simulated + return; + + // Get index, which is the index for the vectors mStateSystemGroup and mSocValuesSteps before time + size_t index = 0; + for ( size_t i = 1; i < mNumberOfSteps; ++i ) + if ( mTimeSteps[i] > time ) + { + index = i - 1; + break; + } + + // Calculate factor1 and factor2, which are used to scale linearly between the point of time for index and (index+1) + const T deltaTime = mTimeSteps[index + 1] - mTimeSteps[index]; + const T factor1 = ( mTimeSteps[index + 1] - time ) / deltaTime; + const T factor2 = ( time - mTimeSteps[index] ) / deltaTime; + + // Reset time, states and SoCs + mTime = time; + mStateSystemGroup.mStateVector = mStatesSteps[index] * factor1 + mStatesSteps[index] * factor2; + for ( size_t i = 0; i < mSocStates.size(); ++i ) + { + const T newSocValue = mSocValuesSteps[index][i] * factor1 + mSocValuesSteps[index + 1][i] * factor2; + const T deltaCapacityASec = + ( newSocValue - mSocValuesSteps[mNumberOfSteps - 1][i] ) / 100.0 * mSocStates[i]->GetActualCapacity(); + mSocStates[i]->SetStoredEnergy< state::SocSetFormat::DELTA >( deltaCapacityASec ); + } + UpdateSystemValues(); + UpdateSystem(); + + BOOST_FOREACH ( boost::shared_ptr< state::ThermalState< double > > &thermalState, mThermalStates ) + thermalState->ResetPowerDissipationToTime( time ); +} + +template < typename Matrix, typename T, bool filterTypeChoice > +void ElectricalSimulation< Matrix, T, filterTypeChoice >::SaveCapacityForLaterReset() +{ + for ( size_t i = 0; i < mSocStates.size(); ++i ) + { + mSavedSocValues[i] = mSocStates[i]->template GetValue< state::SocGetFormat::AS >(); + mSavedSocOffsets[i] = mSocStates[i]->template GetOffset< state::SocGetFormat::AS >(); + } +} + +template < typename Matrix, typename T, bool filterTypeChoice > +void ElectricalSimulation< Matrix, T, filterTypeChoice >::LoadCapacityForLaterReset() +{ + for ( size_t i = 0; i < mSocStates.size(); ++i ) + { + mSocStates[i]->template SetOffset< state::SocSetFormat::ABSOLUT >( mSavedSocOffsets[i] ); + mSocStates[i]->template SetStoredEnergy< state::SocSetFormat::ABSOLUT >( mSavedSocValues[i] ); + } +} + +template < typename Matrix, typename T, bool filterTypeChoice > +void ElectricalSimulation< Matrix, T, filterTypeChoice >::ResetSocStates() +{ + for ( size_t i = 0; i < mCellElements.size(); ++i ) + mCellElements[i]->ResetSocValue(); +} + +template < typename Matrix, typename T, bool filterTypeChoice > +void ElectricalSimulation< Matrix, T, filterTypeChoice >::ResetSystemStates() +{ + mStateSystemGroup.ResetStates(); +} + +template < typename Matrix, typename T, bool filterTypeChoice > +void ElectricalSimulation< Matrix, T, filterTypeChoice >::SetPowerStopCriterion( T maximumDeviation ) +{ + mPowerStopCriterion = maximumDeviation / 100; +} + } // namespace simulation #endif