diff --git a/src/OMSimulatorLib/BusConnector.cpp b/src/OMSimulatorLib/BusConnector.cpp index b779d16e4..de34c1b11 100644 --- a/src/OMSimulatorLib/BusConnector.cpp +++ b/src/OMSimulatorLib/BusConnector.cpp @@ -25,21 +25,20 @@ oms::BusConnector::~BusConnector() } } -oms_status_enu_t oms::BusConnector::exportToSSD(pugi::xml_node &root) const +oms_status_enu_t oms::BusConnector::exportToSSD(pugi::xml_node& root) const { pugi::xml_node bus_node = root.append_child(oms::ssp::Draft20180219::bus); bus_node.append_attribute("name") = name; pugi::xml_node signals_node = bus_node.append_child(oms::ssp::Draft20180219::signals); - for(auto& connector : conrefs) { + for(auto& connector : conrefs) + { pugi::xml_node signal_node = signals_node.append_child(oms::ssp::Draft20180219::signal); signal_node.append_attribute("name") = connector.c_str(); } if (this->geometry) - { return reinterpret_cast(this->geometry)->exportToSSD(bus_node); - } return oms_status_ok; } diff --git a/src/OMSimulatorLib/CMakeLists.txt b/src/OMSimulatorLib/CMakeLists.txt index 98da3b4bc..0fe5e259f 100644 --- a/src/OMSimulatorLib/CMakeLists.txt +++ b/src/OMSimulatorLib/CMakeLists.txt @@ -57,6 +57,7 @@ list(APPEND OMSIMULATORLIB_SOURCES ResultReader.cpp) list(APPEND OMSIMULATORLIB_SOURCES ResultWriter.cpp) list(APPEND OMSIMULATORLIB_SOURCES Scope.cpp) list(APPEND OMSIMULATORLIB_SOURCES SignalDerivative.cpp) +list(APPEND OMSIMULATORLIB_SOURCES Snapshot.cpp) list(APPEND OMSIMULATORLIB_SOURCES StepSizeConfiguration.cpp) list(APPEND OMSIMULATORLIB_SOURCES System.cpp) list(APPEND OMSIMULATORLIB_SOURCES SystemSC.cpp) diff --git a/src/OMSimulatorLib/Component.cpp b/src/OMSimulatorLib/Component.cpp index e7f8e9b6b..1ea287c68 100644 --- a/src/OMSimulatorLib/Component.cpp +++ b/src/OMSimulatorLib/Component.cpp @@ -33,9 +33,9 @@ #include "Flags.h" #include "Model.h" +#include "OMSFileSystem.h" #include "System.h" #include "TLMBusConnector.h" -#include void oms::fmiLogger(jm_callbacks* c, jm_string module, jm_log_level_enu_t log_level, jm_string message) { diff --git a/src/OMSimulatorLib/ComponentFMUCS.cpp b/src/OMSimulatorLib/ComponentFMUCS.cpp index fc1ff1b97..9771a0385 100644 --- a/src/OMSimulatorLib/ComponentFMUCS.cpp +++ b/src/OMSimulatorLib/ComponentFMUCS.cpp @@ -34,6 +34,7 @@ #include "Flags.h" #include "Logging.h" #include "Model.h" +#include "OMSFileSystem.h" #include "ssd/Tags.h" #include "System.h" #include "SystemTLM.h" @@ -41,7 +42,6 @@ #include #include -#include #include oms::ComponentFMUCS::ComponentFMUCS(const ComRef& cref, System* parentSystem, const std::string& fmuPath) @@ -251,12 +251,12 @@ oms::Component* oms::ComponentFMUCS::NewComponent(const oms::ComRef& cref, oms:: } // parse modelDescription.xml to get start values before instantiating fmu's - component->values.parseModelDescription((tempDir / "modelDescription.xml").string().c_str()); + component->values.parseModelDescription(tempDir); return component; } -oms::Component* oms::ComponentFMUCS::NewComponent(const pugi::xml_node& node, oms::System* parentSystem, const std::string& sspVersion, const std::unordered_map& oms_snapshot) +oms::Component* oms::ComponentFMUCS::NewComponent(const pugi::xml_node& node, oms::System* parentSystem, const std::string& sspVersion, const Snapshot& snapshot) { ComRef cref = ComRef(node.attribute("name").as_string()); std::string type = node.attribute("type").as_string(); @@ -297,7 +297,7 @@ oms::Component* oms::ComponentFMUCS::NewComponent(const pugi::xml_node& node, om { // set parameter bindings associated with the component std::string tempdir = parentSystem->getModel()->getTempDirectory(); - component->values.importFromSnapshot(*it, sspVersion, oms_snapshot); + component->values.importFromSnapshot(*it, sspVersion, snapshot); } else { diff --git a/src/OMSimulatorLib/ComponentFMUCS.h b/src/OMSimulatorLib/ComponentFMUCS.h index 74faacd1e..3f0a44f4a 100644 --- a/src/OMSimulatorLib/ComponentFMUCS.h +++ b/src/OMSimulatorLib/ComponentFMUCS.h @@ -36,6 +36,7 @@ #include "ComRef.h" #include "Values.h" #include "ResultWriter.h" +#include "Snapshot.h" #include "Variable.h" #include @@ -55,7 +56,7 @@ namespace oms ~ComponentFMUCS(); static Component* NewComponent(const ComRef& cref, System* parentSystem, const std::string& fmuPath); - static Component* NewComponent(const pugi::xml_node& node, System* parentSystem, const std::string& sspVersion, const std::unordered_map& oms_snapshot); + static Component* NewComponent(const pugi::xml_node& node, System* parentSystem, const std::string& sspVersion, const Snapshot& snapshot); const FMUInfo* getFMUInfo() const {return &(this->fmuInfo);} oms_status_enu_t exportToSSD(pugi::xml_node& node, pugi::xml_node& ssvNode) const; diff --git a/src/OMSimulatorLib/ComponentFMUME.cpp b/src/OMSimulatorLib/ComponentFMUME.cpp index e2511cd01..be4eb9d54 100644 --- a/src/OMSimulatorLib/ComponentFMUME.cpp +++ b/src/OMSimulatorLib/ComponentFMUME.cpp @@ -34,13 +34,13 @@ #include "Flags.h" #include "Logging.h" #include "Model.h" +#include "OMSFileSystem.h" #include "ssd/Tags.h" #include "System.h" #include "SystemSC.h" #include #include -#include #include oms::ComponentFMUME::ComponentFMUME(const ComRef& cref, System* parentSystem, const std::string& fmuPath) @@ -253,12 +253,12 @@ oms::Component* oms::ComponentFMUME::NewComponent(const oms::ComRef& cref, oms:: } // parse modelDescription.xml to get start values before instantiating fmu's - component->values.parseModelDescription((tempDir / "modelDescription.xml").string().c_str()); + component->values.parseModelDescription(tempDir); return component; } -oms::Component* oms::ComponentFMUME::NewComponent(const pugi::xml_node& node, oms::System* parentSystem, const std::string& sspVersion, const std::unordered_map& oms_snapshot) +oms::Component* oms::ComponentFMUME::NewComponent(const pugi::xml_node& node, oms::System* parentSystem, const std::string& sspVersion, const Snapshot& snapshot) { ComRef cref = ComRef(node.attribute("name").as_string()); std::string type = node.attribute("type").as_string(); @@ -299,7 +299,7 @@ oms::Component* oms::ComponentFMUME::NewComponent(const pugi::xml_node& node, om { // set parameter bindings associated with the component std::string tempdir = parentSystem->getModel()->getTempDirectory(); - component->values.importFromSnapshot(*it, sspVersion, oms_snapshot); + component->values.importFromSnapshot(*it, sspVersion, snapshot); } else { diff --git a/src/OMSimulatorLib/ComponentFMUME.h b/src/OMSimulatorLib/ComponentFMUME.h index af68301ba..bcc999401 100644 --- a/src/OMSimulatorLib/ComponentFMUME.h +++ b/src/OMSimulatorLib/ComponentFMUME.h @@ -36,6 +36,7 @@ #include "ComRef.h" #include "Values.h" #include "ResultWriter.h" +#include "Snapshot.h" #include "Variable.h" #include @@ -53,7 +54,7 @@ namespace oms ~ComponentFMUME(); static Component* NewComponent(const oms::ComRef& cref, System* parentSystem, const std::string& fmuPath); - static Component* NewComponent(const pugi::xml_node& node, System* parentSystem, const std::string& sspVersion, const std::unordered_map& oms_snapshot); + static Component* NewComponent(const pugi::xml_node& node, System* parentSystem, const std::string& sspVersion, const Snapshot& snapshot); const FMUInfo* getFMUInfo() const {return &(this->fmuInfo);} oms_status_enu_t exportToSSD(pugi::xml_node& node, pugi::xml_node& ssvNode) const; diff --git a/src/OMSimulatorLib/ComponentTable.cpp b/src/OMSimulatorLib/ComponentTable.cpp index e74cade2d..d688b2d98 100644 --- a/src/OMSimulatorLib/ComponentTable.cpp +++ b/src/OMSimulatorLib/ComponentTable.cpp @@ -33,9 +33,10 @@ #include "Logging.h" #include "Model.h" +#include "OMSFileSystem.h" #include "ssd/Tags.h" #include "System.h" -#include + #include oms::ComponentTable::ComponentTable(const ComRef& cref, System* parentSystem, const std::string& path) @@ -103,7 +104,7 @@ oms::Component* oms::ComponentTable::NewComponent(const oms::ComRef& cref, oms:: return component; } -oms::Component* oms::ComponentTable::NewComponent(const pugi::xml_node& node, oms::System* parentSystem, const std::string& sspVersion, const std::unordered_map& oms_snapshot) +oms::Component* oms::ComponentTable::NewComponent(const pugi::xml_node& node, oms::System* parentSystem, const std::string& sspVersion, const Snapshot& snapshot) { ComRef cref = ComRef(node.attribute("name").as_string()); std::string type = node.attribute("type").as_string(); diff --git a/src/OMSimulatorLib/ComponentTable.h b/src/OMSimulatorLib/ComponentTable.h index 236367ae6..8a858c8f8 100644 --- a/src/OMSimulatorLib/ComponentTable.h +++ b/src/OMSimulatorLib/ComponentTable.h @@ -37,6 +37,7 @@ #include "ResultReader.h" #include "ResultWriter.h" #include "SignalDerivative.h" +#include "Snapshot.h" #include #include #include @@ -52,7 +53,7 @@ namespace oms ~ComponentTable(); static Component* NewComponent(const oms::ComRef& cref, System* parentSystem, const std::string& path); - static Component* NewComponent(const pugi::xml_node& node, System* parentSystem, const std::string& sspVersion, const std::unordered_map& oms_snapshot); + static Component* NewComponent(const pugi::xml_node& node, System* parentSystem, const std::string& sspVersion, const Snapshot& snapshot); oms_status_enu_t exportToSSD(pugi::xml_node& node, pugi::xml_node& ssvNode) const; oms_status_enu_t exportToSSVTemplate(pugi::xml_node& ssvNode) {return oms_status_ok;} diff --git a/src/OMSimulatorLib/Connector.cpp b/src/OMSimulatorLib/Connector.cpp index 8383a5e3f..4148e8b1d 100644 --- a/src/OMSimulatorLib/Connector.cpp +++ b/src/OMSimulatorLib/Connector.cpp @@ -137,7 +137,7 @@ oms::Connector* oms::Connector::NewConnector(const pugi::xml_node& node, const s return connector; } -std::string oms::Connector::getTypeString(const pugi::xml_node &node, const std::string& sspVersion) +std::string oms::Connector::getTypeString(const pugi::xml_node& node, const std::string& sspVersion) { if (sspVersion == "Draft20180219") { diff --git a/src/OMSimulatorLib/Model.cpp b/src/OMSimulatorLib/Model.cpp index 8e2d84e19..247d61bcd 100644 --- a/src/OMSimulatorLib/Model.cpp +++ b/src/OMSimulatorLib/Model.cpp @@ -31,15 +31,15 @@ #include "Model.h" +#include "Component.h" #include "CSVWriter.h" #include "Flags.h" #include "MATWriter.h" +#include "OMSFileSystem.h" #include "Scope.h" #include "ssd/Tags.h" #include "System.h" -#include "Component.h" -#include #include #include @@ -143,7 +143,7 @@ oms_status_enu_t oms::Model::rename(const ComRef& cref, const ComRef& newCref) return logError("Model \"" + std::string(getCref()) + "\" does not contain system \"" + std::string(front) + "\""); } -oms_status_enu_t oms::Model::loadSnapshot(const pugi::xml_node node) +oms_status_enu_t oms::Model::loadSnapshot(const pugi::xml_node& node) { // This method will not change the name of the model. // If a renaming is requested then it will happen in Scope::loadSnapshot. @@ -154,20 +154,13 @@ oms_status_enu_t oms::Model::loadSnapshot(const pugi::xml_node node) System* old_root_system = system; system = NULL; - // internally create the oms:snapshot from snapshot - pugi::xml_document snapshot; - pugi::xml_node oms_snapshot = snapshot.append_child(oms::ssp::Version1_0::snap_shot); - pugi::xml_node ssd_file = oms_snapshot.append_child(oms::ssp::Version1_0::oms_file); - ssd_file.append_attribute("name") = "SystemStructure.ssd"; - ssd_file.append_copy(node); - - std::unordered_map snapshotFiles; - for (const auto &it : oms_snapshot.children()) - snapshotFiles[it.attribute("name").as_string()] = it; + Snapshot snapshot; // this is a temporary workaroud, loadSnapshot will be removed later + snapshot.importResourcesXML("SystemStructure.ssd", node); + //snapshot.debugPrintAll(); bool old_copyResources = copyResources(); copyResources(false); - oms_status_enu_t status = importFromSnapshot(snapshotFiles); + oms_status_enu_t status = importFromSnapshot(snapshot); copyResources(old_copyResources); if (oms_status_ok != status) @@ -185,25 +178,17 @@ oms_status_enu_t oms::Model::loadSnapshot(const pugi::xml_node node) return oms_status_ok; } -oms_status_enu_t oms::Model::importSnapshot(const char* snapshot) +oms_status_enu_t oms::Model::importSnapshot(const char* snapshot_) { if (!validState(oms_modelState_virgin)) return logError_ModelInWrongState(this); - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load(snapshot); - if (!result) - return logError("loading snapshot failed (" + std::string(result.description()) + ")"); - - pugi::xml_node oms_snapshot = doc.document_element(); // oms:snapshot - - std::unordered_map snapshotFiles; - for (const auto& it : oms_snapshot.children()) - snapshotFiles[it.attribute("name").as_string()] = it; + Snapshot snapshot; + snapshot.import(snapshot_); + //snapshot.debugPrintAll(); // get ssd:SystemStructureDescription - pugi::xml_node ssd_file = oms_snapshot.find_child_by_attribute(oms::ssp::Version1_0::oms_file, "name", "SystemStructure.ssd"); - pugi::xml_node ssdNode = ssd_file.child(oms::ssp::Draft20180219::ssd::system_structure_description); + pugi::xml_node ssdNode = snapshot.getResourcesFile( "SystemStructure.ssd"); ComRef new_cref = ComRef(ssdNode.attribute("name").as_string()); std::string ssdVersion = ssdNode.attribute("version").as_string(); @@ -219,7 +204,7 @@ oms_status_enu_t oms::Model::importSnapshot(const char* snapshot) bool old_copyResources = copyResources(); copyResources(false); - oms_status_enu_t status = importFromSnapshot(snapshotFiles); + oms_status_enu_t status = importFromSnapshot(snapshot); copyResources(old_copyResources); if (oms_status_ok != status) @@ -621,15 +606,12 @@ oms_status_enu_t oms::Model::exportToSSD(pugi::xml_node& node, pugi::xml_node& s return oms_status_ok; } -oms_status_enu_t oms::Model::importFromSnapshot(const std::unordered_map& oms_snapshot) +oms_status_enu_t oms::Model::importFromSnapshot(const Snapshot& snapshot) { - auto oms_file_ssd = oms_snapshot.find("SystemStructure.ssd"); - if (oms_file_ssd == oms_snapshot.end()) - { + pugi::xml_node ssdNode = snapshot.getResourcesFile("SystemStructure.ssd"); + if (!ssdNode) return logError("loading \"SystemStructure.ssd\" from failed"); - } - pugi::xml_node ssdNode = oms_file_ssd->second.child(oms::ssp::Draft20180219::ssd::system_structure_description); std::string sspVersion = ssdNode.attribute("version").as_string(); if(sspVersion == "Draft20180219") @@ -654,7 +636,7 @@ oms_status_enu_t oms::Model::importFromSnapshot(const std::unordered_mapimportFromSnapshot(*it, sspVersion, oms_snapshot)) + if (oms_status_ok != system->importFromSnapshot(*it, sspVersion, snapshot)) return oms_status_error; } else if (name == oms::ssp::Draft20180219::ssd::default_experiment) diff --git a/src/OMSimulatorLib/Model.h b/src/OMSimulatorLib/Model.h index 21f2beb08..807543af0 100644 --- a/src/OMSimulatorLib/Model.h +++ b/src/OMSimulatorLib/Model.h @@ -37,9 +37,9 @@ #include "Element.h" #include "ResultWriter.h" #include "Types.h" +#include "Snapshot.h" #include #include -#include #if (BOOST_VERSION >= 105300) #include @@ -76,7 +76,7 @@ namespace oms oms_status_enu_t exportSnapshot(const ComRef& cref, char** contents); oms_status_enu_t exportSSVTemplate(const ComRef& cref, const std::string& filename); oms_status_enu_t exportSSMTemplate(const ComRef& cref, const std::string& filename); - oms_status_enu_t importFromSnapshot(const std::unordered_map& oms_snapshot); + oms_status_enu_t importFromSnapshot(const Snapshot& snapshot); oms_status_enu_t importSnapshot(const char* snapshot); oms_status_enu_t exportToFile(const std::string& filename) const; oms_system_enu_t getSystemType(const pugi::xml_node& node, const std::string& sspVersion); @@ -122,7 +122,7 @@ namespace oms bool useThreadPool() {return (pool != nullptr);} ctpl::thread_pool& getThreadPool() {assert(pool); return *pool;} - oms_status_enu_t loadSnapshot(const pugi::xml_node node); + oms_status_enu_t loadSnapshot(const pugi::xml_node& node); private: Model(const ComRef& cref, const std::string& tempDir); diff --git a/src/OMSimulatorLib/OMSFileSystem.cpp b/src/OMSimulatorLib/OMSFileSystem.cpp index bbe42c40f..286e9bf71 100644 --- a/src/OMSimulatorLib/OMSFileSystem.cpp +++ b/src/OMSimulatorLib/OMSFileSystem.cpp @@ -29,7 +29,7 @@ * */ -#include +#include "OMSFileSystem.h" #include #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__) @@ -45,11 +45,27 @@ extern "C" #if OMC_STD_FS == 1 // We have C++17; it has temp_directory_path and canonical +filesystem::path oms_temp_directory_path(void) +{ + return filesystem::temp_directory_path(); +} + +filesystem::path oms_canonical(filesystem::path p) +{ + return filesystem::canonical(p); +} #else #include -#if !(BOOST_VERSION >= 104600) // no temp_directory_path in boost < 1.46 +#if (BOOST_VERSION >= 104600) // no temp_directory_path in boost < 1.46 +filesystem::path oms_temp_directory_path(void) { + return filesystem::temp_directory_path(); +} +filesystem::path oms_canonical(filesystem::path p) { + return filesystem::canonical(p); +} +#else filesystem::path oms_temp_directory_path(void) { #if (_WIN32) @@ -84,6 +100,38 @@ filesystem::path oms_canonical(filesystem::path p) #endif #endif +// https://svn.boost.org/trac10/ticket/1976 +filesystem::path naive_uncomplete(const filesystem::path& path, const filesystem::path& base) +{ + if (path.has_root_path()) + { + if (path.root_path() != base.root_path()) + return path; + else + return naive_uncomplete(path.relative_path(), base.relative_path()); + } + + if (base.has_root_path()) + throw "cannot uncomplete a relative path from a rooted base"; + + typedef filesystem::path::const_iterator path_iterator; + path_iterator path_it = path.begin(); + path_iterator base_it = base.begin(); + while (path_it != path.end() && base_it != base.end()) + { + if (*path_it != *base_it) + break; + ++path_it; ++base_it; + } + + filesystem::path result; + for (; base_it != base.end(); ++base_it) + result /= ".."; + for (; path_it != path.end(); ++path_it) + result /= *path_it; + return result; +} + filesystem::path oms_unique_path(const std::string& prefix) { const char lt[] = "0123456789abcdefghijklmnopqrstuvwxyz"; @@ -97,7 +145,7 @@ filesystem::path oms_unique_path(const std::string& prefix) return p; } -void oms_copy_file(const filesystem::path &from, const filesystem::path &to) +void oms_copy_file(const filesystem::path& from, const filesystem::path& to) { #if defined(__MINGW32__) || defined(__MINGW64__) /* The MINGW implementation succeeds for filesystem::copy_file, but does not diff --git a/src/OMSimulatorLib/OMSFileSystem.h b/src/OMSimulatorLib/OMSFileSystem.h index 3be2c0460..5e869a5ea 100644 --- a/src/OMSimulatorLib/OMSFileSystem.h +++ b/src/OMSimulatorLib/OMSFileSystem.h @@ -18,13 +18,6 @@ namespace filesystem = std::experimental::filesystem::v1; #if OMC_STD_FS == 1 -static inline filesystem::path oms_temp_directory_path(void) { - return filesystem::temp_directory_path(); -} -static inline filesystem::path oms_canonical(filesystem::path p) { - return filesystem::canonical(p); -} - #define OMS_RECURSIVE_DIRECTORY_ITERATOR(path) (filesystem::recursive_directory_iterator{path}) #else // boost part @@ -56,22 +49,12 @@ static inline filesystem::path oms_canonical(filesystem::path p) { #include namespace filesystem = boost::filesystem; +#endif -#if (BOOST_VERSION >= 104600) // no temp_directory_path in boost < 1.46 -static inline filesystem::path oms_temp_directory_path(void) { - return filesystem::temp_directory_path(); -} -static inline filesystem::path oms_canonical(filesystem::path p) { - return filesystem::canonical(p); -} -#else filesystem::path oms_temp_directory_path(void); filesystem::path oms_canonical(filesystem::path p); -#endif - -#endif - -void oms_copy_file(const filesystem::path &from, const filesystem::path &to); +void oms_copy_file(const filesystem::path& from, const filesystem::path& to); filesystem::path oms_unique_path(const std::string& prefix); +filesystem::path naive_uncomplete(const filesystem::path& path, const filesystem::path& base); #endif diff --git a/src/OMSimulatorLib/OMSimulator.cpp b/src/OMSimulatorLib/OMSimulator.cpp index 0bc0e2a31..589e7b618 100644 --- a/src/OMSimulatorLib/OMSimulator.cpp +++ b/src/OMSimulatorLib/OMSimulator.cpp @@ -43,6 +43,7 @@ #include "ResultReader.h" #include "Scope.h" #include "SignalDerivative.h" +#include "Snapshot.h" #include "System.h" #include "SystemWC.h" #if !defined(NO_TLM) @@ -1645,12 +1646,10 @@ oms_status_enu_t oms_extractFMIKind(const char* filename, oms_fmi_kind_enu_t* ki if (status != 0) return logError("failed to extract modelDescription.xml from \"" + std::string(filename) + "\""); - std::string xml_file = oms::Scope::GetInstance().getTempDirectory() + "/modelDescription.xml"; - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file(xml_file.c_str()); - if (!result) - return logError("loading \"" + xml_file + "\" failed (" + std::string(result.description()) + ")"); - const pugi::xml_node node = doc.document_element(); // ssd:SystemStructureDescription + oms::Snapshot snapshot; + if (oms_status_ok != snapshot.importResourcesFile("modelDescription.xml", oms::Scope::GetInstance().getTempDirectory())) + return logError("Failed to import"); + const pugi::xml_node node = snapshot.getResourcesFile("modelDescription.xml"); bool cs = (std::string(node.child("CoSimulation").attribute("modelIdentifier").as_string()) != ""); bool me = (std::string(node.child("ModelExchange").attribute("modelIdentifier").as_string()) != ""); diff --git a/src/OMSimulatorLib/ResultReader.cpp b/src/OMSimulatorLib/ResultReader.cpp index 81c38cdcb..0cb28ce0c 100644 --- a/src/OMSimulatorLib/ResultReader.cpp +++ b/src/OMSimulatorLib/ResultReader.cpp @@ -32,14 +32,13 @@ #include "ResultReader.h" #include "CSVReader.h" -#include "MatReader.h" #include "Logging.h" +#include "MatReader.h" +#include "OMSFileSystem.h" #include "Util.h" #include -#include - oms::ResultReader::ResultReader(const char* filename) { } diff --git a/src/OMSimulatorLib/Scope.cpp b/src/OMSimulatorLib/Scope.cpp index 852668d1f..427c5d860 100644 --- a/src/OMSimulatorLib/Scope.cpp +++ b/src/OMSimulatorLib/Scope.cpp @@ -34,11 +34,10 @@ #include "Flags.h" #include "System.h" #include "Component.h" +#include "Snapshot.h" #include -#include #include #include "ssd/Tags.h" -#include oms::Scope::Scope() : tempDir(".") @@ -201,27 +200,11 @@ oms_status_enu_t oms::Scope::importModel(const std::string& filename, char** _cr if (oms_status_ok != oms::Scope::miniunz(filename, temp_root.string(), true)) return logError("failed to extract \"SystemStructure.ssd\" from \"" + filename + "\""); - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file((temp_root / "SystemStructure.ssd").string().c_str()); - if (!result) - return logError("loading \"" + std::string(filename) + "\" failed (" + std::string(result.description()) + ")"); - - const pugi::xml_node node = doc.document_element(); // ssd:SystemStructureDescription - - // internally create the oms:snapshot from ssp - pugi::xml_document snapshot; - pugi::xml_node oms_snapshot = snapshot.append_child(oms::ssp::Version1_0::snap_shot); - - pugi::xml_node ssd_file = oms_snapshot.append_child(oms::ssp::Version1_0::oms_file); - ssd_file.append_attribute("name") = "SystemStructure.ssd"; - ssd_file.append_copy(node); - - /*construct mappedSnapshot from oms_snapshot - eg: filename -> mappedSnapshot; - mappedSnapshot["SystemStructure.ssd"] = ssd_file; + Snapshot snapshot; + snapshot.importResourcesFile("SystemStructure.ssd", temp_root); + const pugi::xml_node node = snapshot.getResourcesFile("SystemStructure.ssd"); + if (!node) + return logError("failed to load \"SystemStructure.ssd\""); ComRef cref = ComRef(node.attribute("name").as_string()); std::string ssdVersion = node.attribute("version").as_string(); @@ -244,30 +227,13 @@ oms_status_enu_t oms::Scope::importModel(const std::string& filename, char** _cr // add the remaining resources (e.g) .ssv, .ssm and signalFilter.xml to oms:snapshot for (const auto &entry : OMS_RECURSIVE_DIRECTORY_ITERATOR(model->getTempDirectory())) - { if (entry.path().has_extension()) - { - if (entry.path().extension() == ".ssv") - { - // ssv files - addSnapshotResources(oms_snapshot, entry.path().string(), mappedSnapshot); - } - else if (entry.path().extension() == ".ssm") - { - // ssm files - addSnapshotResources(oms_snapshot, entry.path().string(), mappedSnapshot); - } - else if (entry.path().filename()== "signalFilter.xml") - { - // signalFilter.xml - addSnapshotResources(oms_snapshot, entry.path().string(), mappedSnapshot); - } - } - } + if (".ssv" == entry.path().extension() || ".ssm" == entry.path().extension() || ".xml" == entry.path().extension()) + snapshot.importResourcesFile(naive_uncomplete(entry.path(), model->getTempDirectory()), model->getTempDirectory()); - // snapshot.save(std::cout); + // snapshot.debugPrintAll(); - oms_status_enu_t status = model->importFromSnapshot(mappedSnapshot); + oms_status_enu_t status = model->importFromSnapshot(snapshot); model->copyResources(old_copyResources); Scope::GetInstance().setWorkingDirectory(cd); @@ -284,27 +250,6 @@ oms_status_enu_t oms::Scope::importModel(const std::string& filename, char** _cr return oms_status_ok; } -oms_status_enu_t oms::Scope::addSnapshotResources(pugi::xml_node& oms_snapshot, std::string path, std::unordered_map &mappedSnapshot) -{ - filesystem::path p(path); - std::string filename = "resources/" + p.filename().string(); - - pugi::xml_node oms_file = oms_snapshot.append_child(oms::ssp::Version1_0::oms_file); - oms_file.append_attribute("name") = filename.c_str(); - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file(path.c_str()); - if (!result) - return logError("loading \"" + filename + "\" to failed (" + std::string(result.description()) + ")"); - - pugi::xml_node oms_node = doc.document_element(); - oms_file.append_copy(oms_node); - - // map the filename with oms_file node - mappedSnapshot[filename] = oms_file; - - return oms_status_ok; -} - oms_status_enu_t oms::Scope::setTempDirectory(const std::string& newTempDir) { try diff --git a/src/OMSimulatorLib/Scope.h b/src/OMSimulatorLib/Scope.h index 51359d09f..e421a6d8a 100644 --- a/src/OMSimulatorLib/Scope.h +++ b/src/OMSimulatorLib/Scope.h @@ -39,7 +39,6 @@ #include #include #include -#include namespace oms { @@ -73,8 +72,6 @@ namespace oms oms_status_enu_t loadSnapshot(const ComRef& cref, const char* snapshot, char** newCref); - oms_status_enu_t addSnapshotResources(pugi::xml_node& oms_snapshot, std::string filename, std::unordered_map& mappedSnapshot); - const std::string& getTempDirectory() const {return GetInstance().tempDir;} std::string getWorkingDirectory(); diff --git a/src/OMSimulatorLib/Snapshot.cpp b/src/OMSimulatorLib/Snapshot.cpp new file mode 100644 index 000000000..9eb8cb5a8 --- /dev/null +++ b/src/OMSimulatorLib/Snapshot.cpp @@ -0,0 +1,118 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-CurrentYear, Open Source Modelica Consortium (OSMC), + * c/o Linköpings universitet, Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR + * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES + * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, + * ACCORDING TO RECIPIENTS CHOICE. + * + * The OpenModelica software and the Open Source Modelica + * Consortium (OSMC) Public License (OSMC-PL) are obtained + * from OSMC, either from the above address, + * from the URLs: http://www.ida.liu.se/projects/OpenModelica or + * http://www.openmodelica.org, and in the OpenModelica distribution. + * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +#include "Snapshot.h" + +#include "Logging.h" + +#include + +oms::Snapshot::Snapshot() +{ + // set the document with the root node + doc.append_child(oms::ssp::Version1_0::snap_shot); +} + +oms::Snapshot::~Snapshot() +{ +} + +oms_status_enu_t oms::Snapshot::import(const char* snapshot) +{ + doc.reset(); + pugi::xml_parse_result result = doc.load_string(snapshot); + if (!result) + return logError("loading snapshot failed (" + std::string(result.description()) + ")"); + return oms_status_ok; +} + +oms_status_enu_t oms::Snapshot::importResourcesFile(const filesystem::path& filename, const filesystem::path& root) +{ + filesystem::path p = root / filename; + + pugi::xml_document tmp_doc; + pugi::xml_parse_result result = tmp_doc.load_file(p.c_str()); + if (!result) + return logError("loading resource \"" + p.generic_string() + "\" failed (" + std::string(result.description()) + ")"); + + return importResourcesXML(filename, tmp_doc.document_element()); +} + +oms_status_enu_t oms::Snapshot::importResourcesMemory(const filesystem::path& filename, const char* contents) +{ + pugi::xml_document tmp_doc; + pugi::xml_parse_result result = tmp_doc.load_string(contents); + if (!result) + return logError("loading resource \"" + filename.generic_string() + "\" failed (" + std::string(result.description()) + ")"); + + return importResourcesXML(filename, tmp_doc.document_element()); +} + +oms_status_enu_t oms::Snapshot::importResourcesXML(const filesystem::path& filename, const pugi::xml_node& node) +{ + pugi::xml_node oms_snapshot = doc.document_element(); + pugi::xml_node oms_file = oms_snapshot.append_child(oms::ssp::Version1_0::oms_file); + oms_file.append_attribute("name") = filename.generic_string().c_str(); + oms_file.append_copy(node); + + return oms_status_ok; +} + +void oms::Snapshot::getResources(std::vector& resources) +{ + pugi::xml_node oms_snapshot = doc.document_element(); + for (const auto& it : oms_snapshot.children()) + resources.push_back(it.attribute("name").as_string()); +} + +pugi::xml_node oms::Snapshot::getResourcesFile(const filesystem::path& filename) const +{ + pugi::xml_node oms_snapshot = doc.document_element(); + pugi::xml_node node = oms_snapshot.find_child_by_attribute(oms::ssp::Version1_0::oms_file, "name", filename.generic_string().c_str()); + + if (!node) + logError("Failed to find node \"" + filename.generic_string() + "\""); + + return node.first_child(); +} + +void oms::Snapshot::debugPrintNode(const filesystem::path& filename) const +{ + pugi::xml_node node = getResourcesFile(filename); + + if (node) + node.print(std::cout, " "); +} + +void oms::Snapshot::debugPrintAll() const +{ + doc.save(std::cout, " "); +} diff --git a/src/OMSimulatorLib/Snapshot.h b/src/OMSimulatorLib/Snapshot.h new file mode 100644 index 000000000..044efa5a3 --- /dev/null +++ b/src/OMSimulatorLib/Snapshot.h @@ -0,0 +1,71 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-CurrentYear, Open Source Modelica Consortium (OSMC), + * c/o Linköpings universitet, Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR + * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES + * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, + * ACCORDING TO RECIPIENTS CHOICE. + * + * The OpenModelica software and the Open Source Modelica + * Consortium (OSMC) Public License (OSMC-PL) are obtained + * from OSMC, either from the above address, + * from the URLs: http://www.ida.liu.se/projects/OpenModelica or + * http://www.openmodelica.org, and in the OpenModelica distribution. + * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +#ifndef _OMS_SNAPSHOT_H_ +#define _OMS_SNAPSHOT_H_ + +#include "OMSFileSystem.h" +#include "Types.h" +#include "ssd/Tags.h" + +#include +#include +#include + +namespace oms +{ + class Snapshot + { + public: + Snapshot(); + ~Snapshot(); + + oms_status_enu_t import(const char* snapshot); + oms_status_enu_t importResourcesFile(const filesystem::path& filename, const filesystem::path& root); + oms_status_enu_t importResourcesMemory(const filesystem::path& filename, const char* contents); + oms_status_enu_t importResourcesXML(const filesystem::path& filename, const pugi::xml_node& node); + void getResources(std::vector& resources); + pugi::xml_node getResourcesFile(const filesystem::path& filename) const; + + void debugPrintNode(const filesystem::path& filename) const; + void debugPrintAll() const; + + private: + // stop the compiler generating methods copying the object + Snapshot(Snapshot const& copy); ///< not implemented + Snapshot& operator=(Snapshot const& copy); ///< not implemented + + private: + pugi::xml_document doc; // snapshot document + }; +} + +#endif diff --git a/src/OMSimulatorLib/System.cpp b/src/OMSimulatorLib/System.cpp index 6adbbb373..4e6f7508b 100644 --- a/src/OMSimulatorLib/System.cpp +++ b/src/OMSimulatorLib/System.cpp @@ -31,22 +31,19 @@ #include "System.h" -#include "AlgLoop.h" #include "Component.h" #include "ComponentFMUCS.h" #include "ComponentFMUME.h" #include "ComponentTable.h" -#include "ExternalModel.h" #include "Flags.h" #include "Model.h" -#include "ResultWriter.h" +#include "OMSFileSystem.h" #include "ssd/Tags.h" #include "SystemSC.h" #include "SystemTLM.h" #include "SystemWC.h" -#include "Types.h" #include "Variable.h" -#include + #include oms::System::System(const oms::ComRef& cref, oms_system_enu_t type, oms::Model* parentModel, oms::System* parentSystem, oms_solver_enu_t solverMethod) @@ -502,7 +499,7 @@ oms_status_enu_t oms::System::exportToSSD(pugi::xml_node& node, pugi::xml_node& return oms_status_ok; } -oms_status_enu_t oms::System::importFromSnapshot(const pugi::xml_node& node, const std::string& sspVersion, const std::unordered_map& oms_snapshot) +oms_status_enu_t oms::System::importFromSnapshot(const pugi::xml_node& node, const std::string& sspVersion, const Snapshot& snapshot) { std::map startValuesFileSources; ///< ssvFileSource mapped with ssmFilesource if mapping is provided, otherwise only ssvFilesource entry is made @@ -537,7 +534,7 @@ oms_status_enu_t oms::System::importFromSnapshot(const pugi::xml_node& node, con if (ssvFileSource.empty()) // inline parameterBinding { std::string tempdir = getModel()->getTempDirectory(); - if (oms_status_ok != values.importFromSnapshot(*it, sspVersion, oms_snapshot)) + if (oms_status_ok != values.importFromSnapshot(*it, sspVersion, snapshot)) return logError("Failed to import " + std::string(oms::ssp::Version1_0::ssd::parameter_bindings)); } else @@ -562,7 +559,7 @@ oms_status_enu_t oms::System::importFromSnapshot(const pugi::xml_node& node, con // hierarchical level parameter bindings belonging to // provided either as inline or .csv files { - if (oms_status_ok != values.importFromSnapshot(*it, sspVersion, oms_snapshot)) + if (oms_status_ok != values.importFromSnapshot(*it, sspVersion, snapshot)) return logError("Failed to import " + std::string(oms::ssp::Version1_0::ssd::parameter_bindings)); } } @@ -625,7 +622,7 @@ oms_status_enu_t oms::System::importFromSnapshot(const pugi::xml_node& node, con if (!system) return oms_status_error; - if (oms_status_ok != system->importFromSnapshot(*itElements, sspVersion, oms_snapshot)) + if (oms_status_ok != system->importFromSnapshot(*itElements, sspVersion, snapshot)) return oms_status_error; } else if (name == oms::ssp::Draft20180219::ssd::component) @@ -636,14 +633,14 @@ oms_status_enu_t oms::System::importFromSnapshot(const pugi::xml_node& node, con if ("application/x-fmu-sharedlibrary" == type || type.empty() && getType() != oms_system_tlm) { if (getType() == oms_system_wc) - component = ComponentFMUCS::NewComponent(*itElements, this, sspVersion, oms_snapshot); + component = ComponentFMUCS::NewComponent(*itElements, this, sspVersion, snapshot); else if (getType() == oms_system_sc) - component = ComponentFMUME::NewComponent(*itElements, this, sspVersion, oms_snapshot); + component = ComponentFMUME::NewComponent(*itElements, this, sspVersion, snapshot); else return logError("wrong xml schema detected: " + name); } else if ("application/table" == type) - component = ComponentTable::NewComponent(*itElements, this, sspVersion, oms_snapshot); + component = ComponentTable::NewComponent(*itElements, this, sspVersion, snapshot); #if !defined(NO_TLM) else if (itElements->attribute("type") == nullptr && getType() == oms_system_tlm) { std::string name = itElements->attribute("name").as_string(); @@ -754,7 +751,7 @@ oms_status_enu_t oms::System::importFromSnapshot(const pugi::xml_node& node, con // check for ssv file sources exist and set the values before the connections for (auto const& ssvSource : startValuesFileSources) { - importStartValuesFromSSV(ssvSource.first, ssvSource.second, oms_snapshot); + importStartValuesFromSSV(ssvSource.first, ssvSource.second, snapshot); } } else if (name == oms::ssp::Draft20180219::ssd::annotations) @@ -2406,30 +2403,17 @@ oms_status_enu_t oms::System::addAlgLoop(oms_ssc_t SCC, const int algLoopNum) return oms_status_ok; } -oms_status_enu_t oms::System::importStartValuesFromSSV(const std::string& ssvPath, const std::string ssmPath, const std::unordered_map& oms_snapshot) +oms_status_enu_t oms::System::importStartValuesFromSSV(const std::string& ssvPath, const std::string ssmPath, const Snapshot& snapshot) { // mapping between a parameter in the source and a parameter of the system or component being parametrized std::multimap mappedEntry; if (!ssmPath.empty()) - if (oms_status_ok != importParameterMappingFromSSM(ssmPath, oms_snapshot, mappedEntry)) - return oms_status_error; - - return importStartValuesFromSSVHelper(ssvPath, oms_snapshot, mappedEntry); -} - -oms_status_enu_t oms::System::importStartValuesFromSSVHelper(const std::string& ssvPath, const std::unordered_map& oms_snapshot, const std::multimap& mappedEntry) -{ - auto ssvFile = oms_snapshot.find(ssvPath); - if (ssvFile == oms_snapshot.end()) - return logError("Failed to find in snapshot"); + importParameterMappingFromSSM(ssmPath, snapshot, mappedEntry); - pugi::xml_node parameterSet = ssvFile->second.child(oms::ssp::Version1_0::ssv::parameter_set); // ssv:ParameterSet + pugi::xml_node parameterSet = snapshot.getResourcesFile(ssvPath); pugi::xml_node parameters = parameterSet.child(oms::ssp::Version1_0::ssv::parameters); - if (!parameters) - return oms_status_ok; - for (pugi::xml_node_iterator it = parameters.begin(); it != parameters.end(); ++it) { std::string name = it->name(); @@ -2525,15 +2509,9 @@ oms_status_enu_t oms::System::updateAlgebraicLoops(const std::vector< oms_ssc_t return oms_status_ok; } -oms_status_enu_t oms::System::importParameterMappingFromSSM(const std::string& ssmPath, const std::unordered_map& oms_snapshot, std::multimap& mappedEntry) +void oms::System::importParameterMappingFromSSM(const std::string& ssmPath, const Snapshot& snapshot, std::multimap& mappedEntry) { - auto ssmFile = oms_snapshot.find(ssmPath); - if (ssmFile == oms_snapshot.end()) - return logError("Failed to find in snapshot"); - - pugi::xml_node parameterMapping = ssmFile->second.child(oms::ssp::Version1_0::ssm::parameter_mapping); - if (!parameterMapping) - return oms_status_ok; + pugi::xml_node parameterMapping = snapshot.getResourcesFile(ssmPath); for (pugi::xml_node_iterator it = parameterMapping.begin(); it != parameterMapping.end(); ++it) { @@ -2545,8 +2523,6 @@ oms_status_enu_t oms::System::importParameterMappingFromSSM(const std::string& s mappedEntry.insert(std::make_pair(source, it->attribute("target").as_string())); } } - - return oms_status_ok; } oms_status_enu_t oms::System::solveAlgLoop(DirectedGraph& graph, int loopNumber) diff --git a/src/OMSimulatorLib/System.h b/src/OMSimulatorLib/System.h index 85a48f448..4fbee6ffc 100644 --- a/src/OMSimulatorLib/System.h +++ b/src/OMSimulatorLib/System.h @@ -40,13 +40,15 @@ #include "DirectedGraph.h" #include "Element.h" #include "ExternalModel.h" -#include "Values.h" #include "ResultWriter.h" +#include "Snapshot.h" #include "ssd/ConnectorGeometry.h" #if !defined(NO_TLM) #include "TLMBusConnector.h" #endif #include "Types.h" +#include "Values.h" + #include #include #include @@ -83,7 +85,7 @@ namespace oms oms_status_enu_t addSubModel(const ComRef& cref, const std::string& fmuPath); bool validCref(const ComRef& cref); oms_status_enu_t exportToSSD(pugi::xml_node& node, pugi::xml_node& ssvNode) const; - oms_status_enu_t importFromSnapshot(const pugi::xml_node& node, const std::string& sspVersion, const std::unordered_map& oms_snapshot); + oms_status_enu_t importFromSnapshot(const pugi::xml_node& node, const std::string& sspVersion, const Snapshot& snapshot); virtual oms_status_enu_t exportToSSD_SimulationInformation(pugi::xml_node& node) const = 0; virtual oms_status_enu_t importFromSSD_SimulationInformation(const pugi::xml_node& node, const std::string& sspVersion) = 0; void setGeometry(const ssd::ElementGeometry& geometry) {element.setGeometry(&geometry);} @@ -232,9 +234,8 @@ namespace oms oms_status_enu_t importTLMBus(const pugi::xml_node& node, Component* component); oms_status_enu_t importBusConnectorSignals(const pugi::xml_node& node); oms_status_enu_t importBusConnectorGeometry(const pugi::xml_node& node); - oms_status_enu_t importStartValuesFromSSV(const std::string& ssvPath, const std::string ssmPath, const std::unordered_map& oms_snapshot); - oms_status_enu_t importStartValuesFromSSVHelper(const std::string& ssvPath, const std::unordered_map& oms_snapshot, const std::multimap& mappedEntry); - oms_status_enu_t importParameterMappingFromSSM(const std::string& ssmPath, const std::unordered_map& oms_snapshot, std::multimap& mappedEntry); + oms_status_enu_t importStartValuesFromSSV(const std::string& ssvPath, const std::string ssmPath, const Snapshot& snapshot); + void importParameterMappingFromSSM(const std::string& ssmPath, const Snapshot& snapshot, std::multimap& mappedEntry); std::vector algLoops; ///< Vector of algebraic loop objects }; diff --git a/src/OMSimulatorLib/SystemSC.cpp b/src/OMSimulatorLib/SystemSC.cpp index d70e3b97c..68bb3ca2a 100644 --- a/src/OMSimulatorLib/SystemSC.cpp +++ b/src/OMSimulatorLib/SystemSC.cpp @@ -36,11 +36,8 @@ #include "ComponentTable.h" #include "Flags.h" #include "Model.h" -#include "Types.h" #include "ssd/Tags.h" -#include /* prototypes for CVODE fcts., consts. */ -#include /* serial N_Vector types, fcts., macros */ -#include /* Default dense linear solver */ + int oms::cvode_rhs(realtype t, N_Vector y, N_Vector ydot, void* user_data) { diff --git a/src/OMSimulatorLib/SystemWC.cpp b/src/OMSimulatorLib/SystemWC.cpp index e07789396..804f4d609 100644 --- a/src/OMSimulatorLib/SystemWC.cpp +++ b/src/OMSimulatorLib/SystemWC.cpp @@ -35,10 +35,9 @@ #include "ComponentFMUCS.h" #include "Flags.h" #include "Model.h" -#include "SignalDerivative.h" #include "ssd/Tags.h" #include "SystemTLM.h" -#include "Types.h" + #include #include #include diff --git a/src/OMSimulatorLib/SystemWC.h b/src/OMSimulatorLib/SystemWC.h index ea23d474d..b500f81ec 100644 --- a/src/OMSimulatorLib/SystemWC.h +++ b/src/OMSimulatorLib/SystemWC.h @@ -38,6 +38,7 @@ #include "StepSizeConfiguration.h" #include "System.h" #include "Types.h" + #include namespace oms diff --git a/src/OMSimulatorLib/TLM/ExternalModel.cpp b/src/OMSimulatorLib/TLM/ExternalModel.cpp index 2db2346ac..acef05563 100644 --- a/src/OMSimulatorLib/TLM/ExternalModel.cpp +++ b/src/OMSimulatorLib/TLM/ExternalModel.cpp @@ -61,7 +61,7 @@ oms::ExternalModel* oms::ExternalModel::NewComponent(const oms::ComRef& cref, Sy return model; } -oms_status_enu_t oms::ExternalModel::setRealParameter(const std::string &var, double value) +oms_status_enu_t oms::ExternalModel::setRealParameter(const std::string& var, double value) { std::map>::iterator it; it = realParameters.find(var); @@ -74,7 +74,7 @@ oms_status_enu_t oms::ExternalModel::setRealParameter(const std::string &var, do return oms_status_error; } -oms_status_enu_t oms::ExternalModel::getRealParameter(const std::string &var, double &value) +oms_status_enu_t oms::ExternalModel::getRealParameter(const std::string& var, double &value) { std::map>::iterator it; it = realParameters.find(var); diff --git a/src/OMSimulatorLib/TLM/SystemTLM.cpp b/src/OMSimulatorLib/TLM/SystemTLM.cpp index 5ee356902..e3dc4aab5 100644 --- a/src/OMSimulatorLib/TLM/SystemTLM.cpp +++ b/src/OMSimulatorLib/TLM/SystemTLM.cpp @@ -122,7 +122,7 @@ oms_status_enu_t oms::SystemTLM::importFromSSD_SimulationInformation(const pugi: return oms_status_ok; } -oms_status_enu_t oms::SystemTLM::importFromSSD_SimulationInformationHelper(const pugi::xml_node & node) +oms_status_enu_t oms::SystemTLM::importFromSSD_SimulationInformationHelper(const pugi::xml_node& node) { pugi::xml_node tlmmasterNode = node.child("oms::ssp::Draft20180219::tlm_master"); for (auto it = tlmmasterNode.attributes_begin(); it != tlmmasterNode.attributes_end(); ++it) @@ -421,7 +421,7 @@ void oms::SystemTLM::disconnectFromSockets(const oms::ComRef cref) } } -oms_status_enu_t oms::SystemTLM::setSocketData(const std::string &address, int managerPort, int monitorPort) +oms_status_enu_t oms::SystemTLM::setSocketData(const std::string& address, int managerPort, int monitorPort) { if (!getModel()->validState(oms_modelState_virgin)) return logError_ModelInWrongState(this); diff --git a/src/OMSimulatorLib/TLM/TLMBusConnector.cpp b/src/OMSimulatorLib/TLM/TLMBusConnector.cpp index d8585bd13..4484fb76a 100644 --- a/src/OMSimulatorLib/TLM/TLMBusConnector.cpp +++ b/src/OMSimulatorLib/TLM/TLMBusConnector.cpp @@ -46,7 +46,7 @@ oms::TLMBusConnector::~TLMBusConnector() } } -oms_status_enu_t oms::TLMBusConnector::exportToSSD(pugi::xml_node &root) const +oms_status_enu_t oms::TLMBusConnector::exportToSSD(pugi::xml_node& root) const { pugi::xml_node bus_node = root.append_child(oms::ssp::Draft20180219::bus); bus_node.append_attribute("name") = name; @@ -61,16 +61,15 @@ oms_status_enu_t oms::TLMBusConnector::exportToSSD(pugi::xml_node &root) const bus_node.append_attribute("interpolation") = "finegrained"; pugi::xml_node signals_node = bus_node.append_child(oms::ssp::Draft20180219::signals); - for(auto& connector : connectors) { + for(auto& connector : connectors) + { pugi::xml_node signal_node = signals_node.append_child(oms::ssp::Draft20180219::signal); signal_node.append_attribute("name") = connector.second.c_str(); signal_node.append_attribute("type") = connector.first.c_str(); } if (this->geometry) - { return reinterpret_cast(this->geometry)->exportToSSD(bus_node); - } return oms_status_ok; } diff --git a/src/OMSimulatorLib/Util.h b/src/OMSimulatorLib/Util.h index d763b160a..42ac188b5 100644 --- a/src/OMSimulatorLib/Util.h +++ b/src/OMSimulatorLib/Util.h @@ -32,12 +32,12 @@ #ifndef _OMS_UTIL_H_ #define _OMS_UTIL_H_ -#include -#include #include #include #include #include +#include +#include // trim from start (in place) // https://stackoverflow.com/a/217605/7534030 diff --git a/src/OMSimulatorLib/Values.cpp b/src/OMSimulatorLib/Values.cpp index dfba8dda8..605d666b2 100644 --- a/src/OMSimulatorLib/Values.cpp +++ b/src/OMSimulatorLib/Values.cpp @@ -30,19 +30,16 @@ */ -#include "Util.h" -#include "Logging.h" #include "Values.h" -#include "Types.h" -#include "ComRef.h" + +#include "Logging.h" #include "ssd/Tags.h" -#include +#include "Util.h" -#include +#include #include +#include #include -#include -#include oms::Values::Values() @@ -106,7 +103,7 @@ oms_status_enu_t oms::Values::deleteStartValue(const ComRef& cref) oms_status_enu_t oms::Values::exportToSSD(pugi::xml_node& node) const { // skip this if there is nothing to export - if (realStartValues.empty() && integerStartValues.empty() && booleanStartValues.empty()) + if (this->empty()) return oms_status_ok; // Top level Parameter nodes @@ -125,7 +122,7 @@ oms_status_enu_t oms::Values::exportToSSD(pugi::xml_node& node) const return oms_status_ok; } -oms_status_enu_t oms::Values::importFromSnapshot(const pugi::xml_node& node, const std::string& sspVersion, const std::unordered_map& oms_snapshot) +oms_status_enu_t oms::Values::importFromSnapshot(const pugi::xml_node& node, const std::string& sspVersion, const Snapshot& snapshot) { for (pugi::xml_node parameterBindingNode = node.child(oms::ssp::Version1_0::ssd::parameter_binding); parameterBindingNode; parameterBindingNode = parameterBindingNode.next_sibling(oms::ssp::Version1_0::ssd::parameter_binding)) { @@ -133,11 +130,10 @@ oms_status_enu_t oms::Values::importFromSnapshot(const pugi::xml_node& node, con if (!ssvFile.empty()) // parameter binding provided with .ssv file { - auto oms_ssv_file = oms_snapshot.find(ssvFile); - if (oms_snapshot.end() == oms_ssv_file) + pugi::xml_node parameterSet = snapshot.getResourcesFile(ssvFile); + if (!parameterSet) return logError("loading \"" + ssvFile + "\" from failed"); - pugi::xml_node parameterSet = oms_ssv_file->second.child(oms::ssp::Version1_0::ssv::parameter_set); // ssv:ParameterSet pugi::xml_node parameters = parameterSet.child(oms::ssp::Version1_0::ssv::parameters); // check for parameterMapping (e.g) @@ -149,11 +145,10 @@ oms_status_enu_t oms::Values::importFromSnapshot(const pugi::xml_node& node, con std::string ssmFileSource = ssd_parameterMapping.attribute("source").as_string(); if (!ssmFileSource.empty()) { - auto oms_ssm_file = oms_snapshot.find(ssmFileSource); - if (oms_snapshot.end() == oms_ssm_file) + pugi::xml_node ssm_parameterMapping = snapshot.getResourcesFile(ssmFileSource); + if (!ssm_parameterMapping) return logError("loading \"" + ssmFileSource + "\" from failed"); - pugi::xml_node ssm_parameterMapping = oms_ssm_file->second.child(oms::ssp::Version1_0::ssm::parameter_mapping); // ssm:ParameterMapping importParameterMapping(ssm_parameterMapping); } } @@ -260,40 +255,25 @@ oms_status_enu_t oms::Values::exportStartValuesHelper(pugi::xml_node& node) cons * returns mapped cref if entry found associated with parameter mapping, * otherwise return the default cref */ -oms::ComRef oms::Values::getMappedCrefEntry(ComRef cref) const +oms::ComRef oms::Values::getMappedCrefEntry(const ComRef& cref) const { - if (mappedEntry.empty()) - { - return cref; - } - - ComRef mappedCref = cref; for (const auto &it : mappedEntry) - { if (it.second == cref) - { - mappedCref = it.first; - break; - } - } + return it.first; - return mappedCref; + return cref; } -/* - * export parameter mapping inline associated with parameterbinding - * - * - * - * - * - */ -oms_status_enu_t oms::Values::exportParameterMappingInline(pugi::xml_node& node) const +// export parameter mapping inline associated with parameterbinding +// +// +// +// +// +void oms::Values::exportParameterMappingInline(pugi::xml_node& node) const { if (mappedEntry.empty()) - { - return oms_status_ok; - } + return; pugi::xml_node ssd_parameter_mapping = node.append_child(oms::ssp::Version1_0::ssd::parameter_mapping); pugi::xml_node ssm_parameter_mapping = ssd_parameter_mapping.append_child(oms::ssp::Version1_0::ssm::parameter_mapping); @@ -304,18 +284,16 @@ oms_status_enu_t oms::Values::exportParameterMappingInline(pugi::xml_node& node) ssm_mapping_entry.append_attribute("source") = it.first.c_str(); ssm_mapping_entry.append_attribute("target") = it.second.c_str(); } - - return oms_status_ok; } /* * exports the start values read from modeldescription.xml to ssv template */ -oms_status_enu_t oms::Values::exportToSSVTemplate(pugi::xml_node& node, const ComRef& cref) +void oms::Values::exportToSSVTemplate(pugi::xml_node& node, const ComRef& cref) { // skip this if there is nothing to export if (modelDescriptionRealStartValues.empty() && modelDescriptionIntegerStartValues.empty() && modelDescriptionBooleanStartValues.empty()) - return oms_status_ok; + return; // realStartValues for (const auto& r : modelDescriptionRealStartValues) @@ -344,8 +322,6 @@ oms_status_enu_t oms::Values::exportToSSVTemplate(pugi::xml_node& node, const Co pugi::xml_node node_parameter_type = node_parameter.append_child(oms::ssp::Version1_0::ssv::boolean_type); node_parameter_type.append_attribute("value") = b.second; } - - return oms_status_ok; } /* @@ -386,96 +362,87 @@ oms_status_enu_t oms::Values::exportToSSMTemplate(pugi::xml_node& node, const Co return oms_status_ok; } -oms_status_enu_t oms::Values::importStartValuesHelper(pugi::xml_node& parameters) +oms_status_enu_t oms::Values::importStartValuesHelper(const pugi::xml_node& parameters) { - if (parameters) + if (!parameters) + return oms_status_ok; + + for(pugi::xml_node_iterator itparameters = parameters.begin(); itparameters != parameters.end(); ++itparameters) { - for(pugi::xml_node_iterator itparameters = parameters.begin(); itparameters != parameters.end(); ++itparameters) + std::string name = itparameters->name(); + std::vector mappedcrefs; + if (name == oms::ssp::Version1_0::ssv::parameter) { - std::string name = itparameters->name(); - std::vector mappedcrefs; - if (name == oms::ssp::Version1_0::ssv::parameter) + ComRef cref = ComRef(itparameters->attribute("name").as_string()); + + // check cref has any mapping entry + if (!mappedEntry.empty()) { - ComRef cref = ComRef(itparameters->attribute("name").as_string()); - // check cref has any mapping entry - if (!mappedEntry.empty()) + auto mapfind = mappedEntry.equal_range(cref); + for (auto it = mapfind.first; it != mapfind.second; ++it) + mappedcrefs.push_back(it->second); + } + + if (itparameters->child(oms::ssp::Version1_0::ssv::real_type)) + { + double value = itparameters->child(oms::ssp::Version1_0::ssv::real_type).attribute("value").as_double(); + if (!mappedcrefs.empty()) { - auto mapfind = mappedEntry.equal_range(cref); - for (auto it = mapfind.first; it != mapfind.second; ++it) - { - mappedcrefs.push_back(it->second); - } + for (const auto &mappedcref : mappedcrefs) + setReal(mappedcref, value); } - - if (itparameters->child(oms::ssp::Version1_0::ssv::real_type)) + else { - double value = itparameters->child(oms::ssp::Version1_0::ssv::real_type).attribute("value").as_double(); - if (!mappedcrefs.empty()) - { - for (const auto &mappedcref : mappedcrefs) - { - setReal(mappedcref, value); - } - } - else - { - // no mapping entry found, apply the default cref found in ssv file - setReal(cref, value); - } + // no mapping entry found, apply the default cref found in ssv file + setReal(cref, value); } - else if (itparameters->child(oms::ssp::Version1_0::ssv::integer_type)) + } + else if (itparameters->child(oms::ssp::Version1_0::ssv::integer_type)) + { + int value = itparameters->child(oms::ssp::Version1_0::ssv::integer_type).attribute("value").as_int(); + if (!mappedcrefs.empty()) { - int value = itparameters->child(oms::ssp::Version1_0::ssv::integer_type).attribute("value").as_int(); - if (!mappedcrefs.empty()) - { - for (const auto &mappedcref : mappedcrefs) - { - setInteger(mappedcref, value); - } - } - else - { - // no mapping entry found, apply the default cref found in ssv file - setInteger(cref, value); - } + for (const auto &mappedcref : mappedcrefs) + setInteger(mappedcref, value); } - else if(itparameters->child(oms::ssp::Version1_0::ssv::boolean_type)) + else { - bool value = itparameters->child(oms::ssp::Version1_0::ssv::boolean_type).attribute("value").as_bool(); - if (!mappedcrefs.empty()) - { - for (const auto &mappedcref : mappedcrefs) - { - setBoolean(mappedcref, value); - } - } - else - { - // no mapping entry found, apply the default cref found in ssv file - setBoolean(cref, value); - } + // no mapping entry found, apply the default cref found in ssv file + setInteger(cref, value); + } + } + else if(itparameters->child(oms::ssp::Version1_0::ssv::boolean_type)) + { + bool value = itparameters->child(oms::ssp::Version1_0::ssv::boolean_type).attribute("value").as_bool(); + if (!mappedcrefs.empty()) + { + for (const auto &mappedcref : mappedcrefs) + setBoolean(mappedcref, value); } else { - logError("Failed to import " + std::string(oms::ssp::Version1_0::ssv::parameter) + ":Unknown ParameterBinding-type"); + // no mapping entry found, apply the default cref found in ssv file + setBoolean(cref, value); } } + else + { + logError("Failed to import " + std::string(oms::ssp::Version1_0::ssv::parameter) + ":Unknown ParameterBinding-type"); + } } } return oms_status_ok; } -oms_status_enu_t oms::Values::parseModelDescription(const char *filename) +oms_status_enu_t oms::Values::parseModelDescription(const filesystem::path& root) { - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file(filename); - pugi::xml_node node = doc.document_element(); // modelDescription.xml + Snapshot snapshot; + snapshot.importResourcesFile("modelDescription.xml", root); + const pugi::xml_node node = snapshot.getResourcesFile("modelDescription.xml"); - if (!result) - { + if (!node) return logError("Failed to load modelDescription.xml"); - } //std::string fmiVersion = node.attribute("fmiVersion").as_string(); @@ -511,27 +478,19 @@ oms_status_enu_t oms::Values::parseModelDescription(const char *filename) return oms_status_ok; } -oms_status_enu_t oms::Values::importParameterMapping(pugi::xml_node& parameterMapping) +void oms::Values::importParameterMapping(const pugi::xml_node& parameterMapping) { - if (parameterMapping) + if (!parameterMapping) + return; + + for (pugi::xml_node_iterator it = parameterMapping.begin(); it != parameterMapping.end(); ++it) { - for (pugi::xml_node_iterator itparametermapping = parameterMapping.begin(); itparametermapping != parameterMapping.end(); ++itparametermapping) - { - std::string name = itparametermapping->name(); - if (name == oms::ssp::Version1_0::ssm::parameter_mapping_entry) - { - ComRef source = itparametermapping->attribute("source").as_string(); - if (!source.isEmpty()) - { - mappedEntry.insert(std::make_pair(source, itparametermapping->attribute("target").as_string())); - } - else - { - // default value will be applied - } - } - } - } + std::string name = it->name(); + if (oms::ssp::Version1_0::ssm::parameter_mapping_entry != name) + continue; - return oms_status_ok; + ComRef source = it->attribute("source").as_string(); + if (!source.isEmpty()) + mappedEntry.insert(std::make_pair(source, it->attribute("target").as_string())); + } } diff --git a/src/OMSimulatorLib/Values.h b/src/OMSimulatorLib/Values.h index 6e1deefa0..1e2f33f4b 100644 --- a/src/OMSimulatorLib/Values.h +++ b/src/OMSimulatorLib/Values.h @@ -33,10 +33,12 @@ #define _OMS_VALUES_H_ #include "ComRef.h" +#include "OMSFileSystem.h" +#include "Snapshot.h" #include "Types.h" -#include + #include -#include +#include namespace oms { @@ -51,23 +53,25 @@ namespace oms oms_status_enu_t setBoolean(const ComRef& cref, bool value); oms_status_enu_t exportToSSD(pugi::xml_node& node) const; - oms_status_enu_t importFromSnapshot(const pugi::xml_node& node, const std::string& sspVersion, const std::unordered_map& oms_snapshot); + oms_status_enu_t importFromSnapshot(const pugi::xml_node& node, const std::string& sspVersion, const Snapshot& snapshot); oms_status_enu_t deleteStartValue(const ComRef& cref); oms_status_enu_t exportToSSV(pugi::xml_node& ssvNode) const; - oms_status_enu_t exportToSSVTemplate(pugi::xml_node& ssvNode, const ComRef& cref); ///< start values read from modelDescription.xml and creates a ssv template + void exportToSSVTemplate(pugi::xml_node& ssvNode, const ComRef& cref); ///< start values read from modelDescription.xml and creates a ssv template oms_status_enu_t exportToSSMTemplate(pugi::xml_node& ssmNode, const ComRef& cref); ///< start values read from modelDescription.xml and creates a ssm template + oms_status_enu_t parseModelDescription(const filesystem::path& root); ///< path without the filename, i.e. modelDescription.xml + + private: oms_status_enu_t exportStartValuesHelper(pugi::xml_node& node) const; - oms_status_enu_t exportParameterMappingInline(pugi::xml_node& node) const; - oms_status_enu_t importStartValuesHelper(pugi::xml_node& parameters); - oms_status_enu_t importParameterMapping(pugi::xml_node& parameterMapping); - oms_status_enu_t parseModelDescription(const char *filename); + void exportParameterMappingInline(pugi::xml_node& node) const; + oms_status_enu_t importStartValuesHelper(const pugi::xml_node& parameters); + void importParameterMapping(const pugi::xml_node& parameterMapping); + oms::ComRef getMappedCrefEntry(const ComRef& cref) const; bool empty() const; - oms::ComRef getMappedCrefEntry(ComRef cref) const; - + public: std::map realStartValues; ///< parameters and start values defined before instantiating the FMU std::map integerStartValues; ///< parameters and start values defined before instantiating the FMU std::map booleanStartValues; ///< parameters and start values defined before instantiating the FMU @@ -81,8 +85,6 @@ namespace oms std::map modelDescriptionBooleanStartValues; ///< boolean start values read from modelDescription.xml std::multimap mappedEntry; ///< parameter names and values provided in the parameter source are to be mapped to the parameters of the component or system - - std::string path; }; } diff --git a/src/OMSimulatorLib/Variable.cpp b/src/OMSimulatorLib/Variable.cpp index a0920205d..1458c5c70 100644 --- a/src/OMSimulatorLib/Variable.cpp +++ b/src/OMSimulatorLib/Variable.cpp @@ -33,6 +33,7 @@ #include "Logging.h" #include "Util.h" + #include #include #include diff --git a/src/OMSimulatorLib/Variable.h b/src/OMSimulatorLib/Variable.h index f03bf80f5..5cffea637 100644 --- a/src/OMSimulatorLib/Variable.h +++ b/src/OMSimulatorLib/Variable.h @@ -35,6 +35,7 @@ #include "ComRef.h" #include "Connector.h" #include "Types.h" + #include #include #include diff --git a/src/OMSimulatorLib/ssd/ConnectionGeometry.cpp b/src/OMSimulatorLib/ssd/ConnectionGeometry.cpp index a0e9f3714..0c0d35a3a 100644 --- a/src/OMSimulatorLib/ssd/ConnectionGeometry.cpp +++ b/src/OMSimulatorLib/ssd/ConnectionGeometry.cpp @@ -181,12 +181,12 @@ oms_status_enu_t oms::ssd::ConnectionGeometry::importFromSSD(const pugi::xml_nod double* pointsX = new double[pointsXVector.size()]; int i = 0; - for (auto& px : pointsXVector) + for (const auto& px : pointsXVector) pointsX[i++] = std::atof(px.c_str()); double* pointsY = new double[pointsYVector.size()]; i = 0; - for (auto& py : pointsYVector) + for (const auto& py : pointsYVector) pointsY[i++] = std::atof(py.c_str()); setPoints(pointsXVector.size(), pointsX, pointsY);