From fe10070b85bff7a605757927783a732588164eb7 Mon Sep 17 00:00:00 2001 From: micheltakken Date: Tue, 14 Nov 2023 09:56:15 +0100 Subject: [PATCH] Add JSON porter for network and simulation import new json model --- src/CMakeLists.txt | 1 + src/architecture/Network.h | 20 ++- src/architecture/Network.hh | 14 +- src/architecture/Node.h | 13 ++ src/architecture/Node.hh | 10 ++ src/baseSimulator.h | 4 +- src/baseSimulator.hh | 4 +- src/main.cpp | 30 +--- src/nodalAnalysis/NodalAnalysis.hh | 15 +- src/porting/CMakeLists.txt | 11 ++ src/porting/jsonPorter.h | 36 +++++ src/porting/jsonPorter.hh | 237 +++++++++++++++++++++++++++++ src/simulation/Fluid.h | 9 ++ src/simulation/Fluid.hh | 4 + src/simulation/Simulation.h | 39 ++++- src/simulation/Simulation.hh | 30 +++- 16 files changed, 430 insertions(+), 47 deletions(-) create mode 100644 src/porting/CMakeLists.txt create mode 100644 src/porting/jsonPorter.h create mode 100644 src/porting/jsonPorter.hh diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 59c5b4a..f8a4de4 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,6 +10,7 @@ set(HEADER_LIST add_subdirectory(nodalAnalysis) add_subdirectory(architecture) add_subdirectory(simulation) +add_subdirectory(porting) target_sources(${TARGET_NAME} PUBLIC ${SOURCE_LIST} ${HEADER_LIST}) target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}) \ No newline at end of file diff --git a/src/architecture/Network.h b/src/architecture/Network.h index a230c48..6b7b9b2 100755 --- a/src/architecture/Network.h +++ b/src/architecture/Network.h @@ -49,10 +49,10 @@ struct Group { * @param[in] nodeIds Ids of the nodes that constitute this group. * @param[in] channelIds Ids of the channels that constitute this group. */ - Group(int groupId_, std::unordered_set nodeIds_, std::unordered_set channelIds_) : + Group(int groupId_, std::unordered_set nodeIds_, std::unordered_set channelIds_, Network* network_) : groupId(groupId_), nodeIds(nodeIds_), channelIds(channelIds_) { for (auto& nodeId : nodeIds) { - if (nodeId <= 0) { + if (network_->getNode(nodeId)->getGround()) { grounded = true; } } @@ -95,6 +95,14 @@ class Network { */ Network(std::unordered_map>> nodes); + /** + * @brief Constructor of the Network + * @param[in] nodes Nodes of the network. + * @param[in] channels Channels of the network. + */ + Network(std::unordered_map>> nodes, + std::unordered_map>> channels); + /** * @brief Constructor of the Network from a JSON string * @param json json string @@ -110,7 +118,7 @@ class Network { /** * @brief Get a pointer to the node with the specific id. */ - std::shared_ptr>& getNode(int nodeId) const; + std::shared_ptr>& getNode(int nodeId); /** * @brief Adds a new channel to the network. @@ -184,6 +192,12 @@ class Network { * @brief Sorts the nodes and channels into detached 1D domain groups */ void sortGroups(); + + /** + * @brief Set the modules of the network for a hybrid simulation. + * @param[in] modules The modules that handle the CFD simulations. + */ + void setModules(std::unordered_map>> modules); }; } // namespace arch \ No newline at end of file diff --git a/src/architecture/Network.hh b/src/architecture/Network.hh index 61e7169..be487e4 100755 --- a/src/architecture/Network.hh +++ b/src/architecture/Network.hh @@ -18,6 +18,11 @@ namespace arch { nodes(nodes_), channels(channels_), flowRatePumps(flowRatePumps_), pressurePumps(pressurePumps_), modules(modules_) { } + template + Network::Network(std::unordered_map>> nodes_, + std::unordered_map>> channels_) : + nodes(nodes_), channels(std::move(channels_)) { } + template Network::Network(std::unordered_map>> nodes_) : nodes(nodes_) { @@ -153,7 +158,7 @@ namespace arch { } template - std::shared_ptr>& Network::getNode(int nodeId) const { + std::shared_ptr>& Network::getNode(int nodeId) { return nodes.at(nodeId); }; @@ -181,6 +186,11 @@ namespace arch { return std::get<0>(modules.at(moduleId)); } + template + void Network::setModules(std::unordered_map>> modules_) { + this->modules = std::move(modules_); + } + template const std::unordered_map>>& Network::getNodes() const { return nodes; @@ -287,7 +297,7 @@ namespace arch { } } - Group* addGroup = new Group(groupId, nodeIds, channelIds); + Group* addGroup = new Group(groupId, nodeIds, channelIds, this); groups.try_emplace(groupId, addGroup); groupId++; diff --git a/src/architecture/Node.h b/src/architecture/Node.h index 7769661..6663d92 100755 --- a/src/architecture/Node.h +++ b/src/architecture/Node.h @@ -13,6 +13,7 @@ namespace arch { int const id; std::vector pos; T pressure = 0; + bool ground = false; public: /** @@ -35,6 +36,18 @@ namespace arch { */ void setPressure(T pressure); + /** + * @brief Set the ground node role to the node. + * @param[in] ground Boolean value for ground node role. + */ + void setGround(bool ground); + + /** + * @brief Get the ground node role of the node. + * @returns Boolean value for ground node role. + */ + bool getGround(); + /** * @brief Get id of the node. * @returns id. diff --git a/src/architecture/Node.hh b/src/architecture/Node.hh index a1f8938..2994fb9 100755 --- a/src/architecture/Node.hh +++ b/src/architecture/Node.hh @@ -34,4 +34,14 @@ namespace arch { return pressure; } + template + void Node::setGround(bool ground_) { + ground = ground_; + } + + template + bool Node::getGround() { + return ground; + } + } // namespace arch \ No newline at end of file diff --git a/src/baseSimulator.h b/src/baseSimulator.h index 64ac17e..376f529 100644 --- a/src/baseSimulator.h +++ b/src/baseSimulator.h @@ -13,4 +13,6 @@ #include "architecture/Network.h" #include "architecture/Node.h" #include "architecture/Platform.h" -#include "architecture/PressurePump.h" \ No newline at end of file +#include "architecture/PressurePump.h" + +#include "porting/jsonPorter.h" \ No newline at end of file diff --git a/src/baseSimulator.hh b/src/baseSimulator.hh index 55a07e4..12fc414 100644 --- a/src/baseSimulator.hh +++ b/src/baseSimulator.hh @@ -12,4 +12,6 @@ #include "architecture/Module.hh" #include "architecture/Network.hh" #include "architecture/Node.hh" -#include "architecture/PressurePump.hh" \ No newline at end of file +#include "architecture/PressurePump.hh" + +#include "porting/jsonPorter.hh" \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 4485a22..824afe3 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,40 +11,20 @@ using T = double; int main(int argc, char const* argv []) { - std::cout << "[Main] Create simulation object..." << std::endl; - - // New simulation object - sim::Simulation testSimulation = sim::Simulation(); - - std::cout << "[Main] Load the JSON network..." << std::endl; - - // Load and set the network from a JSON file - //std::string file("../examples/Hybrid/Network1.JSON"); std::string file = argv[1]; - arch::Network* network = new arch::Network(file); - std::cout << "[Main] Add pressure and Flow rate pumps..." << std::endl; - // Add Pressure and Flow Rate Pumps - network->setPressurePump(0, T(1e3)); - testSimulation.setNetwork(network); - - std::cout << "[Main] Set the continuous phase fluid..." << std::endl; - // Define and set the continuous phase fluid - sim::Fluid* fluid0 = new sim::Fluid(0, T(1000), T(1e-3)); - fluid0->setName("Water"); - testSimulation.setContinuousPhase(fluid0); + std::cout << "[Main] Create simulation object..." << std::endl; - std::cout << "[Main] Set the resistance model..." << std::endl; - // Define and set the resistance model - sim::ResistanceModel2DPoiseuille* resistanceModel = new sim::ResistanceModel2DPoiseuille(fluid0->getViscosity()); - testSimulation.setResistanceModel(resistanceModel); + // Load and set the network from a JSON file + arch::Network network = porting::networkFromJSON(file); + // Load and set the simulation from a JSON file + sim::Simulation testSimulation = porting::simulationFromJSON(file, &network); std::cout << "[Main] Simulation..." << std::endl; // Perform simulation and store results testSimulation.simulate(); - std::cout << "[Main] Results..." << std::endl; // Print the results testSimulation.printResults(); diff --git a/src/nodalAnalysis/NodalAnalysis.hh b/src/nodalAnalysis/NodalAnalysis.hh index b0d9430..73aadd2 100644 --- a/src/nodalAnalysis/NodalAnalysis.hh +++ b/src/nodalAnalysis/NodalAnalysis.hh @@ -21,19 +21,18 @@ namespace nodal { template bool conductNodalAnalysis( const arch::Network* network) { - const int groundNodeValue = 0; const int nNodes = network->getNodes().size() - 1; // -1 due to ground node std::unordered_set conductingNodeIds; std::unordered_map groundNodeIds; // Sort nodes into conducting nodes and ground nodes. - // First loop, all nodes with id > 0 are conduting nodes. + // First loop, all nodes with id > 0 are conducting nodes. int iPump = nNodes; for (const auto& [key, group] : network->getGroups()) { for (const auto& nodeId : group->nodeIds) { - if(nodeId > groundNodeValue && nodeId != group->groundNodeId) { + if(!network->getNodes().at(nodeId)->getGround() && nodeId != group->groundNodeId) { conductingNodeIds.emplace(nodeId); - } else if (nodeId > groundNodeValue && nodeId == group->groundNodeId) { + } else if (!network->getNodes().at(nodeId)->getGround() && nodeId == group->groundNodeId) { groundNodeIds.emplace(nodeId, iPump); iPump++; } @@ -54,16 +53,16 @@ namespace nodal { const T conductance = 1. / channel.second->getResistance(); // main diagonal elements of G - if (nodeAMatrixId > groundNodeValue) { + if (!network->getNodes().at(nodeAMatrixId)->getGround()) { A(nodeAMatrixId, nodeAMatrixId) += conductance; } - if (nodeBMatrixId > groundNodeValue) { + if (!network->getNodes().at(nodeBMatrixId)->getGround()) { A(nodeBMatrixId, nodeBMatrixId) += conductance; } // minor diagonal elements of G (if no ground node was present) - if (nodeAMatrixId > groundNodeValue && nodeBMatrixId > groundNodeValue) { + if (!network->getNodes().at(nodeAMatrixId)->getGround() && !network->getNodes().at(nodeBMatrixId)->getGround()) { A(nodeAMatrixId, nodeBMatrixId) -= conductance; A(nodeBMatrixId, nodeAMatrixId) -= conductance; } @@ -175,7 +174,7 @@ namespace nodal { auto& node = network->getNodes().at(nodeMatrixId); if (contains(conductingNodeIds, nodeMatrixId)) { node->setPressure(x(nodeMatrixId)); - } else if (nodeMatrixId <= groundNodeValue) { + } else if (node->getGround()) { node->setPressure(0.0); } } diff --git a/src/porting/CMakeLists.txt b/src/porting/CMakeLists.txt new file mode 100644 index 0000000..b5775c7 --- /dev/null +++ b/src/porting/CMakeLists.txt @@ -0,0 +1,11 @@ +set(SOURCE_LIST + jsonPorter.hh +) + +set(HEADER_LIST + jsonPorter.h +) + +target_sources(${TARGET_NAME} PUBLIC ${SOURCE_LIST} ${HEADER_LIST}) +target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}) +target_link_libraries(${TARGET_NAME} PUBLIC lbmLib) \ No newline at end of file diff --git a/src/porting/jsonPorter.h b/src/porting/jsonPorter.h new file mode 100644 index 0000000..313977c --- /dev/null +++ b/src/porting/jsonPorter.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include +#include +#include + +#include "../architecture/Channel.h" +#include "../architecture/FlowRatePump.h" +#include "../architecture/lbmModule.h" +#include "../architecture/Network.h" +#include "../architecture/Node.h" +#include "../architecture/Platform.h" +#include "../architecture/PressurePump.h" + +#include "../simulation/Simulation.h" + +#include "nlohmann/json.hpp" + +namespace porting { + + /** + * @brief Constructor of the Network from a JSON string + * @param json json string + * @return Network network + */ + template + arch::Network networkFromJSON(std::string jsonFile); + + template + sim::Simulation simulationFromJSON(std::string jsonFile, arch::Network* network_); + + template + void resultToJSON(std::string jsonFile); + +} // namespace porting \ No newline at end of file diff --git a/src/porting/jsonPorter.hh b/src/porting/jsonPorter.hh new file mode 100644 index 0000000..93e8226 --- /dev/null +++ b/src/porting/jsonPorter.hh @@ -0,0 +1,237 @@ +#include + +#include "jsonPorter.h" + +#include "../architecture/Channel.h" +#include "../architecture/lbmModule.h" +#include "../architecture/Module.h" +#include "../architecture/Network.h" +#include "../architecture/Node.h" +#include "../architecture/Platform.h" + +#include "../simulation/Fluid.h" +#include "../simulation/ResistanceModels.h" + +namespace porting { + + using json = nlohmann::json; + + template + arch::Network networkFromJSON(std::string jsonFile) { + + std::ifstream f(jsonFile); + json jsonString = json::parse(f); + + std::unordered_map>> nodes; + std::unordered_map>> channels; + + int count=0; + for (auto& node : jsonString["network"]["nodes"]) { + arch::Node* addNode = new arch::Node(count, T(node["x"]), T(node["y"])); + if(node["ground"]) { + addNode->setGround(true); + } + nodes.try_emplace(count, addNode); + count++; + } + + count=0; + for (auto& channel : jsonString["network"]["channels"]) { + arch::RectangularChannel* addChannel = new arch::RectangularChannel(count, nodes.at(channel["node1"]), nodes.at(channel["node2"]), + channel["width"], channel["height"]); + channels.try_emplace(count, addChannel); + count++; + } + + arch::Network network (nodes, std::move(channels)); + + return network; + } + + template + sim::Simulation simulationFromJSON(std::string jsonFile, arch::Network* network_) { + + std::ifstream f(jsonFile); + json jsonString = json::parse(f); + + sim::Simulation simulation = sim::Simulation(); + + int counter; + + // Define the platform + sim::Platform platform = sim::Platform::NONE; + if (!jsonString["simulation"].contains("platform")) { + throw std::invalid_argument("Please define a platform. The following platforms are possible:\ncontinuous\nbigDroplet\nmixing"); + } + if (jsonString["simulation"]["platform"] == "continuous") { + platform = sim::Platform::CONTINUOUS; + } else if (jsonString["simulation"]["platform"] == "bigDroplet") { + platform = sim::Platform::DROPLET; + } else if (jsonString["simulation"]["platform"] == "mixing") { + platform = sim::Platform::MIXING; + } else { + throw std::invalid_argument("Platform is invalid. The following platforms are possible:\ncontinuous\nbigDroplet\nmixing"); + } + simulation.setPlatform(platform); + + // Define the simulation type + sim::Type simType = sim::Type::NONE; + if (!jsonString["simulation"].contains("type")) { + throw std::invalid_argument("Please define a simulation type. The following types are possible:\n1D\nhybrid\nCFD"); + } + if (jsonString["simulation"]["type"] == "1D") { + simType = sim::Type::_1D; + } else if (jsonString["simulation"]["type"] == "hybrid") { + simType = sim::Type::HYBRID; + } else if (jsonString["simulation"]["type"] == "CFD") { + simType = sim::Type::CFD; + } else { + throw std::invalid_argument("Simulation type is invalid. The following types are possible:\n1D\nhybrid\nCFD"); + } + simulation.setType(simType); + + // Import fluids + if (!jsonString["simulation"].contains("fluids") || jsonString["simulation"]["fluids"].empty()) { + throw std::invalid_argument("No fluids are defined. Please define at least 1 fluid."); + } + std::vector>> fluids; + counter = 0; + for (auto& fluid : jsonString["simulation"]["fluids"]) { + if (fluid.contains("density") && fluid.contains("viscosity") && fluid.contains("concentration") && fluid.contains("name")) { + T density = fluid["density"]; + T viscosity = fluid["viscosity"]; + std::string name = fluid["name"]; + std::unique_ptr> newFluid = std::make_unique>( counter, density, viscosity, name ); + fluids.push_back(std::move(newFluid)); + counter++; + } else { + throw std::invalid_argument("Wrongly defined fluid. Please provide following information for fluids:\nname\ndensity\nviscosity\nconcentration"); + } + } + simulation.setFluids(fluids); + + if (platform == sim::Platform::DROPLET) { + // NOT YET SUPPORTED + throw std::invalid_argument("Droplet simulations are not yet supported in the simulator."); + // Import bigDroplet injections + int activeFixture = 0; + if (!jsonString["simulation"].contains("fixtures")) { + throw std::invalid_argument("Please define at least one fixture."); + } + if (!jsonString["simulation"].contains("activeFixture")) { + throw std::invalid_argument("Please define an active fixture."); + } else { + activeFixture = jsonString["simulation"]["activeFixture"]; + } + /**TODO + * Add droplets with droplets.push_back (similar to fluids above) + */ + } + + if (platform == sim::Platform::MIXING) { + // NOT YET SUPPORTED + throw std::invalid_argument("Mixing simulations are not yet supported in the simulator."); + // Import Species for Mixing platform + // TODO + // Import bolus injections in fixture + // TODO + } + + if (simType == sim::Type::HYBRID) { + // Import simulators (modules) + counter = 0; + if (!jsonString["simulation"]["settings"].contains("simulators") || jsonString["simulation"]["settings"]["simulators"].empty()) { + throw std::invalid_argument("Hybrid simulation type was set, but no CFD simulators were defined."); + } + std::unordered_map>> modules; + for (auto& module : jsonString["simulation"]["settings"]["simulators"]) { + std::unordered_map>> Nodes; + std::unordered_map> Openings; + for (auto& opening : module["Openings"]) { + int nodeId = opening["node"]; + Nodes.try_emplace(nodeId, network_->getNode(nodeId)); + std::vector normal = { opening["normal"]["x"], opening["normal"]["y"] }; + arch::Opening opening_(network_->getNode(nodeId), normal, opening["width"]); + Openings.try_emplace(nodeId, opening_); + } + std::vector position = { module["posX"], module["posY"] }; + std::vector size = { module["sizeX"], module["sizeY"] }; + arch::lbmModule* addModule = new arch::lbmModule( counter, module["name"], module["stlFile"], + position, size, Nodes, Openings, + module["charPhysLength"], module["charPhysVelocity"], + module["alpha"], module["resolution"], module["epsilon"], module["tau"]); + modules.try_emplace(counter, addModule); + counter++; + } + network_->setModules(std::move(modules)); + } + network_->sortGroups(); + + if (simType == sim::Type::CFD) { + // NOT YET SUPPORTED + throw std::invalid_argument("Full CFD simulations are not yet supported in the simulator."); + } + + // Import pumps + if (!jsonString["simulation"].contains("pumps") || jsonString["simulation"]["pumps"].empty()) { + throw std::invalid_argument("No pumps are defined. Please define at least 1 pump."); + } + for (auto& pump : jsonString["simulation"]["pumps"]) { + if (pump.contains("channel") && pump.contains("type")) { + int channelId = pump["channel"]; + if (pump["type"] == "PumpPressure") { + if (pump.contains("deltaP")) { + T pressure = pump["deltaP"]; + network_->setPressurePump(channelId, pressure); + } else { + throw std::invalid_argument("Please set the pressure value 'deltaP' for Pressure pump in channel " + channelId); + } + } else if (pump["type"] == "PumpFlowrate") { + if (pump.contains("flowRate")) { + T flowRate = pump["flowRate"]; + network_->setPressurePump(channelId, flowRate); + } else { + throw std::invalid_argument("Please set the flow rate value 'flowRate' for Flowrate pump in channel " + channelId); + } + } else { + throw std::invalid_argument("Invalid pump type. Please choose one of the following:\nPumpPressure\nPumpFlowrate"); + } + } else { + throw std::invalid_argument("Wrongly defined pump. Please provide following information for pumps:\nchannel\ntype"); + } + } + + // Import Boundary Conditions and set Continuous phase + if (jsonString["simulation"].contains("activeFixture")) { + if (!jsonString["simulation"].contains("fixtures") || jsonString["simulation"]["fixtures"].size()-1 < jsonString["simulation"]["activeFixture"]) { + throw std::invalid_argument("The active fixture does not exist."); + } + if (jsonString["simulation"]["fixtures"].contains("boundaryConditions")) { + /** TODO + * Set new default values for pressure/flowrate pump + */ + } + if (jsonString["simulation"]["fixtures"].contains("phase")) { + simulation.setContinuousPhase(jsonString["simulation"]["fixtures"]["phase"]); + } + } + + // Import resistance model + sim::ResistanceModel2DPoiseuille* resistanceModel = new sim::ResistanceModel2DPoiseuille(simulation.getContinuousPhase()->getViscosity()); + simulation.setResistanceModel(resistanceModel); + + simulation.setNetwork(network_); + + return simulation; + + } + + template + void resultToJSON(std::string jsonFile) { + + std::ifstream f(jsonFile); + json jsonString = json::parse(f); + + } + +} // namespace porting \ No newline at end of file diff --git a/src/simulation/Fluid.h b/src/simulation/Fluid.h index ac8b922..ae038ed 100644 --- a/src/simulation/Fluid.h +++ b/src/simulation/Fluid.h @@ -25,6 +25,15 @@ class Fluid { */ Fluid(int id, T density, T viscosity); + /** + * @brief Constructs a fluid. + * @param[in] id Unique identifier of the fluid. + * @param[in] density Density of the fluid in kg/m^3. + * @param[in] viscosity Viscosity of the fluid in Pas. + * @param[in] name Name of the fluid. + */ + Fluid(int id, T density, T viscosity, std::string name); + /** * @brief Set name of fluid. * @param[in] name Name of the fluid. diff --git a/src/simulation/Fluid.hh b/src/simulation/Fluid.hh index 4c5c5bb..8202ef2 100644 --- a/src/simulation/Fluid.hh +++ b/src/simulation/Fluid.hh @@ -7,6 +7,10 @@ namespace sim { template Fluid::Fluid(int id_, T density_, T viscosity_) : id(id_), density(density_), viscosity(viscosity_) { } +template +Fluid::Fluid(int id_, T density_, T viscosity_, std::string name_) : id(id_), density(density_), + viscosity(viscosity_), name(name_) { } + template void Fluid::setName(std::string name_) { this->name = std::move(name_); diff --git a/src/simulation/Simulation.h b/src/simulation/Simulation.h index 29981d4..04c5233 100644 --- a/src/simulation/Simulation.h +++ b/src/simulation/Simulation.h @@ -13,6 +13,20 @@ namespace sim { + enum class Platform { + NONE, + CONTINUOUS, ///< A simulation with a single continuous fluid. + DROPLET, ///< A simulation with droplets filling a channel cross-section + MIXING ///< A simulation wit multiple miscible fluids. + }; + + enum class Type { + NONE, + _1D, ///< A simulation in the 1D abstraction level + HYBRID, ///< A simulation combining the 1D and CFD abstraction levels + CFD ///< A simulation in the CFD abstraction level + }; + /** * @brief Class that conducts the simulation and owns all parameters necessary for it. */ @@ -20,9 +34,12 @@ namespace sim { class Simulation { private: // TODO: Add static member variable that keeps track of total memory allocated for lbm sim + Platform platform = Platform::NONE; + Type simType = Type::NONE; arch::Network* network; ///< Network for which the simulation should be conducted. ResistanceModel2DPoiseuille* resistanceModel; ///< The resistance model used for te simulation. - Fluid* continuousPhase = nullptr; ///< Fluid of the continuous phase. + std::vector>> fluids; + int continuousPhase = 0; ///< Fluid of the continuous phase. /** * @brief Initializes the resistance model and the channel resistances of the empty channels. @@ -48,7 +65,13 @@ namespace sim { * @brief Define which fluid should act as continuous phase, i.e., as carrier fluid for the droplets. * @param[in] fluid The fluid the continuous phase consists of. */ - void setContinuousPhase(Fluid* fluid); + void setContinuousPhase(int fluidId); + + /** + * @brief Define which fluid should act as continuous phase, i.e., as carrier fluid for the droplets. + * @param[in] fluid The fluid the continuous phase consists of. + */ + void setFluids(std::vector>>& fluids); /** * @brief Get the continuous phase. @@ -72,5 +95,17 @@ namespace sim { * @brief Print the results as pressure at the nodes and flow rates at the channels */ void printResults(); + + /** + * @brief Set the platform of the simulation. + * @param[in] platform + */ + void setPlatform(Platform platform); + + /** + * @brief Set the type of the simulation. + * @param[in] type + */ + void setType(Type type); }; } // namespace sim \ No newline at end of file diff --git a/src/simulation/Simulation.hh b/src/simulation/Simulation.hh index 17e3ec5..d85a4c4 100644 --- a/src/simulation/Simulation.hh +++ b/src/simulation/Simulation.hh @@ -36,8 +36,13 @@ namespace sim { } template - void Simulation::setContinuousPhase(Fluid* fluid_) { - this->continuousPhase = fluid_; + void Simulation::setContinuousPhase(int fluidId_) { + this->continuousPhase = fluidId_; + } + + template + void Simulation::setFluids(std::vector>>& fluids_) { + this->fluids = std::move(fluids_); } template @@ -45,6 +50,21 @@ namespace sim { this->resistanceModel = model_; } + template + void Simulation::setPlatform(Platform platform_) { + this->platform = platform_; + } + + template + void Simulation::setType(Type type_) { + this->simType = type_; + } + + template + Fluid* Simulation::getContinuousPhase() { + return fluids[continuousPhase].get(); + } + template void Simulation::simulate() { @@ -107,7 +127,7 @@ namespace sim { template void Simulation::initialize() { // set resistance model - this->resistanceModel = new ResistanceModel2DPoiseuille(continuousPhase->getViscosity()); + this->resistanceModel = new ResistanceModel2DPoiseuille(fluids[continuousPhase]->getViscosity()); // compute and set channel lengths std::cout << "[Simulation] Compute and set channel lengths..." << std::endl; @@ -127,8 +147,8 @@ namespace sim { } for (auto& [key, module] : network->getModules()) { - module->lbmInit(continuousPhase->getViscosity(), - continuousPhase->getDensity()); + module->lbmInit(fluids[continuousPhase]->getViscosity(), + fluids[continuousPhase]->getDensity()); } // TODO: this is boilerplate code, and can be done way more efficiently in a recursive manner