diff --git a/.gitignore b/.gitignore
index 48ab192130a8c3994cf4f013ea5c57ad7cb4e00b..9156ce91b45dd384ba5ffb4b029e0a4724997937 100644
--- a/.gitignore
+++ b/.gitignore
@@ -247,3 +247,4 @@ ModelManifest.xml
 /MC_Backend_Win/MODELS
 /MC_Backend_Win/MODELI/Sample
 /MC_Backend_Win/fd9a-e8c9-6abb-2f17
+/MC_Backend_Win/UNZIP
diff --git a/FMU-Core b/FMU-Core
index 6625e00268bcfde0b6b2b9c237e05c1a20c23922..b36003d99442732b3835897b4da3d9617efca79e 160000
--- a/FMU-Core
+++ b/FMU-Core
@@ -1 +1 @@
-Subproject commit 6625e00268bcfde0b6b2b9c237e05c1a20c23922
+Subproject commit b36003d99442732b3835897b4da3d9617efca79e
diff --git a/Files/Files.vcxitems b/Files/Files.vcxitems
index b39446cf2be76fb165e885bc996c97006fe583c5..08640af0c8474c44d3c37d7ce13900c9a579b716 100644
--- a/Files/Files.vcxitems
+++ b/Files/Files.vcxitems
@@ -16,15 +16,17 @@
     <ProjectCapability Include="SourceItemsFromImports" />
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="$(MSBuildThisFileDirectory)FmuFile.hpp" />
+    <ClInclude Include="$(MSBuildThisFileDirectory)ModelDescription.h" />
+    <ClInclude Include="$(MSBuildThisFileDirectory)FmuFileManager.h" />
     <ClInclude Include="$(MSBuildThisFileDirectory)ModeliFile.hpp" />
     <ClInclude Include="$(MSBuildThisFileDirectory)Unzipper.hpp" />
     <ClInclude Include="$(MSBuildThisFileDirectory)zip_file.hpp" />
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="$(MSBuildThisFileDirectory)FmuFile.cpp">
+    <ClCompile Include="$(MSBuildThisFileDirectory)ModelDescription.cpp">
       <PrecompiledHeader>NotUsing</PrecompiledHeader>
     </ClCompile>
+    <ClCompile Include="$(MSBuildThisFileDirectory)FmuFileManager.cpp" />
     <ClCompile Include="$(MSBuildThisFileDirectory)ModeliFile.cpp" />
     <ClCompile Include="$(MSBuildThisFileDirectory)Unzipper.cpp" />
   </ItemGroup>
diff --git a/Files/Files.vcxitems.filters b/Files/Files.vcxitems.filters
index 189ec2078a477e60f8dbc2be5afa1986781ac481..24285bdf197834b607217454af3d1f0a865e9e13 100644
--- a/Files/Files.vcxitems.filters
+++ b/Files/Files.vcxitems.filters
@@ -11,9 +11,6 @@
     </Filter>
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="$(MSBuildThisFileDirectory)FmuFile.hpp">
-      <Filter>Header</Filter>
-    </ClInclude>
     <ClInclude Include="$(MSBuildThisFileDirectory)ModeliFile.hpp">
       <Filter>Header</Filter>
     </ClInclude>
@@ -23,16 +20,25 @@
     <ClInclude Include="$(MSBuildThisFileDirectory)zip_file.hpp">
       <Filter>Header</Filter>
     </ClInclude>
+    <ClInclude Include="$(MSBuildThisFileDirectory)FmuFileManager.h">
+      <Filter>Header</Filter>
+    </ClInclude>
+    <ClInclude Include="$(MSBuildThisFileDirectory)ModelDescription.h">
+      <Filter>Header</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="$(MSBuildThisFileDirectory)FmuFile.cpp">
-      <Filter>Source</Filter>
-    </ClCompile>
     <ClCompile Include="$(MSBuildThisFileDirectory)ModeliFile.cpp">
       <Filter>Source</Filter>
     </ClCompile>
     <ClCompile Include="$(MSBuildThisFileDirectory)Unzipper.cpp">
       <Filter>Source</Filter>
     </ClCompile>
+    <ClCompile Include="$(MSBuildThisFileDirectory)FmuFileManager.cpp">
+      <Filter>Source</Filter>
+    </ClCompile>
+    <ClCompile Include="$(MSBuildThisFileDirectory)ModelDescription.cpp">
+      <Filter>Source</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/Files/FmuFileManager.cpp b/Files/FmuFileManager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ff069a56b554cd1ef9009b96c7b7c8ed029577e8
--- /dev/null
+++ b/Files/FmuFileManager.cpp
@@ -0,0 +1,100 @@
+#include "FmuFileManager.h"
+#include "Unzipper.hpp"
+#include "boost/filesystem.hpp"
+
+namespace fs = boost::filesystem;
+
+namespace Files
+{
+    FmuFileManager::FmuFileManager()
+    {
+    }
+
+    FmuFileManager::~FmuFileManager()
+    {
+    }
+
+    ModelDescription FmuFileManager::add_model(std::vector<unsigned char> buffer)
+    {
+        // Unzip the fmu from byte buffer
+        auto unzip_dir = create_unzip_dir();
+        Unzipper::Unzip(std::move(buffer), unzip_dir);
+        return add_from_unzipped(unzip_dir);
+    }
+
+    ModelDescription FmuFileManager::add_model(std::string path)
+    {
+        // Unzip the fmu from byte buffer
+        auto unzip_dir = create_unzip_dir();
+        Unzipper::Unzip(path, unzip_dir);
+        return add_from_unzipped(unzip_dir);
+    }
+
+    void FmuFileManager::remove_model(std::string model_name)
+    {
+        if (m_models.count(model_name) == 1)
+        {
+            fs::remove_all(m_models[model_name].get_model_dir());
+            m_models.erase(model_name);
+        }
+    }
+
+    std::vector<ModelDescription> FmuFileManager::get_all()
+    {
+        std::vector<ModelDescription> retval;
+        for (auto element : m_models)
+        {
+            retval.push_back(element.second);
+        }
+        return retval;
+    }
+
+    void FmuFileManager::clear()
+    {
+        fs::remove_all(MODELS_DIR);
+        m_models.clear();
+    }
+
+    std::string FmuFileManager::create_unzip_dir()
+    {
+        fs::path unzip_path;
+        do
+        {
+            unzip_path /= UNZIP_DIR;
+            unzip_path /= fs::unique_path();
+        } while (fs::exists(unzip_path));
+        fs::create_directories(unzip_path);
+        return unzip_path.generic_string();
+    }
+
+    ModelDescription FmuFileManager::add_from_unzipped(std::string unzip_dir)
+    {
+        // Load the model description
+        ModelDescription model;
+        model.set_model_dir(unzip_dir);
+        model.load();
+        // Check if the model exists
+        if (m_models.count(model.get_model_name()) == 1)
+        {
+            // Clean temp
+            fs::remove_all(unzip_dir);
+            // Return existing instance
+            return m_models[model.get_model_name()];
+        }
+        else
+        {
+            // Move to the MODELS dir
+            fs::path new_dir;
+            new_dir /= MODELS_DIR;
+            new_dir /= model.get_model_name();
+            // Windows requires the parent path to exist but the leaf directory must not exist!
+            fs::create_directories(new_dir);
+            fs::remove_all(new_dir);
+            fs::rename(fs::path(unzip_dir), new_dir);
+            model.set_model_dir(new_dir.generic_string());
+            // Return the new model
+            m_models.emplace(model.get_model_name(), model);
+            return model;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Files/FmuFileManager.h b/Files/FmuFileManager.h
new file mode 100644
index 0000000000000000000000000000000000000000..95c3d92e22feb36a491677d18df707be5ceb4a22
--- /dev/null
+++ b/Files/FmuFileManager.h
@@ -0,0 +1,42 @@
+#pragma once
+#include "ModelDescription.h"
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace Files
+{
+    /// Manages the FmuFiles which are contained in the MODELS directory.
+    class FmuFileManager
+    {
+    public:
+        FmuFileManager();
+        FmuFileManager(const FmuFileManager&) = delete;
+        ModelDescription& operator=(const FmuFileManager&) = delete;
+        ~FmuFileManager();
+
+        /// Add a new ModelDescription from a buffer and return it
+        ModelDescription add_model(std::vector<unsigned char> buffer);
+        /// Add a new ModelDescription from the filesystem
+        ModelDescription add_model(std::string path);
+        /// Removes the ModelDescription from the filesystem
+        void remove_model(std::string model_name);
+        /// Returns a vector of all model descriptions
+        std::vector<ModelDescription> get_all();
+        /// Clears the models
+        void clear();
+    private:
+        const std::string MODELS_DIR = "MODELS";
+        const std::string UNZIP_DIR = "UNZIP";
+        // Store model_name, decription
+        std::map<std::string, ModelDescription> m_models;
+        // Creates an empty directory for unzipping the fmu.
+        // The path to the directory is returned.
+        std::string create_unzip_dir();
+
+        // Add a model description that has been unzipped to the unzip_dir
+        ModelDescription add_from_unzipped(std::string unzip_dir);     
+    };
+
+}
\ No newline at end of file
diff --git a/Files/FmuFile.cpp b/Files/ModelDescription.cpp
similarity index 56%
rename from Files/FmuFile.cpp
rename to Files/ModelDescription.cpp
index f1e5263291fc2a98392e5dd8d7c6225766768eb8..ec7e210adedf7f7487775371ad9e0ff598de68bd 100644
--- a/Files/FmuFile.cpp
+++ b/Files/ModelDescription.cpp
@@ -1,8 +1,7 @@
-#include "FmuFile.hpp"
+#include "ModelDescription.h"
 #include "boost/filesystem.hpp"
 #include "boost/property_tree/ptree.hpp"
 #include "boost/property_tree/xml_parser.hpp"
-#include "Unzipper.hpp"
 #include <iostream>
 
 namespace fs = boost::filesystem;
@@ -10,24 +9,29 @@ namespace pt = boost::property_tree;
 
 namespace Files
 {
-    void FmuFile::unzip_and_load(std::function<void(std::string unzipPath)> unzipAction)
+    ModelDescription::ModelDescription()
+    {
+    }
+    ModelDescription::~ModelDescription()
     {
-        // Unzip the fmu
-        m_unzippedPath = fs::unique_path().generic_string();
-        unzipAction(m_unzippedPath);
-        // Parse the model description
-        std::string xmlPath = m_unzippedPath + "/modelDescription.xml";
-        pt::ptree md;
-        pt::read_xml(xmlPath, md);
-        m_modelName = md.get<std::string>("fmiModelDescription.CoSimulation.<xmlattr>.modelIdentifier");
-        m_guid = md.get<std::string>("fmiModelDescription.<xmlattr>.guid");
-        load_value_refs(md);       
     }
 
-    void FmuFile::load_value_refs(const boost::property_tree::ptree & xmlRoot)
+    void ModelDescription::load()
     {
+        // Create & load ptree
+        std::string xmlPath = m_model_dir + "/modelDescription.xml";
+        if (!fs::exists(xmlPath))
+        {
+            // Do not crash. Load nothing.
+            return;
+        }
+        pt::ptree desc;
+        pt::read_xml(xmlPath, desc);
+        // Load model information
+        m_model_name = desc.get<std::string>("fmiModelDescription.CoSimulation.<xmlattr>.modelIdentifier");
+        m_guid = desc.get<std::string>("fmiModelDescription.<xmlattr>.guid");
         // The valuereferences
-        for (auto scalar_var : xmlRoot.get_child("fmiModelDescription.ModelVariables"))
+        for (auto scalar_var : desc.get_child("fmiModelDescription.ModelVariables"))
         {
             // Simplify the checking and adding a value reference
             auto check_and_add = [scalar_var](std::string varType, std::vector<unsigned int>& vr_vector)
@@ -52,35 +56,20 @@ namespace Files
         }
     }
 
-    FmuFile::FmuFile(std::string pathToFmu)
+    void ModelDescription::set_model_dir(std::string model_dir)
     {
-        unzip_and_load([pathToFmu](std::string unzipPath)
-        {
-            Unzipper::Unzip(pathToFmu, unzipPath);
-        });
-    }
-    FmuFile::FmuFile(const std::vector<unsigned char>& buffer)
-    {
-        unzip_and_load([&](std::string unzipPath)
-        {
-            Unzipper::Unzip(buffer, unzipPath);
-        });
+        m_model_dir = model_dir;
     }
 
-    FmuFile::~FmuFile()
+    std::string ModelDescription::get_model_dir()
     {
-        boost::system::error_code error;
-        fs::remove_all(m_unzippedPath, error);
-        if (error)
-        {
-            std::cout << error.message() << std::endl;
-        }
+        return m_model_dir;
     }
 
-    std::string FmuFile::GetBinaryPath()
+    std::string ModelDescription::get_binary_path()
     {
         // The pathToFmu of the binary depends on the system
-        fs::path binaryPath = m_unzippedPath;
+        fs::path binaryPath = m_model_dir;
         binaryPath /=  "binaries";
 #if __linux__
 #if __arm__
@@ -97,38 +86,43 @@ namespace Files
 #else
 #error system ist not supported
 #endif
-        binaryPath /= m_modelName;
+        binaryPath /= m_model_name;
         // Return canonical (absolute) pathToFmu.
         // Don not use relative paths for dynamic library loading (security)!
         return fs::weakly_canonical(binaryPath).generic_string();
     }
 
-    std::string FmuFile::GetGUID()
+    std::string ModelDescription::get_model_name()
+    {
+        return m_model_name;
+    }
+
+    std::string ModelDescription::get_guid()
     {
         return m_guid;
     }
-    std::string FmuFile::GetResourceUri()
+    std::string ModelDescription::get_resource_uri()
     {
         // Create prefix
         std::string prefix = "file:///";	// mandatory according to the fmi doc
         // Create pathToFmu object
-        std::string resourceDir = m_unzippedPath + "/resources";
+        std::string resourceDir = m_model_dir + "/resources";
         // Append absolute pathToFmu of the mod		
         return prefix + resourceDir;
     }
-    std::vector<unsigned int> FmuFile::get_int_vrs()
+    std::vector<unsigned int> ModelDescription::get_int_vrs()
     {
         return m_int_vrs;
     }
-    std::vector<unsigned int> FmuFile::get_real_vrs()
+    std::vector<unsigned int> ModelDescription::get_real_vrs()
     {
         return m_real_vrs;
     }
-    std::vector<unsigned int> FmuFile::get_bool_vrs()
+    std::vector<unsigned int> ModelDescription::get_bool_vrs()
     {
         return m_bool_vrs;
     }
-    std::vector<unsigned int> FmuFile::get_string_vrs()
+    std::vector<unsigned int> ModelDescription::get_string_vrs()
     {
         return m_string_vrs;
     }
diff --git a/Files/FmuFile.hpp b/Files/ModelDescription.h
similarity index 58%
rename from Files/FmuFile.hpp
rename to Files/ModelDescription.h
index f662febef2c92aa50d6fbbbc1c32df4f48c74ed4..b322d013e87467c9a705135f1e7b571443927038 100644
--- a/Files/FmuFile.hpp
+++ b/Files/ModelDescription.h
@@ -9,42 +9,40 @@ namespace Files
 {
     /// Handles the fmu file. On creation the fmu is extracted.
     /// On destruction the extracted files are cleaned up.
-    class FmuFile
+    class ModelDescription
     {
     private:
         // FMU info
-        std::string m_modelName;
+        std::string m_model_name;
         std::string m_guid;
         // The path where the extracted fmu is stored
-        std::string m_unzippedPath;
+        std::string m_model_dir;
         // ValueReferences for each type
         std::vector<unsigned int> m_int_vrs;
         std::vector<unsigned int> m_real_vrs;
         std::vector<unsigned int> m_bool_vrs;
         std::vector<unsigned int> m_string_vrs;
 
-        /// Unzips the fmu and loads the modelDescription
-        /// The unzip action must be passed in.
-        void unzip_and_load(std::function<void(std::string unzipPath)> unzipAction);
-        void load_value_refs(const boost::property_tree::ptree& xmlRoot);
-
     public:
         /// Initialize from local file
-        FmuFile(std::string pathToFmu);
-        /// Initialize from fmu in memory
-        FmuFile(const std::vector<unsigned char>& buffer);
-        FmuFile(const FmuFile&) = delete;
-        FmuFile(FmuFile&&) = default;
-        FmuFile& operator=(const FmuFile&) = delete;
-        FmuFile& operator=(FmuFile&&) = default;
-        ~FmuFile();
+        ModelDescription();
+        ~ModelDescription();
 
+        /// Load the modelDescription.xml. Set the model_dir before.
+        void load();
+        /// Set the directory of the model
+        /// The xml is not parsed.
+        void set_model_dir(std::string model_dir);
+        /// Returns the path to the directory where the fmu has been unzipped
+        std::string get_model_dir();
         /// Returns the canonicial path to the binary without extension.
-        std::string GetBinaryPath();
+        std::string get_binary_path();
+        /// Returns the model identifier
+        std::string get_model_name();
         /// Returns the guid from the modelDescription xml
-        std::string GetGUID();
+        std::string get_guid();
         /// Create an URI to the resource dir. The uri is "file:///" + absolutePath of modelDir
-        std::string GetResourceUri();
+        std::string get_resource_uri();
 
         std::vector<unsigned int> get_int_vrs();
         std::vector<unsigned int> get_real_vrs();
diff --git a/Files/ModeliFile.cpp b/Files/ModeliFile.cpp
index 86515f9615ef14b9220ec4f1c5f649dc1a244bbb..b737ace071ae5b978a0c3ebbb92a5d855d210023 100644
--- a/Files/ModeliFile.cpp
+++ b/Files/ModeliFile.cpp
@@ -1,5 +1,4 @@
 #include "ModeliFile.hpp"
-#include "FmuFile.hpp"
 #include "Unzipper.hpp"
 #include "ChannelLink.h"
 #include "boost/property_tree/ptree.hpp"
@@ -11,27 +10,45 @@ namespace pt = boost::property_tree;
 
 namespace Files
 {
-    ModeliFile::ModeliFile(std::string modeliFile)
+    ModeliFile::ModeliFile(std::string path_to_modeli)
     {
-        // Extract the modeliFile to MODELS/**filename without extension**
-        fs::path modeliPath(modeliFile);
-        fs::path extractPath(MODEL_DIR);
-        extractPath /= modeliPath.stem();
-        m_unzipDir = extractPath.generic_string();
-        Unzipper::Unzip(modeliFile, m_unzipDir);
-        // Load the xml file
-        pt::read_xml((fs::path(m_unzipDir) / "ChannelLinks.xml").generic_string(), m_modelixml);
+        unzip_modeli_file(path_to_modeli);
+
     }
     ModeliFile::~ModeliFile()
     {
-        fs::remove_all(m_unzipDir);
+        fs::remove_all(m_unzip_dir);
     }
 
-    std::vector<Simulation::ChannelLink> ModeliFile::GetChannelLinks()
+    std::vector<Simulation::ChannelLink> ModeliFile::get_channel_links()
+    {
+        return m_channel_links;
+    }
+
+    std::shared_ptr<FmuFileManager> ModeliFile::get_fmu_file_manager()
+    {
+        return m_file_manager;
+    }
+    std::map<std::string, ModelDescription> ModeliFile::get_model_for_instance()
+    {
+        return m_model_for_instance;
+    }
+    void ModeliFile::unzip_modeli_file(std::string path_to_modeli)
+    {
+        // Extract the modeliFile to *U*NZIP_DIR**/**filename without extension**
+        fs::path modeliPath(path_to_modeli);
+        fs::path extractPath(path_to_modeli);
+        extractPath /= modeliPath.stem();
+        m_unzip_dir = extractPath.generic_string();
+        Unzipper::Unzip(modeliPath.generic_string(), m_unzip_dir);
+    }
+    void ModeliFile::parse_modeli_xml(std::string xml_path)
     {
-        std::vector<Simulation::ChannelLink> links;
+        // Load the xml file
+        boost::property_tree::ptree modeli_xml;
+        pt::read_xml((fs::path(m_unzip_dir) / "ChannelLinks.xml").generic_string(), modeli_xml);
         // Parse the channel links
-        for (auto c : m_modelixml.get_child("ChannelLinks"))
+        for (auto c : modeli_xml.get_child("ChannelLinks"))
         {
             // Only add the channel link if it is actually linked
             if (c.second.get<bool>("Linked"))
@@ -43,40 +60,18 @@ namespace Files
                 channelLink.MasterValueRef = c.second.get<unsigned int>("MasterChannel.ValueRef");
                 channelLink.SlaveInstanceName = c.second.get<std::string>("SlaveChannel.DataSourceName");
                 channelLink.SlaveValueRef = c.second.get<unsigned int>("SlaveChannel.ValueRef");
-                links.push_back(channelLink);
+                m_channel_links.push_back(std::move(channelLink));
             }
         }
-        return	links;
-    }
-
-    std::vector<std::unique_ptr<FmuFile>> ModeliFile::GetFmus()
-    {
-        std::vector<std::unique_ptr<Files::FmuFile>> files;
-        // Parse the fmu Files
-        for (auto source : m_modelixml.get_child("Description.DataSources"))
-        {
-            // Only fmu datasources
-            if (source.second.get<std::string>("SourceType") == "FMUDataSource")
-            {
-                // Create the FumFile and add it to the vector
-                files.push_back(std::make_unique<FmuFile>(
-                    m_unzipDir + "/" + source.second.get<std::string>("Location")));
-            }
-        }
-        return files;
-    }
-    std::vector<std::string> ModeliFile::GetInstanceNames()
-    {
-        std::vector<std::string> names;
         // Parse the fmu Files
-        for (auto source : m_modelixml.get_child("Description.DataSources"))
+        for (auto source : modeli_xml.get_child("Description.DataSources"))
         {
             // Only fmu datasources
             if (source.second.get<std::string>("SourceType") == "FMUDataSource")
             {
-                names.push_back(source.second.get<std::string>("InstanceName"));
+                m_model_for_instance.emplace(source.second.get<std::string>("InstanceName"),
+                                             m_file_manager->add_model(m_unzip_dir + "/" + source.second.get<std::string>("Location")));
             }
         }
-        return names;
     }
 }
\ No newline at end of file
diff --git a/Files/ModeliFile.hpp b/Files/ModeliFile.hpp
index 2139fc2c1152314563b168f85b1dc67b63a798ac..26e144bc645e2cf082ea5fe393a123d3179bb11f 100644
--- a/Files/ModeliFile.hpp
+++ b/Files/ModeliFile.hpp
@@ -1,38 +1,40 @@
 #pragma once
-#include "boost/property_tree/ptree.hpp"
+#include "ChannelLink.h"
+#include "FmuFileManager.h"
 #include <memory>
 #include <string>
 #include <utility>
 #include <vector>
-#include "ChannelLink.h"
 
 namespace Files
 {
-    // Forward declare
-    class FmuFile;
-
     /// Extracts a modeli file and the included information.
     /// The extracted files will be removed when the instance is destructed.
     class ModeliFile
     {
     public:
         /// Create a new instance from the given file location.
-        ModeliFile(std::string modeliFile);
+        ModeliFile(std::string path_to_modeli);
         ModeliFile(const ModeliFile&) = delete;
         void operator=(const ModeliFile&) = delete;
         ~ModeliFile();
 
         /// Extracts the channel links from the xml file in the modeli file
-        std::vector<Simulation::ChannelLink> GetChannelLinks();
+        std::vector<Simulation::ChannelLink> get_channel_links();
         /// Extracts the path and instancName of th fmus
-        std::vector<std::unique_ptr<FmuFile>> GetFmus();
-        std::vector<std::string> GetInstanceNames();
+        std::shared_ptr<FmuFileManager> get_fmu_file_manager();
+        std::map<std::string, ModelDescription> get_model_for_instance();
     private:
-        // Relative path to the dir where the modeli will be stored temporally
-        const std::string MODEL_DIR = "MODELI";
-        // Where the modeli file is extracted to
-        std::string m_unzipDir;
-        // Store the parsed properties
-        boost::property_tree::ptree m_modelixml;
+        // Where the modeli file will be unzipped
+        const std::string UNZIP_DIR = "UNZIP";
+        std::string m_unzip_dir;
+        // models & instance names
+        std::shared_ptr<FmuFileManager> m_file_manager;
+        std::map<std::string, ModelDescription> m_model_for_instance;
+        std::vector<Simulation::ChannelLink> m_channel_links;
+        // Unzip the contents of the modeli file
+        void unzip_modeli_file(std::string path_to_modeli);
+        // Parse the xml file and store the relevant data
+        void parse_modeli_xml(std::string xml_path);
     };
 }
\ No newline at end of file
diff --git a/Files/Unzipper.cpp b/Files/Unzipper.cpp
index e2093429901766c54a3959a61b42cb4b45db6f42..7a4b3de0f1cd7d6ccf54b6aa0fc87b2eaf7f9a40 100644
--- a/Files/Unzipper.cpp
+++ b/Files/Unzipper.cpp
@@ -4,27 +4,25 @@
 
 void Unzipper::Unzip(std::string zipFile, std::string unzipDir)
 {
-	miniz_cpp::zip_file zip(zipFile);
-	Unzip(zip, unzipDir);
+	Unzip(std::make_unique<miniz_cpp::zip_file>(zipFile), unzipDir);
 }
 
-void Unzipper::Unzip(const std::vector<unsigned char>& zipFile, std::string unzipDir)
+void Unzipper::Unzip(std::vector<unsigned char> buffer, std::string unzipDir)
 {
-	miniz_cpp::zip_file zip(zipFile);
-	Unzip(zip, unzipDir);
+	Unzip(std::make_unique<miniz_cpp::zip_file>(std::move(buffer)), unzipDir);
 }
 
-void Unzipper::Unzip(miniz_cpp::zip_file & zipFile, std::string unzipDir)
+void Unzipper::Unzip(std::unique_ptr<miniz_cpp::zip_file> zipFile, std::string unzipDir)
 {
 	namespace fs = boost::filesystem;
 	// Use boost path :)
 	fs::path unzipPath(unzipDir);
 	// Create folder structure, ifstream does not create them for us
-	for (auto info : zipFile.infolist())
+	for (auto info : zipFile->infolist())
 	{
 		fs::path folder = (unzipPath / info.filename).parent_path();
 		bool res = fs::create_directories(folder);
 	}
 	// Unzip
-	zipFile.extractall(unzipDir);
+	zipFile->extractall(unzipDir);
 }
diff --git a/Files/Unzipper.hpp b/Files/Unzipper.hpp
index e41471c3f8201bbc107e29708fe23bdbb77c8a5a..38664a579271c4f4bf616e24850486006ef3f1a9 100644
--- a/Files/Unzipper.hpp
+++ b/Files/Unzipper.hpp
@@ -1,20 +1,22 @@
 #pragma once
+#include <memory>
 #include <string>
 #include <vector>
 
 namespace miniz_cpp
 {
-	class zip_file;
+    class zip_file;
 }
 
 /// Can extract a zip file which contains a folder structure
 class Unzipper
 {
 public:
-	/// Extracts the zip file to the extractDir
-	static void Unzip(std::string zipFile, std::string unzipDir);
-	/// Extracts the zip file to the extractDir
-	static void Unzip(const std::vector<unsigned char>& zipFile, std::string unzipDir);
-	/// Unzip from a zip_file to unzipDir.
-	static void Unzip(miniz_cpp::zip_file& zipFile, std::string unzipDir);
+    /// Extracts the zip file to the extractDir
+    static void Unzip(std::string path, std::string unzipDir);
+    /// Extracts the zip file to the extractDir
+    static void Unzip(std::vector<unsigned char> buffer, std::string unzipDir);
+private:
+    /// Unzip from a zip_file to unzipDir.
+    static void Unzip(std::unique_ptr<miniz_cpp::zip_file> zipFile, std::string unzipDir);
 };
\ No newline at end of file
diff --git a/Main/main.cpp b/Main/main.cpp
index d83bad99384406f011dd3d977822f62ff7e283bb..42499cc1f975ded802f1bea419f50c697de83196 100644
--- a/Main/main.cpp
+++ b/Main/main.cpp
@@ -1,5 +1,4 @@
 #include "ModeliFile.hpp"
-#include "FmuFile.hpp"
 #include "Simulator.hpp"
 #include "ModeliGrpcServer.h"
 #include "grpc++/grpc++.h"
@@ -43,20 +42,22 @@ int main(int argc, char *argv[])
             {
                 port = vm["port"].as<unsigned short>();
             }
-            auto fmuEngine = std::make_unique<Simulation::Simulator>();
+            auto simulator = std::make_unique<Simulation::Simulator>();
+            auto file_manager = std::make_shared<Files::FmuFileManager>();
             // Load the modeli file into the engine
             if (vm.count("modeli"))
             {
                 try
                 {
                     Files::ModeliFile modeliFile(vm["modeli"].as<std::string>());
-                    for (size_t i = 0; i < modeliFile.GetFmus().size(); i++)
+                    file_manager = modeliFile.get_fmu_file_manager();
+                    for (auto instance_and_model : modeliFile.get_model_for_instance())
                     {
-                        fmuEngine->AddFmu(std::move(modeliFile.GetFmus()[i]), modeliFile.GetInstanceNames()[i]);
+                        simulator->AddFmu(instance_and_model.second, instance_and_model.first);
                     }
-                    for (auto channelLink : modeliFile.GetChannelLinks())
+                    for (auto channelLink : modeliFile.get_channel_links())
                     {
-                        fmuEngine->AddChannelLink(channelLink);
+                        simulator->AddChannelLink(channelLink);
                     }
                 }
                 catch (std::exception err)
@@ -65,7 +66,7 @@ int main(int argc, char *argv[])
                 }
             }
             // Configuration for rpc
-            ModeliGrpcServer service(std::move(fmuEngine));
+            ModeliGrpcServer service(std::move(simulator), file_manager);
             std::string targetUri = "0.0.0.0:" + std::to_string(port);
             // Start the server
             grpc::ServerBuilder builder;
diff --git a/Simulation/FmuEntity.cpp b/Simulation/FmuEntity.cpp
index ede247e59880112bb26294e550a80ee5b117aa5c..54c099462d4968537983c09ea09bdaafb7369823 100644
--- a/Simulation/FmuEntity.cpp
+++ b/Simulation/FmuEntity.cpp
@@ -3,16 +3,16 @@
 namespace Simulation
 {
 
-    FmuEntity::FmuEntity(std::string instance_name, std::unique_ptr<Files::FmuFile> file, NativeFmu::LoggerCallback logger) :
+    FmuEntity::FmuEntity(std::string instance_name, Files::ModelDescription file, NativeFmu::LoggerCallback logger) :
         m_instance_name(instance_name),
         m_file(std::move(file)),
         m_logger(logger)
     {
         m_fmu = std::make_shared<NativeFmu::CoSimFmu>();
-        m_fmu->SetBooleanVr(m_file->get_bool_vrs());
-        m_fmu->SetIntegerVr(m_file->get_int_vrs());
-        m_fmu->SetRealVr(m_file->get_real_vrs());
-        m_fmu->SetStringVr(m_file->get_string_vrs());
+        m_fmu->SetBooleanVr(m_file.get_bool_vrs());
+        m_fmu->SetIntegerVr(m_file.get_int_vrs());
+        m_fmu->SetRealVr(m_file.get_real_vrs());
+        m_fmu->SetStringVr(m_file.get_string_vrs());
     }
 
     std::string FmuEntity::GetInstanceName()
@@ -27,7 +27,7 @@ namespace Simulation
 
     bool FmuEntity::InstantiateFmu()
     {
-        std::pair<bool, std::string> loadDllRes = m_fmu->LoadDll(m_file->GetBinaryPath());
+        std::pair<bool, std::string> loadDllRes = m_fmu->LoadDll(m_file.get_binary_path());
         if (!loadDllRes.first)
         {
             m_logger(m_instance_name, fmi2Warning, "", "Failed LoadLibrary, Error: " + loadDllRes.second);
@@ -38,7 +38,7 @@ namespace Simulation
         namespace ph = std::placeholders;
         m_fmu->SetLoggerCallback(m_logger);
         // Instantiate
-        if (!m_fmu->Instantiate(m_instance_name, m_file->GetGUID(), m_file->GetResourceUri()))
+        if (!m_fmu->Instantiate(m_instance_name, m_file.get_guid(), m_file.get_resource_uri()))
         {
             m_logger(m_instance_name, fmi2Warning, "", "Instantiation failed.");
             return false;
@@ -63,8 +63,5 @@ namespace Simulation
 
     FmuEntity::~FmuEntity()
     {
-        // Destroy in rigth order
-        m_fmu.reset();
-        m_file.reset();
     }
 }
\ No newline at end of file
diff --git a/Simulation/FmuEntity.h b/Simulation/FmuEntity.h
index ff9546b1944907e99639faf27af07daae9ce38cb..2d4f7ec27e26ba7cb81f96b80abe999abdef76a1 100644
--- a/Simulation/FmuEntity.h
+++ b/Simulation/FmuEntity.h
@@ -1,17 +1,17 @@
 #pragma once
 #include "CoSimFmu.h"
-#include "FmuFile.hpp"
+#include "ModelDescription.h"
 #include "BasicFmuCallbacks.h"
 #include <memory>
 
 namespace Simulation
 {
-    /// Manages the lifitimes of a FmuFile and its' CoSimFmu instance.
-    /// Simplifies instantiation and Initialization of the fmu.
+    /// Keeps a CoSimFmu together with its model description.
+    /// Instantiation and Initialization of the fmu are simplified because they are kept together.
     class FmuEntity
     {
     public:
-        FmuEntity(std::string instance_name, std::unique_ptr<Files::FmuFile> file, NativeFmu::LoggerCallback logger);
+        FmuEntity(std::string instance_name, Files::ModelDescription model, NativeFmu::LoggerCallback logger);
 
         std::string GetInstanceName();
 
@@ -27,7 +27,7 @@ namespace Simulation
         ~FmuEntity();
     private:
         std::string m_instance_name;
-        std::unique_ptr<Files::FmuFile> m_file;
+        Files::ModelDescription m_file;
         std::shared_ptr<NativeFmu::CoSimFmu> m_fmu;
         NativeFmu::LoggerCallback m_logger;
     };
diff --git a/Simulation/ModeliGrpcServer.cpp b/Simulation/ModeliGrpcServer.cpp
index cb96e65c49c312a515fab17356c407099c8cb42e..a985683cd8ccaeb4ad2d911c78f67d7588b0c4dd 100644
--- a/Simulation/ModeliGrpcServer.cpp
+++ b/Simulation/ModeliGrpcServer.cpp
@@ -1,12 +1,13 @@
 #include "ModeliGrpcServer.h"
 #include "ChannelLink.h"
-#include "FmuFile.hpp"
+#include "FmuFileManager.h"
 #include "Simulator.hpp"
-#include "CoSimFmu.h"
 
 namespace ph = std::placeholders;
 
-ModeliGrpcServer::ModeliGrpcServer(std::unique_ptr<Simulation::Simulator> simulator) :m_simulator(std::move(simulator))
+ModeliGrpcServer::ModeliGrpcServer(std::unique_ptr<Simulation::Simulator> simulator, std::shared_ptr<Files::FmuFileManager> file_manager) :
+    m_simulator(std::move(simulator)),
+    m_fmu_file_manager(std::move(file_manager))
 {
     // Register the callbacks
     m_simulator->RegisterLogCallback(std::bind(&ModeliGrpcServer::LogArrived, this, ph::_1, ph::_2, ph::_3, ph::_4));
@@ -60,20 +61,22 @@ Status ModeliGrpcServer::AddFmu(ServerContext * context, ServerReader<::ModeliRp
     // Read the chunks
     while (reader->Read(&request))
     {
+        if (instanceName == "")
+        {
+            instanceName = request.instance_name();
+        }
         // Intial assignments
         if (buffer.size() == 0)
         {
             buffer.reserve(request.total_size());
         }
-        if (instanceName == "")
-        {
-            instanceName = request.instance_name();
-        }
         // Insert recceived data
         buffer.insert(buffer.end(), request.chunk().begin(), request.chunk().end());
     }
+    // Add to the file manager
+    auto model_description = m_fmu_file_manager->add_model(std::move(buffer));
     // Try to add the fmu
-    response->set_success(m_simulator->AddFmu(std::make_unique<Files::FmuFile>(buffer), instanceName));
+    response->set_success(m_simulator->AddFmu(std::move(model_description), instanceName));
     return Status::OK;
 }
 
@@ -160,11 +163,11 @@ Status ModeliGrpcServer::NewValues(ServerContext * context, const::ModeliRpc::Ne
         {
             streamOpen = writer->Write(*item);
         }
-        else if(m_new_values.is_finished())
+        else if (m_new_values.is_finished())
         {
             // No value available and no more will come
             break;
-        }       
+        }
     }
     return Status::OK;
 }
diff --git a/Simulation/ModeliGrpcServer.h b/Simulation/ModeliGrpcServer.h
index 2cced814975b203999dddc1ad09e56d42234c2b1..e1198abe040962f67f6e42ff1473018b24ce7a34 100644
--- a/Simulation/ModeliGrpcServer.h
+++ b/Simulation/ModeliGrpcServer.h
@@ -12,13 +12,17 @@ namespace Simulation
     class Simulator;
 }
 
+namespace Files
+{
+    class FmuFileManager;
+}
 
 /// This class implements the server side of the grpc definition.
 /// It is in charge of controlling the simulation and sending feedback to the frontend.
 class ModeliGrpcServer final : public ModeliRpc::ModeliBackend::Service
 {
 public:
-    ModeliGrpcServer(std::unique_ptr<Simulation::Simulator> unique_ptr);
+    ModeliGrpcServer(std::unique_ptr<Simulation::Simulator> simulator, std::shared_ptr<Files::FmuFileManager> file_manager);
     ModeliGrpcServer(const ModeliGrpcServer&) = delete;
     void operator=(const ModeliGrpcServer&) = delete;
     ~ModeliGrpcServer();
@@ -75,10 +79,11 @@ public:
         std::string message	///< The message that has been logged
     );
 private:
+    std::shared_ptr<Files::FmuFileManager> m_fmu_file_manager;
     // Execue the simulation commands
     std::unique_ptr<Simulation::Simulator> m_simulator;
     // Wait for logs to arrive
     Utility::ConcurrentQueue<ModeliRpc::LogResponse> m_logs;
     // Wait for values to arrive
     Utility::ConcurrentQueue<ModeliRpc::NewValuesResponse> m_new_values;
-};
+};
\ No newline at end of file
diff --git a/Simulation/Simulator.cpp b/Simulation/Simulator.cpp
index e8d7dbbceaf68a75f68ce6018c30ca63f1847fce..0c4461a4d4058f3a3ba773ac7c6a2718f0f4ee9f 100644
--- a/Simulation/Simulator.cpp
+++ b/Simulation/Simulator.cpp
@@ -177,7 +177,7 @@ namespace Simulation
                 auto boolRes = fmu->GetBoolean();
                 auto stringRes = fmu->GetString();
                 // Send the values			
-                onValuesArrived(fmu->GetInstanceName(), current_time,
+                onValuesArrived(entity->GetInstanceName(), current_time,
                                 fmu->GetIntegerVr(), intRes.second,
                                 fmu->GetRealVr(), realRes.second,
                                 fmu->GetBooleanVr(), boolRes.second,
@@ -290,19 +290,6 @@ namespace Simulation
         m_log_callback(instanceName, status, category, message);
     }
 
-    std::shared_ptr<NativeFmu::CoSimFmu> Simulator::get_fmu_or_log(std::string instance_name, std::string msg)
-    {
-        if (auto entity = m_fmus->GetEntity(instance_name))
-        {
-            return entity->GetCoSimFmu().lock();
-        }
-        else
-        {
-            onLog(instance_name, fmi2Warning, "", "Instance was not found while executing: " + msg);
-            return nullptr;
-        }
-    }
-
     bool Simulator::AddChannelLink(ChannelLink channelLink)
     {
         return m_dispatcher.dispatch_fn<bool>([&]()
@@ -320,20 +307,25 @@ namespace Simulation
         }).get();
     }
 
-    bool Simulator::AddFmu(std::unique_ptr<Files::FmuFile> fmuFile, std::string instance_name)
+    bool Simulator::FmuInstanceExists(std::string instance_name)
     {
-        // Fail early if instance name exists (asking for state -> dispatch)
-        if (m_dispatcher.dispatch_fn<bool>([&]()
+        return m_dispatcher.dispatch_fn<bool>([&]()
         {
             return m_fmus->Contains(instance_name);
-        }).get())
+        }).get();
+    }
+
+    bool Simulator::AddFmu(Files::ModelDescription model, std::string instance_name)
+    {
+        // Fail early if instance name exists (asking for state -> dispatch)
+        if (FmuInstanceExists(instance_name))
         {
             return false;
         }
         // Heavy instantiation work outside the simulation
         std::shared_ptr<FmuEntity> entity = std::make_shared<FmuEntity>(
             instance_name,
-            std::move(fmuFile),
+            std::move(model),
             std::bind(&Simulator::onLog, this, ph::_1, ph::_2, ph::_3, ph::_4));
         if (!entity->InstantiateFmu())
         {
@@ -377,50 +369,66 @@ namespace Simulation
     }
     int Simulator::SetInteger(std::string instance_name, std::vector<unsigned int> vr, std::vector<int> values)
     {
-        if (auto fmu = get_fmu_or_log(instance_name, "set integer"))
+        if (auto entity = m_fmus->GetEntity(instance_name))
         {
-            return fmu->SetInteger(vr.data(), vr.size(), values.data());
+            if (auto fmu = entity->GetCoSimFmu().lock())
+            {
+                fmu->SetInteger(vr.data(), vr.size(), values.data());
+            }
         }
         else
         {
+            onLog(instance_name, fmi2Warning, "", "Cannot set integer values, instance not found.");
             return fmi2Warning;
         }
     }
     int Simulator::SetReal(std::string instance_name, std::vector<unsigned int> vr, std::vector<double> values)
     {
-        if (auto fmu = get_fmu_or_log(instance_name, "set real"))
+        if (auto entity = m_fmus->GetEntity(instance_name))
         {
-            return fmu->SetReal(vr.data(), vr.size(), values.data());
+            if (auto fmu = entity->GetCoSimFmu().lock())
+            {
+                fmu->SetReal(vr.data(), vr.size(), values.data());
+            }
         }
         else
         {
+            onLog(instance_name, fmi2Warning, "", "Cannot set real values, instance not found.");
             return fmi2Warning;
         }
     }
     int Simulator::SetBoolean(std::string instance_name, std::vector<unsigned int> vr, std::vector<int> values)
     {
-        if (auto fmu = get_fmu_or_log(instance_name, "set boolean"))
+        if (auto entity = m_fmus->GetEntity(instance_name))
         {
-            return fmu->SetBoolean(vr.data(), vr.size(), values.data());
+            if (auto fmu = entity->GetCoSimFmu().lock())
+            {
+                fmu->SetBoolean(vr.data(), vr.size(), values.data());
+            }
         }
         else
         {
+            onLog(instance_name, fmi2Warning, "", "Cannot set boolean values, instance not found.");
             return fmi2Warning;
         }
     }
     int Simulator::SetString(std::string instance_name, std::vector<unsigned int> vr, std::vector<std::string> values)
     {
-        if (auto fmu = get_fmu_or_log(instance_name, "set integer"))
+        if (auto entity = m_fmus->GetEntity(instance_name))
         {
-            std::vector<const char*> converted;
-            for (auto element : values)
+            if (auto fmu = entity->GetCoSimFmu().lock())
             {
-                converted.push_back(element.c_str());
+                std::vector<const char*> converted;
+                for (auto element : values)
+                {
+                    converted.push_back(element.c_str());
+                }
+                fmu->SetString(vr.data(), vr.size(), converted.data());
             }
-            return fmu->SetString(vr.data(), vr.size(), converted.data());
         }
         else
         {
+            onLog(instance_name, fmi2Warning, "", "Cannot set string value, instance not found.");
             return fmi2Warning;
         }
     }
diff --git a/Simulation/Simulator.hpp b/Simulation/Simulator.hpp
index 32d46f8a28775b2b26a057b03bcfd662b9a0c528..03aa44af7300d7c0e8c544bdd287065d76543313 100644
--- a/Simulation/Simulator.hpp
+++ b/Simulation/Simulator.hpp
@@ -1,22 +1,13 @@
 #pragma once
 #include "ChannelLink.h"
 #include "QueueDispatcher.h"
+#include "ModelDescription.h"
 #include "boost/optional.hpp"
 #include <functional>
 #include <list>
 #include <thread>
 #include <vector>
 
-namespace Files
-{
-    class FmuFile;
-}
-
-namespace NativeFmu
-{
-    class CoSimFmu;
-}
-
 namespace Simulation
 {
     class FmuContainer;
@@ -48,13 +39,12 @@ namespace Simulation
     {
     public:
         Simulator();
+        Simulator(Simulator&&) = default;
         Simulator(const Simulator&) = delete;
-        void operator=(const Simulator&) = delete;
+        Simulator& operator=(Simulator&&) = default;
+        Simulator& operator=(const Simulator&) = delete;      
         ~Simulator();
 
-        /// Add callbacks for the server
-
-
         /// Runs the simulation in realtime with endtime set to DBL_MAX
         int Play();
         /// Runs the simulation as fast as possible until endTime is reached.
@@ -69,8 +59,10 @@ namespace Simulation
         /// Remove a ChannelLink
         bool RemoveChannelLink(ChannelLink channelLink);
 
+        /// Returns true if the instance is already part of the simulation
+        bool FmuInstanceExists(std::string instance_name);
         /// Add a fmu which was loaded by FmuFile class
-        bool AddFmu(std::unique_ptr<Files::FmuFile> fmuFile, std::string instanceName);
+        bool AddFmu(Files::ModelDescription model, std::string instanceName);
         /// Remove the FMU with matching instanceName
         bool RemoveFMU(std::string instanceName);
 
@@ -126,8 +118,5 @@ namespace Simulation
                              const std::vector<unsigned int> stringVrs, const std::vector<const char*> stringValues);
         // Spread the word: A log has arrived (also used as callback for the fmus)
         void onLog(std::string instanceName, int status, std::string category, std::string message);
-
-        // logs if the fmu was not found, nullptr is returned in this case
-        std::shared_ptr<NativeFmu::CoSimFmu> get_fmu_or_log(std::string instance_name, std::string msg);
     };
 }
\ No newline at end of file