From 681a99ab3466a5199b6f5a62541f0016a0a9c9a4 Mon Sep 17 00:00:00 2001 From: Christoph Schwarzmeier <christoph.schwarzmeier@fau.de> Date: Wed, 1 Feb 2023 14:19:42 +0100 Subject: [PATCH] Fix incorrect treatment of body force density in FSLBM module --- .../FreeSurface/BubblyPoiseuille.cpp | 14 +- .../FreeSurface/BubblyPoiseuille.prm | 11 +- apps/showcases/FreeSurface/CapillaryWave.cpp | 14 +- apps/showcases/FreeSurface/CapillaryWave.prm | 3 +- .../FreeSurface/DamBreakCylindrical.cpp | 14 +- .../FreeSurface/DamBreakCylindrical.prm | 11 +- .../FreeSurface/DamBreakRectangular.cpp | 14 +- .../FreeSurface/DamBreakRectangular.prm | 11 +- apps/showcases/FreeSurface/DropImpact.cpp | 14 +- apps/showcases/FreeSurface/DropImpact.prm | 11 +- apps/showcases/FreeSurface/DropWetting.cpp | 14 +- apps/showcases/FreeSurface/DropWetting.prm | 11 +- apps/showcases/FreeSurface/GravityWave.cpp | 69 ++++++-- apps/showcases/FreeSurface/GravityWave.prm | 9 +- .../FreeSurface/GravityWaveCodegen.cpp | 43 ++--- .../GravityWaveLatticeModelGeneration.py | 49 +++--- apps/showcases/FreeSurface/MovingDrop.cpp | 14 +- apps/showcases/FreeSurface/MovingDrop.prm | 11 +- apps/showcases/FreeSurface/RisingBubble.cpp | 14 +- apps/showcases/FreeSurface/RisingBubble.prm | 3 +- apps/showcases/FreeSurface/TaylorBubble.cpp | 14 +- apps/showcases/FreeSurface/TaylorBubble.prm | 3 +- apps/showcases/FreeSurface/ZalesakDisk.cpp | 14 +- apps/showcases/FreeSurface/ZalesakDisk.prm | 3 +- .../communication/SimpleCommunication.h | 18 +- src/lbm/free_surface/InitFunctions.h | 92 ++++++++++ src/lbm/free_surface/VtkWriter.h | 29 +++- .../FreeSurfaceBoundaryHandling.impl.h | 24 +-- src/lbm/free_surface/dynamics/CMakeLists.txt | 2 +- .../free_surface/dynamics/ForceDensitySweep.h | 159 ++++++++++++++++++ .../dynamics/ForceWeightingSweep.h | 96 ----------- .../dynamics/SurfaceDynamicsHandler.h | 50 ++++-- .../dynamics/functionality/AdvectMass.h | 4 +- .../free_surface/surface_geometry/Utility.cpp | 6 +- .../dynamics/CellConversionTest.cpp | 8 +- .../lbm/free_surface/dynamics/CodegenTest.cpp | 81 +++++---- .../lbm/free_surface/dynamics/InflowTest.cpp | 8 +- .../LatticeModelGenerationFreeSurface.py | 44 ++--- .../dynamics/WettingConversionTest.cpp | 10 +- 39 files changed, 631 insertions(+), 388 deletions(-) create mode 100644 src/lbm/free_surface/dynamics/ForceDensitySweep.h delete mode 100644 src/lbm/free_surface/dynamics/ForceWeightingSweep.h diff --git a/apps/showcases/FreeSurface/BubblyPoiseuille.cpp b/apps/showcases/FreeSurface/BubblyPoiseuille.cpp index f3726c245..e27edf893 100644 --- a/apps/showcases/FreeSurface/BubblyPoiseuille.cpp +++ b/apps/showcases/FreeSurface/BubblyPoiseuille.cpp @@ -176,7 +176,6 @@ int main(int argc, char** argv) const std::string excessMassDistributionModel = modelParameters.getParameter< std::string >("excessMassDistributionModel"); const std::string curvatureModel = modelParameters.getParameter< std::string >("curvatureModel"); - const bool enableForceWeighting = modelParameters.getParameter< bool >("enableForceWeighting"); const bool useSimpleMassExchange = modelParameters.getParameter< bool >("useSimpleMassExchange"); const bool enableBubbleModel = modelParameters.getParameter< bool >("enableBubbleModel"); const bool enableBubbleSplits = modelParameters.getParameter< bool >("enableBubbleSplits"); @@ -187,7 +186,6 @@ int main(int argc, char** argv) WALBERLA_LOG_DEVEL_VAR_ON_ROOT(pdfRefillingModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(excessMassDistributionModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(curvatureModel); - WALBERLA_LOG_DEVEL_VAR_ON_ROOT(enableForceWeighting); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(useSimpleMassExchange); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(enableBubbleModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(enableBubbleSplits); @@ -205,11 +203,11 @@ int main(int argc, char** argv) createNonUniformBlockForest(domainSize, cellsPerBlock, numBlocks, periodicity); // add force field - const BlockDataID forceFieldID = + const BlockDataID forceDensityFieldID = field::addToStorage< VectorField_T >(blockForest, "Force field", force, field::fzyx, uint_c(1)); // create lattice model - const LatticeModel_T latticeModel = LatticeModel_T(collisionModel, ForceModel_T(forceFieldID)); + const LatticeModel_T latticeModel = LatticeModel_T(collisionModel, ForceModel_T(forceDensityFieldID)); // add pdf field const BlockDataID pdfFieldID = lbm::addPdfFieldToStorage(blockForest, "PDF field", latticeModel, @@ -276,7 +274,7 @@ int main(int argc, char** argv) freeSurfaceBoundaryHandling->initFlagsFromFillLevel(); // communication after initialization - Communication_T communication(blockForest, flagFieldID, fillFieldID, forceFieldID); + Communication_T communication(blockForest, flagFieldID, fillFieldID, forceDensityFieldID); communication(); PdfCommunication_T pdfCommunication(blockForest, pdfFieldID); @@ -316,9 +314,9 @@ int main(int argc, char** argv) // add boundary handling for standard boundaries and free surface boundaries const SurfaceDynamicsHandler< LatticeModel_T, FlagField_T, ScalarField_T, VectorField_T > dynamicsHandler( - blockForest, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, normalFieldID, curvatureFieldID, + blockForest, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, normalFieldID, curvatureFieldID, freeSurfaceBoundaryHandling, bubbleModel, pdfReconstructionModel, pdfRefillingModel, excessMassDistributionModel, - relaxationRate, force, surfaceTension, enableForceWeighting, useSimpleMassExchange, cellConversionThreshold, + relaxationRate, force, surfaceTension, useSimpleMassExchange, cellConversionThreshold, cellConversionForceThreshold); dynamicsHandler.addSweeps(timeloop); @@ -331,7 +329,7 @@ int main(int argc, char** argv) // add VTK output addVTKOutput< LatticeModel_T, FreeSurfaceBoundaryHandling_T, PdfField_T, FlagField_T, ScalarField_T, VectorField_T >( - blockForest, timeloop, walberlaEnv.config(), flagInfo, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, + blockForest, timeloop, walberlaEnv.config(), flagInfo, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, geometryHandler.getCurvatureFieldID(), geometryHandler.getNormalFieldID(), geometryHandler.getObstNormalFieldID()); diff --git a/apps/showcases/FreeSurface/BubblyPoiseuille.prm b/apps/showcases/FreeSurface/BubblyPoiseuille.prm index cfd43e279..e4fb01b3d 100644 --- a/apps/showcases/FreeSurface/BubblyPoiseuille.prm +++ b/apps/showcases/FreeSurface/BubblyPoiseuille.prm @@ -30,7 +30,6 @@ ModelParameters pdfRefillingModel EquilibriumRefilling; excessMassDistributionModel EvenlyAllInterface; curvatureModel FiniteDifferenceMethod; - enableForceWeighting false; useSimpleMassExchange false; enableBubbleModel true; enableBubbleSplits false; // only used if enableBubbleModel=true @@ -75,16 +74,16 @@ VTK writers { + fill_level; + mapped_flag; velocity; density; - //pdf; - flag; - fill_level; - force; curvature; normal; obstacle_normal; - mapped_flag; + //pdf; + //flag; + //force_density; } inclusion_filters diff --git a/apps/showcases/FreeSurface/CapillaryWave.cpp b/apps/showcases/FreeSurface/CapillaryWave.cpp index 2a6ebb277..64148c5b3 100644 --- a/apps/showcases/FreeSurface/CapillaryWave.cpp +++ b/apps/showcases/FreeSurface/CapillaryWave.cpp @@ -240,7 +240,6 @@ int main(int argc, char** argv) const std::string excessMassDistributionModel = modelParameters.getParameter< std::string >("excessMassDistributionModel"); const std::string curvatureModel = modelParameters.getParameter< std::string >("curvatureModel"); - const bool enableForceWeighting = modelParameters.getParameter< bool >("enableForceWeighting"); const bool useSimpleMassExchange = modelParameters.getParameter< bool >("useSimpleMassExchange"); const real_t cellConversionThreshold = modelParameters.getParameter< real_t >("cellConversionThreshold"); const real_t cellConversionForceThreshold = modelParameters.getParameter< real_t >("cellConversionForceThreshold"); @@ -251,7 +250,6 @@ int main(int argc, char** argv) WALBERLA_LOG_DEVEL_VAR_ON_ROOT(pdfRefillingModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(excessMassDistributionModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(curvatureModel); - WALBERLA_LOG_DEVEL_VAR_ON_ROOT(enableForceWeighting); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(useSimpleMassExchange); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(cellConversionThreshold); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(cellConversionForceThreshold); @@ -273,11 +271,11 @@ int main(int argc, char** argv) createNonUniformBlockForest(domainSize, cellsPerBlock, numBlocks, periodicity); // add force field - const BlockDataID forceFieldID = + const BlockDataID forceDensityFieldID = field::addToStorage< VectorField_T >(blockForest, "Force field", force, field::fzyx, uint_c(1)); // create lattice model - const LatticeModel_T latticeModel = LatticeModel_T(collisionModel, ForceModel_T(forceFieldID)); + const LatticeModel_T latticeModel = LatticeModel_T(collisionModel, ForceModel_T(forceDensityFieldID)); // add pdf field const BlockDataID pdfFieldID = lbm::addPdfFieldToStorage(blockForest, "PDF field", latticeModel, field::fzyx); @@ -346,7 +344,7 @@ int main(int argc, char** argv) freeSurfaceBoundaryHandling->initFlagsFromFillLevel(); // communication after initialization - Communication_T communication(blockForest, flagFieldID, fillFieldID, forceFieldID); + Communication_T communication(blockForest, flagFieldID, fillFieldID, forceDensityFieldID); communication(); PdfCommunication_T pdfCommunication(blockForest, pdfFieldID); @@ -386,9 +384,9 @@ int main(int argc, char** argv) // add boundary handling for standard boundaries and free surface boundaries const SurfaceDynamicsHandler< LatticeModel_T, FlagField_T, ScalarField_T, VectorField_T > dynamicsHandler( - blockForest, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, normalFieldID, curvatureFieldID, + blockForest, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, normalFieldID, curvatureFieldID, freeSurfaceBoundaryHandling, bubbleModel, pdfReconstructionModel, pdfRefillingModel, excessMassDistributionModel, - relaxationRate, force, surfaceTension, enableForceWeighting, useSimpleMassExchange, cellConversionThreshold, + relaxationRate, force, surfaceTension, useSimpleMassExchange, cellConversionThreshold, cellConversionForceThreshold); dynamicsHandler.addSweeps(timeloop); @@ -408,7 +406,7 @@ int main(int argc, char** argv) // add VTK output addVTKOutput< LatticeModel_T, FreeSurfaceBoundaryHandling_T, PdfField_T, FlagField_T, ScalarField_T, VectorField_T >( - blockForest, timeloop, walberlaEnv.config(), flagInfo, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, + blockForest, timeloop, walberlaEnv.config(), flagInfo, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, geometryHandler.getCurvatureFieldID(), geometryHandler.getNormalFieldID(), geometryHandler.getObstNormalFieldID()); diff --git a/apps/showcases/FreeSurface/CapillaryWave.prm b/apps/showcases/FreeSurface/CapillaryWave.prm index b73208639..a2d60bd59 100644 --- a/apps/showcases/FreeSurface/CapillaryWave.prm +++ b/apps/showcases/FreeSurface/CapillaryWave.prm @@ -28,7 +28,6 @@ ModelParameters pdfRefillingModel EquilibriumRefilling; excessMassDistributionModel EvenlyAllInterface; curvatureModel FiniteDifferenceMethod; - enableForceWeighting false; useSimpleMassExchange false; cellConversionThreshold 1e-2; cellConversionForceThreshold 1e-1; @@ -85,7 +84,7 @@ VTK //obstacle_normal; //pdf; //flag; - //force; + //force_density; } inclusion_filters diff --git a/apps/showcases/FreeSurface/DamBreakCylindrical.cpp b/apps/showcases/FreeSurface/DamBreakCylindrical.cpp index d082b5fcc..f48e23232 100644 --- a/apps/showcases/FreeSurface/DamBreakCylindrical.cpp +++ b/apps/showcases/FreeSurface/DamBreakCylindrical.cpp @@ -379,7 +379,6 @@ int main(int argc, char** argv) const std::string excessMassDistributionModel = modelParameters.getParameter< std::string >("excessMassDistributionModel"); const std::string curvatureModel = modelParameters.getParameter< std::string >("curvatureModel"); - const bool enableForceWeighting = modelParameters.getParameter< bool >("enableForceWeighting"); const bool useSimpleMassExchange = modelParameters.getParameter< bool >("useSimpleMassExchange"); const real_t cellConversionThreshold = modelParameters.getParameter< real_t >("cellConversionThreshold"); const real_t cellConversionForceThreshold = modelParameters.getParameter< real_t >("cellConversionForceThreshold"); @@ -391,7 +390,6 @@ int main(int argc, char** argv) WALBERLA_LOG_DEVEL_VAR_ON_ROOT(pdfRefillingModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(excessMassDistributionModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(curvatureModel); - WALBERLA_LOG_DEVEL_VAR_ON_ROOT(enableForceWeighting); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(useSimpleMassExchange); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(cellConversionThreshold); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(cellConversionForceThreshold); @@ -420,12 +418,12 @@ int main(int argc, char** argv) const CollisionModel_T collisionModel = lbm::collision_model::SRTField< ScalarField_T >(relaxationRateFieldID); // add force field - const BlockDataID forceFieldID = + const BlockDataID forceDensityFieldID = field::addToStorage< VectorField_T >(blockForest, "Force field", force, field::fzyx, uint_c(1)); // create lattice model const LatticeModel_T latticeModel = - LatticeModel_T(collisionModel, lbm::force_model::GuoField< VectorField_T >(forceFieldID)); + LatticeModel_T(collisionModel, lbm::force_model::GuoField< VectorField_T >(forceDensityFieldID)); // add pdf field const BlockDataID pdfFieldID = lbm::addPdfFieldToStorage(blockForest, "PDF field", latticeModel, field::fzyx); @@ -455,7 +453,7 @@ int main(int argc, char** argv) freeSurfaceBoundaryHandling->initFlagsFromFillLevel(); // communication after initialization - Communication_T communication(blockForest, flagFieldID, fillFieldID, forceFieldID); + Communication_T communication(blockForest, flagFieldID, fillFieldID, forceDensityFieldID); communication(); PdfCommunication_T pdfCommunication(blockForest, pdfFieldID); @@ -500,9 +498,9 @@ int main(int argc, char** argv) // add boundary handling for standard boundaries and free surface boundaries const SurfaceDynamicsHandler< LatticeModel_T, FlagField_T, ScalarField_T, VectorField_T > dynamicsHandler( - blockForest, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, normalFieldID, curvatureFieldID, + blockForest, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, normalFieldID, curvatureFieldID, freeSurfaceBoundaryHandling, bubbleModel, pdfReconstructionModel, pdfRefillingModel, excessMassDistributionModel, - relaxationRate, force, surfaceTension, enableForceWeighting, useSimpleMassExchange, cellConversionThreshold, + relaxationRate, force, surfaceTension, useSimpleMassExchange, cellConversionThreshold, cellConversionForceThreshold, relaxationRateFieldID, smagorinskyConstant); dynamicsHandler.addSweeps(timeloop); @@ -531,7 +529,7 @@ int main(int argc, char** argv) // add VTK output addVTKOutput< LatticeModel_T, FreeSurfaceBoundaryHandling_T, PdfField_T, FlagField_T, ScalarField_T, VectorField_T >( - blockForest, timeloop, walberlaEnv.config(), flagInfo, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, + blockForest, timeloop, walberlaEnv.config(), flagInfo, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, geometryHandler.getCurvatureFieldID(), geometryHandler.getNormalFieldID(), geometryHandler.getObstNormalFieldID()); diff --git a/apps/showcases/FreeSurface/DamBreakCylindrical.prm b/apps/showcases/FreeSurface/DamBreakCylindrical.prm index aee842982..ccf8a13ff 100644 --- a/apps/showcases/FreeSurface/DamBreakCylindrical.prm +++ b/apps/showcases/FreeSurface/DamBreakCylindrical.prm @@ -28,7 +28,6 @@ ModelParameters pdfRefillingModel EquilibriumRefilling; excessMassDistributionModel EvenlyAllInterface; curvatureModel FiniteDifferenceMethod; - enableForceWeighting false; useSimpleMassExchange false; cellConversionThreshold 1e-2; cellConversionForceThreshold 1e-1; @@ -78,16 +77,16 @@ VTK writers { + fill_level; + mapped_flag; velocity; density; - //pdf; - flag; - fill_level; - force; curvature; normal; obstacle_normal; - mapped_flag; + //pdf; + //flag; + //force_density; } inclusion_filters diff --git a/apps/showcases/FreeSurface/DamBreakRectangular.cpp b/apps/showcases/FreeSurface/DamBreakRectangular.cpp index 6c7109b16..e7abd62e6 100644 --- a/apps/showcases/FreeSurface/DamBreakRectangular.cpp +++ b/apps/showcases/FreeSurface/DamBreakRectangular.cpp @@ -336,7 +336,6 @@ int main(int argc, char** argv) const std::string excessMassDistributionModel = modelParameters.getParameter< std::string >("excessMassDistributionModel"); const std::string curvatureModel = modelParameters.getParameter< std::string >("curvatureModel"); - const bool enableForceWeighting = modelParameters.getParameter< bool >("enableForceWeighting"); const bool useSimpleMassExchange = modelParameters.getParameter< bool >("useSimpleMassExchange"); const real_t cellConversionThreshold = modelParameters.getParameter< real_t >("cellConversionThreshold"); const real_t cellConversionForceThreshold = modelParameters.getParameter< real_t >("cellConversionForceThreshold"); @@ -348,7 +347,6 @@ int main(int argc, char** argv) WALBERLA_LOG_DEVEL_VAR_ON_ROOT(pdfRefillingModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(excessMassDistributionModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(curvatureModel); - WALBERLA_LOG_DEVEL_VAR_ON_ROOT(enableForceWeighting); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(useSimpleMassExchange); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(cellConversionThreshold); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(cellConversionForceThreshold); @@ -377,11 +375,11 @@ int main(int argc, char** argv) const CollisionModel_T collisionModel = lbm::collision_model::SRTField< ScalarField_T >(relaxationRateFieldID); // add force field - const BlockDataID forceFieldID = + const BlockDataID forceDensityFieldID = field::addToStorage< VectorField_T >(blockForest, "Force field", force, field::fzyx, uint_c(1)); // create lattice model - const LatticeModel_T latticeModel = LatticeModel_T(collisionModel, ForceModel_T(forceFieldID)); + const LatticeModel_T latticeModel = LatticeModel_T(collisionModel, ForceModel_T(forceDensityFieldID)); // add pdf field const BlockDataID pdfFieldID = lbm::addPdfFieldToStorage(blockForest, "PDF field", latticeModel, field::fzyx); @@ -444,7 +442,7 @@ int main(int argc, char** argv) freeSurfaceBoundaryHandling->initFlagsFromFillLevel(); // communication after initialization - Communication_T communication(blockForest, flagFieldID, fillFieldID, forceFieldID); + Communication_T communication(blockForest, flagFieldID, fillFieldID, forceDensityFieldID); communication(); PdfCommunication_T pdfCommunication(blockForest, pdfFieldID); @@ -489,9 +487,9 @@ int main(int argc, char** argv) // add boundary handling for standard boundaries and free surface boundaries const SurfaceDynamicsHandler< LatticeModel_T, FlagField_T, ScalarField_T, VectorField_T > dynamicsHandler( - blockForest, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, normalFieldID, curvatureFieldID, + blockForest, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, normalFieldID, curvatureFieldID, freeSurfaceBoundaryHandling, bubbleModel, pdfReconstructionModel, pdfRefillingModel, excessMassDistributionModel, - relaxationRate, force, surfaceTension, enableForceWeighting, useSimpleMassExchange, cellConversionThreshold, + relaxationRate, force, surfaceTension, useSimpleMassExchange, cellConversionThreshold, cellConversionForceThreshold, relaxationRateFieldID, smagorinskyConstant); dynamicsHandler.addSweeps(timeloop); @@ -516,7 +514,7 @@ int main(int argc, char** argv) // add VTK output addVTKOutput< LatticeModel_T, FreeSurfaceBoundaryHandling_T, PdfField_T, FlagField_T, ScalarField_T, VectorField_T >( - blockForest, timeloop, walberlaEnv.config(), flagInfo, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, + blockForest, timeloop, walberlaEnv.config(), flagInfo, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, geometryHandler.getCurvatureFieldID(), geometryHandler.getNormalFieldID(), geometryHandler.getObstNormalFieldID()); diff --git a/apps/showcases/FreeSurface/DamBreakRectangular.prm b/apps/showcases/FreeSurface/DamBreakRectangular.prm index 8c4bc96e7..8e424f919 100644 --- a/apps/showcases/FreeSurface/DamBreakRectangular.prm +++ b/apps/showcases/FreeSurface/DamBreakRectangular.prm @@ -28,7 +28,6 @@ ModelParameters pdfRefillingModel EquilibriumRefilling; excessMassDistributionModel EvenlyAllInterface; curvatureModel FiniteDifferenceMethod; - enableForceWeighting false; useSimpleMassExchange false; cellConversionThreshold 1e-2; cellConversionForceThreshold 1e-1; @@ -78,16 +77,16 @@ VTK writers { + fill_level; + mapped_flag; velocity; density; - //pdf; - flag; - fill_level; - force; curvature; normal; obstacle_normal; - mapped_flag; + //pdf; + //flag; + //force_density; } inclusion_filters diff --git a/apps/showcases/FreeSurface/DropImpact.cpp b/apps/showcases/FreeSurface/DropImpact.cpp index e5df0d56d..896c5b098 100644 --- a/apps/showcases/FreeSurface/DropImpact.cpp +++ b/apps/showcases/FreeSurface/DropImpact.cpp @@ -183,7 +183,6 @@ int main(int argc, char** argv) const std::string excessMassDistributionModel = modelParameters.getParameter< std::string >("excessMassDistributionModel"); const std::string curvatureModel = modelParameters.getParameter< std::string >("curvatureModel"); - const bool enableForceWeighting = modelParameters.getParameter< bool >("enableForceWeighting"); const bool useSimpleMassExchange = modelParameters.getParameter< bool >("useSimpleMassExchange"); const bool enableBubbleModel = modelParameters.getParameter< bool >("enableBubbleModel"); const bool enableBubbleSplits = modelParameters.getParameter< bool >("enableBubbleSplits"); @@ -194,7 +193,6 @@ int main(int argc, char** argv) WALBERLA_LOG_DEVEL_VAR_ON_ROOT(pdfRefillingModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(excessMassDistributionModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(curvatureModel); - WALBERLA_LOG_DEVEL_VAR_ON_ROOT(enableForceWeighting); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(useSimpleMassExchange); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(enableBubbleModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(enableBubbleSplits); @@ -212,11 +210,11 @@ int main(int argc, char** argv) createNonUniformBlockForest(domainSize, cellsPerBlock, numBlocks, periodicity); // add force field - const BlockDataID forceFieldID = + const BlockDataID forceDensityFieldID = field::addToStorage< VectorField_T >(blockForest, "Force field", force, field::fzyx, uint_c(1)); // create lattice model - const LatticeModel_T latticeModel = LatticeModel_T(collisionModel, ForceModel_T(forceFieldID)); + const LatticeModel_T latticeModel = LatticeModel_T(collisionModel, ForceModel_T(forceDensityFieldID)); // add pdf field const BlockDataID pdfFieldID = @@ -269,7 +267,7 @@ int main(int argc, char** argv) freeSurfaceBoundaryHandling->initFlagsFromFillLevel(); // communication after initialization - Communication_T communication(blockForest, flagFieldID, fillFieldID, forceFieldID); + Communication_T communication(blockForest, flagFieldID, fillFieldID, forceDensityFieldID); communication(); PdfCommunication_T pdfCommunication(blockForest, pdfFieldID); @@ -314,9 +312,9 @@ int main(int argc, char** argv) // add boundary handling for standard boundaries and free surface boundaries const SurfaceDynamicsHandler< LatticeModel_T, FlagField_T, ScalarField_T, VectorField_T > dynamicsHandler( - blockForest, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, normalFieldID, curvatureFieldID, + blockForest, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, normalFieldID, curvatureFieldID, freeSurfaceBoundaryHandling, bubbleModel, pdfReconstructionModel, pdfRefillingModel, excessMassDistributionModel, - relaxationRate, force, surfaceTension, enableForceWeighting, useSimpleMassExchange, cellConversionThreshold, + relaxationRate, force, surfaceTension, useSimpleMassExchange, cellConversionThreshold, cellConversionForceThreshold); dynamicsHandler.addSweeps(timeloop); @@ -329,7 +327,7 @@ int main(int argc, char** argv) // add VTK output addVTKOutput< LatticeModel_T, FreeSurfaceBoundaryHandling_T, PdfField_T, FlagField_T, ScalarField_T, VectorField_T >( - blockForest, timeloop, walberlaEnv.config(), flagInfo, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, + blockForest, timeloop, walberlaEnv.config(), flagInfo, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, geometryHandler.getCurvatureFieldID(), geometryHandler.getNormalFieldID(), geometryHandler.getObstNormalFieldID()); diff --git a/apps/showcases/FreeSurface/DropImpact.prm b/apps/showcases/FreeSurface/DropImpact.prm index 76580d98f..8437db98e 100644 --- a/apps/showcases/FreeSurface/DropImpact.prm +++ b/apps/showcases/FreeSurface/DropImpact.prm @@ -32,7 +32,6 @@ ModelParameters pdfRefillingModel EquilibriumRefilling; excessMassDistributionModel EvenlyAllInterface; curvatureModel FiniteDifferenceMethod; - enableForceWeighting false; useSimpleMassExchange false; enableBubbleModel false; enableBubbleSplits false; // only used if enableBubbleModel=true @@ -77,16 +76,16 @@ VTK writers { + fill_level; + mapped_flag; velocity; density; - //pdf; - flag; - fill_level; - force; curvature; normal; obstacle_normal; - mapped_flag; + //pdf; + //flag; + //force_density; } inclusion_filters diff --git a/apps/showcases/FreeSurface/DropWetting.cpp b/apps/showcases/FreeSurface/DropWetting.cpp index c2aca47f5..bdba59086 100644 --- a/apps/showcases/FreeSurface/DropWetting.cpp +++ b/apps/showcases/FreeSurface/DropWetting.cpp @@ -238,7 +238,6 @@ int main(int argc, char** argv) const std::string excessMassDistributionModel = modelParameters.getParameter< std::string >("excessMassDistributionModel"); const std::string curvatureModel = modelParameters.getParameter< std::string >("curvatureModel"); - const bool enableForceWeighting = modelParameters.getParameter< bool >("enableForceWeighting"); const bool useSimpleMassExchange = modelParameters.getParameter< bool >("useSimpleMassExchange"); const bool enableBubbleModel = modelParameters.getParameter< bool >("enableBubbleModel"); const bool enableBubbleSplits = modelParameters.getParameter< bool >("enableBubbleSplits"); @@ -249,7 +248,6 @@ int main(int argc, char** argv) WALBERLA_LOG_DEVEL_VAR_ON_ROOT(pdfRefillingModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(excessMassDistributionModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(curvatureModel); - WALBERLA_LOG_DEVEL_VAR_ON_ROOT(enableForceWeighting); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(useSimpleMassExchange); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(enableBubbleModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(enableBubbleSplits); @@ -271,11 +269,11 @@ int main(int argc, char** argv) createNonUniformBlockForest(domainSize, cellsPerBlock, numBlocks, periodicity); // add force field - const BlockDataID forceFieldID = + const BlockDataID forceDensityFieldID = field::addToStorage< VectorField_T >(blockForest, "Force field", force, field::fzyx, uint_c(1)); // create lattice model - const LatticeModel_T latticeModel = LatticeModel_T(collisionModel, ForceModel_T(forceFieldID)); + const LatticeModel_T latticeModel = LatticeModel_T(collisionModel, ForceModel_T(forceDensityFieldID)); // add pdf field const BlockDataID pdfFieldID = lbm::addPdfFieldToStorage(blockForest, "PDF field", latticeModel, field::fzyx); @@ -306,7 +304,7 @@ int main(int argc, char** argv) freeSurfaceBoundaryHandling->initFlagsFromFillLevel(); // communication after initialization - Communication_T communication(blockForest, flagFieldID, fillFieldID, forceFieldID); + Communication_T communication(blockForest, flagFieldID, fillFieldID, forceDensityFieldID); communication(); PdfCommunication_T pdfCommunication(blockForest, pdfFieldID); @@ -351,9 +349,9 @@ int main(int argc, char** argv) // add boundary handling for standard boundaries and free surface boundaries const SurfaceDynamicsHandler< LatticeModel_T, FlagField_T, ScalarField_T, VectorField_T > dynamicsHandler( - blockForest, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, normalFieldID, curvatureFieldID, + blockForest, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, normalFieldID, curvatureFieldID, freeSurfaceBoundaryHandling, bubbleModel, pdfReconstructionModel, pdfRefillingModel, excessMassDistributionModel, - relaxationRate, force, surfaceTension, enableForceWeighting, useSimpleMassExchange, cellConversionThreshold, + relaxationRate, force, surfaceTension, useSimpleMassExchange, cellConversionThreshold, cellConversionForceThreshold); dynamicsHandler.addSweeps(timeloop); @@ -372,7 +370,7 @@ int main(int argc, char** argv) // add VTK output addVTKOutput< LatticeModel_T, FreeSurfaceBoundaryHandling_T, PdfField_T, FlagField_T, ScalarField_T, VectorField_T >( - blockForest, timeloop, walberlaEnv.config(), flagInfo, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, + blockForest, timeloop, walberlaEnv.config(), flagInfo, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, geometryHandler.getCurvatureFieldID(), geometryHandler.getNormalFieldID(), geometryHandler.getObstNormalFieldID()); diff --git a/apps/showcases/FreeSurface/DropWetting.prm b/apps/showcases/FreeSurface/DropWetting.prm index e10ae9273..5e93daa21 100644 --- a/apps/showcases/FreeSurface/DropWetting.prm +++ b/apps/showcases/FreeSurface/DropWetting.prm @@ -28,7 +28,6 @@ ModelParameters pdfRefillingModel EquilibriumRefilling; excessMassDistributionModel EvenlyAllInterface; curvatureModel FiniteDifferenceMethod; - enableForceWeighting false; useSimpleMassExchange false; enableBubbleModel false; enableBubbleSplits false; // only used if enableBubbleModel=true @@ -75,16 +74,16 @@ VTK writers { + fill_level; + mapped_flag; velocity; density; - //pdf; - flag; - fill_level; - force; curvature; normal; obstacle_normal; - mapped_flag; + //pdf; + //flag; + //force_density; } inclusion_filters diff --git a/apps/showcases/FreeSurface/GravityWave.cpp b/apps/showcases/FreeSurface/GravityWave.cpp index 10b52e266..acca70e45 100644 --- a/apps/showcases/FreeSurface/GravityWave.cpp +++ b/apps/showcases/FreeSurface/GravityWave.cpp @@ -308,8 +308,9 @@ int main(int argc, char** argv) const real_t reynoldsNumber = physicsParameters.getParameter< real_t >("reynoldsNumber"); const real_t waveNumber = real_c(2) * math::pi / real_c(domainSize[0]); const real_t waveFrequency = reynoldsNumber * viscosity / real_c(domainSize[0]) / initialAmplitude; - const real_t forceY = -(waveFrequency * waveFrequency) / waveNumber / std::tanh(waveNumber * liquidDepth); - const Vector3< real_t > force(real_c(0), forceY, real_c(0)); + const real_t gravitationalAccelerationY = + -(waveFrequency * waveFrequency) / waveNumber / std::tanh(waveNumber * liquidDepth); + const Vector3< real_t > acceleration(real_c(0), gravitationalAccelerationY, real_c(0)); const bool enableWetting = physicsParameters.getParameter< bool >("enableWetting"); const real_t contactAngle = physicsParameters.getParameter< real_t >("contactAngle"); @@ -320,7 +321,7 @@ int main(int argc, char** argv) WALBERLA_LOG_DEVEL_VAR_ON_ROOT(contactAngle); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(timesteps); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(viscosity); - WALBERLA_LOG_DEVEL_VAR_ON_ROOT(force); + WALBERLA_LOG_DEVEL_VAR_ON_ROOT(acceleration); // read model parameters from parameter file const auto modelParameters = walberlaEnv.config()->getOneBlock("ModelParameters"); @@ -329,7 +330,6 @@ int main(int argc, char** argv) const std::string excessMassDistributionModel = modelParameters.getParameter< std::string >("excessMassDistributionModel"); const std::string curvatureModel = modelParameters.getParameter< std::string >("curvatureModel"); - const bool enableForceWeighting = modelParameters.getParameter< bool >("enableForceWeighting"); const bool useSimpleMassExchange = modelParameters.getParameter< bool >("useSimpleMassExchange"); const real_t cellConversionThreshold = modelParameters.getParameter< real_t >("cellConversionThreshold"); const real_t cellConversionForceThreshold = modelParameters.getParameter< real_t >("cellConversionForceThreshold"); @@ -340,7 +340,6 @@ int main(int argc, char** argv) WALBERLA_LOG_DEVEL_VAR_ON_ROOT(pdfRefillingModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(excessMassDistributionModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(curvatureModel); - WALBERLA_LOG_DEVEL_VAR_ON_ROOT(enableForceWeighting); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(useSimpleMassExchange); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(cellConversionThreshold); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(cellConversionForceThreshold); @@ -362,11 +361,11 @@ int main(int argc, char** argv) createNonUniformBlockForest(domainSize, cellsPerBlock, numBlocks, periodicity); // add force field - const BlockDataID forceFieldID = - field::addToStorage< VectorField_T >(blockForest, "Force field", force, field::fzyx, uint_c(1)); + const BlockDataID forceDensityFieldID = field::addToStorage< VectorField_T >( + blockForest, "Force density field", Vector3< real_t >(real_c(0)), field::fzyx, uint_c(1)); // create lattice model - const LatticeModel_T latticeModel = LatticeModel_T(collisionModel, ForceModel_T(forceFieldID)); + const LatticeModel_T latticeModel = LatticeModel_T(collisionModel, ForceModel_T(forceDensityFieldID)); // add pdf field const BlockDataID pdfFieldID = lbm::addPdfFieldToStorage(blockForest, "PDF field", latticeModel, field::fzyx); @@ -435,8 +434,48 @@ int main(int argc, char** argv) // might not detect solid flags correctly freeSurfaceBoundaryHandling->initFlagsFromFillLevel(); + // initialize sine profile such that there is exactly one period in the domain, i.e., with wavelength=domainSize[0]; + // every length is normalized with domainSize[0] + for (auto blockIt = blockForest->begin(); blockIt != blockForest->end(); ++blockIt) + { + ScalarField_T* const fillField = blockIt->getData< ScalarField_T >(fillFieldID); + + WALBERLA_FOR_ALL_CELLS(fillFieldIt, fillField, { + // cell in block-local coordinates + const Cell localCell = fillFieldIt.cell(); + + // get cell in global coordinates + Cell globalCell = fillFieldIt.cell(); + blockForest->transformBlockLocalToGlobalCell(globalCell, *blockIt, localCell); + + // Monte-Carlo like estimation of the fill level: + // create uniformly-distributed sample points in each cell and count the number of points below the sine + // profile; this fraction of points is used as the fill level to initialize the profile + uint_t numPointsBelow = uint_c(0); + + for (uint_t xSample = uint_c(0); xSample <= fillLevelInitSamples; ++xSample) + { + // value of the sine-function + const real_t functionValue = initializationProfile(real_c(globalCell[0]) + real_c(xSample) * stepsize, + initialAmplitude, liquidDepth, real_c(domainSize[0])); + + for (uint_t ySample = uint_c(0); ySample <= fillLevelInitSamples; ++ySample) + { + const real_t yPoint = real_c(globalCell[1]) + real_c(ySample) * stepsize; + // with operator <, a fill level of 1 can not be reached when the line is equal to the cell's top border; + // with operator <=, a fill level of 0 can not be reached when the line is equal to the cell's bottom + // border + if (yPoint < functionValue) { ++numPointsBelow; } + } + } + + // fill level is fraction of points below sine profile + fillField->get(localCell) = real_c(numPointsBelow) / real_c(numTotalPoints); + }) // WALBERLA_FOR_ALL_CELLS + } + // communication after initialization - Communication_T communication(blockForest, flagFieldID, fillFieldID, forceFieldID); + Communication_T communication(blockForest, flagFieldID, fillFieldID, forceDensityFieldID); communication(); PdfCommunication_T pdfCommunication(blockForest, pdfFieldID); @@ -457,7 +496,11 @@ int main(int argc, char** argv) else { bubbleModel = std::make_shared< bubble_model::BubbleModelConstantPressure >(real_c(1)); } // initialize hydrostatic pressure - initHydrostaticPressure< PdfField_T >(blockForest, pdfFieldID, force, liquidDepth); + initHydrostaticPressure< PdfField_T >(blockForest, pdfFieldID, acceleration, liquidDepth); + + // initialize force density field + initForceDensityField< PdfField_T, FlagField_T, VectorField_T, ScalarField_T >( + blockForest, forceDensityFieldID, fillFieldID, pdfFieldID, flagFieldID, flagInfo, acceleration); // set density in non-liquid or non-interface cells to one (after initializing with hydrostatic pressure) setDensityInNonFluidCellsToOne< FlagField_T, PdfField_T >(blockForest, flagInfo, flagFieldID, pdfFieldID); @@ -485,9 +528,9 @@ int main(int argc, char** argv) // add boundary handling for standard boundaries and free surface boundaries const SurfaceDynamicsHandler< LatticeModel_T, FlagField_T, ScalarField_T, VectorField_T > dynamicsHandler( - blockForest, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, normalFieldID, curvatureFieldID, + blockForest, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, normalFieldID, curvatureFieldID, freeSurfaceBoundaryHandling, bubbleModel, pdfReconstructionModel, pdfRefillingModel, excessMassDistributionModel, - relaxationRate, force, surfaceTension, enableForceWeighting, useSimpleMassExchange, cellConversionThreshold, + relaxationRate, acceleration, surfaceTension, useSimpleMassExchange, cellConversionThreshold, cellConversionForceThreshold); dynamicsHandler.addSweeps(timeloop); @@ -513,7 +556,7 @@ int main(int argc, char** argv) // add VTK output addVTKOutput< LatticeModel_T, FreeSurfaceBoundaryHandling_T, PdfField_T, FlagField_T, ScalarField_T, VectorField_T >( - blockForest, timeloop, walberlaEnv.config(), flagInfo, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, + blockForest, timeloop, walberlaEnv.config(), flagInfo, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, geometryHandler.getCurvatureFieldID(), geometryHandler.getNormalFieldID(), geometryHandler.getObstNormalFieldID()); diff --git a/apps/showcases/FreeSurface/GravityWave.prm b/apps/showcases/FreeSurface/GravityWave.prm index 0400d62da..ffc5a4c49 100644 --- a/apps/showcases/FreeSurface/GravityWave.prm +++ b/apps/showcases/FreeSurface/GravityWave.prm @@ -8,9 +8,9 @@ BlockForestParameters DomainParameters { - domainWidth 200; // equivalent to wavelength - liquidDepth 100; - initialAmplitude 2; + domainWidth 50; // equivalent to wavelength + liquidDepth 25; + initialAmplitude 0.5; } PhysicsParameters @@ -28,7 +28,6 @@ ModelParameters pdfRefillingModel EquilibriumRefilling; excessMassDistributionModel EvenlyAllInterface; curvatureModel FiniteDifferenceMethod; - enableForceWeighting false; useSimpleMassExchange false; cellConversionThreshold 1e-2; cellConversionForceThreshold 1e-1; @@ -85,7 +84,7 @@ VTK //obstacle_normal; //pdf; //flag; - //force; + force_density; } inclusion_filters diff --git a/apps/showcases/FreeSurface/GravityWaveCodegen.cpp b/apps/showcases/FreeSurface/GravityWaveCodegen.cpp index 1658f9290..dd603d62c 100644 --- a/apps/showcases/FreeSurface/GravityWaveCodegen.cpp +++ b/apps/showcases/FreeSurface/GravityWaveCodegen.cpp @@ -46,8 +46,9 @@ namespace free_surface { namespace GravityWaveCodegen { -using ScalarField_T = GhostLayerField< real_t, 1 >; -using VectorField_T = GhostLayerField< Vector3< real_t >, 1 >; +using ScalarField_T = GhostLayerField< real_t, 1 >; +using VectorField_T = GhostLayerField< Vector3< real_t >, 1 >; +using VectorFieldFlattened_T = GhostLayerField< real_t, 3 >; using LatticeModel_T = lbm::GravityWaveLatticeModel; using LatticeModelStencil_T = LatticeModel_T::Stencil; @@ -309,8 +310,8 @@ int main(int argc, char** argv) const real_t reynoldsNumber = physicsParameters.getParameter< real_t >("reynoldsNumber"); const real_t waveNumber = real_c(2) * math::pi / real_c(domainSize[0]); const real_t waveFrequency = reynoldsNumber * viscosity / real_c(domainSize[0]) / initialAmplitude; - const real_t forceY = -(waveFrequency * waveFrequency) / waveNumber / std::tanh(waveNumber * liquidDepth); - const Vector3< real_t > force(real_c(0), forceY, real_c(0)); + const real_t accelerationY = -(waveFrequency * waveFrequency) / waveNumber / std::tanh(waveNumber * liquidDepth); + const Vector3< real_t > acceleration(real_c(0), accelerationY, real_c(0)); const bool enableWetting = physicsParameters.getParameter< bool >("enableWetting"); const real_t contactAngle = physicsParameters.getParameter< real_t >("contactAngle"); @@ -321,7 +322,7 @@ int main(int argc, char** argv) WALBERLA_LOG_DEVEL_VAR_ON_ROOT(contactAngle); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(timesteps); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(viscosity); - WALBERLA_LOG_DEVEL_VAR_ON_ROOT(force); + WALBERLA_LOG_DEVEL_VAR_ON_ROOT(acceleration); // read model parameters from parameter file const auto modelParameters = walberlaEnv.config()->getOneBlock("ModelParameters"); @@ -330,7 +331,6 @@ int main(int argc, char** argv) const std::string excessMassDistributionModel = modelParameters.getParameter< std::string >("excessMassDistributionModel"); const std::string curvatureModel = modelParameters.getParameter< std::string >("curvatureModel"); - const bool enableForceWeighting = modelParameters.getParameter< bool >("enableForceWeighting"); const bool useSimpleMassExchange = modelParameters.getParameter< bool >("useSimpleMassExchange"); const real_t cellConversionThreshold = modelParameters.getParameter< real_t >("cellConversionThreshold"); const real_t cellConversionForceThreshold = modelParameters.getParameter< real_t >("cellConversionForceThreshold"); @@ -341,7 +341,6 @@ int main(int argc, char** argv) WALBERLA_LOG_DEVEL_VAR_ON_ROOT(pdfRefillingModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(excessMassDistributionModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(curvatureModel); - WALBERLA_LOG_DEVEL_VAR_ON_ROOT(enableForceWeighting); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(useSimpleMassExchange); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(cellConversionThreshold); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(cellConversionForceThreshold); @@ -363,11 +362,11 @@ int main(int argc, char** argv) createNonUniformBlockForest(domainSize, cellsPerBlock, numBlocks, periodicity); // add force field - const BlockDataID forceFieldID = - field::addToStorage< VectorField_T >(blockForest, "Force field", force, field::fzyx, uint_c(1)); + const BlockDataID forceDensityFieldID = + field::addToStorage< VectorFieldFlattened_T >(blockForest, "Force field", real_c(0), field::fzyx, uint_c(1)); // create lattice model - LatticeModel_T latticeModel = LatticeModel_T(force[0], force[1], force[2], relaxationRate); + LatticeModel_T latticeModel = LatticeModel_T(forceDensityFieldID, relaxationRate); // add pdf field const BlockDataID pdfFieldID = lbm::addPdfFieldToStorage(blockForest, "PDF field", latticeModel, field::fzyx); @@ -437,7 +436,7 @@ int main(int argc, char** argv) freeSurfaceBoundaryHandling->initFlagsFromFillLevel(); // communication after initialization - Communication_T communication(blockForest, flagFieldID, fillFieldID, forceFieldID); + Communication_T communication(blockForest, flagFieldID, fillFieldID, forceDensityFieldID); communication(); PdfCommunication_T pdfCommunication(blockForest, pdfFieldID); @@ -458,7 +457,11 @@ int main(int argc, char** argv) else { bubbleModel = std::make_shared< bubble_model::BubbleModelConstantPressure >(real_c(1)); } // initialize hydrostatic pressure - initHydrostaticPressure< PdfField_T >(blockForest, pdfFieldID, force, liquidDepth); + initHydrostaticPressure< PdfField_T >(blockForest, pdfFieldID, acceleration, liquidDepth); + + // initialize force density field + initForceDensityFieldCodegen< PdfField_T, FlagField_T, VectorFieldFlattened_T, ScalarField_T >( + blockForest, forceDensityFieldID, fillFieldID, pdfFieldID, flagFieldID, flagInfo, acceleration); // set density in non-liquid or non-interface cells to 1 (after initializing with hydrostatic pressure) setDensityInNonFluidCellsToOne< FlagField_T, PdfField_T >(blockForest, flagInfo, flagFieldID, pdfFieldID); @@ -485,11 +488,12 @@ int main(int argc, char** argv) const ConstBlockDataID normalFieldID = geometryHandler.getConstNormalFieldID(); // add boundary handling for standard boundaries and free surface boundaries - const SurfaceDynamicsHandler< LatticeModel_T, FlagField_T, ScalarField_T, VectorField_T, true > dynamicsHandler( - blockForest, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, normalFieldID, curvatureFieldID, - freeSurfaceBoundaryHandling, bubbleModel, pdfReconstructionModel, pdfRefillingModel, excessMassDistributionModel, - relaxationRate, force, surfaceTension, enableForceWeighting, useSimpleMassExchange, cellConversionThreshold, - cellConversionForceThreshold); + const SurfaceDynamicsHandler< LatticeModel_T, FlagField_T, ScalarField_T, VectorField_T, true, + VectorFieldFlattened_T > + dynamicsHandler(blockForest, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, normalFieldID, + curvatureFieldID, freeSurfaceBoundaryHandling, bubbleModel, pdfReconstructionModel, + pdfRefillingModel, excessMassDistributionModel, relaxationRate, acceleration, surfaceTension, + useSimpleMassExchange, cellConversionThreshold, cellConversionForceThreshold); dynamicsHandler.addSweeps(timeloop); @@ -513,8 +517,9 @@ int main(int argc, char** argv) timeloop.addFuncAfterTimeStep(symmetryEvaluator, "Evaluator: symmetry norm"); // add VTK output - addVTKOutput< LatticeModel_T, FreeSurfaceBoundaryHandling_T, PdfField_T, FlagField_T, ScalarField_T, VectorField_T >( - blockForest, timeloop, walberlaEnv.config(), flagInfo, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, + addVTKOutput< LatticeModel_T, FreeSurfaceBoundaryHandling_T, PdfField_T, FlagField_T, ScalarField_T, VectorField_T, + true, VectorFieldFlattened_T >( + blockForest, timeloop, walberlaEnv.config(), flagInfo, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, geometryHandler.getCurvatureFieldID(), geometryHandler.getNormalFieldID(), geometryHandler.getObstNormalFieldID()); diff --git a/apps/showcases/FreeSurface/GravityWaveLatticeModelGeneration.py b/apps/showcases/FreeSurface/GravityWaveLatticeModelGeneration.py index 22f474fcf..aa61ee797 100644 --- a/apps/showcases/FreeSurface/GravityWaveLatticeModelGeneration.py +++ b/apps/showcases/FreeSurface/GravityWaveLatticeModelGeneration.py @@ -1,5 +1,5 @@ import sympy as sp - +import pystencils as ps from lbmpy.creationfunctions import LBMConfig, LBMOptimisation, create_lb_collision_rule from lbmpy.enums import ForceModel, Method, Stencil from lbmpy.stencils import LBStencil @@ -7,28 +7,31 @@ from lbmpy.stencils import LBStencil from pystencils_walberla import CodeGeneration from lbmpy_walberla import generate_lattice_model -# general parameters -stencil = LBStencil(Stencil.D3Q19) -omega = sp.Symbol('omega') -force = sp.symbols('force_:3') -layout = 'fzyx' - -# method definition -lbm_config = LBMConfig(stencil=stencil, - method=Method.SRT, - relaxation_rate=omega, - compressible=True, - force=force, - force_model=ForceModel.GUO, - zero_centered=False, - streaming_pattern='pull') # free surface implementation only works with pull pattern - -# optimizations to be used by the code generator -lbm_opt = LBMOptimisation(cse_global=True, - field_layout=layout) - -collision_rule = create_lb_collision_rule(lbm_config=lbm_config, - lbm_optimisation=lbm_opt) with CodeGeneration() as ctx: + # general parameters + layout = 'fzyx' + data_type = "float64" if ctx.double_accuracy else "float32" + + stencil = LBStencil(Stencil.D3Q19) + omega = sp.Symbol('omega') + force_field = ps.fields(f"force(3): {data_type}[3D]", layout='fzyx') + + # method definition + lbm_config = LBMConfig(stencil=stencil, + method=Method.SRT, + relaxation_rate=omega, + compressible=True, + force=force_field, + force_model=ForceModel.GUO, + zero_centered=False, + streaming_pattern='pull') # free surface implementation only works with pull pattern + + # optimizations to be used by the code generator + lbm_opt = LBMOptimisation(cse_global=True, + field_layout=layout) + + collision_rule = create_lb_collision_rule(lbm_config=lbm_config, + lbm_optimisation=lbm_opt) + generate_lattice_model(ctx, "GravityWaveLatticeModel", collision_rule, field_layout=layout) diff --git a/apps/showcases/FreeSurface/MovingDrop.cpp b/apps/showcases/FreeSurface/MovingDrop.cpp index 9ddba4ae8..352a85c72 100644 --- a/apps/showcases/FreeSurface/MovingDrop.cpp +++ b/apps/showcases/FreeSurface/MovingDrop.cpp @@ -170,7 +170,6 @@ int main(int argc, char** argv) const std::string excessMassDistributionModel = modelParameters.getParameter< std::string >("excessMassDistributionModel"); const std::string curvatureModel = modelParameters.getParameter< std::string >("curvatureModel"); - const bool enableForceWeighting = modelParameters.getParameter< bool >("enableForceWeighting"); const bool useSimpleMassExchange = modelParameters.getParameter< bool >("useSimpleMassExchange"); const bool enableBubbleModel = modelParameters.getParameter< bool >("enableBubbleModel"); const bool enableBubbleSplits = modelParameters.getParameter< bool >("enableBubbleSplits"); @@ -181,7 +180,6 @@ int main(int argc, char** argv) WALBERLA_LOG_DEVEL_VAR_ON_ROOT(pdfRefillingModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(excessMassDistributionModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(curvatureModel); - WALBERLA_LOG_DEVEL_VAR_ON_ROOT(enableForceWeighting); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(useSimpleMassExchange); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(enableBubbleModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(enableBubbleSplits); @@ -199,11 +197,11 @@ int main(int argc, char** argv) createNonUniformBlockForest(domainSize, cellsPerBlock, numBlocks, periodicity); // add force field - const BlockDataID forceFieldID = + const BlockDataID forceDensityFieldID = field::addToStorage< VectorField_T >(blockForest, "Force field", force, field::fzyx, uint_c(1)); // create lattice model - const LatticeModel_T latticeModel = LatticeModel_T(collisionModel, ForceModel_T(forceFieldID)); + const LatticeModel_T latticeModel = LatticeModel_T(collisionModel, ForceModel_T(forceDensityFieldID)); // add pdf field const BlockDataID pdfFieldID = @@ -233,7 +231,7 @@ int main(int argc, char** argv) freeSurfaceBoundaryHandling->initFlagsFromFillLevel(); // communication after initialization - Communication_T communication(blockForest, flagFieldID, fillFieldID, forceFieldID); + Communication_T communication(blockForest, flagFieldID, fillFieldID, forceDensityFieldID); communication(); PdfCommunication_T pdfCommunication(blockForest, pdfFieldID); @@ -275,9 +273,9 @@ int main(int argc, char** argv) // add boundary handling for standard boundaries and free surface boundaries const SurfaceDynamicsHandler< LatticeModel_T, FlagField_T, ScalarField_T, VectorField_T > dynamicsHandler( - blockForest, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, normalFieldID, curvatureFieldID, + blockForest, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, normalFieldID, curvatureFieldID, freeSurfaceBoundaryHandling, bubbleModel, pdfReconstructionModel, pdfRefillingModel, excessMassDistributionModel, - relaxationRate, force, surfaceTension, enableForceWeighting, useSimpleMassExchange, cellConversionThreshold, + relaxationRate, force, surfaceTension, useSimpleMassExchange, cellConversionThreshold, cellConversionForceThreshold); dynamicsHandler.addSweeps(timeloop); @@ -290,7 +288,7 @@ int main(int argc, char** argv) // add VTK output addVTKOutput< LatticeModel_T, FreeSurfaceBoundaryHandling_T, PdfField_T, FlagField_T, ScalarField_T, VectorField_T >( - blockForest, timeloop, walberlaEnv.config(), flagInfo, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, + blockForest, timeloop, walberlaEnv.config(), flagInfo, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, geometryHandler.getCurvatureFieldID(), geometryHandler.getNormalFieldID(), geometryHandler.getObstNormalFieldID()); diff --git a/apps/showcases/FreeSurface/MovingDrop.prm b/apps/showcases/FreeSurface/MovingDrop.prm index dff95569f..dceed84e7 100644 --- a/apps/showcases/FreeSurface/MovingDrop.prm +++ b/apps/showcases/FreeSurface/MovingDrop.prm @@ -30,7 +30,6 @@ ModelParameters pdfRefillingModel EquilibriumRefilling; excessMassDistributionModel EvenlyAllInterface; curvatureModel FiniteDifferenceMethod; - enableForceWeighting false; useSimpleMassExchange false; enableBubbleModel false; enableBubbleSplits false; // only used if enableBubbleModel=true @@ -75,16 +74,16 @@ VTK writers { + fill_level; + mapped_flag; velocity; density; - //pdf; - flag; - fill_level; - force; curvature; normal; obstacle_normal; - mapped_flag; + //pdf; + //flag; + //force_density; } inclusion_filters diff --git a/apps/showcases/FreeSurface/RisingBubble.cpp b/apps/showcases/FreeSurface/RisingBubble.cpp index ef48f46cc..09bef1b3f 100644 --- a/apps/showcases/FreeSurface/RisingBubble.cpp +++ b/apps/showcases/FreeSurface/RisingBubble.cpp @@ -247,7 +247,6 @@ int main(int argc, char** argv) const std::string excessMassDistributionModel = modelParameters.getParameter< std::string >("excessMassDistributionModel"); const std::string curvatureModel = modelParameters.getParameter< std::string >("curvatureModel"); - const bool enableForceWeighting = modelParameters.getParameter< bool >("enableForceWeighting"); const bool useSimpleMassExchange = modelParameters.getParameter< bool >("useSimpleMassExchange"); const real_t cellConversionThreshold = modelParameters.getParameter< real_t >("cellConversionThreshold"); const real_t cellConversionForceThreshold = modelParameters.getParameter< real_t >("cellConversionForceThreshold"); @@ -258,7 +257,6 @@ int main(int argc, char** argv) WALBERLA_LOG_DEVEL_VAR_ON_ROOT(pdfRefillingModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(excessMassDistributionModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(curvatureModel); - WALBERLA_LOG_DEVEL_VAR_ON_ROOT(enableForceWeighting); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(useSimpleMassExchange); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(cellConversionThreshold); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(cellConversionForceThreshold); @@ -280,11 +278,11 @@ int main(int argc, char** argv) createNonUniformBlockForest(domainSize, cellsPerBlock, numBlocks, periodicity); // add force field - const BlockDataID forceFieldID = + const BlockDataID forceDensityFieldID = field::addToStorage< VectorField_T >(blockForest, "Force field", force, field::fzyx, uint_c(1)); // create lattice model - const LatticeModel_T latticeModel = LatticeModel_T(collisionModel, ForceModel_T(forceFieldID)); + const LatticeModel_T latticeModel = LatticeModel_T(collisionModel, ForceModel_T(forceDensityFieldID)); // add various fields const BlockDataID pdfFieldID = lbm::addPdfFieldToStorage(blockForest, "PDF field", latticeModel, field::fzyx); @@ -315,7 +313,7 @@ int main(int argc, char** argv) freeSurfaceBoundaryHandling->initFlagsFromFillLevel(); // communication after initialization - Communication_T communication(blockForest, flagFieldID, fillFieldID, forceFieldID); + Communication_T communication(blockForest, flagFieldID, fillFieldID, forceDensityFieldID); communication(); PdfCommunication_T pdfCommunication(blockForest, pdfFieldID); @@ -358,9 +356,9 @@ int main(int argc, char** argv) // add boundary handling for standard boundaries and free surface boundaries const SurfaceDynamicsHandler< LatticeModel_T, FlagField_T, ScalarField_T, VectorField_T > dynamicsHandler( - blockForest, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, normalFieldID, curvatureFieldID, + blockForest, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, normalFieldID, curvatureFieldID, freeSurfaceBoundaryHandling, bubbleModel, pdfReconstructionModel, pdfRefillingModel, excessMassDistributionModel, - relaxationRate, force, surfaceTension, enableForceWeighting, useSimpleMassExchange, cellConversionThreshold, + relaxationRate, force, surfaceTension, useSimpleMassExchange, cellConversionThreshold, cellConversionForceThreshold); dynamicsHandler.addSweeps(timeloop); @@ -386,7 +384,7 @@ int main(int argc, char** argv) // add VTK output addVTKOutput< LatticeModel_T, FreeSurfaceBoundaryHandling_T, PdfField_T, FlagField_T, ScalarField_T, VectorField_T >( - blockForest, timeloop, walberlaEnv.config(), flagInfo, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, + blockForest, timeloop, walberlaEnv.config(), flagInfo, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, geometryHandler.getCurvatureFieldID(), geometryHandler.getNormalFieldID(), geometryHandler.getObstNormalFieldID()); diff --git a/apps/showcases/FreeSurface/RisingBubble.prm b/apps/showcases/FreeSurface/RisingBubble.prm index 62f1053d2..1acf65000 100644 --- a/apps/showcases/FreeSurface/RisingBubble.prm +++ b/apps/showcases/FreeSurface/RisingBubble.prm @@ -29,7 +29,6 @@ ModelParameters pdfRefillingModel EquilibriumRefilling; excessMassDistributionModel EvenlyAllInterface; curvatureModel FiniteDifferenceMethod; - enableForceWeighting false; useSimpleMassExchange false; cellConversionThreshold 1e-2; cellConversionForceThreshold 1e-1; @@ -86,7 +85,7 @@ VTK //obstacle_normal; //pdf; //flag; - //force; + //force_density; } inclusion_filters diff --git a/apps/showcases/FreeSurface/TaylorBubble.cpp b/apps/showcases/FreeSurface/TaylorBubble.cpp index 57436886d..9672337ed 100644 --- a/apps/showcases/FreeSurface/TaylorBubble.cpp +++ b/apps/showcases/FreeSurface/TaylorBubble.cpp @@ -253,7 +253,6 @@ int main(int argc, char** argv) const std::string excessMassDistributionModel = modelParameters.getParameter< std::string >("excessMassDistributionModel"); const std::string curvatureModel = modelParameters.getParameter< std::string >("curvatureModel"); - const bool enableForceWeighting = modelParameters.getParameter< bool >("enableForceWeighting"); const bool useSimpleMassExchange = modelParameters.getParameter< bool >("useSimpleMassExchange"); const real_t cellConversionThreshold = modelParameters.getParameter< real_t >("cellConversionThreshold"); const real_t cellConversionForceThreshold = modelParameters.getParameter< real_t >("cellConversionForceThreshold"); @@ -264,7 +263,6 @@ int main(int argc, char** argv) WALBERLA_LOG_DEVEL_VAR_ON_ROOT(pdfRefillingModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(excessMassDistributionModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(curvatureModel); - WALBERLA_LOG_DEVEL_VAR_ON_ROOT(enableForceWeighting); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(useSimpleMassExchange); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(cellConversionThreshold); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(cellConversionForceThreshold); @@ -286,11 +284,11 @@ int main(int argc, char** argv) createNonUniformBlockForest(domainSize, cellsPerBlock, numBlocks, periodicity); // add force field - const BlockDataID forceFieldID = + const BlockDataID forceDensityFieldID = field::addToStorage< VectorField_T >(blockForest, "Force field", force, field::fzyx, uint_c(1)); // create lattice model - const LatticeModel_T latticeModel = LatticeModel_T(collisionModel, ForceModel_T(forceFieldID)); + const LatticeModel_T latticeModel = LatticeModel_T(collisionModel, ForceModel_T(forceDensityFieldID)); // add various fields const BlockDataID pdfFieldID = lbm::addPdfFieldToStorage(blockForest, "PDF field", latticeModel, field::fzyx); @@ -345,7 +343,7 @@ int main(int argc, char** argv) freeSurfaceBoundaryHandling->initFlagsFromFillLevel(); // communication after initialization - Communication_T communication(blockForest, flagFieldID, fillFieldID, forceFieldID); + Communication_T communication(blockForest, flagFieldID, fillFieldID, forceDensityFieldID); communication(); PdfCommunication_T pdfCommunication(blockForest, pdfFieldID); @@ -388,9 +386,9 @@ int main(int argc, char** argv) // add boundary handling for standard boundaries and free surface boundaries const SurfaceDynamicsHandler< LatticeModel_T, FlagField_T, ScalarField_T, VectorField_T > dynamicsHandler( - blockForest, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, normalFieldID, curvatureFieldID, + blockForest, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, normalFieldID, curvatureFieldID, freeSurfaceBoundaryHandling, bubbleModel, pdfReconstructionModel, pdfRefillingModel, excessMassDistributionModel, - relaxationRate, force, surfaceTension, enableForceWeighting, useSimpleMassExchange, cellConversionThreshold, + relaxationRate, force, surfaceTension, useSimpleMassExchange, cellConversionThreshold, cellConversionForceThreshold); dynamicsHandler.addSweeps(timeloop); @@ -414,7 +412,7 @@ int main(int argc, char** argv) // add VTK output addVTKOutput< LatticeModel_T, FreeSurfaceBoundaryHandling_T, PdfField_T, FlagField_T, ScalarField_T, VectorField_T >( - blockForest, timeloop, walberlaEnv.config(), flagInfo, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, + blockForest, timeloop, walberlaEnv.config(), flagInfo, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, geometryHandler.getCurvatureFieldID(), geometryHandler.getNormalFieldID(), geometryHandler.getObstNormalFieldID()); diff --git a/apps/showcases/FreeSurface/TaylorBubble.prm b/apps/showcases/FreeSurface/TaylorBubble.prm index e413afc7f..c4096891f 100644 --- a/apps/showcases/FreeSurface/TaylorBubble.prm +++ b/apps/showcases/FreeSurface/TaylorBubble.prm @@ -31,7 +31,6 @@ ModelParameters pdfRefillingModel EquilibriumRefilling; excessMassDistributionModel EvenlyAllInterface; curvatureModel FiniteDifferenceMethod; - enableForceWeighting false; useSimpleMassExchange false; cellConversionThreshold 1e-2; cellConversionForceThreshold 1e-1; @@ -88,7 +87,7 @@ VTK obstacle_normal; //pdf; //flag; - //force; + //force_density; } inclusion_filters diff --git a/apps/showcases/FreeSurface/ZalesakDisk.cpp b/apps/showcases/FreeSurface/ZalesakDisk.cpp index 02beb5706..edbaab294 100644 --- a/apps/showcases/FreeSurface/ZalesakDisk.cpp +++ b/apps/showcases/FreeSurface/ZalesakDisk.cpp @@ -163,7 +163,6 @@ int main(int argc, char** argv) const std::string excessMassDistributionModel = modelParameters.getParameter< std::string >("excessMassDistributionModel"); const std::string curvatureModel = modelParameters.getParameter< std::string >("curvatureModel"); - const bool enableForceWeighting = modelParameters.getParameter< bool >("enableForceWeighting"); const bool useSimpleMassExchange = modelParameters.getParameter< bool >("useSimpleMassExchange"); const real_t cellConversionThreshold = modelParameters.getParameter< real_t >("cellConversionThreshold"); const real_t cellConversionForceThreshold = modelParameters.getParameter< real_t >("cellConversionForceThreshold"); @@ -174,7 +173,6 @@ int main(int argc, char** argv) WALBERLA_LOG_DEVEL_VAR_ON_ROOT(pdfRefillingModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(excessMassDistributionModel); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(curvatureModel); - WALBERLA_LOG_DEVEL_VAR_ON_ROOT(enableForceWeighting); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(useSimpleMassExchange); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(cellConversionThreshold); WALBERLA_LOG_DEVEL_VAR_ON_ROOT(cellConversionForceThreshold); @@ -192,11 +190,11 @@ int main(int argc, char** argv) createNonUniformBlockForest(domainSize, cellsPerBlock, numBlocks, periodicity); // add force field - const BlockDataID forceFieldID = + const BlockDataID forceDensityFieldID = field::addToStorage< VectorField_T >(blockForest, "Force field", force, field::fzyx, uint_c(1)); // create lattice model - const LatticeModel_T latticeModel = LatticeModel_T(collisionModel, ForceModel_T(forceFieldID)); + const LatticeModel_T latticeModel = LatticeModel_T(collisionModel, ForceModel_T(forceDensityFieldID)); // add pdf field const BlockDataID pdfFieldID = lbm::addPdfFieldToStorage(blockForest, "PDF field", latticeModel, field::fzyx); @@ -254,7 +252,7 @@ int main(int argc, char** argv) freeSurfaceBoundaryHandling->initFlagsFromFillLevel(); // communication after initialization - Communication_T communication(blockForest, flagFieldID, fillFieldID, forceFieldID); + Communication_T communication(blockForest, flagFieldID, fillFieldID, forceDensityFieldID); communication(); PdfCommunication_T pdfCommunication(blockForest, pdfFieldID); @@ -298,9 +296,9 @@ int main(int argc, char** argv) // add boundary handling for standard boundaries and free surface boundaries const SurfaceDynamicsHandler< LatticeModel_T, FlagField_T, ScalarField_T, VectorField_T > dynamicsHandler( - blockForest, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, normalFieldID, curvatureFieldID, + blockForest, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, normalFieldID, curvatureFieldID, freeSurfaceBoundaryHandling, bubbleModel, pdfReconstructionModel, pdfRefillingModel, excessMassDistributionModel, - relaxationRate, force, surfaceTension, enableForceWeighting, useSimpleMassExchange, cellConversionThreshold, + relaxationRate, force, surfaceTension, useSimpleMassExchange, cellConversionThreshold, cellConversionForceThreshold); dynamicsHandler.addSweeps(timeloop); @@ -313,7 +311,7 @@ int main(int argc, char** argv) // add VTK output addVTKOutput< LatticeModel_T, FreeSurfaceBoundaryHandling_T, PdfField_T, FlagField_T, ScalarField_T, VectorField_T >( - blockForest, timeloop, walberlaEnv.config(), flagInfo, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, + blockForest, timeloop, walberlaEnv.config(), flagInfo, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, geometryHandler.getCurvatureFieldID(), geometryHandler.getNormalFieldID(), geometryHandler.getObstNormalFieldID()); diff --git a/apps/showcases/FreeSurface/ZalesakDisk.prm b/apps/showcases/FreeSurface/ZalesakDisk.prm index 259774efd..b9af1280c 100644 --- a/apps/showcases/FreeSurface/ZalesakDisk.prm +++ b/apps/showcases/FreeSurface/ZalesakDisk.prm @@ -26,7 +26,6 @@ ModelParameters pdfRefillingModel EquilibriumRefilling; excessMassDistributionModel EvenlyAllInterface; curvatureModel FiniteDifferenceMethod; - enableForceWeighting false; useSimpleMassExchange false; cellConversionThreshold 1e-2; cellConversionForceThreshold 1e-1; @@ -81,7 +80,7 @@ VTK //obstacle_normal; //pdf; //flag; - //force; + //force_density; } inclusion_filters diff --git a/src/lbm/blockforest/communication/SimpleCommunication.h b/src/lbm/blockforest/communication/SimpleCommunication.h index 42bffe263..764152da6 100644 --- a/src/lbm/blockforest/communication/SimpleCommunication.h +++ b/src/lbm/blockforest/communication/SimpleCommunication.h @@ -42,10 +42,11 @@ using communication::UniformBufferedScheme; template< typename Stencil_T > class SimpleCommunication : public communication::UniformBufferedScheme< Stencil_T > { - using RealScalarField_T = GhostLayerField< real_t, 1 >; - using VectorField_T = GhostLayerField< Vector3< real_t >, 1 >; - using PdfField_T = GhostLayerField< real_t, Stencil_T::Size >; - using UintScalarField_T = GhostLayerField< uint_t, 1 >; + using RealScalarField_T = GhostLayerField< real_t, 1 >; + using VectorField_T = GhostLayerField< Vector3< real_t >, 1 >; + using VectorFieldFlattened_T = GhostLayerField< real_t, 3 >; + using PdfField_T = GhostLayerField< real_t, Stencil_T::Size >; + using UintScalarField_T = GhostLayerField< uint_t, 1 >; using FlagField16_T = FlagField< uint16_t >; using FlagField32_T = FlagField< uint32_t >; @@ -151,7 +152,14 @@ class SimpleCommunication : public communication::UniformBufferedScheme< Stencil { this->addPackInfo(make_shared< PackInfo< UintScalarField_T > >(fieldId)); } - else { WALBERLA_ABORT("Problem with UID"); } + else + { + if (firstBlock.isDataClassOrSubclassOf< VectorFieldFlattened_T >(fieldId)) + { + this->addPackInfo(make_shared< PackInfo< VectorFieldFlattened_T > >(fieldId)); + } + else { WALBERLA_ABORT("Problem with UID"); } + } } } } diff --git a/src/lbm/free_surface/InitFunctions.h b/src/lbm/free_surface/InitFunctions.h index b98f55d54..22cd09c62 100644 --- a/src/lbm/free_surface/InitFunctions.h +++ b/src/lbm/free_surface/InitFunctions.h @@ -200,6 +200,98 @@ void initHydrostaticPressure(const std::weak_ptr< StructuredBlockForest >& block } } +/*********************************************************************************************************************** + * Initialize the force density field with a given acceleration and density of each cell. + **********************************************************************************************************************/ +template< typename PdfField_T, typename FlagField_T, typename VectorField_T, typename ScalarField_T > +void initForceDensityField(const std::weak_ptr< StructuredBlockForest >& blockForestPtr, + const BlockDataID& forceDensityFieldID, const ConstBlockDataID& fillFieldID, + const ConstBlockDataID& pdfFieldID, const ConstBlockDataID& flagFieldID, + const FlagInfo< FlagField_T >& flagInfo, const Vector3< real_t >& acceleration) +{ + const auto blockForest = blockForestPtr.lock(); + WALBERLA_CHECK_NOT_NULLPTR(blockForest); + + for (auto blockIt = blockForest->begin(); blockIt != blockForest->end(); ++blockIt) + { + VectorField_T* const forceDensityField = blockIt->getData< VectorField_T >(forceDensityFieldID); + const ScalarField_T* const fillField = blockIt->getData< const ScalarField_T >(fillFieldID); + const PdfField_T* const pdfField = blockIt->getData< const PdfField_T >(pdfFieldID); + const FlagField_T* const flagField = blockIt->getData< const FlagField_T >(flagFieldID); + + WALBERLA_FOR_ALL_CELLS(forceDensityFieldIt, forceDensityField, fillFieldIt, fillField, pdfFieldIt, pdfField, + flagFieldIt, flagField, { + // set force density in cells to acceleration * density * fillLevel (see equation 15 + // in Koerner et al., 2005); + + *forceDensityFieldIt = Vector3< real_t >(real_c(0)); + + if (flagInfo.isInterface(*flagFieldIt)) + { + const real_t density = pdfField->getDensity(pdfFieldIt.cell()); + *forceDensityFieldIt = acceleration * *fillFieldIt * density; + } + + else + { + if (flagInfo.isLiquid(*flagFieldIt)) + { + const real_t density = pdfField->getDensity(pdfFieldIt.cell()); + *forceDensityFieldIt = acceleration * density; + } + } + }) // WALBERLA_FOR_ALL_CELLS + } +} + +/*********************************************************************************************************************** + * Initialize the force density field with a given acceleration and density of each cell. + * Differs from the version above by using a flattened vector field (GhostLayerField< real_t, 3 >). This is necessary + * because Pystencils does not support VectorField_T (GhostLayerField< Vector3<real_t>, 1 >). + **********************************************************************************************************************/ +template< typename PdfField_T, typename FlagField_T, typename VectorFieldFlattened_T, typename ScalarField_T > +void initForceDensityFieldCodegen(const std::weak_ptr< StructuredBlockForest >& blockForestPtr, + const BlockDataID& forceDensityFieldID, const ConstBlockDataID& fillFieldID, + const ConstBlockDataID& pdfFieldID, const ConstBlockDataID& flagFieldID, + const FlagInfo< FlagField_T >& flagInfo, const Vector3< real_t >& acceleration) +{ + const auto blockForest = blockForestPtr.lock(); + WALBERLA_CHECK_NOT_NULLPTR(blockForest); + + for (auto blockIt = blockForest->begin(); blockIt != blockForest->end(); ++blockIt) + { + VectorFieldFlattened_T* const forceDensityField = blockIt->getData< VectorFieldFlattened_T >(forceDensityFieldID); + const ScalarField_T* const fillField = blockIt->getData< const ScalarField_T >(fillFieldID); + const PdfField_T* const pdfField = blockIt->getData< const PdfField_T >(pdfFieldID); + const FlagField_T* const flagField = blockIt->getData< const FlagField_T >(flagFieldID); + + WALBERLA_FOR_ALL_CELLS(forceDensityFieldIt, forceDensityField, fillFieldIt, fillField, pdfFieldIt, pdfField, + flagFieldIt, flagField, { + // set force density in cells to acceleration * density * fillLevel (see equation 15 + // in Koerner et al., 2005); + + if (flagInfo.isInterface(*flagFieldIt)) + { + const real_t density = pdfField->getDensity(pdfFieldIt.cell()); + forceDensityFieldIt[0] = acceleration[0] * *fillFieldIt * density; + forceDensityFieldIt[1] = acceleration[1] * *fillFieldIt * density; + forceDensityFieldIt[2] = acceleration[2] * *fillFieldIt * density; + } + + else + { + if (flagInfo.isLiquid(*flagFieldIt)) + { + const real_t density = pdfField->getDensity(pdfFieldIt.cell()); + forceDensityFieldIt[0] = acceleration[0] * density; + forceDensityFieldIt[1] = acceleration[1] * density; + forceDensityFieldIt[2] = acceleration[2] * density; + } + } + }) // WALBERLA_FOR_ALL_CELLS + } +} + /*********************************************************************************************************************** * Set density in non-liquid and non-interface cells to 1. **********************************************************************************************************************/ diff --git a/src/lbm/free_surface/VtkWriter.h b/src/lbm/free_surface/VtkWriter.h index f98549a8f..0683479e1 100644 --- a/src/lbm/free_surface/VtkWriter.h +++ b/src/lbm/free_surface/VtkWriter.h @@ -47,13 +47,14 @@ namespace free_surface * config-file. **********************************************************************************************************************/ template< typename LatticeModel_T, typename FreeSurfaceBoundaryHandling_T, typename PdfField_T, typename FlagField_T, - typename ScalarField_T, typename VectorField_T > + typename ScalarField_T, typename VectorField_T, bool useCodegen = false, + typename VectorFieldFlattened_T = GhostLayerField< real_t, 3 > > void addVTKOutput(const std::weak_ptr< StructuredBlockForest >& blockForestPtr, SweepTimeloop& timeloop, const std::weak_ptr< Config >& configPtr, const typename FreeSurfaceBoundaryHandling_T::FlagInfo_T& flagInfo, const BlockDataID& pdfFieldID, - const BlockDataID& flagFieldID, const BlockDataID& fillFieldID, const BlockDataID& forceFieldID, - const BlockDataID& curvatureFieldID, const BlockDataID& normalFieldID, - const BlockDataID& obstacleNormalFieldID) + const BlockDataID& flagFieldID, const BlockDataID& fillFieldID, + const BlockDataID& forceDensityFieldID, const BlockDataID& curvatureFieldID, + const BlockDataID& normalFieldID, const BlockDataID& obstacleNormalFieldID) { const auto blockForest = blockForestPtr.lock(); WALBERLA_CHECK_NOT_NULLPTR(blockForest); @@ -85,7 +86,15 @@ void addVTKOutput(const std::weak_ptr< StructuredBlockForest >& blockForestPtr, writers.push_back(std::make_shared< VTKWriter< VectorField_T, float > >(normalFieldID, "normal")); writers.push_back( std::make_shared< VTKWriter< VectorField_T, float > >(obstacleNormalFieldID, "obstacle_normal")); - writers.push_back(std::make_shared< VTKWriter< VectorField_T, float > >(forceFieldID, "force")); + if constexpr (useCodegen) + { + writers.push_back( + std::make_shared< VTKWriter< VectorFieldFlattened_T, float > >(forceDensityFieldID, "force_density")); + } + else + { + writers.push_back(std::make_shared< VTKWriter< VectorField_T, float > >(forceDensityFieldID, "force_density")); + } // map flagIDs to integer values const auto flagMapper = @@ -118,6 +127,16 @@ void addVTKOutput(const std::weak_ptr< StructuredBlockForest >& blockForestPtr, preVTKComm.addPackInfo(std::make_shared< field::communication::PackInfo< VectorField_T > >(normalFieldID)); preVTKComm.addPackInfo( std::make_shared< field::communication::PackInfo< VectorField_T > >(obstacleNormalFieldID)); + if constexpr (useCodegen) + { + preVTKComm.addPackInfo( + std::make_shared< field::communication::PackInfo< VectorFieldFlattened_T > >(forceDensityFieldID)); + } + else + { + preVTKComm.addPackInfo( + std::make_shared< field::communication::PackInfo< VectorField_T > >(forceDensityFieldID)); + } beforeFuncs["ghost_layer_synchronization"] = preVTKComm; diff --git a/src/lbm/free_surface/boundary/FreeSurfaceBoundaryHandling.impl.h b/src/lbm/free_surface/boundary/FreeSurfaceBoundaryHandling.impl.h index 254293cff..1fdb69f98 100644 --- a/src/lbm/free_surface/boundary/FreeSurfaceBoundaryHandling.impl.h +++ b/src/lbm/free_surface/boundary/FreeSurfaceBoundaryHandling.impl.h @@ -180,12 +180,12 @@ FreeSurfaceBoundaryHandling< LatticeModel_T, FlagField_T, ScalarField_T >::FreeS // define IDs (static const variables) template< typename LatticeModel_T, typename FlagField_T, typename ScalarField_T > -const field::FlagUID - FreeSurfaceBoundaryHandling< LatticeModel_T, FlagField_T, ScalarField_T >::noSlipFlagID = field::FlagUID("NoSlip"); +const field::FlagUID FreeSurfaceBoundaryHandling< LatticeModel_T, FlagField_T, ScalarField_T >::noSlipFlagID = + field::FlagUID("NoSlip"); template< typename LatticeModel_T, typename FlagField_T, typename ScalarField_T > -const field::FlagUID - FreeSurfaceBoundaryHandling< LatticeModel_T, FlagField_T, ScalarField_T >::ubbFlagID = field::FlagUID("UBB"); +const field::FlagUID FreeSurfaceBoundaryHandling< LatticeModel_T, FlagField_T, ScalarField_T >::ubbFlagID = + field::FlagUID("UBB"); template< typename LatticeModel_T, typename FlagField_T, typename ScalarField_T > const field::FlagUID FreeSurfaceBoundaryHandling< LatticeModel_T, FlagField_T, ScalarField_T >::ubbInflowFlagID = @@ -200,20 +200,20 @@ const field::FlagUID FreeSurfaceBoundaryHandling< LatticeModel_T, FlagField_T, S field::FlagUID("PressureOutflow"); template< typename LatticeModel_T, typename FlagField_T, typename ScalarField_T > -const field::FlagUID - FreeSurfaceBoundaryHandling< LatticeModel_T, FlagField_T, ScalarField_T >::outletFlagID = field::FlagUID("Outlet"); +const field::FlagUID FreeSurfaceBoundaryHandling< LatticeModel_T, FlagField_T, ScalarField_T >::outletFlagID = + field::FlagUID("Outlet"); template< typename LatticeModel_T, typename FlagField_T, typename ScalarField_T > const field::FlagUID FreeSurfaceBoundaryHandling< LatticeModel_T, FlagField_T, ScalarField_T >::freeSlipFlagID = field::FlagUID("FreeSlip"); template< typename LatticeModel_T, typename FlagField_T, typename ScalarField_T > -const BoundaryUID - FreeSurfaceBoundaryHandling< LatticeModel_T, FlagField_T, ScalarField_T >::noSlipBoundaryID = BoundaryUID("NoSlip"); +const BoundaryUID FreeSurfaceBoundaryHandling< LatticeModel_T, FlagField_T, ScalarField_T >::noSlipBoundaryID = + BoundaryUID("NoSlip"); template< typename LatticeModel_T, typename FlagField_T, typename ScalarField_T > -const BoundaryUID - FreeSurfaceBoundaryHandling< LatticeModel_T, FlagField_T, ScalarField_T >::ubbBoundaryID = BoundaryUID("UBB"); +const BoundaryUID FreeSurfaceBoundaryHandling< LatticeModel_T, FlagField_T, ScalarField_T >::ubbBoundaryID = + BoundaryUID("UBB"); template< typename LatticeModel_T, typename FlagField_T, typename ScalarField_T > const BoundaryUID FreeSurfaceBoundaryHandling< LatticeModel_T, FlagField_T, ScalarField_T >::ubbInflowBoundaryID = @@ -228,8 +228,8 @@ const BoundaryUID FreeSurfaceBoundaryHandling< LatticeModel_T, FlagField_T, Scal BoundaryUID("PressureOutflow"); template< typename LatticeModel_T, typename FlagField_T, typename ScalarField_T > -const BoundaryUID - FreeSurfaceBoundaryHandling< LatticeModel_T, FlagField_T, ScalarField_T >::outletBoundaryID = BoundaryUID("Outlet"); +const BoundaryUID FreeSurfaceBoundaryHandling< LatticeModel_T, FlagField_T, ScalarField_T >::outletBoundaryID = + BoundaryUID("Outlet"); template< typename LatticeModel_T, typename FlagField_T, typename ScalarField_T > const BoundaryUID FreeSurfaceBoundaryHandling< LatticeModel_T, FlagField_T, ScalarField_T >::freeSlipBoundaryID = diff --git a/src/lbm/free_surface/dynamics/CMakeLists.txt b/src/lbm/free_surface/dynamics/CMakeLists.txt index 458fabdfe..2d7145db3 100644 --- a/src/lbm/free_surface/dynamics/CMakeLists.txt +++ b/src/lbm/free_surface/dynamics/CMakeLists.txt @@ -5,7 +5,7 @@ target_sources( lbm ExcessMassDistributionModel.h ExcessMassDistributionSweep.h ExcessMassDistributionSweep.impl.h - ForceWeightingSweep.h + ForceDensitySweep.h PdfReconstructionModel.h PdfRefillingModel.h PdfRefillingSweep.h diff --git a/src/lbm/free_surface/dynamics/ForceDensitySweep.h b/src/lbm/free_surface/dynamics/ForceDensitySweep.h new file mode 100644 index 000000000..afe418e9c --- /dev/null +++ b/src/lbm/free_surface/dynamics/ForceDensitySweep.h @@ -0,0 +1,159 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// waLBerla is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file ForceDensitySweep.h +//! \ingroup dynamics +//! \author Christoph Schwarzmeier <christoph.schwarzmeier@fau.de> +//! \brief Weight force in interface cells with fill level and density (equation 15 in Koerner et al., 2005). +// +//====================================================================================================================== + +#pragma once + +#include "core/logging/Logging.h" + +#include "domain_decomposition/BlockDataID.h" + +#include "field/FlagField.h" +#include "field/GhostLayerField.h" + +#include "lbm/field/PdfField.h" +#include "lbm/free_surface/FlagInfo.h" + +namespace walberla +{ +namespace free_surface +{ +/*********************************************************************************************************************** + * Update the force density field as in equation 15 in Koerner et al., 2005. with "acceleration * density * fill level". + **********************************************************************************************************************/ +template< typename LatticeModel_T, typename FlagField_T, typename VectorField_T, typename ScalarField_T > +class ForceDensitySweep +{ + public: + ForceDensitySweep(BlockDataID forceDensityFieldID, ConstBlockDataID pdfFieldID, ConstBlockDataID flagFieldID, + ConstBlockDataID fillFieldID, const FlagInfo< FlagField_T >& flagInfo, + const Vector3< real_t >& globalAcceleration) + : forceDensityFieldID_(forceDensityFieldID), pdfFieldID_(pdfFieldID), flagFieldID_(flagFieldID), + fillFieldID_(fillFieldID), flagInfo_(flagInfo), globalAcceleration_(globalAcceleration) + {} + + void operator()(IBlock* const block) + { + using PdfField_T = lbm::PdfField< LatticeModel_T >; + + VectorField_T* const forceDensityField = block->getData< VectorField_T >(forceDensityFieldID_); + const PdfField_T* const pdfField = block->getData< const PdfField_T >(pdfFieldID_); + const FlagField_T* const flagField = block->getData< const FlagField_T >(flagFieldID_); + const ScalarField_T* const fillField = block->getData< const ScalarField_T >(fillFieldID_); + + WALBERLA_FOR_ALL_CELLS(forceDensityFieldIt, forceDensityField, pdfFieldIt, pdfField, flagFieldIt, flagField, + fillFieldIt, fillField, { + flag_t flag = *flagFieldIt; + + // set force density in cells to acceleration * density * fillLevel (see equation 15 + // in Koerner et al., 2005); + if (flagInfo_.isInterface(flag)) + { + const real_t density = pdfField->getDensity(pdfFieldIt.cell()); + *forceDensityFieldIt = globalAcceleration_ * *fillFieldIt * density; + } + + else + { + if (flagInfo_.isLiquid(flag)) + { + const real_t density = pdfField->getDensity(pdfFieldIt.cell()); + *forceDensityFieldIt = globalAcceleration_ * density; + } + } + }) // WALBERLA_FOR_ALL_CELLS + } + + private: + using flag_t = typename FlagField_T::flag_t; + + BlockDataID forceDensityFieldID_; + ConstBlockDataID pdfFieldID_; + ConstBlockDataID flagFieldID_; + ConstBlockDataID fillFieldID_; + FlagInfo< FlagField_T > flagInfo_; + Vector3< real_t > globalAcceleration_; +}; // class ForceDensitySweep + +/*********************************************************************************************************************** + * Update the force density field as in equation 15 in Koerner et al., 2005. with "acceleration * density * fill level". + * Differs from the version above by using a flattened vector field (GhostLayerField< real_t, 3 >). This is necessary + * because Pystencils does not support VectorField_T (GhostLayerField< Vector3<real_t>, 1 >). + **********************************************************************************************************************/ +template< typename LatticeModel_T, typename FlagField_T, typename VectorFieldFlattened_T, typename ScalarField_T > +class ForceDensityCodegenSweep +{ + public: + ForceDensityCodegenSweep(BlockDataID forceDensityFieldID, ConstBlockDataID pdfFieldID, ConstBlockDataID flagFieldID, + ConstBlockDataID fillFieldID, const FlagInfo< FlagField_T >& flagInfo, + const Vector3< real_t >& globalAcceleration) + : forceDensityFieldID_(forceDensityFieldID), pdfFieldID_(pdfFieldID), flagFieldID_(flagFieldID), + fillFieldID_(fillFieldID), flagInfo_(flagInfo), globalAcceleration_(globalAcceleration) + {} + + void operator()(IBlock* const block) + { + using PdfField_T = lbm::PdfField< LatticeModel_T >; + + VectorFieldFlattened_T* const forceDensityField = block->getData< VectorFieldFlattened_T >(forceDensityFieldID_); + const PdfField_T* const pdfField = block->getData< const PdfField_T >(pdfFieldID_); + const FlagField_T* const flagField = block->getData< const FlagField_T >(flagFieldID_); + const ScalarField_T* const fillField = block->getData< const ScalarField_T >(fillFieldID_); + + WALBERLA_FOR_ALL_CELLS(forceDensityFieldIt, forceDensityField, pdfFieldIt, pdfField, flagFieldIt, flagField, + fillFieldIt, fillField, { + flag_t flag = *flagFieldIt; + + // set force density in cells to acceleration * density * fillLevel (see equation 15 + // in Koerner et al., 2005); + if (flagInfo_.isInterface(flag)) + { + const real_t density = pdfField->getDensity(pdfFieldIt.cell()); + forceDensityFieldIt[0] = globalAcceleration_[0] * *fillFieldIt * density; + forceDensityFieldIt[1] = globalAcceleration_[1] * *fillFieldIt * density; + forceDensityFieldIt[2] = globalAcceleration_[2] * *fillFieldIt * density; + } + else + { + if (flagInfo_.isLiquid(flag)) + { + const real_t density = pdfField->getDensity(pdfFieldIt.cell()); + forceDensityFieldIt[0] = globalAcceleration_[0] * density; + forceDensityFieldIt[1] = globalAcceleration_[1] * density; + forceDensityFieldIt[2] = globalAcceleration_[2] * density; + } + } + }) // WALBERLA_FOR_ALL_CELLS + } + + private: + using flag_t = typename FlagField_T::flag_t; + + BlockDataID forceDensityFieldID_; + ConstBlockDataID pdfFieldID_; + ConstBlockDataID flagFieldID_; + ConstBlockDataID fillFieldID_; + FlagInfo< FlagField_T > flagInfo_; + Vector3< real_t > globalAcceleration_; +}; // class ForceDensitySweep + +} // namespace free_surface +} // namespace walberla diff --git a/src/lbm/free_surface/dynamics/ForceWeightingSweep.h b/src/lbm/free_surface/dynamics/ForceWeightingSweep.h deleted file mode 100644 index 4a13fb3b4..000000000 --- a/src/lbm/free_surface/dynamics/ForceWeightingSweep.h +++ /dev/null @@ -1,96 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla is free software: you can -// redistribute it and/or modify it under the terms of the GNU General Public -// License as published by the Free Software Foundation, either version 3 of -// the License, or (at your option) any later version. -// -// waLBerla is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. -// -// You should have received a copy of the GNU General Public License along -// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file ForceWeightingSweep.h -//! \ingroup dynamics -//! \author Christoph Schwarzmeier <christoph.schwarzmeier@fau.de> -//! \brief Weight force in interface cells with fill level and density (equation 15 in Koerner et al., 2005). -// -//====================================================================================================================== - -#pragma once - -#include "core/logging/Logging.h" - -#include "domain_decomposition/BlockDataID.h" - -#include "field/FlagField.h" -#include "field/GhostLayerField.h" - -#include "lbm/field/PdfField.h" -#include "lbm/free_surface/FlagInfo.h" - -namespace walberla -{ -namespace free_surface -{ -/*********************************************************************************************************************** - * Weight the specified force in interface cells according to their density and fill level, as in equation 15 in Koerner - * et al., 2005. - * In liquid cells, the force is set to the specified constant global force. - **********************************************************************************************************************/ -template< typename LatticeModel_T, typename FlagField_T, typename VectorField_T, typename ScalarField_T > -class ForceWeightingSweep -{ - public: - ForceWeightingSweep(BlockDataID forceFieldID, ConstBlockDataID pdfFieldID, ConstBlockDataID flagFieldID, - ConstBlockDataID fillFieldID, const FlagInfo< FlagField_T >& flagInfo, - const Vector3< real_t >& globalForce) - : forceFieldID_(forceFieldID), pdfFieldID_(pdfFieldID), flagFieldID_(flagFieldID), fillFieldID_(fillFieldID), - flagInfo_(flagInfo), globalForce_(globalForce) - {} - - void operator()(IBlock* const block) - { - using PdfField_T = lbm::PdfField< LatticeModel_T >; - - VectorField_T* const forceField = block->getData< VectorField_T >(forceFieldID_); - const PdfField_T* const pdfField = block->getData< const PdfField_T >(pdfFieldID_); - const FlagField_T* const flagField = block->getData< const FlagField_T >(flagFieldID_); - const ScalarField_T* const fillField = block->getData< const ScalarField_T >(fillFieldID_); - - WALBERLA_FOR_ALL_CELLS(forceFieldIt, forceField, pdfFieldIt, pdfField, flagFieldIt, flagField, fillFieldIt, - fillField, { - flag_t flag = *flagFieldIt; - - // set force in interface cells to globalForce_ * density * fillLevel (see equation 15 - // in Koerner et al., 2005) - if (flagInfo_.isInterface(flag)) - { - const real_t density = pdfField->getDensity(pdfFieldIt.cell()); - const real_t fillLevel = *fillFieldIt; - *forceFieldIt = globalForce_ * fillLevel * density; - } - else - { - // set force to globalForce_ in all non-interface cells - *forceFieldIt = globalForce_; - } - }) // WALBERLA_FOR_ALL_CELLS - } - - private: - using flag_t = typename FlagField_T::flag_t; - - BlockDataID forceFieldID_; - ConstBlockDataID pdfFieldID_; - ConstBlockDataID flagFieldID_; - ConstBlockDataID fillFieldID_; - FlagInfo< FlagField_T > flagInfo_; - Vector3< real_t > globalForce_; -}; // class ForceWeightingSweep - -} // namespace free_surface -} // namespace walberla diff --git a/src/lbm/free_surface/dynamics/SurfaceDynamicsHandler.h b/src/lbm/free_surface/dynamics/SurfaceDynamicsHandler.h index 93f204d30..d65469940 100644 --- a/src/lbm/free_surface/dynamics/SurfaceDynamicsHandler.h +++ b/src/lbm/free_surface/dynamics/SurfaceDynamicsHandler.h @@ -48,7 +48,7 @@ #include "ConversionFlagsResetSweep.h" #include "ExcessMassDistributionModel.h" #include "ExcessMassDistributionSweep.h" -#include "ForceWeightingSweep.h" +#include "ForceDensitySweep.h" #include "PdfReconstructionModel.h" #include "PdfRefillingModel.h" #include "PdfRefillingSweep.h" @@ -59,7 +59,7 @@ namespace walberla namespace free_surface { template< typename LatticeModel_T, typename FlagField_T, typename ScalarField_T, typename VectorField_T, - bool useCodegen = false > + bool useCodegen = false, typename VectorFieldFlattened_T = GhostLayerField< real_t, 3 > > class SurfaceDynamicsHandler { protected: @@ -74,22 +74,22 @@ class SurfaceDynamicsHandler public: SurfaceDynamicsHandler(const std::shared_ptr< StructuredBlockForest >& blockForest, BlockDataID pdfFieldID, - BlockDataID flagFieldID, BlockDataID fillFieldID, BlockDataID forceFieldID, + BlockDataID flagFieldID, BlockDataID fillFieldID, BlockDataID forceDensityFieldID, ConstBlockDataID normalFieldID, ConstBlockDataID curvatureFieldID, const std::shared_ptr< FreeSurfaceBoundaryHandling_T >& freeSurfaceBoundaryHandling, const std::shared_ptr< BubbleModelBase >& bubbleModel, const std::string& pdfReconstructionModel, const std::string& pdfRefillingModel, const std::string& excessMassDistributionModel, real_t relaxationRate, - const Vector3< real_t >& globalForce, real_t surfaceTension, bool enableForceWeighting, + const Vector3< real_t >& globalAcceleration, real_t surfaceTension, bool useSimpleMassExchange, real_t cellConversionThreshold, real_t cellConversionForceThreshold, BlockDataID relaxationRateFieldID = BlockDataID(), real_t smagorinskyConstant = real_c(0)) : blockForest_(blockForest), pdfFieldID_(pdfFieldID), flagFieldID_(flagFieldID), fillFieldID_(fillFieldID), - forceFieldID_(forceFieldID), normalFieldID_(normalFieldID), curvatureFieldID_(curvatureFieldID), + forceDensityFieldID_(forceDensityFieldID), normalFieldID_(normalFieldID), curvatureFieldID_(curvatureFieldID), bubbleModel_(bubbleModel), freeSurfaceBoundaryHandling_(freeSurfaceBoundaryHandling), pdfReconstructionModel_(pdfReconstructionModel), pdfRefillingModel_({ pdfRefillingModel }), excessMassDistributionModel_({ excessMassDistributionModel }), relaxationRate_(relaxationRate), - globalForce_(globalForce), surfaceTension_(surfaceTension), enableForceWeighting_(enableForceWeighting), + globalAcceleration_(globalAcceleration), surfaceTension_(surfaceTension), useSimpleMassExchange_(useSimpleMassExchange), cellConversionThreshold_(cellConversionThreshold), cellConversionForceThreshold_(cellConversionForceThreshold), relaxationRateFieldID_(relaxationRateFieldID), smagorinskyConstant_(smagorinskyConstant) @@ -141,16 +141,33 @@ class SurfaceDynamicsHandler Set< SUID >::emptySet(), StateSweep::onlyGasAndBoundary) << Sweep(emptySweep, "Empty sweep: boundary handling", StateSweep::onlyGasAndBoundary); - if (enableForceWeighting_) + if (!(floatIsEqual(globalAcceleration_[0], real_c(0), real_c(1e-14)) && + floatIsEqual(globalAcceleration_[1], real_c(0), real_c(1e-14)) && + floatIsEqual(globalAcceleration_[2], real_c(0), real_c(1e-14)))) { // add sweep for weighting force in interface cells with fill level and density - const ForceWeightingSweep< LatticeModel_T, FlagField_T, VectorField_T, ScalarField_T > forceWeightingSweep( - forceFieldID_, pdfFieldID_, flagFieldID_, fillFieldID_, flagInfo, globalForce_); - timeloop.add() << Sweep(forceWeightingSweep, "Sweep: force weighting", Set< SUID >::emptySet(), - StateSweep::onlyGasAndBoundary) - << Sweep(emptySweep, "Empty sweep: force weighting", StateSweep::onlyGasAndBoundary) - << AfterFunction(CommunicationCorner_T(blockForest_, forceFieldID_), - "Communication: after force weighting sweep"); + if constexpr (useCodegen) + { + // different versions for codegen because pystencils does not support 'Ghostlayerfield<Vector3(), 1>' + const ForceDensityCodegenSweep< LatticeModel_T, FlagField_T, VectorFieldFlattened_T, ScalarField_T > + forceDensityCodegenSweep(forceDensityFieldID_, pdfFieldID_, flagFieldID_, fillFieldID_, flagInfo, + globalAcceleration_); + timeloop.add() << Sweep(forceDensityCodegenSweep, "Sweep: force weighting", Set< SUID >::emptySet(), + StateSweep::onlyGasAndBoundary) + << Sweep(emptySweep, "Empty sweep: force weighting", StateSweep::onlyGasAndBoundary) + << AfterFunction(CommunicationCorner_T(blockForest_, forceDensityFieldID_), + "Communication: after force weighting sweep"); + } + else + { + const ForceDensitySweep< LatticeModel_T, FlagField_T, VectorField_T, ScalarField_T > forceDensitySweep( + forceDensityFieldID_, pdfFieldID_, flagFieldID_, fillFieldID_, flagInfo, globalAcceleration_); + timeloop.add() << Sweep(forceDensitySweep, "Sweep: force weighting", Set< SUID >::emptySet(), + StateSweep::onlyGasAndBoundary) + << Sweep(emptySweep, "Empty sweep: force weighting", StateSweep::onlyGasAndBoundary) + << AfterFunction(CommunicationCorner_T(blockForest_, forceDensityFieldID_), + "Communication: after force weighting sweep"); + } } // sweep for @@ -412,7 +429,7 @@ class SurfaceDynamicsHandler BlockDataID pdfFieldID_; BlockDataID flagFieldID_; BlockDataID fillFieldID_; - BlockDataID forceFieldID_; + BlockDataID forceDensityFieldID_; ConstBlockDataID normalFieldID_; ConstBlockDataID curvatureFieldID_; @@ -424,9 +441,8 @@ class SurfaceDynamicsHandler PdfRefillingModel pdfRefillingModel_; ExcessMassDistributionModel excessMassDistributionModel_; real_t relaxationRate_; - Vector3< real_t > globalForce_; + Vector3< real_t > globalAcceleration_; real_t surfaceTension_; - bool enableForceWeighting_; bool useSimpleMassExchange_; real_t cellConversionThreshold_; real_t cellConversionForceThreshold_; diff --git a/src/lbm/free_surface/dynamics/functionality/AdvectMass.h b/src/lbm/free_surface/dynamics/functionality/AdvectMass.h index 5e198e2db..9ec9e655c 100644 --- a/src/lbm/free_surface/dynamics/functionality/AdvectMass.h +++ b/src/lbm/free_surface/dynamics/functionality/AdvectMass.h @@ -207,8 +207,8 @@ real_t advectMass(const FlagField_T* flagField, const ConstScalarIt_T& fillSrc, bool neighborNoFluidNeig = !flagInfo.isLiquid(neighIt.neighbor(relevantDir[0], relevantDir[1], relevantDir[2])); bool neighborStandardCell = !(neighborNoGasNeig || neighborNoFluidNeig); bool neighborWettingCell = flagInfo.isKeepInterfaceForWetting(flagFieldIt.neighbor( - relevantDir[0], relevantDir[1], - relevantDir[2])); // evaluate flag of this cell (flagFieldIt) and not the neighborhood flags (neighIt) + relevantDir[0], relevantDir[1], + relevantDir[2])); // evaluate flag of this cell (flagFieldIt) and not the neighborhood flags (neighIt) if (neighborNoGasNeig && neighborNoFluidNeig && !neighborWettingCell) // neighboring cell has only interface neighbors diff --git a/src/lbm/free_surface/surface_geometry/Utility.cpp b/src/lbm/free_surface/surface_geometry/Utility.cpp index 9b1582c66..ef9f2520a 100644 --- a/src/lbm/free_surface/surface_geometry/Utility.cpp +++ b/src/lbm/free_surface/surface_geometry/Utility.cpp @@ -391,9 +391,9 @@ Vector3< real_t > getInterfacePoint(const Vector3< real_t >& normal, real_t fill real_t getCellEdgeIntersection(const Vector3< real_t >& edgePoint, const Vector3< real_t >& edgeDirection, const Vector3< real_t >& normal, const Vector3< real_t >& surfacePoint) { - //#ifndef BELOW_CELL - //# define BELOW_CELL (-10) - //#endif + // #ifndef BELOW_CELL + // # define BELOW_CELL (-10) + // #endif #ifndef ABOVE_CELL # define ABOVE_CELL (-20) diff --git a/tests/lbm/free_surface/dynamics/CellConversionTest.cpp b/tests/lbm/free_surface/dynamics/CellConversionTest.cpp index 6f7645c84..b11c64421 100644 --- a/tests/lbm/free_surface/dynamics/CellConversionTest.cpp +++ b/tests/lbm/free_surface/dynamics/CellConversionTest.cpp @@ -109,8 +109,8 @@ void testCellConversion() BlockDataID pdfFieldID = lbm::addPdfFieldToStorage(blockForest, "PDF field", latticeModel, field::fzyx); BlockDataID fillFieldID = field::addToStorage< ScalarField_T >(blockForest, "Fill levels", real_c(1.0), field::fzyx, uint_c(1)); - BlockDataID forceFieldID = field::addToStorage< VectorField_T >( - blockForest, "Force field", Vector3< real_t >(real_c(0)), field::fzyx, uint_c(1)); + BlockDataID forceDensityFieldID = field::addToStorage< VectorField_T >( + blockForest, "Force density field", Vector3< real_t >(real_c(0)), field::fzyx, uint_c(1)); BlockDataID curvatureFieldID = field::addToStorage< ScalarField_T >(blockForest, "Curvature", real_c(0.0), field::fzyx, uint_c(1)); BlockDataID normalFieldID = field::addToStorage< VectorField_T >( @@ -162,9 +162,9 @@ void testCellConversion() // add various sweeps for surface dynamics SurfaceDynamicsHandler< LatticeModel_T, FlagField_T, ScalarField_T, VectorField_T > dynamicsHandler( - blockForest, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, normalFieldID, curvatureFieldID, + blockForest, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, normalFieldID, curvatureFieldID, freeSurfaceBoundaryHandling, bubbleModel, "NormalBasedKeepCenter", "EquilibriumRefilling", "EvenlyNewInterface", - relaxRate, Vector3< real_t >(real_c(0)), real_c(0), false, false, real_c(1e-3), real_c(1e-1)); + relaxRate, Vector3< real_t >(real_c(0)), real_c(0), false, real_c(1e-3), real_c(1e-1)); dynamicsHandler.addSweeps(timeloop); real_t initialMass = diff --git a/tests/lbm/free_surface/dynamics/CodegenTest.cpp b/tests/lbm/free_surface/dynamics/CodegenTest.cpp index a141a0a3c..9a00890aa 100644 --- a/tests/lbm/free_surface/dynamics/CodegenTest.cpp +++ b/tests/lbm/free_surface/dynamics/CodegenTest.cpp @@ -27,6 +27,7 @@ #include "core/debug/TestSubsystem.h" #include "lbm/field/AddToStorage.h" +#include "lbm/free_surface/InitFunctions.h" #include "lbm/free_surface/bubble_model/Geometry.h" #include "lbm/free_surface/dynamics/SurfaceDynamicsHandler.h" #include "lbm/free_surface/surface_geometry/SurfaceGeometryHandler.h" @@ -44,8 +45,9 @@ namespace free_surface namespace CodegenTest { -using ScalarField_T = GhostLayerField< real_t, 1 >; -using VectorField_T = GhostLayerField< Vector3< real_t >, 1 >; +using ScalarField_T = GhostLayerField< real_t, 1 >; +using VectorField_T = GhostLayerField< Vector3< real_t >, 1 >; +using VectorFieldFlattened_T = GhostLayerField< real_t, 3 >; template< bool useCodegen > void runSimulation() @@ -54,6 +56,7 @@ void runSimulation() using ForceModel_T = lbm::force_model::GuoField< VectorField_T >; using LatticeModel_T = typename std::conditional< useCodegen, lbm::GeneratedLatticeModel_FreeSurface, lbm::D3Q19< CollisionModel_T, true, ForceModel_T, 2 > >::type; + using PdfField_T = lbm::PdfField< LatticeModel_T >; using Communication_T = blockforest::SimpleCommunication< typename LatticeModel_T::CommunicationStencil >; @@ -76,39 +79,45 @@ void runSimulation() true, true, true); // periodicity // physics parameters - const real_t dropDiameter = real_c(2); - const real_t relaxationRate = real_c(1.8); - const real_t surfaceTension = real_c(1e-5); - const bool enableWetting = false; - const real_t contactAngle = real_c(0); - const Vector3< real_t > force = Vector3< real_t >(real_c(1e-5), real_c(0), real_c(0)); + const real_t dropDiameter = real_c(2); + const real_t relaxationRate = real_c(1.8); + const real_t surfaceTension = real_c(1e-5); + const bool enableWetting = false; + const real_t contactAngle = real_c(0); + const Vector3< real_t > acceleration = Vector3< real_t >(real_c(1e-5), real_c(0), real_c(0)); // model parameters const std::string pdfReconstructionModel = "NormalBasedKeepCenter"; const std::string pdfRefillingModel = "EquilibriumRefilling"; const std::string excessMassDistributionModel = "EvenlyAllInterface"; const std::string curvatureModel = "FiniteDifferenceMethod"; - const bool enableForceWeighting = false; const bool useSimpleMassExchange = false; const real_t cellConversionThreshold = real_c(1e-2); const real_t cellConversionForceThreshold = real_c(1e-1); // add force field - const BlockDataID forceFieldID = - field::addToStorage< VectorField_T >(blockForest, "Force field", force, field::fzyx, uint_c(1)); + std::shared_ptr< BlockDataID > forceDensityFieldIDPtr = nullptr; std::shared_ptr< LatticeModel_T > latticeModel; // create lattice model if constexpr (useCodegen) { - latticeModel = std::make_shared< LatticeModel_T >(force[0], force[1], force[2], relaxationRate); + // add force field of type 'GhostLayerField< real_t, 3 >' as required by pystencils + forceDensityFieldIDPtr = std::make_shared< BlockDataID >(field::addToStorage< VectorFieldFlattened_T >( + blockForest, "Force density field (codegen)", real_c(0), field::fzyx, uint_c(1))); + latticeModel = std::make_shared< LatticeModel_T >(*forceDensityFieldIDPtr, relaxationRate); } else { - latticeModel = std::make_shared< LatticeModel_T >(CollisionModel_T(relaxationRate), ForceModel_T(forceFieldID)); + forceDensityFieldIDPtr = std::make_shared< BlockDataID >(field::addToStorage< VectorField_T >( + blockForest, "Force density field", Vector3< real_t >(0), field::fzyx, uint_c(1))); + latticeModel = + std::make_shared< LatticeModel_T >(CollisionModel_T(relaxationRate), ForceModel_T(*forceDensityFieldIDPtr)); } + WALBERLA_ASSERT_NOT_NULLPTR(forceDensityFieldIDPtr); + // add various fields const BlockDataID pdfFieldID = lbm::addPdfFieldToStorage(blockForest, "PDF field", *latticeModel, field::fzyx); const BlockDataID fillFieldID = @@ -117,7 +126,8 @@ void runSimulation() // add boundary handling const std::shared_ptr< FreeSurfaceBoundaryHandling_T > freeSurfaceBoundaryHandling = std::make_shared< FreeSurfaceBoundaryHandling_T >(blockForest, pdfFieldID, fillFieldID); - const BlockDataID flagFieldID = freeSurfaceBoundaryHandling->getFlagFieldID(); + const BlockDataID flagFieldID = freeSurfaceBoundaryHandling->getFlagFieldID(); + const typename FreeSurfaceBoundaryHandling_T::FlagInfo_T& flagInfo = freeSurfaceBoundaryHandling->getFlagInfo(); // add drop to fill level field const geometry::Sphere sphereDrop(Vector3< real_t >(real_c(0.5) * real_c(domainSize[0]), @@ -129,8 +139,20 @@ void runSimulation() // initialize flag field from fill level field freeSurfaceBoundaryHandling->initFlagsFromFillLevel(); - // initial Communication_Tunication - Communication_T(blockForest, pdfFieldID, fillFieldID, flagFieldID, forceFieldID)(); + if constexpr (useCodegen) + { + initForceDensityFieldCodegen< PdfField_T, FlagField_T, VectorFieldFlattened_T, ScalarField_T >( + blockForest, *forceDensityFieldIDPtr, fillFieldID, pdfFieldID, flagFieldID, flagInfo, acceleration); + } + else + { + // initialize force density field + initForceDensityField< PdfField_T, FlagField_T, VectorField_T, ScalarField_T >( + blockForest, *forceDensityFieldIDPtr, fillFieldID, pdfFieldID, flagFieldID, flagInfo, acceleration); + } + + // initial communication + Communication_T(blockForest, pdfFieldID, fillFieldID, flagFieldID, *forceDensityFieldIDPtr)(); // add bubble model const std::shared_ptr< bubble_model::BubbleModelConstantPressure > bubbleModel = @@ -154,11 +176,12 @@ void runSimulation() geometryHandler.addSweeps(timeloop); // add boundary handling for standard boundaries and free surface boundaries - SurfaceDynamicsHandler< LatticeModel_T, FlagField_T, ScalarField_T, VectorField_T, useCodegen > dynamicsHandler( - blockForest, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, normalFieldID, curvatureFieldID, - freeSurfaceBoundaryHandling, bubbleModel, pdfReconstructionModel, pdfRefillingModel, excessMassDistributionModel, - relaxationRate, force, surfaceTension, enableForceWeighting, useSimpleMassExchange, cellConversionThreshold, - cellConversionForceThreshold); + const SurfaceDynamicsHandler< LatticeModel_T, FlagField_T, ScalarField_T, VectorField_T, useCodegen, + VectorFieldFlattened_T > + dynamicsHandler(blockForest, pdfFieldID, flagFieldID, fillFieldID, *forceDensityFieldIDPtr, normalFieldID, + curvatureFieldID, freeSurfaceBoundaryHandling, bubbleModel, pdfReconstructionModel, + pdfRefillingModel, excessMassDistributionModel, relaxationRate, acceleration, surfaceTension, + useSimpleMassExchange, cellConversionThreshold, cellConversionForceThreshold); dynamicsHandler.addSweeps(timeloop); @@ -172,35 +195,35 @@ void runSimulation() WALBERLA_FOR_ALL_CELLS(fillFieldIt, fillField, { if (fillFieldIt.cell() == Cell(cell_idx_c(1), cell_idx_c(1), cell_idx_c(1))) { - WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(*fillFieldIt, real_c(0.504035), real_c(1e-4)); + WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(*fillFieldIt, real_c(0.512081), real_c(1e-4)); } if (fillFieldIt.cell() == Cell(cell_idx_c(2), cell_idx_c(1), cell_idx_c(1))) { - WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(*fillFieldIt, real_c(0.538017), real_c(1e-4)); + WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(*fillFieldIt, real_c(0.529967), real_c(1e-4)); } if (fillFieldIt.cell() == Cell(cell_idx_c(1), cell_idx_c(2), cell_idx_c(1))) { - WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(*fillFieldIt, real_c(0.504035), real_c(1e-4)); + WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(*fillFieldIt, real_c(0.512081), real_c(1e-4)); } if (fillFieldIt.cell() == Cell(cell_idx_c(2), cell_idx_c(2), cell_idx_c(1))) { - WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(*fillFieldIt, real_c(0.538017), real_c(1e-4)); + WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(*fillFieldIt, real_c(0.529967), real_c(1e-4)); } if (fillFieldIt.cell() == Cell(cell_idx_c(1), cell_idx_c(1), cell_idx_c(2))) { - WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(*fillFieldIt, real_c(0.504035), real_c(1e-4)); + WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(*fillFieldIt, real_c(0.512081), real_c(1e-4)); } if (fillFieldIt.cell() == Cell(cell_idx_c(2), cell_idx_c(1), cell_idx_c(2))) { - WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(*fillFieldIt, real_c(0.538017), real_c(1e-4)); + WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(*fillFieldIt, real_c(0.529967), real_c(1e-4)); } if (fillFieldIt.cell() == Cell(cell_idx_c(1), cell_idx_c(2), cell_idx_c(2))) { - WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(*fillFieldIt, real_c(0.504035), real_c(1e-4)); + WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(*fillFieldIt, real_c(0.512081), real_c(1e-4)); } if (fillFieldIt.cell() == Cell(cell_idx_c(2), cell_idx_c(2), cell_idx_c(2))) { - WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(*fillFieldIt, real_c(0.538017), real_c(1e-4)); + WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(*fillFieldIt, real_c(0.529967), real_c(1e-4)); } }); // WALBERLA_FOR_ALL_CELLS } diff --git a/tests/lbm/free_surface/dynamics/InflowTest.cpp b/tests/lbm/free_surface/dynamics/InflowTest.cpp index da8b5df18..49423ada6 100644 --- a/tests/lbm/free_surface/dynamics/InflowTest.cpp +++ b/tests/lbm/free_surface/dynamics/InflowTest.cpp @@ -90,8 +90,8 @@ void testInflow() BlockDataID pdfFieldID = lbm::addPdfFieldToStorage(blockForest, "PDF field", latticeModel, field::fzyx); BlockDataID fillFieldID = field::addToStorage< ScalarField_T >(blockForest, "Fill levels", real_c(0.0), field::fzyx, uint_c(2)); - BlockDataID forceFieldID = field::addToStorage< VectorField_T >( - blockForest, "Force field", Vector3< real_t >(real_c(0)), field::fzyx, uint_c(1)); + BlockDataID forceDensityFieldID = field::addToStorage< VectorField_T >( + blockForest, "Force density field", Vector3< real_t >(real_c(0)), field::fzyx, uint_c(1)); BlockDataID densityAdaptor = field::addFieldAdaptor< typename lbm::Adaptor< LatticeModel_T >::Density >( blockForest, pdfFieldID, "DensityAdaptor"); BlockDataID velocityAdaptor = field::addFieldAdaptor< typename lbm::Adaptor< LatticeModel_T >::VelocityVector >( @@ -155,9 +155,9 @@ void testInflow() // add boundary handling for standard boundaries and free surface boundaries SurfaceDynamicsHandler< LatticeModel_T, FlagField_T, ScalarField_T, VectorField_T > dynamicsHandler( - blockForest, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, normalFieldID, curvatureFieldID, + blockForest, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, normalFieldID, curvatureFieldID, freeSurfaceBoundaryHandling, bubbleModel, "NormalBasedKeepCenter", "EquilibriumRefilling", "EvenlyNewInterface", - relaxRate, Vector3< real_t >(real_c(0)), real_c(0), false, false, real_c(1e-3), real_c(1e-1)); + relaxRate, Vector3< real_t >(real_c(0)), real_c(0), false, real_c(1e-3), real_c(1e-1)); dynamicsHandler.addSweeps(timeloop); diff --git a/tests/lbm/free_surface/dynamics/LatticeModelGenerationFreeSurface.py b/tests/lbm/free_surface/dynamics/LatticeModelGenerationFreeSurface.py index 0ef55dce4..a1b0b251a 100644 --- a/tests/lbm/free_surface/dynamics/LatticeModelGenerationFreeSurface.py +++ b/tests/lbm/free_surface/dynamics/LatticeModelGenerationFreeSurface.py @@ -1,5 +1,5 @@ import sympy as sp - +import pystencils as ps from lbmpy.creationfunctions import LBMConfig, LBMOptimisation, create_lb_collision_rule from lbmpy.enums import ForceModel, Method, Stencil from lbmpy.stencils import LBStencil @@ -7,28 +7,30 @@ from lbmpy.stencils import LBStencil from pystencils_walberla import CodeGeneration from lbmpy_walberla import generate_lattice_model -# general parameters -stencil = LBStencil(Stencil.D3Q19) -omega = sp.Symbol('omega') -force = sp.symbols('force_:3') -layout = 'fzyx' +with CodeGeneration() as ctx: + # general parameters + layout = 'fzyx' + data_type = "float64" if ctx.double_accuracy else "float32" + + stencil = LBStencil(Stencil.D3Q19) + omega = sp.Symbol('omega') + force_field = ps.fields(f"force(3): {data_type}[3D]", layout=layout) -# method definition -lbm_config = LBMConfig(stencil=stencil, - method=Method.SRT, - relaxation_rate=omega, - compressible=True, - force=force, - force_model=ForceModel.GUO, - zero_centered=False, - streaming_pattern='pull') # free surface implementation only works with pull pattern + # method definition + lbm_config = LBMConfig(stencil=stencil, + method=Method.SRT, + relaxation_rate=omega, + compressible=True, + force=force_field, + force_model=ForceModel.GUO, + zero_centered=False, + streaming_pattern='pull') # free surface implementation only works with pull pattern -# optimizations to be used by the code generator -lbm_opt = LBMOptimisation(cse_global=True, - field_layout=layout) + # optimizations to be used by the code generator + lbm_opt = LBMOptimisation(cse_global=True, + field_layout=layout) -collision_rule = create_lb_collision_rule(lbm_config=lbm_config, - lbm_optimisation=lbm_opt) + collision_rule = create_lb_collision_rule(lbm_config=lbm_config, + lbm_optimisation=lbm_opt) -with CodeGeneration() as ctx: generate_lattice_model(ctx, "GeneratedLatticeModel_FreeSurface", collision_rule, field_layout=layout) diff --git a/tests/lbm/free_surface/dynamics/WettingConversionTest.cpp b/tests/lbm/free_surface/dynamics/WettingConversionTest.cpp index 8a2590c69..b6e03ede0 100644 --- a/tests/lbm/free_surface/dynamics/WettingConversionTest.cpp +++ b/tests/lbm/free_surface/dynamics/WettingConversionTest.cpp @@ -83,8 +83,8 @@ std::vector< Cell > runSimulation(uint_t timesteps, real_t contactAngle) field::addToStorage< ScalarField_T >(blockForest, "Fill level field", real_c(0.0), field::fzyx, uint_c(1)); // add dummy force field - BlockDataID forceFieldID = field::addToStorage< VectorField_T >( - blockForest, "Force field", Vector3< real_t >(real_c(0)), field::fzyx, uint_c(1)); + BlockDataID forceDensityFieldID = field::addToStorage< VectorField_T >( + blockForest, "Force density field", Vector3< real_t >(real_c(0)), field::fzyx, uint_c(1)); // add boundary handling const std::shared_ptr< FreeSurfaceBoundaryHandling_T > freeSurfaceBoundaryHandling = @@ -103,7 +103,7 @@ std::vector< Cell > runSimulation(uint_t timesteps, real_t contactAngle) freeSurfaceBoundaryHandling->initFlagsFromFillLevel(); // initial communication - Communication_T(blockForest, pdfFieldID, fillFieldID, flagFieldID, forceFieldID)(); + Communication_T(blockForest, pdfFieldID, fillFieldID, flagFieldID, forceDensityFieldID)(); // add (dummy) bubble model const bool disableSplits = true; // necessary if a gas bubble could split @@ -124,9 +124,9 @@ std::vector< Cell > runSimulation(uint_t timesteps, real_t contactAngle) // add surface dynamics handler SurfaceDynamicsHandler< LatticeModel_T, FlagField_T, ScalarField_T, VectorField_T > dynamicsHandler( - blockForest, pdfFieldID, flagFieldID, fillFieldID, forceFieldID, normalFieldID, curvatureFieldID, + blockForest, pdfFieldID, flagFieldID, fillFieldID, forceDensityFieldID, normalFieldID, curvatureFieldID, freeSurfaceBoundaryHandling, bubbleModel, "NormalBasedKeepCenter", "EquilibriumRefilling", "EvenlyNewInterface", - relaxRate, Vector3< real_t >(real_c(0)), real_c(1e-2), false, false, real_c(1e-3), real_c(1e-1)); + relaxRate, Vector3< real_t >(real_c(0)), real_c(1e-2), false, real_c(1e-3), real_c(1e-1)); dynamicsHandler.addSweeps(timeloop); timeloop.run(); -- GitLab