diff --git a/src/olbProcessors/AdeConcBoundaries2D.h b/src/olbProcessors/AdeConcBoundaries2D.h new file mode 100644 index 0000000..8e5e754 --- /dev/null +++ b/src/olbProcessors/AdeConcBoundaries2D.h @@ -0,0 +1,57 @@ +#pragma once + +#include +#include + +namespace arch { + +// Forward declared dependencies +template +class Opening; + +template +class Node; + +} + +namespace olb { + +template +class AdeConcBC : public AnalyticalF2D { + +private: + T width; ///< Physical width of the opening. + T xc; ///< The physical x coordinate, xc, of the opening node (center). + T yc; ///< The physical y coordinate, yc, of the opening node (center). + T x0; ///< The physical x coordinate, x0, at which the opening "starts" (bottom for right facing opening). + T y0; ///< The physical y coordinate, y0, at which the opening "starts" (bottom for right facing opening). + std::vector array; ///< Vector that contains the array of concentration values along the opening. + +public: + + AdeConcBC(const arch::Opening& opening, std::vector concentrationField); + + bool operator()(T output[], const T input[]) override; + +}; + +template +class AdeConc1D : public SuperPlaneIntegralF2D { + +private: + T width; ///< Physical width of the opening. + T xc; ///< The physical x coordinate, xc, of the opening node (center). + T yc; ///< The physical y coordinate, yc, of the opening node (center). + T x0; ///< The physical x coordinate, x0, at which the opening "starts" (bottom for right facing opening). + T y0; ///< The physical y coordinate, y0, at which the opening "starts" (bottom for right facing opening). + std::vector array; ///< Vector that contains the array of concentration values along the opening. + +public: + + AdeConc1D(const arch::Opening& opening, std::vector concentrationField); + + bool operator()(T output[], const T input[]) override; + +}; + +} diff --git a/src/olbProcessors/AdeConcBoundaries2D.hh b/src/olbProcessors/AdeConcBoundaries2D.hh new file mode 100644 index 0000000..71eef5a --- /dev/null +++ b/src/olbProcessors/AdeConcBoundaries2D.hh @@ -0,0 +1,37 @@ +#include + +namespace olb { + +template +AdeConcBoundary2D::AdeConcBoundary2D(const arch::Opening& opening, std::vector concentrationField) : + width(opening.width), + xc(opening.node->getPosition()[0]), + yc(opening.node->getPosition()[0]), + x0(xc - opening.tangent[0]*0.5*width), + y0(yc - opening.tangent[1]*0.5*width), + array(concentrationField) { } + +template +bool AdeConcBoundary2D::operator()(T output[], const T input[]) { + T s = std::sqrt((input[0]-x0)*(input[0]-x0) + (input[1]-y0)*(input[1]-y0)); + T d = std::sqrt((input[0]-xc)*(input[0]-xc) + (input[1]-yc)*(input[1]-yc)); + T res = width / array.size(); + if (s < width) { + output[0] = array[std::floor(s/res)]; + } + if (0.5*width - d < 0.0) { + output[0] = T(); + } + return true; +} + +template +AdeConc1D::AdeConc1D(const arch::Opening& opening, std::vector concentrationField) + : SuperPlaneIntegralF2D() + +template +bool AdeConc1D::operator()(T output[], const T input[]) { + +} + +} // namespace olb \ No newline at end of file diff --git a/src/simulation/CFDSim.hh b/src/simulation/CFDSim.hh index 79b546c..77ec6e3 100644 --- a/src/simulation/CFDSim.hh +++ b/src/simulation/CFDSim.hh @@ -47,7 +47,7 @@ namespace sim { } template - bool conductADSimulation(const std::unordered_map>>& cfdSimulators) { + bool conductADSimulation(const std::unordered_map>>& cfdSimulators, bool fieldValues) { bool allConverge = true; @@ -61,7 +61,7 @@ namespace sim { assert(cfdSimulator.second->getModule()->getModuleType() == arch::ModuleType::ESS_LBM); throw std::runtime_error("Simulation of Advection Diffusion not defined for ESS LBM."); #endif - cfdSimulator.second->adSolve(); + cfdSimulator.second->adSolve(fieldValues); if (!cfdSimulator.second->hasAdConverged()) { allConverge = false; diff --git a/src/simulation/MixingModels.hh b/src/simulation/MixingModels.hh index 01fbb44..cea9fcf 100644 --- a/src/simulation/MixingModels.hh +++ b/src/simulation/MixingModels.hh @@ -469,14 +469,18 @@ void DiffusionMixingModel::generateInflows(T timeStep, arch::Network* netw for (auto& [channelId, channel] : network->getChannels()) { // There is only one channel connected to a node at a CFD hybrid node connection if (cfdSimulator->getFlowRates().at(nodeId) > 0.0 && (channel->getNodeA() == nodeId || channel->getNodeB() == nodeId)) { std::unordered_map,std::vector,T>> newDistributions; - std::cout << "Getting here, nodeId is " + std::to_string(nodeId) << std::endl; + std::cout << "Getting here 1, nodeId is " + std::to_string(nodeId) << std::endl; for (const auto& [specieId, concentrationField] : concentrationFieldsIn.at(nodeId)) { - std::cout << "Getting here 2" << std::endl; + std::cout << "Getting here 1.1" << std::endl; T dx = channel->getWidth() / concentrationField.size(); + std::cout << "Getting here 1.2" << std::endl; T pecletNr = (std::abs(channel->getFlowRate()) / channel->getHeight()) / (sim->getSpecie(specieId))->getDiffusivity(); + std::cout << "Getting here 1.3" << std::endl; std::tuple, std::vector, T> analyticalResult = getAnalyticalSolutionHybrid( channel->getLength(), channel->getFlowRate(), channel->getWidth(), noFourierTerms, pecletNr, concentrationField, dx); + std::cout << "Getting here 1.4" << std::endl; newDistributions.try_emplace(specieId, analyticalResult); + std::cout << "Getting here 1.5" << std::endl; } //Create new DiffusiveMixture DiffusiveMixture* newMixture = dynamic_cast*>(sim->addDiffusiveMixture(newDistributions)); @@ -484,9 +488,11 @@ void DiffusionMixingModel::generateInflows(T timeStep, arch::Network* netw this->injectMixtureInEdge(newMixture->getId(), channelId); } else if (cfdSimulator->getFlowRates().at(nodeId) < 0.0 && (channel->getNodeA() == nodeId || channel->getNodeB() == nodeId)) { + std::cout << "Getting here 2, nodeId is " + std::to_string(nodeId) << std::endl; int resolutionIntoCfd = cfdSimulator->getResolution(nodeId); concentrationFieldsOut.try_emplace(nodeId, std::unordered_map>()); for (const auto& [specieId, speciePtr] : sim->getSpecies()) { + std::cout << "Getting here 2.1" << std::endl; std::vector concentrationFieldForCfdInput = defineConcentrationNodeFieldForCfdInput(resolutionIntoCfd, specieId, channelId, channel->getWidth(), mixtures, noFourierTerms); concentrationFieldsOut.at(nodeId).try_emplace(specieId, concentrationFieldForCfdInput); } diff --git a/src/simulation/Simulation.hh b/src/simulation/Simulation.hh index e02aaaa..a971911 100644 --- a/src/simulation/Simulation.hh +++ b/src/simulation/Simulation.hh @@ -639,7 +639,7 @@ namespace sim { // Obtain overal steady-state concentration results bool concentrationConverged = false; while (!concentrationConverged) { - concentrationConverged = conductADSimulation(cfdSimulators); + concentrationConverged = conductADSimulation(cfdSimulators, mixingModel->isDiffusive()); this->mixingModel->propagateSpecies(network, this); } } @@ -682,7 +682,7 @@ namespace sim { // Obtain overal steady-state concentration results bool concentrationConverged = false; while (!concentrationConverged) { - concentrationConverged = conductADSimulation(cfdSimulators); + concentrationConverged = conductADSimulation(cfdSimulators, mixingModel->isDiffusive()); this->mixingModel->propagateSpecies(network, this); } } diff --git a/src/simulation/simulators/cfdSimulator.h b/src/simulation/simulators/cfdSimulator.h index 47ca506..bccf7b2 100755 --- a/src/simulation/simulators/cfdSimulator.h +++ b/src/simulation/simulators/cfdSimulator.h @@ -256,7 +256,7 @@ class CFDSimulator { * @brief Set the boundary values on the lattice at the module nodes. * @param[in] iT Iteration step. */ - virtual void setBoundaryValues(int iT) = 0; + virtual void setBoundaryValues(int iT, bool fieldValues=false) = 0; /** * @brief Prepare the LBM geometry of this simulator. @@ -285,7 +285,7 @@ class CFDSimulator { /** * @brief Conducts the collide and stream operations of the AD lattice(s). */ - virtual void adSolve() + virtual void adSolve(bool fieldValues) { throw std::runtime_error("The function prepareLattice is undefined for this CFD simulator."); } diff --git a/src/simulation/simulators/essContinuous.h b/src/simulation/simulators/essContinuous.h index eb500b1..5a7bf7d 100644 --- a/src/simulation/simulators/essContinuous.h +++ b/src/simulation/simulators/essContinuous.h @@ -83,7 +83,7 @@ namespace sim { * @brief Set the boundary values on the lattice at the module nodes. * @param[in] iT Iteration step. */ - void setBoundaryValues(int iT); + void setBoundaryValues(int iT, bool fieldValues=false); /** * @brief Conducts the collide and stream operations of the lattice. diff --git a/src/simulation/simulators/essContinuous.hh b/src/simulation/simulators/essContinuous.hh index 873b8bc..9d363f3 100644 --- a/src/simulation/simulators/essContinuous.hh +++ b/src/simulation/simulators/essContinuous.hh @@ -17,7 +17,7 @@ namespace sim{ } template - void essLbmSimulator::setBoundaryValues(int iT) + void essLbmSimulator::setBoundaryValues(int iT, bool fieldValues) { setFlowRates(flowRates); setPressures(pressures); diff --git a/src/simulation/simulators/essMixing.h b/src/simulation/simulators/essMixing.h index eb500b1..5a7bf7d 100644 --- a/src/simulation/simulators/essMixing.h +++ b/src/simulation/simulators/essMixing.h @@ -83,7 +83,7 @@ namespace sim { * @brief Set the boundary values on the lattice at the module nodes. * @param[in] iT Iteration step. */ - void setBoundaryValues(int iT); + void setBoundaryValues(int iT, bool fieldValues=false); /** * @brief Conducts the collide and stream operations of the lattice. diff --git a/src/simulation/simulators/essMixing.hh b/src/simulation/simulators/essMixing.hh index 28c0319..e012bae 100644 --- a/src/simulation/simulators/essMixing.hh +++ b/src/simulation/simulators/essMixing.hh @@ -18,7 +18,7 @@ namespace sim{ } template - void essLbmSimulator::setBoundaryValues(int iT) + void essLbmSimulator::setBoundaryValues(int iT, bool fieldValues) { setFlowRates(flowRates); setPressures(pressures); diff --git a/src/simulation/simulators/olbContinuous.h b/src/simulation/simulators/olbContinuous.h index 9ff6572..29bd03e 100644 --- a/src/simulation/simulators/olbContinuous.h +++ b/src/simulation/simulators/olbContinuous.h @@ -174,7 +174,7 @@ using BounceBack = olb::BounceBack; * @brief Set the boundary values on the lattice at the module nodes. * @param[in] iT Iteration step. */ - void setBoundaryValues(int iT) override; + void setBoundaryValues(int iT, bool fieldValues=false) override; /** * @brief Conducts the collide and stream operations of the lattice. diff --git a/src/simulation/simulators/olbContinuous.hh b/src/simulation/simulators/olbContinuous.hh index 5d49fcb..a1e05ac 100644 --- a/src/simulation/simulators/olbContinuous.hh +++ b/src/simulation/simulators/olbContinuous.hh @@ -74,7 +74,7 @@ void lbmSimulator::prepareLattice () { } template -void lbmSimulator::setBoundaryValues (int iT) { +void lbmSimulator::setBoundaryValues (int iT, bool fieldValues) { for (auto& [key, Opening] : this->moduleOpenings) { if (this->groundNodes.at(key)) { @@ -389,15 +389,15 @@ template void lbmSimulator::setFlowProfile2D (int openingKey, T openingWidth) { T maxVelocity = (3./2.)*(flowRates[openingKey]/(openingWidth)); T distance2Wall = getConverter().getConversionFactorLength()/2.; - this->flowProfiles.at(openingKey) = std::make_shared>(getGeometry(), openingKey+3, getConverter().getLatticeVelocity(maxVelocity), distance2Wall); - getLattice().defineU(getGeometry(), openingKey+3, *this->flowProfiles.at(openingKey)); + flowProfiles.at(openingKey) = std::make_shared>(getGeometry(), openingKey+3, getConverter().getLatticeVelocity(maxVelocity), distance2Wall); + getLattice().defineU(getGeometry(), openingKey+3, *flowProfiles.at(openingKey)); } template void lbmSimulator::setPressure2D (int openingKey) { T rhoV = getConverter().getLatticeDensityFromPhysPressure((pressures[openingKey])); - this->densities.at(openingKey) = std::make_shared>(rhoV); - getLattice().defineRho(getGeometry(), openingKey+3, *this->densities.at(openingKey)); + densities.at(openingKey) = std::make_shared>(rhoV); + getLattice().defineRho(getGeometry(), openingKey+3, *densities.at(openingKey)); } template diff --git a/src/simulation/simulators/olbMixing.h b/src/simulation/simulators/olbMixing.h index 82d9400..f021515 100644 --- a/src/simulation/simulators/olbMixing.h +++ b/src/simulation/simulators/olbMixing.h @@ -44,8 +44,8 @@ using ADDynamics = olb::AdvectionDiffusionBGKdynamics; using NoADDynamics = olb::NoDynamics; protected: - std::unordered_map> concentrations; ///< Vector of concentration values at module nodes. > - std::unordered_map>> nodeConcentrationFields; ///< Vector of concentration values at module nodes. >> + std::unordered_map> concentrations; ///< Vector of concentration values at module nodes. > + std::unordered_map>> nodeConcentrationFields; ///< Vector of concentration values at module nodes. >> std::unordered_map*> species; @@ -61,7 +61,7 @@ using NoADDynamics = olb::NoDynamics; std::unordered_map fluxWall; T zeroFlux = 0.0; - std::unordered_map>>> concentrationProfiles; + std::unordered_map>>> concentrationProfiles; ///< Map of concentration field in olb format at module nodes. >> std::unordered_map>>> meanConcentrations; ///< Map of mean pressure values at module nodes. auto& getAdConverter(int key) { @@ -94,13 +94,15 @@ using NoADDynamics = olb::NoDynamics; */ void executeCoupling() override; - void setConcentration2D(int key); + void setConcentrationConst2D(int key); + + void setConcentrationField2D(int key); /** * @brief Update the values at the module nodes based on the simulation result after stepIter iterations. * @param[in] iT Iteration step. */ - void storeCfdResults(int iT); + void storeCfdResults(int iT, bool fieldValues); public: /** @@ -159,7 +161,7 @@ using NoADDynamics = olb::NoDynamics; * @brief Set the boundary values on the lattice at the module nodes. * @param[in] iT Iteration step. */ - void setBoundaryValues(int iT) override; + void setBoundaryValues(int iT, bool fieldValues) override; /** * @brief Conducts the collide and stream operations of the lattice. @@ -174,7 +176,7 @@ using NoADDynamics = olb::NoDynamics; /** * @brief Conducts the collide and stream operations of the AD lattice(s). */ - void adSolve() override; + void adSolve(bool fieldValues) override; /** * @brief Write the vtk file with results of the CFD simulation to file system. diff --git a/src/simulation/simulators/olbMixing.hh b/src/simulation/simulators/olbMixing.hh index 7e6cb0c..d48b638 100644 --- a/src/simulation/simulators/olbMixing.hh +++ b/src/simulation/simulators/olbMixing.hh @@ -84,7 +84,7 @@ void lbmMixingSimulator::prepareLattice () { } template -void lbmMixingSimulator::setBoundaryValues (int iT) { +void lbmMixingSimulator::setBoundaryValues (int iT, bool fieldValues) { for (auto& [key, Opening] : this->moduleOpenings) { if (this->groundNodes.at(key)) { @@ -92,12 +92,19 @@ void lbmMixingSimulator::setBoundaryValues (int iT) { } else { this->setPressure2D(key); } - setConcentration2D(key); + // Constant concentration values + if (!fieldValues) { + setConcentrationConst2D(key); + } + // Constant field values + if (fieldValues) { + setConcentrationField2D(key); + } } } template -void lbmMixingSimulator::storeCfdResults (int iT) { +void lbmMixingSimulator::storeCfdResults (int iT, bool fieldValues) { int input[1] = { }; T output[10]; @@ -115,13 +122,22 @@ void lbmMixingSimulator::storeCfdResults (int iT) { for (auto& [key, Opening] : this->moduleOpenings) { // If the node is an outflow, write the concentration value if (this->flowRates.at(key) < 0.0) { - for (auto& [speciesId, adLattice] : adLattices) { - this->meanConcentrations.at(key).at(speciesId)->operator()(output,input); - this->concentrations.at(key).at(speciesId) = output[0]; - if (iT % 1000 == 0) { - this->meanConcentrations.at(key).at(speciesId)->print(); + // Constant concentration values + if (!fieldValues) { + for (auto& [speciesId, adLattice] : adLattices) { + this->meanConcentrations.at(key).at(speciesId)->operator()(output,input); + this->concentrations.at(key).at(speciesId) = output[0]; + if (iT % 1000 == 0) { + this->meanConcentrations.at(key).at(speciesId)->print(); + } } } + // Field concentration values + if (fieldValues) { + /** TODO: + * + */ + } } } @@ -226,9 +242,9 @@ void lbmMixingSimulator::nsSolve() { } template -void lbmMixingSimulator::adSolve() { +void lbmMixingSimulator::adSolve(bool fieldValues) { // theta = 10 - this->setBoundaryValues(this->step); + this->setBoundaryValues(this->step, fieldValues); for (int iT = 0; iT < 100; ++iT){ for (auto& [speciesId, adLattice] : adLattices) { adLattice->collideAndStream(); @@ -236,7 +252,7 @@ void lbmMixingSimulator::adSolve() { writeVTK(this->step); this->step += 1; } - storeCfdResults(this->step); + storeCfdResults(this->step, fieldValues); } template @@ -370,7 +386,7 @@ void lbmMixingSimulator::prepareCoupling() { } template -void lbmMixingSimulator::setConcentration2D (int key) { +void lbmMixingSimulator::setConcentrationConst2D (int key) { // Set the boundary concentrations for inflows and outflows // If the boundary is an inflow if (this->flowRates.at(key) >= 0.0) { @@ -393,6 +409,30 @@ void lbmMixingSimulator::setConcentration2D (int key) { } } +template +void lbmMixingSimulator::setConcentrationField2D (int key) { + + // Set the boundary concentrations for inflows and outflows + // If the boundary is an inflow + if (this->flowRates.at(key) >= 0.0) { + for (auto& [speciesId, adLattice] : adLattices) { + olb::setAdvectionDiffusionTemperatureBoundary(*adLattice, getAdConverter(speciesId).getLatticeRelaxationFrequency(), this->getGeometry(), key+3); + adLattice->defineRho(this->getGeometry(), key+3, *concentrationProfiles.at(key).at(speciesId)); + } + } + // If the boundary is an outflow + else if (this->flowRates.at(key) < 0.0) { + for (auto& [speciesId, adLattice] : adLattices) { + olb::setRegularizedHeatFluxBoundary(*adLattice, getAdConverter(speciesId).getLatticeRelaxationFrequency(), this->getGeometry(), key+3, &zeroFlux); + } + } + + else { + std::cerr << "Error: Invalid Flow Type Boundary Node." << std::endl; + exit(1); + } +} + template void lbmMixingSimulator::storeConcentrations(std::unordered_map> concentrations_) { this->concentrations = concentrations_; @@ -400,6 +440,11 @@ void lbmMixingSimulator::storeConcentrations(std::unordered_map void lbmMixingSimulator::storeNodeConcentrationFields(std::unordered_map>> concentrationFieldsOut_) { + for (auto& [nodeId, fields] : concentrationFieldsOut_) { + for (auto& [specieId, concField] : fields) { + concentrationProfiles.at(nodeId).at(specieId) = std::make_shared(this->moduleOpenings.at(nodeId), concentrationFieldsOut_.at(nodeId).at(specieId)); + } + } this->nodeConcentrationFields = concentrationFieldsOut_; }