From f12d261b886c4649f8c6e91682cfecc42ea0e1de Mon Sep 17 00:00:00 2001 From: AlexPoiron Date: Tue, 21 Dec 2021 13:39:11 +0100 Subject: [PATCH] #133 CriticalTime Calculation implementation done. Tests added in API, Common and Launcher --- nrt/data/IEEE14/CTC/files/IEEE14.crv | 60 ++++ nrt/data/IEEE14/CTC/files/IEEE14.dyd | 86 +++++ nrt/data/IEEE14/CTC/files/IEEE14.iidm | 236 +++++++++++++ nrt/data/IEEE14/CTC/files/IEEE14.jobs | 31 ++ nrt/data/IEEE14/CTC/files/IEEE14.par | 313 ++++++++++++++++++ nrt/data/IEEE14/CTC/files/fic_MULTIPLE.xml | 16 + .../CTC/reference/aggregatedResults.xml | 4 + nrt/data/IEEE14/cases.py | 10 + .../DYNAggrResXmlExporter.cpp | 28 ++ .../aggregatedResults/DYNAggrResXmlExporter.h | 16 + .../test/TestAggregatedResults.cpp | 12 + .../test/res/criticalTimeResultsRef.xml | 4 + .../xsd/aggregatedResults.xsd | 6 + sources/API/multipleJobs/DYNMultipleJobs.cpp | 12 + sources/API/multipleJobs/DYNMultipleJobs.h | 14 + .../DYNMultipleJobsXmlHandler.cpp | 47 +++ .../multipleJobs/DYNMultipleJobsXmlHandler.h | 37 +++ .../multipleJobs/test/TestMultipleJobs.cpp | 33 ++ .../test/res/criticalTimeCalculation.xml | 4 + sources/API/multipleJobs/xsd/multipleJobs.xsd | 11 + sources/Common/CMakeLists.txt | 2 + sources/Common/DYNCriticalTimeCalculation.cpp | 100 ++++++ sources/Common/DYNCriticalTimeCalculation.h | 136 ++++++++ sources/Common/DYNSimulationResult.cpp | 10 + sources/Common/DYNSimulationResult.h | 12 + .../Dictionaries/DYNAlgorithmsError_en_GB.dic | 18 +- sources/Common/test/TestBaseClasses.cpp | 25 ++ sources/Launcher/CMakeLists.txt | 2 + sources/Launcher/DYNCriticalTimeLauncher.cpp | 130 ++++++++ sources/Launcher/DYNCriticalTimeLauncher.h | 79 +++++ .../DYNRobustnessAnalysisLauncher.cpp | 5 + .../test/TestRobustnessAnalysisLauncher.cpp | 81 +++++ .../Launcher/test/res/CriticalTime/MyCrv.crv | 60 ++++ .../Launcher/test/res/CriticalTime/MyDyd.dyd | 86 +++++ .../test/res/CriticalTime/MyIidm.iidm | 236 +++++++++++++ .../test/res/CriticalTime/MyJobs.jobs | 31 ++ .../Launcher/test/res/CriticalTime/MyPar.par | 313 ++++++++++++++++++ .../test/res/CriticalTime/fic_MULTIPLE.xml | 16 + sources/execDynawoAlgorithms.sh | 28 ++ sources/main.cpp | 32 +- util/envDynawoAlgorithms.sh | 24 +- 41 files changed, 2393 insertions(+), 13 deletions(-) create mode 100644 nrt/data/IEEE14/CTC/files/IEEE14.crv create mode 100644 nrt/data/IEEE14/CTC/files/IEEE14.dyd create mode 100644 nrt/data/IEEE14/CTC/files/IEEE14.iidm create mode 100644 nrt/data/IEEE14/CTC/files/IEEE14.jobs create mode 100644 nrt/data/IEEE14/CTC/files/IEEE14.par create mode 100644 nrt/data/IEEE14/CTC/files/fic_MULTIPLE.xml create mode 100644 nrt/data/IEEE14/CTC/reference/aggregatedResults.xml create mode 100644 sources/API/aggregatedResults/test/res/criticalTimeResultsRef.xml create mode 100644 sources/API/multipleJobs/test/res/criticalTimeCalculation.xml create mode 100644 sources/Common/DYNCriticalTimeCalculation.cpp create mode 100644 sources/Common/DYNCriticalTimeCalculation.h create mode 100644 sources/Launcher/DYNCriticalTimeLauncher.cpp create mode 100644 sources/Launcher/DYNCriticalTimeLauncher.h create mode 100644 sources/Launcher/test/res/CriticalTime/MyCrv.crv create mode 100644 sources/Launcher/test/res/CriticalTime/MyDyd.dyd create mode 100644 sources/Launcher/test/res/CriticalTime/MyIidm.iidm create mode 100644 sources/Launcher/test/res/CriticalTime/MyJobs.jobs create mode 100644 sources/Launcher/test/res/CriticalTime/MyPar.par create mode 100644 sources/Launcher/test/res/CriticalTime/fic_MULTIPLE.xml diff --git a/nrt/data/IEEE14/CTC/files/IEEE14.crv b/nrt/data/IEEE14/CTC/files/IEEE14.crv new file mode 100644 index 00000000..3f726487 --- /dev/null +++ b/nrt/data/IEEE14/CTC/files/IEEE14.crv @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nrt/data/IEEE14/CTC/files/IEEE14.dyd b/nrt/data/IEEE14/CTC/files/IEEE14.dyd new file mode 100644 index 00000000..63b3310a --- /dev/null +++ b/nrt/data/IEEE14/CTC/files/IEEE14.dyd @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nrt/data/IEEE14/CTC/files/IEEE14.iidm b/nrt/data/IEEE14/CTC/files/IEEE14.iidm new file mode 100644 index 00000000..1ec775cf --- /dev/null +++ b/nrt/data/IEEE14/CTC/files/IEEE14.iidm @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nrt/data/IEEE14/CTC/files/IEEE14.jobs b/nrt/data/IEEE14/CTC/files/IEEE14.jobs new file mode 100644 index 00000000..2016f742 --- /dev/null +++ b/nrt/data/IEEE14/CTC/files/IEEE14.jobs @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/nrt/data/IEEE14/CTC/files/IEEE14.par b/nrt/data/IEEE14/CTC/files/IEEE14.par new file mode 100644 index 00000000..cb5a2e34 --- /dev/null +++ b/nrt/data/IEEE14/CTC/files/IEEE14.par @@ -0,0 +1,313 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nrt/data/IEEE14/CTC/files/fic_MULTIPLE.xml b/nrt/data/IEEE14/CTC/files/fic_MULTIPLE.xml new file mode 100644 index 00000000..f3b7cedd --- /dev/null +++ b/nrt/data/IEEE14/CTC/files/fic_MULTIPLE.xml @@ -0,0 +1,16 @@ + + + + + diff --git a/nrt/data/IEEE14/CTC/reference/aggregatedResults.xml b/nrt/data/IEEE14/CTC/reference/aggregatedResults.xml new file mode 100644 index 00000000..9c4bba9a --- /dev/null +++ b/nrt/data/IEEE14/CTC/reference/aggregatedResults.xml @@ -0,0 +1,4 @@ + + + + diff --git a/nrt/data/IEEE14/cases.py b/nrt/data/IEEE14/cases.py index 96aacd36..e55259a6 100755 --- a/nrt/data/IEEE14/cases.py +++ b/nrt/data/IEEE14/cases.py @@ -78,3 +78,13 @@ test_cases.append((case_name, case_description, "CS", job_file, -1, 5, False, standardReturnCodeType, standardReturnCode)) +######################################### +# IEEE14 - Critical Time Calculation # +######################################### + +case_name = "IEEE14_CTC" +case_description = "IEEE14 - Critical Time Calculation input file" +job_file = os.path.join(os.path.dirname(__file__), "CTC", "fic_MULTIPLE.xml") + +test_cases.append((case_name, case_description, "CTC", job_file, -1, 5, False, standardReturnCodeType, standardReturnCode)) + diff --git a/sources/API/aggregatedResults/DYNAggrResXmlExporter.cpp b/sources/API/aggregatedResults/DYNAggrResXmlExporter.cpp index cef1b686..c4bdc0c4 100644 --- a/sources/API/aggregatedResults/DYNAggrResXmlExporter.cpp +++ b/sources/API/aggregatedResults/DYNAggrResXmlExporter.cpp @@ -101,6 +101,34 @@ XmlExporter::exportLoadIncreaseResultsToStream(const vector& formatter->endDocument(); } +void +XmlExporter::exportCriticalTimeResultsToFile(const double& criticalTime, std::string messageCriticalTimeError, const std::string& filePath) const { + fstream file; + file.open(filePath.c_str(), fstream::out); + if (!file.is_open()) { + throw DYNError(DYN::Error::API, KeyError_t::FileGenerationFailed, filePath.c_str()); + } + + exportCriticalTimeResultsToStream(criticalTime, messageCriticalTimeError, file); + file.close(); +} + +void +XmlExporter::exportCriticalTimeResultsToStream(const double& criticalTime, std::string messageCriticalTimeError, std::ostream& stream) const { + FormatterPtr formatter = Formatter::createFormatter(stream, "http://www.rte-france.com/dynawo"); + + formatter->startDocument(); + AttributeList attrs; + formatter->startElement("aggregatedResults", attrs); + attrs.add("criticalTime", criticalTime); + attrs.add("message", messageCriticalTimeError); + formatter->startElement("criticalTimeResults", attrs); + formatter->endElement(); + + formatter->endElement(); // aggregatedResults + formatter->endDocument(); +} + void XmlExporter::appendScenarioResultsElement(const vector& results, FormatterPtr& formatter) const { AttributeList attrs; diff --git a/sources/API/aggregatedResults/DYNAggrResXmlExporter.h b/sources/API/aggregatedResults/DYNAggrResXmlExporter.h index 7d15ba35..19066a3e 100644 --- a/sources/API/aggregatedResults/DYNAggrResXmlExporter.h +++ b/sources/API/aggregatedResults/DYNAggrResXmlExporter.h @@ -60,6 +60,22 @@ class XmlExporter { */ void exportLoadIncreaseResultsToStream(const std::vector& results, std::ostream& stream) const; + /** + * @brief Export critical time calculation results into a file + * + * @param results aggregated results to export + * @param filePath file where the results must be exported + */ + void exportCriticalTimeResultsToFile(const double& criticalTime, std::string messageCriticalTimeError, const std::string& filePath) const; + + /** + * @brief Export critical time calculation results into a steam + * + * @param results aggregated results to export + * @param stream stream where the results must be exported + */ + void exportCriticalTimeResultsToStream(const double& CriticalTime, std::string messageCriticalTimeError, std::ostream& stream) const; + private: /** * @brief append to the formatter a scenario results diff --git a/sources/API/aggregatedResults/test/TestAggregatedResults.cpp b/sources/API/aggregatedResults/test/TestAggregatedResults.cpp index 9944e1ec..502fdbaa 100644 --- a/sources/API/aggregatedResults/test/TestAggregatedResults.cpp +++ b/sources/API/aggregatedResults/test/TestAggregatedResults.cpp @@ -89,4 +89,16 @@ TEST(TestAggregatedResults, TestAggregatedResultsLoadIncreaseResults) { std::cout << ssDiff.str() << std::endl; ASSERT_EQ(ssDiff.str(), "Executing command : diff res/loadIncreaseResultsRef.xml res/loadIncreaseResults.xml\n"); } + +TEST(TestAggregatedResults, TestAggregatedResultsCriticalTimeResults) { + const double& criticalTime = 1; + std::string messageCriticalTimeError = "MyMessage"; + + XmlExporter exporter; + exporter.exportCriticalTimeResultsToFile(criticalTime, messageCriticalTimeError, "res/criticalTimeResults.xml"); + std::stringstream ssDiff; + executeCommand("diff res/criticalTimeResultsRef.xml res/criticalTimeResults.xml", ssDiff); + std::cout << ssDiff.str() << std::endl; + ASSERT_EQ(ssDiff.str(), "Executing command : diff res/criticalTimeResultsRef.xml res/criticalTimeResults.xml\n"); +} } // namespace aggregatedResults diff --git a/sources/API/aggregatedResults/test/res/criticalTimeResultsRef.xml b/sources/API/aggregatedResults/test/res/criticalTimeResultsRef.xml new file mode 100644 index 00000000..72281202 --- /dev/null +++ b/sources/API/aggregatedResults/test/res/criticalTimeResultsRef.xml @@ -0,0 +1,4 @@ + + + + diff --git a/sources/API/aggregatedResults/xsd/aggregatedResults.xsd b/sources/API/aggregatedResults/xsd/aggregatedResults.xsd index 330f9f4a..f7ce0e34 100644 --- a/sources/API/aggregatedResults/xsd/aggregatedResults.xsd +++ b/sources/API/aggregatedResults/xsd/aggregatedResults.xsd @@ -21,6 +21,7 @@ + @@ -55,5 +56,10 @@ + + + + + diff --git a/sources/API/multipleJobs/DYNMultipleJobs.cpp b/sources/API/multipleJobs/DYNMultipleJobs.cpp index b1df18b4..8f507fcd 100644 --- a/sources/API/multipleJobs/DYNMultipleJobs.cpp +++ b/sources/API/multipleJobs/DYNMultipleJobs.cpp @@ -21,9 +21,11 @@ #include "DYNScenarios.h" #include "DYNMarginCalculation.h" +#include "DYNCriticalTimeCalculation.h" using DYNAlgorithms::Scenarios; using DYNAlgorithms::MarginCalculation; +using DYNAlgorithms::CriticalTimeCalculation; namespace multipleJobs { @@ -43,6 +45,11 @@ MultipleJobs::setMarginCalculation(const boost::shared_ptr& m marginCalculation_ = marginCalculation; } +void +MultipleJobs::setCriticalTimeCalculation(const boost::shared_ptr& criticalTimeCalculation) { + criticalTimeCalculation_ = criticalTimeCalculation; +} + boost::shared_ptr MultipleJobs::getScenarios() const { return scenarios_; @@ -52,4 +59,9 @@ boost::shared_ptr MultipleJobs::getMarginCalculation() const { return marginCalculation_; } + +boost::shared_ptr +MultipleJobs::getCriticalTimeCalculation() const { + return criticalTimeCalculation_; +} } // namespace multipleJobs diff --git a/sources/API/multipleJobs/DYNMultipleJobs.h b/sources/API/multipleJobs/DYNMultipleJobs.h index 7b0f2583..4d2bfa31 100644 --- a/sources/API/multipleJobs/DYNMultipleJobs.h +++ b/sources/API/multipleJobs/DYNMultipleJobs.h @@ -25,6 +25,7 @@ namespace DYNAlgorithms { class Scenarios; class MarginCalculation; +class CriticalTimeCalculation; } namespace multipleJobs { @@ -57,6 +58,12 @@ class MultipleJobs { */ void setMarginCalculation(const boost::shared_ptr& marginCalculation); + /** + * @brief Set the critical time calculation input data to launch + * @param criticalTimeCalculation critical time calculation input data to launch + */ + void setCriticalTimeCalculation(const boost::shared_ptr& criticalTimeCalculation); + /** * @brief get the list of scenarios to launch * @return list of scenarios to launch @@ -69,9 +76,16 @@ class MultipleJobs { */ boost::shared_ptr getMarginCalculation() const; + /** + * @brief get the critical time calculation to launch + * @return critical time calculation to launch + */ + boost::shared_ptr getCriticalTimeCalculation() const; + private: boost::shared_ptr scenarios_; ///< scenarios to launch boost::shared_ptr marginCalculation_; ///< margin calculation to launch + boost::shared_ptr criticalTimeCalculation_; ///< critical time calculation to launch }; } // namespace multipleJobs diff --git a/sources/API/multipleJobs/DYNMultipleJobsXmlHandler.cpp b/sources/API/multipleJobs/DYNMultipleJobsXmlHandler.cpp index 63fe22ee..5c1fd03e 100644 --- a/sources/API/multipleJobs/DYNMultipleJobsXmlHandler.cpp +++ b/sources/API/multipleJobs/DYNMultipleJobsXmlHandler.cpp @@ -30,6 +30,7 @@ #include "DYNMultipleJobs.h" #include "DYNMultipleJobsFactory.h" #include "DYNMarginCalculation.h" +#include "DYNCriticalTimeCalculation.h" #include "DYNScenarios.h" #include "DYNScenario.h" @@ -43,18 +44,22 @@ using DYNAlgorithms::Scenarios; using DYNAlgorithms::Scenario; using DYNAlgorithms::MarginCalculation; using DYNAlgorithms::LoadIncrease; +using DYNAlgorithms::CriticalTimeCalculation; namespace multipleJobs { XmlHandler::XmlHandler() : multipleJobsRead_(MultipleJobsFactory::newInstance()), scenariosHandler_(parser::ElementName(multipleJobs_ns, "scenarios")), +criticalTimeCalculationHandler_(parser::ElementName(multipleJobs_ns, "criticalTimeCalculation")), marginCalculationHandler_(parser::ElementName(multipleJobs_ns, "marginCalculation")) { onElement(multipleJobs_ns("multipleJobs/scenarios"), scenariosHandler_); onElement(multipleJobs_ns("multipleJobs/marginCalculation"), marginCalculationHandler_); + onElement(multipleJobs_ns("multipleJobs/criticalTimeCalculation"), criticalTimeCalculationHandler_); scenariosHandler_.onEnd(lambda::bind(&XmlHandler::addScenarios, lambda::ref(*this))); marginCalculationHandler_.onEnd(lambda::bind(&XmlHandler::addMarginCalculation, lambda::ref(*this))); + criticalTimeCalculationHandler_.onEnd(lambda::bind(&XmlHandler::addCriticalTimeCalculation, lambda::ref(*this))); } XmlHandler::~XmlHandler() { @@ -75,6 +80,11 @@ XmlHandler::addMarginCalculation() { multipleJobsRead_->setMarginCalculation(marginCalculationHandler_.get()); } +void +XmlHandler::addCriticalTimeCalculation() { + multipleJobsRead_->setCriticalTimeCalculation(criticalTimeCalculationHandler_.get()); +} + MarginCalculationHandler::MarginCalculationHandler(const elementName_type& root_element) : scenariosHandler_(parser::ElementName(multipleJobs_ns, "scenarios")), loadIncreaseHandler_(parser::ElementName(multipleJobs_ns, "loadIncrease")) { @@ -118,6 +128,43 @@ MarginCalculationHandler::get() const { return marginCalculation_; } +CriticalTimeCalculationHandler::CriticalTimeCalculationHandler(const elementName_type& root_element) { + onStartElement(root_element, lambda::bind(&CriticalTimeCalculationHandler::create, lambda::ref(*this), lambda_args::arg2)); +} + +CriticalTimeCalculationHandler::~CriticalTimeCalculationHandler() { +} + +boost::shared_ptr +CriticalTimeCalculationHandler::get() const { + return criticalTimeCalculation_; +} + +void +CriticalTimeCalculationHandler::create(attributes_type const& attributes) { + criticalTimeCalculation_ = boost::shared_ptr(new CriticalTimeCalculation()); + if (attributes.has("accuracy")) + criticalTimeCalculation_->setAccuracy(attributes["accuracy"]); + + if (attributes.has("jobsFile")) + criticalTimeCalculation_->setJobsFile(attributes["jobsFile"]); + + if (attributes.has("dydId")) + criticalTimeCalculation_->setDydId(attributes["dydId"]); + + if (attributes.has("startPar")) + criticalTimeCalculation_->setStartPar(attributes["startPar"]); + + if (attributes.has("endPar")) + criticalTimeCalculation_->setEndPar(attributes["endPar"]); + + if (attributes.has("minValue")) + criticalTimeCalculation_->setMinValue(attributes["minValue"]); + + if (attributes.has("maxValue")) + criticalTimeCalculation_->setMaxValue(attributes["maxValue"]); +} + ScenariosHandler::ScenariosHandler(const elementName_type& root_element) : scenarioHandler_(parser::ElementName(multipleJobs_ns, "scenario")) { onStartElement(root_element, lambda::bind(&ScenariosHandler::create, lambda::ref(*this), lambda_args::arg2)); diff --git a/sources/API/multipleJobs/DYNMultipleJobsXmlHandler.h b/sources/API/multipleJobs/DYNMultipleJobsXmlHandler.h index 50cc4e3c..ab09bad2 100644 --- a/sources/API/multipleJobs/DYNMultipleJobsXmlHandler.h +++ b/sources/API/multipleJobs/DYNMultipleJobsXmlHandler.h @@ -28,6 +28,7 @@ namespace DYNAlgorithms { class Scenario; class Scenarios; class MarginCalculation; +class CriticalTimeCalculation; class LoadIncrease; } @@ -188,6 +189,36 @@ class MarginCalculationHandler : public xml::sax::parser::ComposableElementHandl boost::shared_ptr marginCalculation_; ///< current margin calculation element }; +class CriticalTimeCalculationHandler : public xml::sax::parser::ComposableElementHandler { + public: + /** + * @brief Constructor + * @param root_element complete name of the element read by the handler + */ + explicit CriticalTimeCalculationHandler(const elementName_type& root_element); + + /** + * @brief default destructor + */ + ~CriticalTimeCalculationHandler(); + + /** + * @brief return the margin calculation read in xml file + * @return margin calculation object build thanks to infos read in xml file + */ + boost::shared_ptr get() const; + + protected: + /** + * @brief Called when the XML element opening tag is read + * @param attributes attributes of the element + */ + void create(attributes_type const& attributes); + + private: + boost::shared_ptr criticalTimeCalculation_; ///< current critical time calculation element +}; + /** * @class XmlHandler * @brief Parameters file handler class @@ -225,9 +256,15 @@ class XmlHandler : public xml::sax::parser::ComposableDocumentHandler { */ void addMarginCalculation(); + /** + * @brief add a margin calculation element to the current MultipleJobs element + */ + void addCriticalTimeCalculation(); + private: boost::shared_ptr multipleJobsRead_; ///< MultipleJobs instance ScenariosHandler scenariosHandler_; ///< handler used to read scenarios element + CriticalTimeCalculationHandler criticalTimeCalculationHandler_; ///< handler used to read critical time calculation element MarginCalculationHandler marginCalculationHandler_; ///< handler used to read margin calculation element }; diff --git a/sources/API/multipleJobs/test/TestMultipleJobs.cpp b/sources/API/multipleJobs/test/TestMultipleJobs.cpp index 0a8de6e9..5f639081 100644 --- a/sources/API/multipleJobs/test/TestMultipleJobs.cpp +++ b/sources/API/multipleJobs/test/TestMultipleJobs.cpp @@ -20,6 +20,7 @@ #include "DYNScenarios.h" #include "DYNScenario.h" #include "DYNMarginCalculation.h" +#include "DYNCriticalTimeCalculation.h" #include "DYNMultipleJobs.h" #include "DYNMultipleJobsFactory.h" #include "DYNMultipleJobsXmlHandler.h" @@ -33,26 +34,34 @@ TEST(TestMultipleJobs, TestMultipleJobsClass) { MultipleJobs mj; boost::shared_ptr mc(new DYNAlgorithms::MarginCalculation()); boost::shared_ptr scenarios(new DYNAlgorithms::Scenarios()); + boost::shared_ptr ct(new DYNAlgorithms::CriticalTimeCalculation()); mj.setScenarios(scenarios); mj.setMarginCalculation(mc); + mj.setCriticalTimeCalculation(ct); ASSERT_EQ(mj.getScenarios(), scenarios); ASSERT_EQ(mj.getMarginCalculation(), mc); + ASSERT_EQ(mj.getCriticalTimeCalculation(), ct); } TEST(TestMultipleJobs, TestMultipleJobsFactory) { boost::shared_ptr mj = MultipleJobsFactory::newInstance(); boost::shared_ptr mc(new DYNAlgorithms::MarginCalculation()); boost::shared_ptr scenarios(new DYNAlgorithms::Scenarios()); + boost::shared_ptr ct(new DYNAlgorithms::CriticalTimeCalculation()); mj->setScenarios(scenarios); mj->setMarginCalculation(mc); + mj->setCriticalTimeCalculation(ct); ASSERT_EQ(mj->getScenarios(), scenarios); ASSERT_EQ(mj->getMarginCalculation(), mc); + ASSERT_EQ(mj->getCriticalTimeCalculation(), ct); boost::shared_ptr mj2 = MultipleJobsFactory::copyInstance(mj); ASSERT_EQ(mj2->getScenarios(), scenarios); ASSERT_EQ(mj2->getMarginCalculation(), mc); + ASSERT_EQ(mj2->getCriticalTimeCalculation(), ct); boost::shared_ptr mj3 = MultipleJobsFactory::copyInstance(*mj); ASSERT_EQ(mj3->getScenarios(), scenarios); ASSERT_EQ(mj3->getMarginCalculation(), mc); + ASSERT_EQ(mj3->getCriticalTimeCalculation(), ct); } TEST(TestMultipleJobs, TestMultipleJobsXmlHandlerMarginCalculation) { @@ -105,4 +114,28 @@ TEST(TestMultipleJobs, TestMultipleJobsXmlHandlerScenarios) { ASSERT_EQ(scenarios->getScenarios()[1]->getCriteriaFile(), "MyScenario2.crt"); ASSERT_EQ(scenarios->getJobsFile(), "myScenarios.jobs"); } + +TEST(TestMultipleJobs, TestMultipleJobsXmlHanderCriticalTime) { + XmlHandler multipleJobsHandler; + std::ifstream stream("res/criticalTimeCalculation.xml"); + + xml::sax::parser::ParserFactory parser_factory; + xml::sax::parser::ParserPtr parser = parser_factory.createParser(); + parser->addXmlSchema("multipleJobs.xsd"); + parser->parse(stream, multipleJobsHandler, true); + boost::shared_ptr mj = multipleJobsHandler.getMultipleJobs(); + assert(mj); + assert(!mj->getScenarios()); + assert(!mj->getMarginCalculation()); + assert(mj->getCriticalTimeCalculation()); + boost::shared_ptr ct(new DYNAlgorithms::CriticalTimeCalculation()); + ct = mj->getCriticalTimeCalculation(); + ASSERT_EQ(ct->getAccuracy(), 0.001); + ASSERT_EQ(ct->getJobsFile(), "Myjobs.jobs"); + ASSERT_EQ(ct->getDydId(), "MyDydId"); + ASSERT_EQ(ct->getStartPar(), "MyStartPar"); + ASSERT_EQ(ct->getEndPar(), "MyEndPar"); + ASSERT_EQ(ct->getMinValue(), 0); + ASSERT_EQ(ct->getMaxValue(), 1); +} } // namespace multipleJobs diff --git a/sources/API/multipleJobs/test/res/criticalTimeCalculation.xml b/sources/API/multipleJobs/test/res/criticalTimeCalculation.xml new file mode 100644 index 00000000..afbe482d --- /dev/null +++ b/sources/API/multipleJobs/test/res/criticalTimeCalculation.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/sources/API/multipleJobs/xsd/multipleJobs.xsd b/sources/API/multipleJobs/xsd/multipleJobs.xsd index 9430b25d..a111a9ef 100644 --- a/sources/API/multipleJobs/xsd/multipleJobs.xsd +++ b/sources/API/multipleJobs/xsd/multipleJobs.xsd @@ -17,6 +17,7 @@ + @@ -54,4 +55,14 @@ + + + + + + + + + + diff --git a/sources/Common/CMakeLists.txt b/sources/Common/CMakeLists.txt index 0173f3c3..bc8cbbeb 100644 --- a/sources/Common/CMakeLists.txt +++ b/sources/Common/CMakeLists.txt @@ -51,6 +51,7 @@ set(DYN_ALGO_COMMON_SOURCES DYNLoadIncrease.cpp DYNSimulationResult.cpp DYNLoadIncreaseResult.cpp + DYNCriticalTimeCalculation.cpp ${CPP_KEYS} ) @@ -60,6 +61,7 @@ set(DYN_ALGO_COMMON_HEADERS DYNScenarios.h DYNSimulationResult.h DYNLoadIncreaseResult.h + DYNCriticalTimeCalculation.h ${INCLUDE_KEYS} ) diff --git a/sources/Common/DYNCriticalTimeCalculation.cpp b/sources/Common/DYNCriticalTimeCalculation.cpp new file mode 100644 index 00000000..2912eba1 --- /dev/null +++ b/sources/Common/DYNCriticalTimeCalculation.cpp @@ -0,0 +1,100 @@ +// +// Copyright (c) 2021, RTE (http://www.rte-france.com) +// See AUTHORS.txt +// All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, you can obtain one at http://mozilla.org/MPL/2.0/. +// SPDX-License-Identifier: MPL-2.0 +// +// This file is part of Dynawo, an hybrid C++/Modelica open source suite +// of simulation tools for power systems. +// + +/** + * @file CriticalTimeCalculation.cpp + * @brief CriticalTimeCalculation description : implementation file + * + */ + +#include "DYNCriticalTimeCalculation.h" +#include "MacrosMessage.h" + +namespace DYNAlgorithms { +CriticalTimeCalculation::CriticalTimeCalculation(): +accuracy_(0.001) { +} + +void +CriticalTimeCalculation::setAccuracy(double accuracy) { + if (accuracy <= 0 || accuracy > 1) + throw DYNAlgorithmsError(IncoherentAccuracyCriticalTime, accuracy); + accuracy_ = accuracy; +} + +double +CriticalTimeCalculation::getAccuracy() const { + return accuracy_; +} + +void +CriticalTimeCalculation::setJobsFile(std::string jobsFile) { + jobsFile_ = jobsFile; +} + +std::string +CriticalTimeCalculation::getJobsFile() const { + return jobsFile_; +} + +void +CriticalTimeCalculation::setDydId(std::string dydId) { + dydId_ = dydId; +} + +std::string +CriticalTimeCalculation::getDydId() const { + return dydId_; +} + +void +CriticalTimeCalculation::setStartPar(std::string startPar) { + startPar_ = startPar; +} + +std::string +CriticalTimeCalculation::getStartPar() const { + return startPar_; +} + +void +CriticalTimeCalculation::setEndPar(std::string endPar) { + endPar_ = endPar; +} + +std::string +CriticalTimeCalculation::getEndPar() const { + return endPar_; +} + +void +CriticalTimeCalculation::setMinValue(double minValue) { + minValue_ = minValue; +} + +double +CriticalTimeCalculation::getMinValue() const { + return minValue_; +} + +void +CriticalTimeCalculation::setMaxValue(double maxValue) { + maxValue_ = maxValue; +} + +double +CriticalTimeCalculation::getMaxValue() { + return maxValue_; +} + +} // namespace DYNAlgorithms diff --git a/sources/Common/DYNCriticalTimeCalculation.h b/sources/Common/DYNCriticalTimeCalculation.h new file mode 100644 index 00000000..e7af29f1 --- /dev/null +++ b/sources/Common/DYNCriticalTimeCalculation.h @@ -0,0 +1,136 @@ +// +// Copyright (c) 2021, RTE (http://www.rte-france.com) +// See AUTHORS.txt +// All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, you can obtain one at http://mozilla.org/MPL/2.0/. +// SPDX-License-Identifier: MPL-2.0 +// +// This file is part of Dynawo, an hybrid C++/Modelica open source suite +// of simulation tools for power systems. +// + +/** + * @file DYNCriticalTimeCalculation.h + * + * @brief CriticalCalculation description : header file + * + */ + +#ifndef COMMON_DYNCRITICALTIMECALCULATION_H_ +#define COMMON_DYNCRITICALTIMECALCULATION_H_ + +#include + +namespace DYNAlgorithms { + +/** + * @brief Margin calculation class + * + * Class for margin calculation element : input data + */ +class CriticalTimeCalculation { + public: + /** + * constructor + */ + CriticalTimeCalculation(); + + /** + * @brief set the accuracy of the algorithm + * @param accuracy accuracy of the algorithm + */ + void setAccuracy(double accuracy); + + /** + * @brief get the accuracy of the algorithm + * @return accuracy of the algorithm + */ + double getAccuracy() const; + + /** + * @brief set the jobs file used for the simulation + * @param jobsFile jobs file used for the simulation + */ + void setJobsFile(std::string jobsFile); + + /** + * @brief get the jobs file used for the simulation + * @return jobs file used for the simulation + */ + std::string getJobsFile() const; + + /** + * @brief set the id parameter + * @param parSetId id parameter we will use + */ + void setDydId(std::string parSetId); + + /** + * @brief set the id parameter + * @return id parameter we will use + */ + std::string getDydId() const; + + /** + * @brief set the start parameter used for the simulation + * @param startPar start parameter used for the simulation + */ + void setStartPar(std::string startPar); + + /** + * @brief set the start parameter used for the simulation + * @return start parameter used for the simulation + */ + std::string getStartPar() const; + + /** + * @brief set the end parameter used for the simulation + * @param endPar end parameter used for the simulation + */ + void setEndPar(std::string endPar); + + /** + * @brief set the end parameter used for the simulation + * @return end parameter used for the simulation + */ + std::string getEndPar() const; + + /** + * @brief set the minimum value used for the simulation + * @param minValue minimum value used for the simulation + */ + void setMinValue(double minValue); + + /** + * @brief set the minimum value used for the simulation + * @return minimum value used for the simulation + */ + double getMinValue() const; + + /** + * @brief set the maximum value used for the simulation + * @param maxValue maximum value used for the simulation + */ + void setMaxValue(double maxValue); + + /** + * @brief set the maximum value used for the simulation + * @return maximum value used for the simulation + */ + double getMaxValue(); + + private: + double accuracy_; ///< accuracy of the algorithm + std::string jobsFile_; ///< jobs file used for the simulation + std::string dydId_; ///< dyd id in the dyd file + std::string startPar_; ///< start parameter used for the simulation + std::string endPar_; ///< end parameter used for the simulation + double minValue_; ///< minimum value for the critical time + double maxValue_; ///< maximum value for the critical time +}; + +} // namespace DYNAlgorithms + +#endif // COMMON_DYNCRITICALTIMECALCULATION_H_ diff --git a/sources/Common/DYNSimulationResult.cpp b/sources/Common/DYNSimulationResult.cpp index 026d91d5..c677f8a1 100644 --- a/sources/Common/DYNSimulationResult.cpp +++ b/sources/Common/DYNSimulationResult.cpp @@ -80,6 +80,16 @@ SimulationResult::setStatus(status_t status) { status_ = status; } +void +SimulationResult::setCriticalTimeMessageError(std::string messageCriticalTimeError) { + messageCriticalTimeError_ = messageCriticalTimeError; +} + +std::string +SimulationResult::getCriticalTimeMessageError() const { + return messageCriticalTimeError_; +} + std::stringstream& SimulationResult::getTimelineStream() { return timelineStream_; diff --git a/sources/Common/DYNSimulationResult.h b/sources/Common/DYNSimulationResult.h index 52dd13c6..70a21b09 100644 --- a/sources/Common/DYNSimulationResult.h +++ b/sources/Common/DYNSimulationResult.h @@ -83,6 +83,17 @@ class SimulationResult { */ void setStatus(status_t status); + /** + * @brief set the message error of the last simulation failed + * @param message the message error + */ + void setCriticalTimeMessageError(std::string messageCriticalTimeError); + + /** + * @brief get the message error of the last simulation failed + */ + std::string getCriticalTimeMessageError() const; + /** * @brief getter of the timeline stream associated to the scenario * @return timeline stream associated to the scenario @@ -157,6 +168,7 @@ class SimulationResult { bool success_; ///< @b true if the simulation reached its end, @b false otherwise status_t status_; ///< detailed output status of the simulation std::vector > failingCriteria_; ///< failing criteria ids + std::string messageCriticalTimeError_; ///< message of the last simulation failed. }; } // namespace DYNAlgorithms diff --git a/sources/Common/Dictionaries/DYNAlgorithmsError_en_GB.dic b/sources/Common/Dictionaries/DYNAlgorithmsError_en_GB.dic index 8a036fab..3db4e8f0 100644 --- a/sources/Common/Dictionaries/DYNAlgorithmsError_en_GB.dic +++ b/sources/Common/Dictionaries/DYNAlgorithmsError_en_GB.dic @@ -11,11 +11,13 @@ // of simulation tools for power systems. // -FileDoesNotExist = file : %1% does not exist -MarginCalculationTaskNotFound = marginCalculation task not found in input files -SystematicAnalysisTaskNotFound = scenarios not found in input files -DirectoryDoesNotExist = directory : %1% does not exist -XmlParsingError = error while parsing file %1% : %2% -IncoherentAccuracy = accuracy of margin calculation should be a number between 1 and 100 (found : %1%) -InputFileFormatNotSupported = input file should be either a zip or a xml file (found %1%) -VariantSetBeforeInit = trying to set variant %1% but analysis context not fully initialized: no IIDM provided during init or init not done +FileDoesNotExist = file : %1% does not exist +MarginCalculationTaskNotFound = marginCalculation task not found in input files +CriticalTimeCalculationTaskNotFound = criticalTimeCalculation task not found in input files +SystematicAnalysisTaskNotFound = scenarios not found in input files +DirectoryDoesNotExist = directory : %1% does not exist +XmlParsingError = error while parsing file %1% : %2% +IncoherentAccuracy = accuracy of margin calculation should be a number between 1 and 100 (found : %1%) +IncoherentAccuracyCriticalTime = accuracy of critical time calculation should be a number between 0 and 1 (found : %1%) +InputFileFormatNotSupported = input file should be either a zip or a xml file (found %1%) +VariantSetBeforeInit = trying to set variant %1% but analysis context not fully initialized: no IIDM provided during init or init not done diff --git a/sources/Common/test/TestBaseClasses.cpp b/sources/Common/test/TestBaseClasses.cpp index 9480dcf1..3029a738 100644 --- a/sources/Common/test/TestBaseClasses.cpp +++ b/sources/Common/test/TestBaseClasses.cpp @@ -17,6 +17,7 @@ #include "DYNScenario.h" #include "DYNScenarios.h" #include "DYNMarginCalculation.h" +#include "DYNCriticalTimeCalculation.h" #include "DYNSimulationResult.h" #include "DYNLoadIncreaseResult.h" #include "MacrosMessage.h" @@ -103,6 +104,30 @@ TEST(TestBaseClasses, testMarginCalculation) { ASSERT_THROW_DYNAWO(mc.setAccuracy(0), DYN::Error::GENERAL, DYNAlgorithms::KeyAlgorithmsError_t::IncoherentAccuracy); } +TEST(TestBaseClasses, testCriticalTimeCalculation) { + CriticalTimeCalculation ct; + ASSERT_EQ(ct.getAccuracy(), 0.001); + + ct.setAccuracy(0.01); + ct.setJobsFile("Myjobs.jobs"); + ct.setDydId("MyDydId"); + ct.setStartPar("MyStartPar"); + ct.setEndPar("MyEndPar"); + ct.setMinValue(1); + ct.setMaxValue(2); + ASSERT_EQ(ct.getAccuracy(), 0.01); + ASSERT_EQ(ct.getJobsFile(), "Myjobs.jobs"); + ASSERT_EQ(ct.getDydId(), "MyDydId"); + ASSERT_EQ(ct.getStartPar(), "MyStartPar"); + ASSERT_EQ(ct.getEndPar(), "MyEndPar"); + ASSERT_EQ(ct.getMinValue(), 1); + ASSERT_EQ(ct.getMaxValue(), 2); + + ASSERT_THROW_DYNAWO(ct.setAccuracy(-1), DYN::Error::GENERAL, DYNAlgorithms::KeyAlgorithmsError_t::IncoherentAccuracyCriticalTime); + ASSERT_THROW_DYNAWO(ct.setAccuracy(2), DYN::Error::GENERAL, DYNAlgorithms::KeyAlgorithmsError_t::IncoherentAccuracyCriticalTime); + ASSERT_THROW_DYNAWO(ct.setAccuracy(0), DYN::Error::GENERAL, DYNAlgorithms::KeyAlgorithmsError_t::IncoherentAccuracyCriticalTime); +} + TEST(TestBaseClasses, testSimulationResult) { SimulationResult sr; ASSERT_TRUE(sr.getScenarioId().empty()); diff --git a/sources/Launcher/CMakeLists.txt b/sources/Launcher/CMakeLists.txt index b8d73303..a74d65b8 100644 --- a/sources/Launcher/CMakeLists.txt +++ b/sources/Launcher/CMakeLists.txt @@ -17,6 +17,7 @@ set(DYN_ALGO_LAUNCHER_SOURCES DYNRobustnessAnalysisLauncher.cpp DYNDataInterfaceContainer.cpp DYNMultiVariantInputs.cpp + DYNCriticalTimeLauncher.cpp ) set(DYN_ALGO_LAUNCHER_HEADERS @@ -27,6 +28,7 @@ set(DYN_ALGO_LAUNCHER_HEADERS DYNRobustnessAnalysisLauncher.h DYNDataInterfaceContainer.h DYNMultiVariantInputs.h + DYNCriticalTimeLauncher.h ) add_library(dynawo_algorithms_Launcher SHARED ${DYN_ALGO_LAUNCHER_SOURCES}) diff --git a/sources/Launcher/DYNCriticalTimeLauncher.cpp b/sources/Launcher/DYNCriticalTimeLauncher.cpp new file mode 100644 index 00000000..547ea0e9 --- /dev/null +++ b/sources/Launcher/DYNCriticalTimeLauncher.cpp @@ -0,0 +1,130 @@ +// +// Copyright (c) 2021, RTE (http://www.rte-france.com) +// See AUTHORS.txt +// All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, you can obtain one at http://mozilla.org/MPL/2.0/. +// SPDX-License-Identifier: MPL-2.0 +// +// This file is part of Dynawo, an hybrid C++/Modelica open source suite +// of simulation tools for power systems. +// + +/** + * @file CriticalTimeLauncher.cpp + * + * @brief Critical Time launcher: implementation of the algorithm and interaction with dynawo core + * + */ + +#ifdef WITH_OPENMP +#include +#endif + +#include +#include +#include +#include +#include "DYNCriticalTimeLauncher.h" +#include "DYNMultipleJobs.h" +#include "DYNAggrResXmlExporter.h" +#include "MacrosMessage.h" + +using multipleJobs::MultipleJobs; + +namespace DYNAlgorithms { + +void +CriticalTimeLauncher::launch() { + const std::string& jobsFile = criticalTimeCalculation_->getJobsFile(); + +#ifdef WITH_OPENMP +omp_set_num_threads(nbThreads_); +#endif + + inputs_.readInputs(workingDirectory_, jobsFile, 1); + boost::shared_ptr job = inputs_.cloneJobEntry(); + SimulationParameters params; + boost::shared_ptr simulation = createAndInitSimulation(workingDirectory_, job, params, results_, inputs_); + + if (simulation) { + boost::shared_ptr modelMulti = boost::dynamic_pointer_cast(simulation->model_); + std::string DDBDir = getEnvVar("DYNAWO_DDB_DIR"); + + const std::string& dydId = criticalTimeCalculation_->getDydId(); + const std::string& endPar = criticalTimeCalculation_->getEndPar(); + + subModel_ = modelMulti->findSubModelByName(dydId); + subModel_->setParameterValue(endPar, DYN::PAR, tSup_, false); + subModel_->setSubModelParameters(); + + simulate(simulation, results_); + } +} + +void +CriticalTimeLauncher::updateIndexes(double& tPrevious, double& curAccuracy, const double& multiplierRound) { + curAccuracy = std::abs(tSup_ - tPrevious); + double midDichotomy = std::round((std::abs(tSup_ - tPrevious) / 2) * multiplierRound) / multiplierRound; + double tmp = tSup_; + + if(results_.getSuccess()) + tSup_ += midDichotomy; + else + tSup_ -= midDichotomy; + + tPrevious = tmp; +} + +void +CriticalTimeLauncher::SearchCriticalTime() { + criticalTimeCalculation_ = multipleJobs_->getCriticalTimeCalculation(); + if (!criticalTimeCalculation_) + throw DYNAlgorithmsError(CriticalTimeCalculationTaskNotFound); + + const double accuracy = criticalTimeCalculation_->getAccuracy(); + double curAccuracy = 1; + const double multiplierRound = 1 / accuracy; + + bool firstSimuPassed = false; + + double tInf = criticalTimeCalculation_->getMinValue(); + tSup_ = criticalTimeCalculation_->getMaxValue(); + double tPrevious = tSup_; + + while(curAccuracy > accuracy) { + launch(); + if (firstSimuPassed) + updateIndexes(tPrevious, curAccuracy, multiplierRound); + else { + if (results_.getSuccess()) + tSup_ += std::round(((tSup_ - tInf) / 2) * multiplierRound) / multiplierRound; + else + tSup_ -= std::round(((tSup_ - tInf) / 2) * multiplierRound) / multiplierRound; + + firstSimuPassed = true; + } + } + // Check if the final result is calculated with a failed simulation + if(!results_.getSuccess()) + tSup_ -= accuracy; + + tSup_ = std::round(tSup_ * multiplierRound) / multiplierRound;; +} + +void +CriticalTimeLauncher::createOutputs(std::map& mapData, bool zipIt) const { + aggregatedResults::XmlExporter exporter; + if (zipIt) { + std::stringstream aggregatedResults; + exporter.exportCriticalTimeResultsToStream(tSup_, results_.getCriticalTimeMessageError(), aggregatedResults); + mapData["aggregatedResults.xml"] = aggregatedResults.str(); + storeOutputs(results_, mapData); + } else { + exporter.exportCriticalTimeResultsToFile(tSup_, results_.getCriticalTimeMessageError(), outputFileFullPath_); + writeOutputs(results_); + } +} + +} // namespace DYNAlgorithms \ No newline at end of file diff --git a/sources/Launcher/DYNCriticalTimeLauncher.h b/sources/Launcher/DYNCriticalTimeLauncher.h new file mode 100644 index 00000000..354acef9 --- /dev/null +++ b/sources/Launcher/DYNCriticalTimeLauncher.h @@ -0,0 +1,79 @@ +// +// Copyright (c) 2021, RTE (http://www.rte-france.com) +// See AUTHORS.txt +// All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, you can obtain one at http://mozilla.org/MPL/2.0/. +// SPDX-License-Identifier: MPL-2.0 +// +// This file is part of Dynawo, an hybrid C++/Modelica open source suite +// of simulation tools for power systems. +// + +/** + * @file DYNMarginCriticalimeLauncher.h + * + * @brief CriticalTime algorithm launcher: header file + * + */ + +#ifndef LAUNCHER_DYNCRITICALTIMELAUNCHER_H_ +#define LAUNCHER_DYNCRITICALTIMELAUNCHER_H_ + +#include +#include +#include +#include +#include "DYNRobustnessAnalysisLauncher.h" +#include "DYNCriticalTimeCalculation.h" +#include "DYNError.h" + +namespace DYNAlgorithms { +class SimulationResults; +class CriticalTimeCalculation; +/** + * @brief Margin Calculation launcher class + * + * Class for margin calculation launched by cvg + */ +class CriticalTimeLauncher : public RobustnessAnalysisLauncher { + public: + /** + * @copydoc RobustnessAnalysisLauncher::launch() + */ + void launch(); + + /** + * @brief Search critical time with a specific default in the simulation. We follow + * dichotomy's algorithm to find it. + */ + void SearchCriticalTime(); + + /** + * @brief Update superior born to find the right critical time + * and calcul the next time value we want to test. + * + * @param tPrevious previous value tested + * @param curAccuracy current accuracy + * @param multiplierRound value used to round results with accuracy + */ + void updateIndexes(double& tPrevious, double& curAccuracy, const double& multiplierRound); + + protected: + double tSup_; ///< value that will be updated until we find the critical time + SimulationResult results_; ///< results of the systematic analysis + boost::shared_ptr subModel_; ///< submodel for each simulation + boost::shared_ptr criticalTimeCalculation_; ///< critical time calculation + + private: + /** + * @copydoc RobustnessAnalysisLauncher::createOutputs() + */ + void createOutputs(std::map& mapData, bool zipIt) const; + +}; +} // namespace DYNAlgorithms + + +#endif // LAUNCHER_DYNCRITICALTIMELAUNCHER_H_ \ No newline at end of file diff --git a/sources/Launcher/DYNRobustnessAnalysisLauncher.cpp b/sources/Launcher/DYNRobustnessAnalysisLauncher.cpp index 0cf13eb4..8630002d 100644 --- a/sources/Launcher/DYNRobustnessAnalysisLauncher.cpp +++ b/sources/Launcher/DYNRobustnessAnalysisLauncher.cpp @@ -382,6 +382,11 @@ RobustnessAnalysisLauncher::simulate(const boost::shared_ptr& s } catch (const DYN::MessageError& m) { std::cerr << m.what() << std::endl; Trace::error() << m.what() << Trace::endline; + + std::string m_str(m.what()); + std::replace(m_str.begin(), m_str.end(), '\n', ' '); + result.setCriticalTimeMessageError(m_str); + simulation->terminate(); result.setSuccess(false); result.setStatus(EXECUTION_PROBLEM_STATUS); diff --git a/sources/Launcher/test/TestRobustnessAnalysisLauncher.cpp b/sources/Launcher/test/TestRobustnessAnalysisLauncher.cpp index 180e2c30..14fefdb1 100644 --- a/sources/Launcher/test/TestRobustnessAnalysisLauncher.cpp +++ b/sources/Launcher/test/TestRobustnessAnalysisLauncher.cpp @@ -30,6 +30,7 @@ #include "MacrosMessage.h" #include "DYNMultipleJobs.h" #include "DYNMarginCalculation.h" +#include "DYNCriticalTimeCalculation.h" testing::Environment* initXmlEnvironment(); @@ -72,6 +73,25 @@ class MyLauncher : public RobustnessAnalysisLauncher { ASSERT_TRUE(exists("res/timeLine/timeline_MyScenario.xml")); } + void launchCriticalTime() { + inputs_.readInputs(workingDirectory_, "MyJobs.jobs", 1); + boost::shared_ptr job = inputs_.cloneJobEntry(); + + SimulationParameters params; + boost::shared_ptr simu = createAndInitSimulation("res/CriticalTime", job, params, result_, inputs_); + ASSERT_TRUE(simu); + status_t status = simulate(simu, result_); + ASSERT_EQ(status, CONVERGENCE_STATUS); + ASSERT_EQ(result_.getStatus(), CONVERGENCE_STATUS); + ASSERT_TRUE(result_.getSuccess()); + + writeResults(); + ASSERT_TRUE(exists("res/CriticalTime/MyOutputFile.zip")); + + writeResults(); + ASSERT_TRUE(exists("res/CriticalTime/MyOutputFile.zip")); + } + void testInputFile(const std::string& inputFile) { ASSERT_EQ(inputFile_, inputFile); } @@ -116,6 +136,21 @@ class MyLauncher : public RobustnessAnalysisLauncher { ASSERT_EQ(mc->getScenarios()->getJobsFile(), "myScenarios.jobs"); } + void testMultipleJobsCriticalTime() { + assert(multipleJobs_); + assert(!multipleJobs_->getScenarios()); + assert(!multipleJobs_->getMarginCalculation()); + assert(multipleJobs_->getCriticalTimeCalculation()); + boost::shared_ptr ct = multipleJobs_->getCriticalTimeCalculation(); + ASSERT_EQ(ct->getAccuracy(), 0.001); + ASSERT_EQ(ct->getJobsFile(), "MyJobs.jobs"); + ASSERT_EQ(ct->getDydId(), "FAULT_GEN_1"); + ASSERT_EQ(ct->getStartPar(), "fault_tBegin"); + ASSERT_EQ(ct->getEndPar(), "fault_tEnd"); + ASSERT_EQ(ct->getMinValue(), 1); + ASSERT_EQ(ct->getMaxValue(), 1.620); + } + protected: void createOutputs(std::map& mapData, bool) const { storeOutputs(result_, mapData); @@ -175,5 +210,51 @@ TEST(TestLauncher, TestRobustnessAnalysisLauncher) { launcher.launch(); } +TEST(TestLauncher, TestRobustnessAnalysisLauncherWithCriticalTime) { + MyLauncher launcher; + + launcher.testInputFile(""); + launcher.setInputFile("/home/MyInputFile"); + launcher.testInputFile("/home/MyInputFile"); + + launcher.testOutputFile(""); + launcher.setOutputFile("MyOutputFile"); + launcher.testOutputFile("MyOutputFile"); + + launcher.testDirectory(""); + launcher.setDirectory("MyDirectory"); + launcher.testDirectory("MyDirectory"); + + launcher.testNbThreads(1); + launcher.testNbThreads(1); + + ASSERT_THROW_DYNAWO(launcher.init(), DYN::Error::GENERAL, DYNAlgorithms::KeyAlgorithmsError_t::DirectoryDoesNotExist); + launcher.testWorkingDirectory(createAbsolutePath("MyDirectory", current_path())); + + launcher.setDirectory("/home/MyDirectory"); + ASSERT_THROW_DYNAWO(launcher.init(), DYN::Error::GENERAL, DYNAlgorithms::KeyAlgorithmsError_t::DirectoryDoesNotExist); + launcher.testWorkingDirectory("/home/MyDirectory"); + + launcher.setDirectory(""); + ASSERT_THROW_DYNAWO(launcher.init(), DYN::Error::GENERAL, DYNAlgorithms::KeyAlgorithmsError_t::FileDoesNotExist); + launcher.testWorkingDirectory(current_path()+"/"); + + launcher.setInputFile("res/MyDummyInputFile.xml"); + ASSERT_THROW_DYNAWO(launcher.init(), DYN::Error::GENERAL, DYNAlgorithms::KeyAlgorithmsError_t::FileDoesNotExist); + + launcher.setInputFile("res/MyInputFile.txt"); + ASSERT_THROW_DYNAWO(launcher.init(), DYN::Error::GENERAL, DYNAlgorithms::KeyAlgorithmsError_t::InputFileFormatNotSupported); + + boost::shared_ptr archive = zip::ZipFileFactory::newInstance(); + archive->addEntry("res/CriticalTime/fic_MULTIPLE.xml"); + zip::ZipOutputStream::write("res/CriticalTime/MyInputFile.zip", archive); + launcher.setInputFile("MyInputFile.zip"); + launcher.setDirectory("res/CriticalTime"); + launcher.setOutputFile("MyOutputFile.zip"); + ASSERT_NO_THROW(launcher.init()); + launcher.testOutputFileFullPath(createAbsolutePath("res/CriticalTime/MyOutputFile.zip", current_path())); + launcher.testMultipleJobsCriticalTime(); + launcher.launchCriticalTime(); +} } // namespace DYNAlgorithms diff --git a/sources/Launcher/test/res/CriticalTime/MyCrv.crv b/sources/Launcher/test/res/CriticalTime/MyCrv.crv new file mode 100644 index 00000000..3f726487 --- /dev/null +++ b/sources/Launcher/test/res/CriticalTime/MyCrv.crv @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sources/Launcher/test/res/CriticalTime/MyDyd.dyd b/sources/Launcher/test/res/CriticalTime/MyDyd.dyd new file mode 100644 index 00000000..4c86e303 --- /dev/null +++ b/sources/Launcher/test/res/CriticalTime/MyDyd.dyd @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sources/Launcher/test/res/CriticalTime/MyIidm.iidm b/sources/Launcher/test/res/CriticalTime/MyIidm.iidm new file mode 100644 index 00000000..1ec775cf --- /dev/null +++ b/sources/Launcher/test/res/CriticalTime/MyIidm.iidm @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sources/Launcher/test/res/CriticalTime/MyJobs.jobs b/sources/Launcher/test/res/CriticalTime/MyJobs.jobs new file mode 100644 index 00000000..0c56d281 --- /dev/null +++ b/sources/Launcher/test/res/CriticalTime/MyJobs.jobs @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/sources/Launcher/test/res/CriticalTime/MyPar.par b/sources/Launcher/test/res/CriticalTime/MyPar.par new file mode 100644 index 00000000..27a25aa1 --- /dev/null +++ b/sources/Launcher/test/res/CriticalTime/MyPar.par @@ -0,0 +1,313 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sources/Launcher/test/res/CriticalTime/fic_MULTIPLE.xml b/sources/Launcher/test/res/CriticalTime/fic_MULTIPLE.xml new file mode 100644 index 00000000..1d1555b2 --- /dev/null +++ b/sources/Launcher/test/res/CriticalTime/fic_MULTIPLE.xml @@ -0,0 +1,16 @@ + + + + + diff --git a/sources/execDynawoAlgorithms.sh b/sources/execDynawoAlgorithms.sh index e935358c..0172169c 100755 --- a/sources/execDynawoAlgorithms.sh +++ b/sources/execDynawoAlgorithms.sh @@ -47,6 +47,7 @@ where [option] can be: CS ([args]) call Dynawo's launcher with given arguments setting LD_LIBRARY_PATH correctly SA ([args]) call a dynamic systematic analysis MC ([args]) call a margin calculation + CTC ([args]) call a critical time calculation --version show Dynawo version --help show this message" @@ -176,6 +177,33 @@ algo_SA() { return ${RETURN_CODE} } +algo_CTC() { + setEnv + + # launch critical time calculation + $DYNAWO_ALGORITHMS_INSTALL_DIR/bin/dynawoAlgorithms --simulationType=CTC $@ + RETURN_CODE=$? + + while (($#)); do + case $1 in + --input) + if [ ! -z "$2" ]; then + if [ -f "$2" ]; then + filter_timeline `dirname $2` + fi + fi + break + ;; + *) + shift + break + ;; + esac + done + + return ${RETURN_CODE} +} + if [ $# -eq 0 ]; then echo "$usage" exit 1 diff --git a/sources/main.cpp b/sources/main.cpp index 230451e8..f4c3e597 100644 --- a/sources/main.cpp +++ b/sources/main.cpp @@ -31,11 +31,13 @@ #include "DYNMarginCalculationLauncher.h" #include "DYNComputeLoadVariationLauncher.h" #include "DYNComputeSimulationLauncher.h" +#include "DYNCriticalTimeLauncher.h" using DYNAlgorithms::ComputeSimulationLauncher; using DYNAlgorithms::SystematicAnalysisLauncher; using DYNAlgorithms::MarginCalculationLauncher; using DYNAlgorithms::ComputeLoadVariationLauncher; +using DYNAlgorithms::CriticalTimeLauncher; namespace po = boost::program_options; @@ -43,11 +45,18 @@ static void launchSimulation(const std::string& jobFile, const std::string& outp static void launchMarginCalculation(const std::string& inputFile, const std::string& outputFile, const std::string& directory, int nbThreads); static void launchSystematicAnalysis(const std::string& inputFile, const std::string& outputFile, const std::string& directory, int nbThreads); static void launchLoadVariationCalculation(const std::string& inputFile, const std::string& outputFile, const std::string& directory, int variation); +static void launchCriticalTimeCalculation(const std::string& inputFile, const std::string& outputFile, const std::string& directory, int nbThreads); int main(int argc, char** argv) { std::string simulationType = ""; std::string inputFile = ""; std::string outputFile = ""; + + std::string simulationMC_SA_CS = "Set the simulation type to launch : MC (Margin calculation), SA (systematic analysis), CS (compute simulation)"; + std::string simulationCTC = " or CTC (critical time calculation)"; + std::string allSimulationsTypeStr = simulationMC_SA_CS.append(simulationCTC); + const char* allSimulationsType = allSimulationsTypeStr.c_str(); + std::vector directoryVec; int nbThreads = 1; int variation = -1; @@ -58,7 +67,7 @@ int main(int argc, char** argv) { desc.add_options() ("help,h", "Produce help message") ("simulationType", po::value(&simulationType)->required(), - "Set the simulation type to launch : MC (Margin calculation), SA (systematic analysis) or CS (compute simulation)") + allSimulationsType) ("input", po::value(&inputFile)->required(), "Set the input file of the simulation (*.zip or *.xml)") ("output", po::value(&outputFile), @@ -103,13 +112,13 @@ int main(int argc, char** argv) { return 1; } - if (simulationType != "MC" && simulationType != "SA" && simulationType != "CS") { + if (simulationType != "MC" && simulationType != "SA" && simulationType != "CS" && simulationType != "CTC") { std::cout << simulationType << " : unknown simulation type" << std::endl; std::cout << desc << std::endl; return 1; } - if (simulationType == "SA" || simulationType == "MC") { + if (simulationType == "SA" || simulationType == "MC" || simulationType == "CTC") { if (outputFile == "") { std::cout << "An output file. (*.zip or *.xml) is required for SA and MC simulations." << std::endl; std::cout << desc << std::endl; @@ -146,6 +155,11 @@ int main(int argc, char** argv) { boost::posix_time::ptime t1 = boost::posix_time::second_clock::local_time(); boost::posix_time::time_duration diff = t1 - t0; std::cout << "Simulation finished in " << diff.total_milliseconds()/1000 << "s" << std::endl; + } else if (simulationType == "CTC") { + launchCriticalTimeCalculation(inputFile, outputFile, directory, nbThreads); + boost::posix_time::ptime t1 = boost::posix_time::second_clock::local_time(); + boost::posix_time::time_duration diff = t1 - t0; + std::cout << "Simulation finished in " << diff.total_milliseconds()/1000 << "s" << std::endl; } } catch (...) { throw; @@ -222,3 +236,15 @@ void launchSystematicAnalysis(const std::string& inputFile, const std::string& o analysisLauncher->launch(); analysisLauncher->writeResults(); } + +void launchCriticalTimeCalculation(const std::string& inputFile, const std::string& outputFile, const std::string& directory, int nbThreads) { + boost::shared_ptr criticalTimeLauncher = boost::shared_ptr(new CriticalTimeLauncher()); + criticalTimeLauncher->setInputFile(inputFile); + criticalTimeLauncher->setOutputFile(outputFile); + criticalTimeLauncher->setDirectory(directory); + criticalTimeLauncher->setNbThreads(nbThreads); + + criticalTimeLauncher->init(); + criticalTimeLauncher->SearchCriticalTime(); + criticalTimeLauncher->writeResults(); +} diff --git a/util/envDynawoAlgorithms.sh b/util/envDynawoAlgorithms.sh index afbb3060..a1045f7b 100755 --- a/util/envDynawoAlgorithms.sh +++ b/util/envDynawoAlgorithms.sh @@ -43,13 +43,15 @@ where [option] can be: SA ([args]) launch a systematic analysis MC ([args]) launch a margin calculation CS ([args]) launch a simple Dynawo simulation + CTC ([args]) launch a critical time calculation =========== Tests nrt ([-p regex] [-n name_filter]) run (filtered) non-regression tests and open the result in chosen browser version-validation clean all built items, then build them all SA-gdb ([args]) launch a systematic analysis with gdb MC-gdb ([args]) launch a margin calculation with gdb - CS-gdb ([args]) launch a simple Dynawo simulationwith gdb + CS-gdb ([args]) launch a simple Dynawo simulation with gdb + CTC-gdb ([args]) launch a critical time calculation with gdb build-tests build and launch dynawo-algorithms's unittest build-tests-coverage build/launch dynawo-algorithms's unittest and generate code coverage report unittest-gdb [arg] call unittest in gdb @@ -659,6 +661,12 @@ launch_MC() { return ${RETURN_CODE} } +launch_CTC() { + $DYNAWO_ALGORITHMS_INSTALL_DIR/bin/dynawoAlgorithms --simulationType CTC $@ + RETURN_CODE=$? + return ${RETURN_CODE} +} + launch_CS_gdb() { gdb -q --args $DYNAWO_ALGORITHMS_INSTALL_DIR/bin/dynawoAlgorithms --simulationType CS $@ RETURN_CODE=$? @@ -677,6 +685,12 @@ launch_MC_gdb() { return ${RETURN_CODE} } +launch_CTC_gdb() { + gdb -q --args $DYNAWO_ALGORITHMS_INSTALL_DIR/bin/dynawoAlgorithms --simulationType CTC $@ + RETURN_CODE=$? + return ${RETURN_CODE} +} + ################################# ########### Main script ######### if [ -n "$BASH_VERSION" ]; then @@ -758,6 +772,9 @@ case $MODE in CS) launch_CS ${ARGS} || error_exit "Dynawo simulation failed" ;; + CTC) + launch_CTC ${ARGS} || error_exit "Critical time calculation failed" + ;; SA-gdb) launch_SA_gdb ${ARGS} || error_exit "Systematic analysis failed" ;; @@ -769,7 +786,10 @@ case $MODE in CS-gdb) launch_CS_gdb ${ARGS} || error_exit "Dynawo simulation failed" ;; - + + CTC-gdb) + launch_CTC_gdb ${ARGS} || error_exit "Critical time calculation failed" + ;; nrt) nrt ${ARGS} || error_exit "Error during Dynawo's non regression tests execution" ;;