diff --git a/CMake/cmake_config_files/BOMBADIL.config.cmake b/CMake/cmake_config_files/BOMBADIL.config.cmake index c0c5cf2f08b2cc925be248441c99a336160fd1bd..9c4bd4ecffab1e63161343ecc493eb9d9bc951a4 100644 --- a/CMake/cmake_config_files/BOMBADIL.config.cmake +++ b/CMake/cmake_config_files/BOMBADIL.config.cmake @@ -26,6 +26,15 @@ SET(BOOST_LIBRARYDIR ${BOOST_ROOT}"/stageMSVC64/lib") ################################################################################# set(VTK_DIR "d:/Tools/VTK/build/VTK-8.0.0") +################################################################################# +# LIGGGHTS +################################################################################# +set(LIGGGHTS_SOURCE_DIR "d:/Tools/LIGGGHTS/src") +set(LIGGGHTS_DEBUG_LIBRARY "d:/Tools/LIGGGHTS/build/Debug/liggghts.lib") +set(LIGGGHTS_RELEASE_LIBRARY "d:/Tools/LIGGGHTS/build/Release/liggghts.lib") + + + ################################################################################# # METIS ################################################################################# diff --git a/apps/cpu/Applications.cmake b/apps/cpu/Applications.cmake index 436db3c5d3cc2f9c3bc867ce633bb6d9585ef0a8..b63689a9dc0d178b7d82c32a0c67a1b4b7946328 100644 --- a/apps/cpu/Applications.cmake +++ b/apps/cpu/Applications.cmake @@ -11,6 +11,9 @@ add_subdirectory(${APPS_ROOT_CPU}/LaminarTubeFlow) add_subdirectory(${APPS_ROOT_CPU}/MultiphaseDropletTest) add_subdirectory(${APPS_ROOT_CPU}/RisingBubble2D) add_subdirectory(${APPS_ROOT_CPU}/JetBreakup) +add_subdirectory(${APPS_ROOT_CPU}/LiggghtsApp) +add_subdirectory(${APPS_ROOT_CPU}/FallingSphere) +add_subdirectory(${APPS_ROOT_CPU}/Nozzle) #add_subdirectory(tests) #add_subdirectory(Applications/gridRf) #add_subdirectory(Applications/greenvortex) diff --git a/apps/cpu/LiggghtsApp/CMakeLists.txt b/apps/cpu/LiggghtsApp/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..f3a2d925f1d082c8f2e9e52e31d8179fe82c9235 --- /dev/null +++ b/apps/cpu/LiggghtsApp/CMakeLists.txt @@ -0,0 +1,3 @@ +PROJECT(LiggghtsApp) + +vf_add_library(BUILDTYPE binary PRIVATE_LINK VirtualFluidsCore basics ${MPI_CXX_LIBRARIES} LiggghtsCoupling FILES LiggghtsApp.cpp ) diff --git a/apps/cpu/LiggghtsApp/LiggghtsApp.cpp b/apps/cpu/LiggghtsApp/LiggghtsApp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..978ae376f1c842b0d108730fb9d2ffe43fa65537 --- /dev/null +++ b/apps/cpu/LiggghtsApp/LiggghtsApp.cpp @@ -0,0 +1,259 @@ +#include <iostream> +#include <string> +#include <memory> + +#include "VirtualFluids.h" + +//#include "lammps.h" +//#include "input.h" +//#include "atom.h" +//#include "modify.h" +//#include "fix_lb_coupling_onetoone.h" + +#include "LiggghtsCouplingCoProcessor.h" +#include "LiggghtsCouplingWrapper.h" +#include "IBcumulantK17LBMKernel.h" + +using namespace std; + + +int main(int argc, char *argv[]) +{ + SPtr<Communicator> comm = MPICommunicator::getInstance(); + int myid = comm->getProcessID(); + + + // bounding box + double g_minX1 = 0; + double g_minX2 = 0; + double g_minX3 = 0; + + double g_maxX1 = 1; + double g_maxX2 = 1; + double g_maxX3 = 2; + + int blockNX[3] = { 16, 16, 16 }; + + double dx = 1./32.; + + double Re = 300; + double nuLB = 5e-5; + + SPtr<LBMKernel> kernel = make_shared<IBcumulantK17LBMKernel>(); + SPtr<BCProcessor> bcProc = make_shared<BCProcessor>(); + kernel->setBCProcessor(bcProc); + + SPtr<BCAdapter> noSlipBCAdapter(new NoSlipBCAdapter()); + noSlipBCAdapter->setBcAlgorithm(SPtr<BCAlgorithm>(new NoSlipBCAlgorithm())); + ////////////////////////////////////////////////////////////////////////////////// + // BC visitor + BoundaryConditionsBlockVisitor bcVisitor; + bcVisitor.addBC(noSlipBCAdapter); + + + + + SPtr<Grid3D> grid = make_shared<Grid3D>(comm); + grid->setPeriodicX1(true); + grid->setPeriodicX2(true); + grid->setPeriodicX3(false); + grid->setDeltaX(dx); + grid->setBlockNX(blockNX[0], blockNX[1], blockNX[2]); + + string outputPath = "d:/temp/lll4"; + + SPtr<Grid3DVisitor> metisVisitor(new MetisPartitioningGridVisitor(comm, MetisPartitioningGridVisitor::LevelBased, + D3Q27System::BSW, MetisPartitioner::RECURSIVE)); + + SPtr<GbObject3D> gridCube = make_shared <GbCuboid3D>(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3); + if (myid == 0) + GbSystem3D::writeGeoObject(gridCube.get(), outputPath + "/geo/gridCube", WbWriterVtkXmlBinary::getInstance()); + + GenBlocksGridVisitor genBlocks(gridCube); + grid->accept(genBlocks); + + SPtr<CoProcessor> ppblocks = + make_shared <WriteBlocksCoProcessor>(grid, SPtr<UbScheduler>(new UbScheduler(1)), outputPath, + WbWriterVtkXmlBinary::getInstance(), comm); + ppblocks->process(0); + ppblocks.reset(); + + double dx2 = 2.0 * dx; + GbCuboid3DPtr wallZmin( + new GbCuboid3D(g_minX1 - dx2, g_minX2 - dx2, g_minX3 - dx2, g_maxX1 + dx2, g_maxX2 + dx2, g_minX3)); + GbSystem3D::writeGeoObject(wallZmin.get(), outputPath + "/geo/wallZmin", WbWriterVtkXmlASCII::getInstance()); + GbCuboid3DPtr wallZmax( + new GbCuboid3D(g_minX1 - dx2, g_minX2 - dx2, g_maxX3, g_maxX1 + dx2, g_maxX2 + dx2, g_maxX3 + dx2)); + GbSystem3D::writeGeoObject(wallZmax.get(), outputPath + "/geo/wallZmax", WbWriterVtkXmlASCII::getInstance()); + + SPtr<D3Q27Interactor> wallZminInt(new D3Q27Interactor(wallZmin, grid, noSlipBCAdapter, Interactor3D::SOLID)); + SPtr<D3Q27Interactor> wallZmaxInt(new D3Q27Interactor(wallZmax, grid, noSlipBCAdapter, Interactor3D::SOLID)); + + InteractorsHelper intHelper(grid, metisVisitor, true); + intHelper.addInteractor(wallZminInt); + intHelper.addInteractor(wallZmaxInt); + intHelper.selectBlocks(); + + SetKernelBlockVisitor kernelVisitor(kernel, nuLB, 1e9, 1e9); + grid->accept(kernelVisitor); + + intHelper.setBC(); + + InitDistributionsBlockVisitor initVisitor; + grid->accept(initVisitor); + + SPtr<UbScheduler> lScheduler = make_shared<UbScheduler>(1); + string inFile1 = "d:/Projects/VirtualFluids_LIGGGHTS_coupling/apps/cpu/LiggghtsApp/in.lbdem"; + //string inFile1 = "d:/Tools/LIGGGHTS/examples/LIGGGHTS/Tutorials_public/chute_wear/in.chute_wear2"; + string inFile2 = "d:/Projects/VirtualFluids_LIGGGHTS_coupling/apps/cpu/LiggghtsApp/in2.lbdem"; + MPI_Comm mpi_comm = *(MPI_Comm*)(comm->getNativeCommunicator()); + LiggghtsCouplingWrapper wrapper(argv, mpi_comm); + + + double d_part = 0.25; + double r_p = d_part / 2.0; + + // SPtr<LBMUnitConverter> units = std::make_shared<LBMUnitConverter>(r_p, 1.480, 2060, r_p/dx); + //SPtr<LBMUnitConverter> units = std::make_shared<LBMUnitConverter>(r_p, LBMUnitConverter::AIR_20C, r_p / dx); + SPtr<LBMUnitConverter> units = std::make_shared<LBMUnitConverter>(r_p, 0.1, 1000, r_p / dx, 0.01); + std::cout << units->toString() << std::endl; + + //return 0; + + double v_frac = 0.1; + double dt_phys = units->getFactorTimeLbToW(); + int demSubsteps = 10; + double dt_dem = dt_phys / (double)demSubsteps; + int vtkSteps = 1; + string demOutDir = outputPath; // "d:/temp/lll2/"; + + wrapper.execCommand("echo log"); + + wrapper.setVariable("r_part", d_part / 2); + wrapper.setVariable("v_frac", v_frac); + + wrapper.execFile((char*)inFile1.c_str()); + + //// set timestep and output directory + wrapper.setVariable("t_step", dt_dem); + wrapper.setVariable("dmp_stp", vtkSteps * demSubsteps); + wrapper.setVariable("dmp_dir", demOutDir); + + wrapper.execFile((char *)inFile2.c_str()); + wrapper.runUpto(demSubsteps - 1); + + + SPtr<LiggghtsCouplingCoProcessor> lcCoProcessor = + make_shared<LiggghtsCouplingCoProcessor>(grid, lScheduler, comm, wrapper, demSubsteps, units); + + // boundary conditions grid + { + SPtr<UbScheduler> geoSch(new UbScheduler(1)); + SPtr<WriteBoundaryConditionsCoProcessor> ppgeo(new WriteBoundaryConditionsCoProcessor( + grid, geoSch, outputPath, WbWriterVtkXmlBinary::getInstance(), comm)); + ppgeo->process(0); + ppgeo.reset(); + } + + grid->accept(bcVisitor); + + OneDistributionSetConnectorsBlockVisitor setConnsVisitor(comm); + grid->accept(setConnsVisitor); + + + // write data for visualization of macroscopic quantities + SPtr<UbScheduler> visSch(new UbScheduler(vtkSteps)); + SPtr<WriteMacroscopicQuantitiesCoProcessor> writeMQCoProcessor( + new WriteMacroscopicQuantitiesCoProcessor(grid, visSch, outputPath, WbWriterVtkXmlBinary::getInstance(), + SPtr<LBMUnitConverter>(new LBMUnitConverter()), comm)); + + int endTime = 1000; //20; + SPtr<Calculator> calculator(new BasicCalculator(grid, lScheduler, endTime)); + calculator->addCoProcessor(lcCoProcessor); + calculator->addCoProcessor(writeMQCoProcessor); + + if (myid == 0) UBLOG(logINFO, "Simulation-start"); + calculator->calculate(); + if (myid == 0) UBLOG(logINFO, "Simulation-end"); + + //MPI_Init(&argc, &argv); + //MPI_Comm mpi_comm = *(MPI_Comm*)(comm->getNativeCommunicator()); + //LiggghtsCouplingWrapper wrapper(argv, mpi_comm); + + //wrapper.execFile("in2.lbdem"); + //wrapper.runUpto(demSubsteps - 1); + + //LAMMPS_NS::LAMMPS *lmp; + // // custom argument vector for LAMMPS library + // const char *lmpargv[] {"liblammps", "-log", "none"}; + // int lmpargc = sizeof(lmpargv)/sizeof(const char *); + + // // explicitly initialize MPI + // MPI_Init(&argc, &argv); + + // // create LAMMPS instance + // lmp = new LAMMPS_NS::LAMMPS(lmpargc, (char **)lmpargv, MPI_COMM_WORLD); + // lmp->input->file("in.lbdem"); + // //lmp->input->one("run 1"); + // + // //# Try extracting a global value + // // print("") + // // print("Attempting to get the number of atoms in simulation") + // // numAtoms = lmp.extract_global("natoms", 0) + // // print("natoms =", numAtoms) + + // // # Try extracting atom's positions + // // print("") + // // print("Attempting to get the atom's positions") + // // pos = lmp.extract_atom("x",3) + // // for k in range(0,numAtoms): + // // print("Pos[%i] = [%f, %f, %f]" % (k, pos[k][0], pos[k][1], pos[k][2])) + + // LAMMPS_NS::FixLbCouplingOnetoone + // *couplingFix + // = dynamic_cast<LAMMPS_NS::FixLbCouplingOnetoone*> + // (lmp->modify->find_fix_style("couple/lb/onetoone",0)); + + // cout << "test1\n"; + // + // //double **t_liggghts = couplingFix->get_torque_ptr(); + // cout << "test2\n"; + + // lmp->input->one("run 9 upto"); + + // for (int step = 0; step < 10; step++) + // { + // + + // int numAtoms = lmp->atom->natoms; + + // //double** pos = (double**)lmp->atom->extract("x"); + // double** pos = lmp->atom->x; + // + // //double* forceX = lmp->atom->fx; + + // for (int i = 0; i < numAtoms; i++) + // { + // double **f_liggghts = couplingFix->get_force_ptr(); + // double** force = lmp->atom->f; + // cout << "Pos[" << i << "] = [" << pos[i][0] << ", " << pos[i][1] << ", " << pos[i][2] << "]\n"; + // cout << "Force1[" << i << "] = [" << f_liggghts[i][0] << ", " << f_liggghts[i][1] << ", " << f_liggghts[i][2] << "]\n"; + // f_liggghts[i][0] += 0; + // f_liggghts[i][1] += 0; + // f_liggghts[i][2] += 500; + // cout << "Force2[" << i << "] = [" << force[i][0] << ", " << force[i][1] << ", " << force[i][2] << "]\n"; + // } + + // couplingFix->comm_force_torque(); + + // lmp->input->one("run 10000"); + // + // } + + // // delete LAMMPS instance + // delete lmp; + + // // stop MPI environment + //MPI_Finalize(); + return 0; +} diff --git a/apps/cpu/LiggghtsApp/in.lbdem b/apps/cpu/LiggghtsApp/in.lbdem new file mode 100644 index 0000000000000000000000000000000000000000..ae2baa373dc75edec41634522e53ade31f459b4d --- /dev/null +++ b/apps/cpu/LiggghtsApp/in.lbdem @@ -0,0 +1,75 @@ +echo none + +units si +atom_style granular +atom_modify map array + + + +communicate single vel yes + +boundary f f f +newton off + +processors * * 1 +region box block 0. 1. 0. 1. 0. 2. units box +create_box 1 box + +variable skin equal 0.01 +neighbor ${skin} bin +neigh_modify delay 0 binsize 0.01 one 1000 + +fix grav all gravity 0.981 vector 0 0 -1 + + +fix m1 all property/global youngsModulus peratomtype 1e8 +fix m2 all property/global poissonsRatio peratomtype 0.4 +fix m3 all property/global coefficientRestitution peratomtypepair 1 0.95 +fix m4 all property/global coefficientFriction peratomtypepair 1 0.45 +fix m5 all property/global coefficientRollingFriction peratomtypepair 1 0.020 + +# lb coupling fix +fix lbcoupling all couple/lb/onetoone + + +pair_style gran model hertz tangential history rolling_friction cdt +pair_coeff * * + +fix 1 all nve/sphere + +fix xwalls1 all wall/gran model hertz tangential history primitive type 1 xplane 0. +fix xwalls2 all wall/gran model hertz tangential history primitive type 1 xplane 1. +fix ywalls1 all wall/gran model hertz tangential history primitive type 1 yplane 0. +fix ywalls2 all wall/gran model hertz tangential history primitive type 1 yplane 1. +fix zwalls1 all wall/gran model hertz tangential history primitive type 1 zplane 0. +fix zwalls2 all wall/gran model hertz tangential history primitive type 1 zplane 2. + +create_atoms 1 single 0.5 0.5 1.75 +#create_atoms 1 single 0.38 0.05 0.05 + +set group all diameter 0.25 density 2400 + +atom_modify sort 0 0.0 + +#fix pts1 all particletemplate/sphere 1 atom_type 1 density constant 1000 radius constant 0.015 +#fix pts2 all particletemplate/sphere 1 atom_type 1 density constant 1000 radius constant 0.01 +#fix pts1 all particletemplate/sphere 1 atom_type 1 density constant 1100 radius constant ${r_part} + +# fix pdd1 all particledistribution/discrete 6778 1 pts1 1.0 +# #fix pdd2 all particledistribution/discrete 6778 2 pts2 0.2 pts3 0.8 + +# # region insreg block 0.1 0.9 0.1 0.9 1.3 1.9 units box + + +# #fix ins all insert/pack seed 1001 distributiontemplate pdd1 insert_every once & +# # overlapcheck yes particles_in_region 350 region insreg ntry_mc 10000 +# fix ins all insert/pack seed 1001 distributiontemplate pdd1 insert_every once & + # overlapcheck yes volumefraction_region ${v_frac} region insreg ntry_mc 10000 +# #fix ins all insert/pack seed 1001 distributiontemplate pdd2 insert_every once & +# # overlapcheck yes volumefraction_region 0.05 region insreg ntry_mc 10000 +# #fix ins all insert/pack seed 1001 distributiontemplate pdd1 insert_every once & +# # overlapcheck yes particles_in_region 1 region insreg ntry_mc 10000 + +echo none + +run 1 diff --git a/apps/cpu/LiggghtsApp/in2.lbdem b/apps/cpu/LiggghtsApp/in2.lbdem new file mode 100644 index 0000000000000000000000000000000000000000..8d6a0748befeea97d6faa7efa87ffd60e5c56cfd --- /dev/null +++ b/apps/cpu/LiggghtsApp/in2.lbdem @@ -0,0 +1,25 @@ + +echo none + +timestep ${t_step} + +# thermo settings +fix ts all check/timestep/gran 10000 0.1 0.1 +compute 1 all erotate/sphere +thermo_style custom step atoms ke c_1 f_ts[1] f_ts[2] cpu +thermo 10000 +thermo_modify lost ignore norm no flush yes +compute_modify thermo_temp dynamic yes + +# particle dump +variable dmp_fname string ${dmp_dir}d_*.liggghts + +# dump dmp all custom ${dmp_stp} ${dmp_fname} & + # id type type x y z ix iy iz vx vy vz fx fy fz omegax omegay omegaz radius + +# dump dmp all custom ${dmp_stp} ${dmp_dir}d_*.liggghts & +# id type type x y z ix iy iz vx vy vz fx fy fz omegax omegay omegaz radius + +dump dmp all custom/vtk ${dmp_stp} ${dmp_dir}/post/atom_*.vtk id type type x y z ix iy iz vx vy vz fx fy fz omegax omegay omegaz radius + +echo none \ No newline at end of file diff --git a/cpu.cmake b/cpu.cmake index bad575aa3854fb2be777e90bba9ea71fb2cbba5a..e5b77c8a43c40c4987f3d2d00d34833c7cb27c61 100644 --- a/cpu.cmake +++ b/cpu.cmake @@ -29,6 +29,8 @@ SET(USE_CATALYST OFF CACHE BOOL "include Paraview Catalyst support") SET(USE_HLRN_LUSTRE OFF CACHE BOOL "include HLRN Lustre support") SET(USE_DEM_COUPLING OFF CACHE BOOL "PE plugin") +SET(USE_LIGGGHTS ON CACHE BOOL "include LIGGGHTS library support") + #MPI IF((NOT ${CMAKE_CXX_COMPILER} MATCHES mpicxx) AND (NOT ${CMAKE_CXX_COMPILER} MATCHES mpiicpc))# OR NOT ${CMAKE_CXX_COMPILER} MATCHES cc OR NOT ${CMAKE_CXX_COMPILER} MATCHES mpiCC) FIND_PACKAGE(MPI REQUIRED) @@ -85,5 +87,9 @@ if(BUILD_VF_PYTHON_BINDINGS) add_subdirectory(src/cpu/pythonbindings) endif() +if(USE_LIGGGHTS) + add_subdirectory(src/cpu/LiggghtsCoupling) +endif() + set (APPS_ROOT_CPU "${VF_ROOT_DIR}/apps/cpu/") include(${APPS_ROOT_CPU}/Applications.cmake) \ No newline at end of file diff --git a/src/cpu/LiggghtsCoupling/CMakeLists.txt b/src/cpu/LiggghtsCoupling/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..ed9d1f0e2bd8d0302f1d37aa3bde8a120ceb2312 --- /dev/null +++ b/src/cpu/LiggghtsCoupling/CMakeLists.txt @@ -0,0 +1,10 @@ + +set(LIGGGHTS_LIBRARIES optimized ${LIGGGHTS_RELEASE_LIBRARY} debug ${LIGGGHTS_DEBUG_LIBRARY}) + +vf_add_library(BUILDTYPE static PUBLIC_LINK basics muparser MPI::MPI_CXX VirtualFluidsCore ${LIGGGHTS_LIBRARIES}) + +vf_get_library_name(library_name) + +#target_link_directories(${library_name} PUBLIC ${LIGGGHTS_BINARY_DIR}) +target_include_directories(${library_name} PUBLIC ${LIGGGHTS_SOURCE_DIR}) + diff --git a/src/cpu/LiggghtsCoupling/IBcumulantK17LBMKernel.cpp b/src/cpu/LiggghtsCoupling/IBcumulantK17LBMKernel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ac0bc35844cb32544d901cbf5a93503d49de4070 --- /dev/null +++ b/src/cpu/LiggghtsCoupling/IBcumulantK17LBMKernel.cpp @@ -0,0 +1,913 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ | +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids 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. +// +// VirtualFluids 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 VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file IBcumulantK17LBMKernel.cpp +//! \ingroup LBM +//! \author Konstantin Kutscher, Martin Geier +//======================================================================================= +#include "IBcumulantK17LBMKernel.h" +#include "D3Q27System.h" +#include "D3Q27EsoTwist3DSplittedVector.h" +#include <cmath> +#include "DataSet3D.h" +#include "LBMKernel.h" +#include "Block3D.h" +#include "BCArray3D.h" + +#define PROOF_CORRECTNESS + +using namespace UbMath; + +////////////////////////////////////////////////////////////////////////// +IBcumulantK17LBMKernel::IBcumulantK17LBMKernel() +{ + this->compressible = true; +} +////////////////////////////////////////////////////////////////////////// +void IBcumulantK17LBMKernel::initDataSet() +{ + SPtr<DistributionArray3D> d(new D3Q27EsoTwist3DSplittedVector(nx[0] + 2, nx[1] + 2, nx[2] + 2, -999.9)); + dataSet->setFdistributions(d); + + particleData = + std::make_shared<CbArray3D<SPtr<IBdynamicsParticleData>, IndexerX3X2X1>>(nx[0] + 2, nx[1] + 2, nx[2] + 2); + + int minX1 = 0; + int minX2 = 0; + int minX3 = 0; + int maxX1 = nx[0]+2; + int maxX2 = nx[1]+2; + int maxX3 = nx[2]+2; + + LBMReal omega = collFactor; + + for (int x3 = minX3; x3 < maxX3; x3++) { + for (int x2 = minX2; x2 < maxX2; x2++) { + for (int x1 = minX1; x1 < maxX1; x1++) { + (*particleData)(x1, x2, x3) = std::make_shared<IBdynamicsParticleData>(); + } + } + } + +} +////////////////////////////////////////////////////////////////////////// +SPtr<LBMKernel> IBcumulantK17LBMKernel::clone() +{ + SPtr<LBMKernel> kernel(new IBcumulantK17LBMKernel()); + kernel->setNX(nx); + std::dynamic_pointer_cast<IBcumulantK17LBMKernel>(kernel)->initDataSet(); + kernel->setCollisionFactor(this->collFactor); + kernel->setBCProcessor(bcProcessor->clone(kernel)); + kernel->setWithForcing(withForcing); + kernel->setForcingX1(muForcingX1); + kernel->setForcingX2(muForcingX2); + kernel->setForcingX3(muForcingX3); + kernel->setIndex(ix1, ix2, ix3); + kernel->setDeltaT(deltaT); + kernel->setBlock(block.lock()); + + return kernel; +} +////////////////////////////////////////////////////////////////////////// +void IBcumulantK17LBMKernel::calculate(int step) +{ + ////////////////////////////////////////////////////////////////////////// + //! Cumulant K17 Kernel is based on + //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a> + //! and + //! <a href="https://doi.org/10.1016/j.jcp.2017.07.004"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.07.004 ]</b></a> + //! + //! The cumulant kernel is executed in the following steps + //! + //////////////////////////////////////////////////////////////////////////////// + //! - Get node index coordinates from thredIdx, blockIdx, blockDim and gridDim. + //! + + using namespace std; + + //initializing of forcing stuff + if (withForcing) + { + muForcingX1.DefineVar("x1", &muX1); muForcingX1.DefineVar("x2", &muX2); muForcingX1.DefineVar("x3", &muX3); + muForcingX2.DefineVar("x1", &muX1); muForcingX2.DefineVar("x2", &muX2); muForcingX2.DefineVar("x3", &muX3); + muForcingX3.DefineVar("x1", &muX1); muForcingX3.DefineVar("x2", &muX2); muForcingX3.DefineVar("x3", &muX3); + + muDeltaT = deltaT; + + muForcingX1.DefineVar("dt", &muDeltaT); + muForcingX2.DefineVar("dt", &muDeltaT); + muForcingX3.DefineVar("dt", &muDeltaT); + + muNu = (1.0 / 3.0) * (1.0 / collFactor - 1.0 / 2.0); + + muForcingX1.DefineVar("nu", &muNu); + muForcingX2.DefineVar("nu", &muNu); + muForcingX3.DefineVar("nu", &muNu); + } + ///////////////////////////////////// + + localDistributions = dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getLocalDistributions(); + nonLocalDistributions = dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getNonLocalDistributions(); + restDistributions = dynamic_pointer_cast<D3Q27EsoTwist3DSplittedVector>(dataSet->getFdistributions())->getZeroDistributions(); + + SPtr<BCArray3D> bcArray = this->getBCProcessor()->getBCArray(); + + const int bcArrayMaxX1 = (int)bcArray->getNX1(); + const int bcArrayMaxX2 = (int)bcArray->getNX2(); + const int bcArrayMaxX3 = (int)bcArray->getNX3(); + + int minX1 = ghostLayerWidth; + int minX2 = ghostLayerWidth; + int minX3 = ghostLayerWidth; + int maxX1 = bcArrayMaxX1 - ghostLayerWidth; + int maxX2 = bcArrayMaxX2 - ghostLayerWidth; + int maxX3 = bcArrayMaxX3 - ghostLayerWidth; + + LBMReal omega = collFactor; + + + + for (int x3 = minX3; x3 < maxX3; x3++) + { + for (int x2 = minX2; x2 < maxX2; x2++) + { + for (int x1 = minX1; x1 < maxX1; x1++) + { + if (!bcArray->isSolid(x1, x2, x3) && !bcArray->isUndefined(x1, x2, x3)) { + int x1p = x1 + 1; + int x2p = x2 + 1; + int x3p = x3 + 1; + ////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////// + //! - Read distributions: style of reading and writing the distributions from/to stored arrays + //! dependent on timestep is based on the esoteric twist algorithm <a + //! href="https://doi.org/10.3390/computation5020019"><b>[ M. Geier et al. (2017), + //! DOI:10.3390/computation5020019 ]</b></a> + //! + //////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////// + + // E N T + // c c c + ////////// + // W S B + // a a a + + // Rest is b + + // mfxyz + // a - negative + // b - null + // c - positive + + // a b c + //-1 0 1 + + LBMReal mfcbb = (*this->localDistributions)(D3Q27System::ET_E, x1, x2, x3); + LBMReal mfbcb = (*this->localDistributions)(D3Q27System::ET_N, x1, x2, x3); + LBMReal mfbbc = (*this->localDistributions)(D3Q27System::ET_T, x1, x2, x3); + LBMReal mfccb = (*this->localDistributions)(D3Q27System::ET_NE, x1, x2, x3); + LBMReal mfacb = (*this->localDistributions)(D3Q27System::ET_NW, x1p, x2, x3); + LBMReal mfcbc = (*this->localDistributions)(D3Q27System::ET_TE, x1, x2, x3); + LBMReal mfabc = (*this->localDistributions)(D3Q27System::ET_TW, x1p, x2, x3); + LBMReal mfbcc = (*this->localDistributions)(D3Q27System::ET_TN, x1, x2, x3); + LBMReal mfbac = (*this->localDistributions)(D3Q27System::ET_TS, x1, x2p, x3); + LBMReal mfccc = (*this->localDistributions)(D3Q27System::ET_TNE, x1, x2, x3); + LBMReal mfacc = (*this->localDistributions)(D3Q27System::ET_TNW, x1p, x2, x3); + LBMReal mfcac = (*this->localDistributions)(D3Q27System::ET_TSE, x1, x2p, x3); + LBMReal mfaac = (*this->localDistributions)(D3Q27System::ET_TSW, x1p, x2p, x3); + + LBMReal mfabb = (*this->nonLocalDistributions)(D3Q27System::ET_W, x1p, x2, x3); + LBMReal mfbab = (*this->nonLocalDistributions)(D3Q27System::ET_S, x1, x2p, x3); + LBMReal mfbba = (*this->nonLocalDistributions)(D3Q27System::ET_B, x1, x2, x3p); + LBMReal mfaab = (*this->nonLocalDistributions)(D3Q27System::ET_SW, x1p, x2p, x3); + LBMReal mfcab = (*this->nonLocalDistributions)(D3Q27System::ET_SE, x1, x2p, x3); + LBMReal mfaba = (*this->nonLocalDistributions)(D3Q27System::ET_BW, x1p, x2, x3p); + LBMReal mfcba = (*this->nonLocalDistributions)(D3Q27System::ET_BE, x1, x2, x3p); + LBMReal mfbaa = (*this->nonLocalDistributions)(D3Q27System::ET_BS, x1, x2p, x3p); + LBMReal mfbca = (*this->nonLocalDistributions)(D3Q27System::ET_BN, x1, x2, x3p); + LBMReal mfaaa = (*this->nonLocalDistributions)(D3Q27System::ET_BSW, x1p, x2p, x3p); + LBMReal mfcaa = (*this->nonLocalDistributions)(D3Q27System::ET_BSE, x1, x2p, x3p); + LBMReal mfaca = (*this->nonLocalDistributions)(D3Q27System::ET_BNW, x1p, x2, x3p); + LBMReal mfcca = (*this->nonLocalDistributions)(D3Q27System::ET_BNE, x1, x2, x3p); + + LBMReal mfbbb = (*this->restDistributions)(x1, x2, x3); + + LBMReal f[D3Q27System::ENDF + 1]; + LBMReal fEq[D3Q27System::ENDF + 1]; + LBMReal fEqSolid[D3Q27System::ENDF + 1]; + LBMReal fPre[D3Q27System::ENDF + 1]; + + f[D3Q27System::REST] = mfbbb; + + f[D3Q27System::E] = mfcbb; + f[D3Q27System::N] = mfbcb; + f[D3Q27System::T] = mfbbc; + f[D3Q27System::NE] = mfccb; + f[D3Q27System::NW] = mfacb; + f[D3Q27System::TE] = mfcbc; + f[D3Q27System::TW] = mfabc; + f[D3Q27System::TN] = mfbcc; + f[D3Q27System::TS] = mfbac; + f[D3Q27System::TNE] = mfccc; + f[D3Q27System::TNW] = mfacc; + f[D3Q27System::TSE] = mfcac; + f[D3Q27System::TSW] = mfaac; + + f[D3Q27System::W] = mfabb; + f[D3Q27System::S] = mfbab; + f[D3Q27System::B] = mfbba; + f[D3Q27System::SW] = mfaab; + f[D3Q27System::SE] = mfcab; + f[D3Q27System::BW] = mfaba; + f[D3Q27System::BE] = mfcba; + f[D3Q27System::BS] = mfbaa; + f[D3Q27System::BN] = mfbca; + f[D3Q27System::BSW] = mfaaa; + f[D3Q27System::BSE] = mfcaa; + f[D3Q27System::BNW] = mfaca; + f[D3Q27System::BNE] = mfcca; + + if ((*particleData)(x1, x2, x3)->solidFraction > SOLFRAC_MIN) { + fPre[D3Q27System::REST] = mfbbb; + + fPre[D3Q27System::E] = mfcbb; + fPre[D3Q27System::N] = mfbcb; + fPre[D3Q27System::T] = mfbbc; + fPre[D3Q27System::NE] = mfccb; + fPre[D3Q27System::NW] = mfacb; + fPre[D3Q27System::TE] = mfcbc; + fPre[D3Q27System::TW] = mfabc; + fPre[D3Q27System::TN] = mfbcc; + fPre[D3Q27System::TS] = mfbac; + fPre[D3Q27System::TNE] = mfccc; + fPre[D3Q27System::TNW] = mfacc; + fPre[D3Q27System::TSE] = mfcac; + fPre[D3Q27System::TSW] = mfaac; + + fPre[D3Q27System::W] = mfabb; + fPre[D3Q27System::S] = mfbab; + fPre[D3Q27System::B] = mfbba; + fPre[D3Q27System::SW] = mfaab; + fPre[D3Q27System::SE] = mfcab; + fPre[D3Q27System::BW] = mfaba; + fPre[D3Q27System::BE] = mfcba; + fPre[D3Q27System::BS] = mfbaa; + fPre[D3Q27System::BN] = mfbca; + fPre[D3Q27System::BSW] = mfaaa; + fPre[D3Q27System::BSE] = mfcaa; + fPre[D3Q27System::BNW] = mfaca; + fPre[D3Q27System::BNE] = mfcca; + } + + (*particleData)(x1, x2, x3)->hydrodynamicForce.fill(0.0); + + if ((*particleData)(x1, x2, x3)->solidFraction <= SOLFRAC_MAX) { + + //////////////////////////////////////////////////////////////////////////////////// + //! - Calculate density and velocity using pyramid summation for low round-off errors as in Eq. + //! (J1)-(J3) <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015), + //! DOI:10.1016/j.camwa.2015.05.001 ]</b></a> + //! + LBMReal drho = ((((mfccc + mfaaa) + (mfaca + mfcac)) + ((mfacc + mfcaa) + (mfaac + mfcca))) + + (((mfbac + mfbca) + (mfbaa + mfbcc)) + ((mfabc + mfcba) + (mfaba + mfcbc)) + + ((mfacb + mfcab) + (mfaab + mfccb))) + + ((mfabb + mfcbb) + (mfbab + mfbcb)) + (mfbba + mfbbc)) + + mfbbb; + + LBMReal rho = c1 + drho; + LBMReal OOrho = c1 / rho; + //////////////////////////////////////////////////////////////////////////////////// + LBMReal vvx = ((((mfccc - mfaaa) + (mfcac - mfaca)) + ((mfcaa - mfacc) + (mfcca - mfaac))) + + (((mfcba - mfabc) + (mfcbc - mfaba)) + ((mfcab - mfacb) + (mfccb - mfaab))) + + (mfcbb - mfabb)) / + rho; + LBMReal vvy = ((((mfccc - mfaaa) + (mfaca - mfcac)) + ((mfacc - mfcaa) + (mfcca - mfaac))) + + (((mfbca - mfbac) + (mfbcc - mfbaa)) + ((mfacb - mfcab) + (mfccb - mfaab))) + + (mfbcb - mfbab)) / + rho; + LBMReal vvz = ((((mfccc - mfaaa) + (mfcac - mfaca)) + ((mfacc - mfcaa) + (mfaac - mfcca))) + + (((mfbac - mfbca) + (mfbcc - mfbaa)) + ((mfabc - mfcba) + (mfcbc - mfaba))) + + (mfbbc - mfbba)) / + rho; + //////////////////////////////////////////////////////////////////////////////////// + // forcing + /////////////////////////////////////////////////////////////////////////////////////////// + if (withForcing) { + muX1 = static_cast<double>(x1 - 1 + ix1 * maxX1); + muX2 = static_cast<double>(x2 - 1 + ix2 * maxX2); + muX3 = static_cast<double>(x3 - 1 + ix3 * maxX3); + + forcingX1 = muForcingX1.Eval(); + forcingX2 = muForcingX2.Eval(); + forcingX3 = muForcingX3.Eval(); + + //////////////////////////////////////////////////////////////////////////////////// + //! - Add half of the acceleration (body force) to the velocity as in Eq. (42) + //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015), + //! DOI:10.1016/j.camwa.2015.05.001 ]</b></a> + //! + vvx += forcingX1 * deltaT * c1o2; // X + vvy += forcingX2 * deltaT * c1o2; // Y + vvz += forcingX3 * deltaT * c1o2; // Z + } + //////////////////////////////////////////////////////////////////////////////////// + // calculate the square of velocities for this lattice node + LBMReal vx2 = vvx * vvx; + LBMReal vy2 = vvy * vvy; + LBMReal vz2 = vvz * vvz; + //////////////////////////////////////////////////////////////////////////////////// + //! - Set relaxation limiters for third order cumulants to default value \f$ \lambda=0.001 \f$ + //! according to section 6 in <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et + //! al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a> + //! + LBMReal wadjust; + LBMReal qudricLimitP = c1o100; + LBMReal qudricLimitM = c1o100; + LBMReal qudricLimitD = c1o100; + //////////////////////////////////////////////////////////////////////////////////// + //! - Chimera transform from well conditioned distributions to central moments as defined in + //! Appendix J in <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015), + //! DOI:10.1016/j.camwa.2015.05.001 ]</b></a> see also Eq. (6)-(14) in <a + //! href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), + //! DOI:10.1016/j.jcp.2017.05.040 ]</b></a> + //! + //////////////////////////////////////////////////////////////////////////////////// + // Z - Dir + forwardInverseChimeraWithK(mfaaa, mfaab, mfaac, vvz, vz2, c36, c1o36); + forwardInverseChimeraWithK(mfaba, mfabb, mfabc, vvz, vz2, c9, c1o9); + forwardInverseChimeraWithK(mfaca, mfacb, mfacc, vvz, vz2, c36, c1o36); + forwardInverseChimeraWithK(mfbaa, mfbab, mfbac, vvz, vz2, c9, c1o9); + forwardInverseChimeraWithK(mfbba, mfbbb, mfbbc, vvz, vz2, c9o4, c4o9); + forwardInverseChimeraWithK(mfbca, mfbcb, mfbcc, vvz, vz2, c9, c1o9); + forwardInverseChimeraWithK(mfcaa, mfcab, mfcac, vvz, vz2, c36, c1o36); + forwardInverseChimeraWithK(mfcba, mfcbb, mfcbc, vvz, vz2, c9, c1o9); + forwardInverseChimeraWithK(mfcca, mfccb, mfccc, vvz, vz2, c36, c1o36); + + //////////////////////////////////////////////////////////////////////////////////// + // Y - Dir + forwardInverseChimeraWithK(mfaaa, mfaba, mfaca, vvy, vy2, c6, c1o6); + forwardChimera(mfaab, mfabb, mfacb, vvy, vy2); + forwardInverseChimeraWithK(mfaac, mfabc, mfacc, vvy, vy2, c18, c1o18); + forwardInverseChimeraWithK(mfbaa, mfbba, mfbca, vvy, vy2, c3o2, c2o3); + forwardChimera(mfbab, mfbbb, mfbcb, vvy, vy2); + forwardInverseChimeraWithK(mfbac, mfbbc, mfbcc, vvy, vy2, c9o2, c2o9); + forwardInverseChimeraWithK(mfcaa, mfcba, mfcca, vvy, vy2, c6, c1o6); + forwardChimera(mfcab, mfcbb, mfccb, vvy, vy2); + forwardInverseChimeraWithK(mfcac, mfcbc, mfccc, vvy, vy2, c18, c1o18); + + //////////////////////////////////////////////////////////////////////////////////// + // X - Dir + forwardInverseChimeraWithK(mfaaa, mfbaa, mfcaa, vvx, vx2, c1, c1); + forwardChimera(mfaba, mfbba, mfcba, vvx, vx2); + forwardInverseChimeraWithK(mfaca, mfbca, mfcca, vvx, vx2, c3, c1o3); + forwardChimera(mfaab, mfbab, mfcab, vvx, vx2); + forwardChimera(mfabb, mfbbb, mfcbb, vvx, vx2); + forwardChimera(mfacb, mfbcb, mfccb, vvx, vx2); + forwardInverseChimeraWithK(mfaac, mfbac, mfcac, vvx, vx2, c3, c1o3); + forwardChimera(mfabc, mfbbc, mfcbc, vvx, vx2); + forwardInverseChimeraWithK(mfacc, mfbcc, mfccc, vvx, vx2, c9, c1o9); + + //////////////////////////////////////////////////////////////////////////////////// + //! - Setting relaxation rates for non-hydrodynamic cumulants (default values). Variable names and + //! equations according to <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. + //! (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a> + //! => [NAME IN PAPER]=[NAME IN CODE]=[DEFAULT VALUE]. + //! - Trace of second order cumulants \f$ C_{200}+C_{020}+C_{002} \f$ used to adjust bulk + //! viscosity:\f$\omega_2=OxxPyyPzz=1.0 \f$. + //! - Third order cumulants \f$ C_{120}+C_{102} \f$, \f$ C_{210}+C_{012} \f$, \f$ C_{201}+C_{021} + //! \f$: \f$\omega_3=OxyyPxzz\f$ set according to Eq. (111) with simplifications assuming + //! \f$\omega_2=1.0\f$. + //! - Third order cumulants \f$ C_{120}-C_{102} \f$, \f$ C_{210}-C_{012} \f$, \f$ C_{201}-C_{021} + //! \f$: \f$\omega_4 = OxyyMxzz\f$ set according to Eq. (112) with simplifications assuming + //! \f$\omega_2 = 1.0\f$. + //! - Third order cumulants \f$ C_{111} \f$: \f$\omega_5 = Oxyz\f$ set according to Eq. (113) with + //! simplifications assuming \f$\omega_2 = 1.0\f$ (modify for different bulk viscosity). + //! - Fourth order cumulants \f$ C_{220} \f$, \f$ C_{202} \f$, \f$ C_{022} \f$, \f$ C_{211} \f$, + //! \f$ C_{121} \f$, \f$ C_{112} \f$: for simplification all set to the same default value \f$ + //! \omega_6=\omega_7=\omega_8=O4=1.0 \f$. + //! - Fifth order cumulants \f$ C_{221}\f$, \f$C_{212}\f$, \f$C_{122}\f$: \f$\omega_9=O5=1.0\f$. + //! - Sixth order cumulant \f$ C_{222}\f$: \f$\omega_{10}=O6=1.0\f$. + //! + //////////////////////////////////////////////////////////// + // 2. + LBMReal OxxPyyPzz = c1; + //////////////////////////////////////////////////////////// + // 3. + LBMReal OxyyPxzz = + c8 * (-c2 + omega) * (c1 + c2 * omega) / (-c8 - c14 * omega + c7 * omega * omega); + LBMReal OxyyMxzz = + c8 * (-c2 + omega) * (-c7 + c4 * omega) / (c56 - c50 * omega + c9 * omega * omega); + LBMReal Oxyz = c24 * (-c2 + omega) * (-c2 - c7 * omega + c3 * omega * omega) / + (c48 + c152 * omega - c130 * omega * omega + c29 * omega * omega * omega); + //////////////////////////////////////////////////////////// + // 4. + LBMReal O4 = c1; + //////////////////////////////////////////////////////////// + // 5. + LBMReal O5 = c1; + //////////////////////////////////////////////////////////// + // 6. + LBMReal O6 = c1; + + //////////////////////////////////////////////////////////////////////////////////// + //! - A and B: parameters for fourth order convergence of the diffusion term according to Eq. (114) + //! and (115) <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), + //! DOI:10.1016/j.jcp.2017.05.040 ]</b></a> with simplifications assuming \f$\omega_2 = 1.0\f$ + //! (modify for different bulk viscosity). + //! + LBMReal A = (c4 + c2 * omega - c3 * omega * omega) / (c2 - c7 * omega + c5 * omega * omega); + LBMReal B = (c4 + c28 * omega - c14 * omega * omega) / (c6 - c21 * omega + c15 * omega * omega); + + //////////////////////////////////////////////////////////////////////////////////// + //! - Compute cumulants from central moments according to Eq. (20)-(23) in + //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), + //! DOI:10.1016/j.jcp.2017.05.040 ]</b></a> + //! + //////////////////////////////////////////////////////////// + // 4. + LBMReal CUMcbb = mfcbb - ((mfcaa + c1o3) * mfabb + c2 * mfbba * mfbab) * OOrho; + LBMReal CUMbcb = mfbcb - ((mfaca + c1o3) * mfbab + c2 * mfbba * mfabb) * OOrho; + LBMReal CUMbbc = mfbbc - ((mfaac + c1o3) * mfbba + c2 * mfbab * mfabb) * OOrho; + + LBMReal CUMcca = mfcca - (((mfcaa * mfaca + c2 * mfbba * mfbba) + c1o3 * (mfcaa + mfaca)) * OOrho - + c1o9 * (drho * OOrho)); + LBMReal CUMcac = mfcac - (((mfcaa * mfaac + c2 * mfbab * mfbab) + c1o3 * (mfcaa + mfaac)) * OOrho - + c1o9 * (drho * OOrho)); + LBMReal CUMacc = mfacc - (((mfaac * mfaca + c2 * mfabb * mfabb) + c1o3 * (mfaac + mfaca)) * OOrho - + c1o9 * (drho * OOrho)); + //////////////////////////////////////////////////////////// + // 5. + LBMReal CUMbcc = + mfbcc - + ((mfaac * mfbca + mfaca * mfbac + c4 * mfabb * mfbbb + c2 * (mfbab * mfacb + mfbba * mfabc)) + + c1o3 * (mfbca + mfbac)) * + OOrho; + LBMReal CUMcbc = + mfcbc - + ((mfaac * mfcba + mfcaa * mfabc + c4 * mfbab * mfbbb + c2 * (mfabb * mfcab + mfbba * mfbac)) + + c1o3 * (mfcba + mfabc)) * + OOrho; + LBMReal CUMccb = + mfccb - + ((mfcaa * mfacb + mfaca * mfcab + c4 * mfbba * mfbbb + c2 * (mfbab * mfbca + mfabb * mfcba)) + + c1o3 * (mfacb + mfcab)) * + OOrho; + //////////////////////////////////////////////////////////// + // 6. + LBMReal CUMccc = + mfccc + ((-c4 * mfbbb * mfbbb - (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca) - + c4 * (mfabb * mfcbb + mfbab * mfbcb + mfbba * mfbbc) - + c2 * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb)) * + OOrho + + (c4 * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac) + + c2 * (mfcaa * mfaca * mfaac) + c16 * mfbba * mfbab * mfabb) * + OOrho * OOrho - + c1o3 * (mfacc + mfcac + mfcca) * OOrho - c1o9 * (mfcaa + mfaca + mfaac) * OOrho + + (c2 * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba) + + (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa) + c1o3 * (mfaac + mfaca + mfcaa)) * + OOrho * OOrho * c2o3 + + c1o27 * ((drho * drho - drho) * OOrho * OOrho)); + + //////////////////////////////////////////////////////////////////////////////////// + //! - Compute linear combinations of second and third order cumulants + //! + //////////////////////////////////////////////////////////// + // 2. + LBMReal mxxPyyPzz = mfcaa + mfaca + mfaac; + LBMReal mxxMyy = mfcaa - mfaca; + LBMReal mxxMzz = mfcaa - mfaac; + //////////////////////////////////////////////////////////// + // 3. + LBMReal mxxyPyzz = mfcba + mfabc; + LBMReal mxxyMyzz = mfcba - mfabc; + + LBMReal mxxzPyyz = mfcab + mfacb; + LBMReal mxxzMyyz = mfcab - mfacb; + + LBMReal mxyyPxzz = mfbca + mfbac; + LBMReal mxyyMxzz = mfbca - mfbac; + + //////////////////////////////////////////////////////////////////////////////////// + // incl. correction + //////////////////////////////////////////////////////////// + //! - Compute velocity gradients from second order cumulants according to Eq. (27)-(32) + //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), + //! DOI:10.1016/j.jcp.2017.05.040 ]</b></a> Further explanations of the correction in viscosity in + //! Appendix H of <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015), + //! DOI:10.1016/j.camwa.2015.05.001 ]</b></a> Note that the division by rho is omitted here as we + //! need rho times the gradients later. + //! + LBMReal Dxy = -c3 * omega * mfbba; + LBMReal Dxz = -c3 * omega * mfbab; + LBMReal Dyz = -c3 * omega * mfabb; + LBMReal dxux = c1o2 * (-omega) * (mxxMyy + mxxMzz) + c1o2 * OxxPyyPzz * (mfaaa - mxxPyyPzz); + LBMReal dyuy = dxux + omega * c3o2 * mxxMyy; + LBMReal dzuz = dxux + omega * c3o2 * mxxMzz; + //////////////////////////////////////////////////////////// + //! - Relaxation of second order cumulants with correction terms according to Eq. (33)-(35) in + //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), + //! DOI:10.1016/j.jcp.2017.05.040 ]</b></a> + //! + mxxPyyPzz += OxxPyyPzz * (mfaaa - mxxPyyPzz) - + c3 * (c1 - c1o2 * OxxPyyPzz) * (vx2 * dxux + vy2 * dyuy + vz2 * dzuz); + mxxMyy += omega * (-mxxMyy) - c3 * (c1 + c1o2 * (-omega)) * (vx2 * dxux - vy2 * dyuy); + mxxMzz += omega * (-mxxMzz) - c3 * (c1 + c1o2 * (-omega)) * (vx2 * dxux - vz2 * dzuz); + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////no correction + // mxxPyyPzz += OxxPyyPzz*(mfaaa - mxxPyyPzz); + // mxxMyy += -(-omega) * (-mxxMyy); + // mxxMzz += -(-omega) * (-mxxMzz); + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + mfabb += omega * (-mfabb); + mfbab += omega * (-mfbab); + mfbba += omega * (-mfbba); + + //////////////////////////////////////////////////////////////////////////////////// + // relax + ////////////////////////////////////////////////////////////////////////// + // incl. limiter + //! - Relaxation of third order cumulants including limiter according to Eq. (116)-(123) + //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), + //! DOI:10.1016/j.jcp.2017.05.040 ]</b></a> + //! + wadjust = Oxyz + (c1 - Oxyz) * abs(mfbbb) / (abs(mfbbb) + qudricLimitD); + mfbbb += wadjust * (-mfbbb); + wadjust = OxyyPxzz + (c1 - OxyyPxzz) * abs(mxxyPyzz) / (abs(mxxyPyzz) + qudricLimitP); + mxxyPyzz += wadjust * (-mxxyPyzz); + wadjust = OxyyMxzz + (c1 - OxyyMxzz) * abs(mxxyMyzz) / (abs(mxxyMyzz) + qudricLimitM); + mxxyMyzz += wadjust * (-mxxyMyzz); + wadjust = OxyyPxzz + (c1 - OxyyPxzz) * abs(mxxzPyyz) / (abs(mxxzPyyz) + qudricLimitP); + mxxzPyyz += wadjust * (-mxxzPyyz); + wadjust = OxyyMxzz + (c1 - OxyyMxzz) * abs(mxxzMyyz) / (abs(mxxzMyyz) + qudricLimitM); + mxxzMyyz += wadjust * (-mxxzMyyz); + wadjust = OxyyPxzz + (c1 - OxyyPxzz) * abs(mxyyPxzz) / (abs(mxyyPxzz) + qudricLimitP); + mxyyPxzz += wadjust * (-mxyyPxzz); + wadjust = OxyyMxzz + (c1 - OxyyMxzz) * abs(mxyyMxzz) / (abs(mxyyMxzz) + qudricLimitM); + mxyyMxzz += wadjust * (-mxyyMxzz); + ////////////////////////////////////////////////////////////////////////// + // no limiter + // mfbbb += OxyyMxzz * (-mfbbb); + // mxxyPyzz += OxyyPxzz * (-mxxyPyzz); + // mxxyMyzz += OxyyMxzz * (-mxxyMyzz); + // mxxzPyyz += OxyyPxzz * (-mxxzPyyz); + // mxxzMyyz += OxyyMxzz * (-mxxzMyyz); + // mxyyPxzz += OxyyPxzz * (-mxyyPxzz); + // mxyyMxzz += OxyyMxzz * (-mxyyMxzz); + + //////////////////////////////////////////////////////////////////////////////////// + //! - Compute inverse linear combinations of second and third order cumulants + //! + mfcaa = c1o3 * (mxxMyy + mxxMzz + mxxPyyPzz); + mfaca = c1o3 * (-c2 * mxxMyy + mxxMzz + mxxPyyPzz); + mfaac = c1o3 * (mxxMyy - c2 * mxxMzz + mxxPyyPzz); + + mfcba = (mxxyMyzz + mxxyPyzz) * c1o2; + mfabc = (-mxxyMyzz + mxxyPyzz) * c1o2; + mfcab = (mxxzMyyz + mxxzPyyz) * c1o2; + mfacb = (-mxxzMyyz + mxxzPyyz) * c1o2; + mfbca = (mxyyMxzz + mxyyPxzz) * c1o2; + mfbac = (-mxyyMxzz + mxyyPxzz) * c1o2; + ////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////// + // 4. + // no limiter + //! - Relax fourth order cumulants to modified equilibrium for fourth order convergence of diffusion + //! according to Eq. (43)-(48) <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et + //! al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a> + //! + CUMacc = -O4 * (c1 / omega - c1o2) * (dyuy + dzuz) * c2o3 * A + (c1 - O4) * (CUMacc); + CUMcac = -O4 * (c1 / omega - c1o2) * (dxux + dzuz) * c2o3 * A + (c1 - O4) * (CUMcac); + CUMcca = -O4 * (c1 / omega - c1o2) * (dyuy + dxux) * c2o3 * A + (c1 - O4) * (CUMcca); + CUMbbc = -O4 * (c1 / omega - c1o2) * Dxy * c1o3 * B + (c1 - O4) * (CUMbbc); + CUMbcb = -O4 * (c1 / omega - c1o2) * Dxz * c1o3 * B + (c1 - O4) * (CUMbcb); + CUMcbb = -O4 * (c1 / omega - c1o2) * Dyz * c1o3 * B + (c1 - O4) * (CUMcbb); + + ////////////////////////////////////////////////////////////////////////// + // 5. + CUMbcc += O5 * (-CUMbcc); + CUMcbc += O5 * (-CUMcbc); + CUMccb += O5 * (-CUMccb); + + ////////////////////////////////////////////////////////////////////////// + // 6. + CUMccc += O6 * (-CUMccc); + + //////////////////////////////////////////////////////////////////////////////////// + //! - Compute central moments from post collision cumulants according to Eq. (53)-(56) in + //! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), + //! DOI:10.1016/j.jcp.2017.05.040 ]</b></a> + //! + + ////////////////////////////////////////////////////////////////////////// + // 4. + mfcbb = CUMcbb + c1o3 * ((c3 * mfcaa + c1) * mfabb + c6 * mfbba * mfbab) * OOrho; + mfbcb = CUMbcb + c1o3 * ((c3 * mfaca + c1) * mfbab + c6 * mfbba * mfabb) * OOrho; + mfbbc = CUMbbc + c1o3 * ((c3 * mfaac + c1) * mfbba + c6 * mfbab * mfabb) * OOrho; + + mfcca = CUMcca + (((mfcaa * mfaca + c2 * mfbba * mfbba) * c9 + c3 * (mfcaa + mfaca)) * OOrho - + (drho * OOrho)) * + c1o9; + mfcac = CUMcac + (((mfcaa * mfaac + c2 * mfbab * mfbab) * c9 + c3 * (mfcaa + mfaac)) * OOrho - + (drho * OOrho)) * + c1o9; + mfacc = CUMacc + (((mfaac * mfaca + c2 * mfabb * mfabb) * c9 + c3 * (mfaac + mfaca)) * OOrho - + (drho * OOrho)) * + c1o9; + + ////////////////////////////////////////////////////////////////////////// + // 5. + mfbcc = CUMbcc + c1o3 * + (c3 * (mfaac * mfbca + mfaca * mfbac + c4 * mfabb * mfbbb + + c2 * (mfbab * mfacb + mfbba * mfabc)) + + (mfbca + mfbac)) * + OOrho; + mfcbc = CUMcbc + c1o3 * + (c3 * (mfaac * mfcba + mfcaa * mfabc + c4 * mfbab * mfbbb + + c2 * (mfabb * mfcab + mfbba * mfbac)) + + (mfcba + mfabc)) * + OOrho; + mfccb = CUMccb + c1o3 * + (c3 * (mfcaa * mfacb + mfaca * mfcab + c4 * mfbba * mfbbb + + c2 * (mfbab * mfbca + mfabb * mfcba)) + + (mfacb + mfcab)) * + OOrho; + + ////////////////////////////////////////////////////////////////////////// + // 6. + mfccc = + CUMccc - ((-c4 * mfbbb * mfbbb - (mfcaa * mfacc + mfaca * mfcac + mfaac * mfcca) - + c4 * (mfabb * mfcbb + mfbab * mfbcb + mfbba * mfbbc) - + c2 * (mfbca * mfbac + mfcba * mfabc + mfcab * mfacb)) * + OOrho + + (c4 * (mfbab * mfbab * mfaca + mfabb * mfabb * mfcaa + mfbba * mfbba * mfaac) + + c2 * (mfcaa * mfaca * mfaac) + c16 * mfbba * mfbab * mfabb) * + OOrho * OOrho - + c1o3 * (mfacc + mfcac + mfcca) * OOrho - c1o9 * (mfcaa + mfaca + mfaac) * OOrho + + (c2 * (mfbab * mfbab + mfabb * mfabb + mfbba * mfbba) + + (mfaac * mfaca + mfaac * mfcaa + mfaca * mfcaa) + c1o3 * (mfaac + mfaca + mfcaa)) * + OOrho * OOrho * c2o3 + + c1o27 * ((drho * drho - drho) * OOrho * OOrho)); + + //////////////////////////////////////////////////////////////////////////////////// + //! - Add acceleration (body force) to first order cumulants according to Eq. (85)-(87) in + //! <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015), + //! DOI:10.1016/j.camwa.2015.05.001 ]</b></a> + //! + mfbaa = -mfbaa; + mfaba = -mfaba; + mfaab = -mfaab; + //////////////////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////////////////////// + //! - Chimera transform from central moments to well conditioned distributions as defined in + //! Appendix J in <a href="https://doi.org/10.1016/j.camwa.2015.05.001"><b>[ M. Geier et al. (2015), + //! DOI:10.1016/j.camwa.2015.05.001 ]</b></a> see also Eq. (88)-(96) in <a + //! href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), + //! DOI:10.1016/j.jcp.2017.05.040 ]</b></a> + //! + //////////////////////////////////////////////////////////////////////////////////// + // X - Dir + backwardInverseChimeraWithK(mfaaa, mfbaa, mfcaa, vvx, vx2, c1, c1); + backwardChimera(mfaba, mfbba, mfcba, vvx, vx2); + backwardInverseChimeraWithK(mfaca, mfbca, mfcca, vvx, vx2, c3, c1o3); + backwardChimera(mfaab, mfbab, mfcab, vvx, vx2); + backwardChimera(mfabb, mfbbb, mfcbb, vvx, vx2); + backwardChimera(mfacb, mfbcb, mfccb, vvx, vx2); + backwardInverseChimeraWithK(mfaac, mfbac, mfcac, vvx, vx2, c3, c1o3); + backwardChimera(mfabc, mfbbc, mfcbc, vvx, vx2); + backwardInverseChimeraWithK(mfacc, mfbcc, mfccc, vvx, vx2, c9, c1o9); + + //////////////////////////////////////////////////////////////////////////////////// + // Y - Dir + backwardInverseChimeraWithK(mfaaa, mfaba, mfaca, vvy, vy2, c6, c1o6); + backwardChimera(mfaab, mfabb, mfacb, vvy, vy2); + backwardInverseChimeraWithK(mfaac, mfabc, mfacc, vvy, vy2, c18, c1o18); + backwardInverseChimeraWithK(mfbaa, mfbba, mfbca, vvy, vy2, c3o2, c2o3); + backwardChimera(mfbab, mfbbb, mfbcb, vvy, vy2); + backwardInverseChimeraWithK(mfbac, mfbbc, mfbcc, vvy, vy2, c9o2, c2o9); + backwardInverseChimeraWithK(mfcaa, mfcba, mfcca, vvy, vy2, c6, c1o6); + backwardChimera(mfcab, mfcbb, mfccb, vvy, vy2); + backwardInverseChimeraWithK(mfcac, mfcbc, mfccc, vvy, vy2, c18, c1o18); + + //////////////////////////////////////////////////////////////////////////////////// + // Z - Dir + backwardInverseChimeraWithK(mfaaa, mfaab, mfaac, vvz, vz2, c36, c1o36); + backwardInverseChimeraWithK(mfaba, mfabb, mfabc, vvz, vz2, c9, c1o9); + backwardInverseChimeraWithK(mfaca, mfacb, mfacc, vvz, vz2, c36, c1o36); + backwardInverseChimeraWithK(mfbaa, mfbab, mfbac, vvz, vz2, c9, c1o9); + backwardInverseChimeraWithK(mfbba, mfbbb, mfbbc, vvz, vz2, c9o4, c4o9); + backwardInverseChimeraWithK(mfbca, mfbcb, mfbcc, vvz, vz2, c9, c1o9); + backwardInverseChimeraWithK(mfcaa, mfcab, mfcac, vvz, vz2, c36, c1o36); + backwardInverseChimeraWithK(mfcba, mfcbb, mfcbc, vvz, vz2, c9, c1o9); + backwardInverseChimeraWithK(mfcca, mfccb, mfccc, vvz, vz2, c36, c1o36); + //////////////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////// + // proof correctness + ////////////////////////////////////////////////////////////////////////// +#ifdef PROOF_CORRECTNESS + LBMReal drho_post = (mfaaa + mfaac + mfaca + mfcaa + mfacc + mfcac + mfccc + mfcca) + + (mfaab + mfacb + mfcab + mfccb) + (mfaba + mfabc + mfcba + mfcbc) + + (mfbaa + mfbac + mfbca + mfbcc) + (mfabb + mfcbb) + (mfbab + mfbcb) + + (mfbba + mfbbc) + mfbbb; + LBMReal dif = drho - drho_post; +#ifdef SINGLEPRECISION + if (dif > 10.0E-7 || dif < -10.0E-7) +#else + if (dif > 10.0E-15 || dif < -10.0E-15) +#endif + { + UB_THROW(UbException( + UB_EXARGS, + "rho=" + UbSystem::toString(drho) + ", rho_post=" + UbSystem::toString(drho_post) + + " dif=" + UbSystem::toString(dif) + " rho is not correct for node " + + UbSystem::toString(x1) + "," + UbSystem::toString(x2) + "," + UbSystem::toString(x3) + + " in " + block.lock()->toString() + " step = " + UbSystem::toString(step))); + } +#endif + //////////////////////////////////////////////////////////////////////////////////// + //! - Write distributions: style of reading and writing the distributions from/to stored arrays + //! dependent on timestep is based on the esoteric twist algorithm <a + //! href="https://doi.org/10.3390/computation5020019"><b>[ M. Geier et al. (2017), + //! DOI:10.3390/computation5020019 ]</b></a> + //! + (*this->localDistributions)(D3Q27System::ET_E, x1, x2, x3) = mfabb; + (*this->localDistributions)(D3Q27System::ET_N, x1, x2, x3) = mfbab; + (*this->localDistributions)(D3Q27System::ET_T, x1, x2, x3) = mfbba; + (*this->localDistributions)(D3Q27System::ET_NE, x1, x2, x3) = mfaab; + (*this->localDistributions)(D3Q27System::ET_NW, x1p, x2, x3) = mfcab; + (*this->localDistributions)(D3Q27System::ET_TE, x1, x2, x3) = mfaba; + (*this->localDistributions)(D3Q27System::ET_TW, x1p, x2, x3) = mfcba; + (*this->localDistributions)(D3Q27System::ET_TN, x1, x2, x3) = mfbaa; + (*this->localDistributions)(D3Q27System::ET_TS, x1, x2p, x3) = mfbca; + (*this->localDistributions)(D3Q27System::ET_TNE, x1, x2, x3) = mfaaa; + (*this->localDistributions)(D3Q27System::ET_TNW, x1p, x2, x3) = mfcaa; + (*this->localDistributions)(D3Q27System::ET_TSE, x1, x2p, x3) = mfaca; + (*this->localDistributions)(D3Q27System::ET_TSW, x1p, x2p, x3) = mfcca; + + (*this->nonLocalDistributions)(D3Q27System::ET_W, x1p, x2, x3) = mfcbb; + (*this->nonLocalDistributions)(D3Q27System::ET_S, x1, x2p, x3) = mfbcb; + (*this->nonLocalDistributions)(D3Q27System::ET_B, x1, x2, x3p) = mfbbc; + (*this->nonLocalDistributions)(D3Q27System::ET_SW, x1p, x2p, x3) = mfccb; + (*this->nonLocalDistributions)(D3Q27System::ET_SE, x1, x2p, x3) = mfacb; + (*this->nonLocalDistributions)(D3Q27System::ET_BW, x1p, x2, x3p) = mfcbc; + (*this->nonLocalDistributions)(D3Q27System::ET_BE, x1, x2, x3p) = mfabc; + (*this->nonLocalDistributions)(D3Q27System::ET_BS, x1, x2p, x3p) = mfbcc; + (*this->nonLocalDistributions)(D3Q27System::ET_BN, x1, x2, x3p) = mfbac; + (*this->nonLocalDistributions)(D3Q27System::ET_BSW, x1p, x2p, x3p) = mfccc; + (*this->nonLocalDistributions)(D3Q27System::ET_BSE, x1, x2p, x3p) = mfacc; + (*this->nonLocalDistributions)(D3Q27System::ET_BNW, x1p, x2, x3p) = mfcac; + (*this->nonLocalDistributions)(D3Q27System::ET_BNE, x1, x2, x3p) = mfaac; + + (*this->restDistributions)(x1, x2, x3) = mfbbb; + ////////////////////////////////////////////////////////////////////////// + f[D3Q27System::REST] = mfbbb; + + f[D3Q27System::E] = mfcbb; + f[D3Q27System::N] = mfbcb; + f[D3Q27System::T] = mfbbc; + f[D3Q27System::NE] = mfccb; + f[D3Q27System::NW] = mfacb; + f[D3Q27System::TE] = mfcbc; + f[D3Q27System::TW] = mfabc; + f[D3Q27System::TN] = mfbcc; + f[D3Q27System::TS] = mfbac; + f[D3Q27System::TNE] = mfccc; + f[D3Q27System::TNW] = mfacc; + f[D3Q27System::TSE] = mfcac; + f[D3Q27System::TSW] = mfaac; + + f[D3Q27System::W] = mfabb; + f[D3Q27System::S] = mfbab; + f[D3Q27System::B] = mfbba; + f[D3Q27System::SW] = mfaab; + f[D3Q27System::SE] = mfcab; + f[D3Q27System::BW] = mfaba; + f[D3Q27System::BE] = mfcba; + f[D3Q27System::BS] = mfbaa; + f[D3Q27System::BN] = mfbca; + f[D3Q27System::BSW] = mfaaa; + f[D3Q27System::BSE] = mfcaa; + f[D3Q27System::BNW] = mfaca; + f[D3Q27System::BNE] = mfcca; + } + if ((*particleData)(x1, x2, x3)->solidFraction < SOLFRAC_MIN) + continue; + + LBMReal vx1, vx2, vx3, drho; + D3Q27System::calcCompMacroscopicValues(f, drho, vx1, vx2, vx3); + D3Q27System::calcCompFeq(fEq, drho, vx1, vx2, vx3); + + std::array<double, 3> uPart; + uPart[0] = (*particleData)(x1, x2, x3)->uPart[0] * (1. + drho); + uPart[1] = (*particleData)(x1, x2, x3)->uPart[1] * (1. + drho); + uPart[2] = (*particleData)(x1, x2, x3)->uPart[2] * (1. + drho); + + D3Q27System::calcCompFeq(fEqSolid, drho, uPart[0], uPart[1], uPart[2]); + + if ((*particleData)(x1, x2, x3)->solidFraction > SOLFRAC_MAX) { + double const bb0 = fEq[D3Q27System::REST] - fEqSolid[D3Q27System::REST]; + f[D3Q27System::REST] = fPre[D3Q27System::REST] + bb0; + for (int iPop = D3Q27System::FSTARTDIR; iPop <= D3Q27System::FENDDIR; iPop++) { + const int iOpp = D3Q27System::INVDIR[iPop]; + double const bb = ((fPre[iOpp] - fEq[iOpp]) - (fPre[iPop] - fEqSolid[iPop])); + double const bbOpp = ((fPre[iPop] - fEq[iPop]) - (fPre[iOpp] - fEqSolid[iOpp])); + + + f[iPop] = fPre[iPop] + bb; + f[iOpp] = fPre[iOpp] + bbOpp; + + (*particleData)(x1, x2, x3)->hydrodynamicForce[0] -= D3Q27System::DX1[iPop] * (bb - bbOpp); + (*particleData)(x1, x2, x3)->hydrodynamicForce[1] -= D3Q27System::DX2[iPop] * (bb - bbOpp); + (*particleData)(x1, x2, x3)->hydrodynamicForce[2] -= D3Q27System::DX3[iPop] * (bb - bbOpp); + } + } else { /* particleData.solidFraction < SOLFRAC_MAX */ +//#ifdef LBDEM_USE_WEIGHING + double const ooo = 1. / omega - 0.5; + double const B = (*particleData)(x1, x2, x3)->solidFraction * ooo / ((1. - (*particleData)(x1, x2, x3)->solidFraction) + ooo); +//#else +// T const B = particleData.solidFraction; +//#endif + double const oneMinB = 1. - B; + + double const bb0 = fEq[D3Q27System::REST] - fEqSolid[D3Q27System::REST]; + f[D3Q27System::REST] = fPre[D3Q27System::REST] + oneMinB * (f[D3Q27System::REST] - fPre[D3Q27System::REST]) + B * bb0; + + for (int iPop = D3Q27System::FSTARTDIR; iPop <= D3Q27System::FENDDIR; iPop++) { + int const iOpp = D3Q27System::INVDIR[iPop]; + double const bb = B * ((fPre[iOpp] - fEq[iOpp]) - (fPre[iPop] - fEqSolid[iPop])); + double const bbOpp = B * ((fPre[iPop] - fEq[iPop]) - (fPre[iOpp] - fEqSolid[iOpp])); + + f[iPop] = fPre[iPop] + oneMinB * (f[iPop] - fPre[iPop]) + bb; + f[iOpp] = fPre[iOpp] + oneMinB * (f[iOpp] - fPre[iOpp]) + bbOpp; + + (*particleData)(x1, x2, x3)->hydrodynamicForce[0] -= D3Q27System::DX1[iPop] * (bb - bbOpp); + (*particleData)(x1, x2, x3)->hydrodynamicForce[1] -= D3Q27System::DX2[iPop] * (bb - bbOpp); + (*particleData)(x1, x2, x3)->hydrodynamicForce[2] -= D3Q27System::DX3[iPop] * (bb - bbOpp); + } + } /* if solidFraction > SOLFRAC_MAX */ + + (*this->restDistributions)(x1, x2, x3) = f[D3Q27System::REST]; + + (*this->localDistributions)(D3Q27System::ET_E, x1, x2, x3) = f[D3Q27System::W] ; + (*this->localDistributions)(D3Q27System::ET_N, x1, x2, x3) = f[D3Q27System::S] ; + (*this->localDistributions)(D3Q27System::ET_T, x1, x2, x3) = f[D3Q27System::B] ; + (*this->localDistributions)(D3Q27System::ET_NE, x1, x2, x3) = f[D3Q27System::SW] ; + (*this->localDistributions)(D3Q27System::ET_NW, x1p, x2, x3) = f[D3Q27System::SE] ; + (*this->localDistributions)(D3Q27System::ET_TE, x1, x2, x3) = f[D3Q27System::BW] ; + (*this->localDistributions)(D3Q27System::ET_TW, x1p, x2, x3) = f[D3Q27System::BE] ; + (*this->localDistributions)(D3Q27System::ET_TN, x1, x2, x3) = f[D3Q27System::BS] ; + (*this->localDistributions)(D3Q27System::ET_TS, x1, x2p, x3) = f[D3Q27System::BN] ; + (*this->localDistributions)(D3Q27System::ET_TNE, x1, x2, x3) = f[D3Q27System::BSW] ; + (*this->localDistributions)(D3Q27System::ET_TNW, x1p, x2, x3) = f[D3Q27System::BSE] ; + (*this->localDistributions)(D3Q27System::ET_TSE, x1, x2p, x3) = f[D3Q27System::BNW] ; + (*this->localDistributions)(D3Q27System::ET_TSW, x1p, x2p, x3) = f[D3Q27System::BNE] ; + + (*this->nonLocalDistributions)(D3Q27System::ET_W, x1p, x2, x3) = f[D3Q27System::E] ; + (*this->nonLocalDistributions)(D3Q27System::ET_S, x1, x2p, x3) = f[D3Q27System::N] ; + (*this->nonLocalDistributions)(D3Q27System::ET_B, x1, x2, x3p) = f[D3Q27System::T] ; + (*this->nonLocalDistributions)(D3Q27System::ET_SW, x1p, x2p, x3) = f[D3Q27System::NE] ; + (*this->nonLocalDistributions)(D3Q27System::ET_SE, x1, x2p, x3) = f[D3Q27System::NW] ; + (*this->nonLocalDistributions)(D3Q27System::ET_BW, x1p, x2, x3p) = f[D3Q27System::TE] ; + (*this->nonLocalDistributions)(D3Q27System::ET_BE, x1, x2, x3p) = f[D3Q27System::TW] ; + (*this->nonLocalDistributions)(D3Q27System::ET_BS, x1, x2p, x3p) = f[D3Q27System::TN] ; + (*this->nonLocalDistributions)(D3Q27System::ET_BN, x1, x2, x3p) = f[D3Q27System::TS] ; + (*this->nonLocalDistributions)(D3Q27System::ET_BSW, x1p, x2p, x3p) = f[D3Q27System::TNE]; + (*this->nonLocalDistributions)(D3Q27System::ET_BSE, x1, x2p, x3p) = f[D3Q27System::TNW]; + (*this->nonLocalDistributions)(D3Q27System::ET_BNW, x1p, x2, x3p) = f[D3Q27System::TSE]; + (*this->nonLocalDistributions)(D3Q27System::ET_BNE, x1, x2, x3p) = f[D3Q27System::TSW]; + } + } + } + } +} +////////////////////////////////////////////////////////////////////////// + diff --git a/src/cpu/LiggghtsCoupling/IBcumulantK17LBMKernel.h b/src/cpu/LiggghtsCoupling/IBcumulantK17LBMKernel.h new file mode 100644 index 0000000000000000000000000000000000000000..503d1970979afa83cf6d1d65ccd43356a5123720 --- /dev/null +++ b/src/cpu/LiggghtsCoupling/IBcumulantK17LBMKernel.h @@ -0,0 +1,155 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ | +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids 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. +// +// VirtualFluids 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 VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file IBcumulantK17LBMKernel.h +//! \ingroup LBM +//! \author Konstantin Kutscher, Martin Geier +//======================================================================================= + +#ifndef IBcumulantK17LBMKernel_h__ +#define IBcumulantK17LBMKernel_h__ + +#include "LBMKernel.h" +#include "BCProcessor.h" +#include "D3Q27System.h" +#include "UbTiming.h" +#include "CbArray4D.h" +#include "CbArray3D.h" +#include "IBdynamicsParticleData.h" + + +//! \brief Compressible cumulant LBM kernel. +//! \details LBM implementation that use Cascaded Cumulant Lattice Boltzmann method for D3Q27 model +//! +//! The model is publisched in +//! <a href="http://dx.doi.org/10.1016/j.jcp.2017.05.040"><b>[ Geier et al., (2017), 10.1016/j.jcp.2017.05.040]</b></a>, +//! <a href="http://dx.doi.org/10.1016/j.jcp.2017.07.004"><b>[ Geier et al., (2017), 10.1016/j.jcp.2017.07.004]</b></a> +//! +class IBcumulantK17LBMKernel : public LBMKernel +{ +public: + IBcumulantK17LBMKernel(); + ~IBcumulantK17LBMKernel() = default; + void calculate(int step) override; + SPtr<LBMKernel> clone() override; + double getCalculationTime() override { return .0; } + CbArray3D<SPtr<IBdynamicsParticleData>, IndexerX3X2X1>::CbArray3DPtr getParticleData() { return particleData; }; + void setParticleData(CbArray3D<SPtr<IBdynamicsParticleData>, IndexerX3X2X1>::CbArray3DPtr particleData) + { + this->particleData = particleData; + }; + +protected: + inline void forwardInverseChimeraWithK(LBMReal& mfa, LBMReal& mfb, LBMReal& mfc, LBMReal vv, LBMReal v2, LBMReal Kinverse, LBMReal K); + inline void backwardInverseChimeraWithK(LBMReal& mfa, LBMReal& mfb, LBMReal& mfc, LBMReal vv, LBMReal v2, LBMReal Kinverse, LBMReal K); + inline void forwardChimera(LBMReal& mfa, LBMReal& mfb, LBMReal& mfc, LBMReal vv, LBMReal v2); + inline void backwardChimera(LBMReal& mfa, LBMReal& mfb, LBMReal& mfc, LBMReal vv, LBMReal v2); + + virtual void initDataSet(); + + CbArray4D<LBMReal, IndexerX4X3X2X1>::CbArray4DPtr localDistributions; + CbArray4D<LBMReal, IndexerX4X3X2X1>::CbArray4DPtr nonLocalDistributions; + CbArray3D<LBMReal, IndexerX3X2X1>::CbArray3DPtr restDistributions; + + mu::value_type muX1, muX2, muX3; + mu::value_type muDeltaT; + mu::value_type muNu; + LBMReal forcingX1; + LBMReal forcingX2; + LBMReal forcingX3; + + CbArray3D<SPtr<IBdynamicsParticleData>, IndexerX3X2X1>::CbArray3DPtr particleData; +}; + +//////////////////////////////////////////////////////////////////////////////// +//! \brief forward chimera transformation \ref forwardInverseChimeraWithK +//! Transformation from distributions to central moments according to Eq. (6)-(14) in +//! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a> +//! Modified for lower round-off errors. +//////////////////////////////////////////////////////////////////////////////// +inline void IBcumulantK17LBMKernel::forwardInverseChimeraWithK(LBMReal& mfa, LBMReal& mfb, LBMReal& mfc, LBMReal vv, LBMReal v2, LBMReal Kinverse, LBMReal K) +{ + using namespace UbMath; + LBMReal m2 = mfa + mfc; + LBMReal m1 = mfc - mfa; + LBMReal m0 = m2 + mfb; + mfa = m0; + m0 *= Kinverse; + m0 += c1; + mfb = (m1 * Kinverse - m0 * vv) * K; + mfc = ((m2 - c2 * m1 * vv) * Kinverse + v2 * m0) * K; +} +//////////////////////////////////////////////////////////////////////////////// +//! \brief backward chimera transformation \ref backwardInverseChimeraWithK +//! Transformation from central moments to distributions according to Eq. (57)-(65) in +//! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a> +//! ] Modified for lower round-off errors. +//////////////////////////////////////////////////////////////////////////////// +inline void IBcumulantK17LBMKernel::backwardInverseChimeraWithK(LBMReal& mfa, LBMReal& mfb, LBMReal& mfc, LBMReal vv, LBMReal v2, LBMReal Kinverse, LBMReal K) +{ + using namespace UbMath; + LBMReal m0 = (((mfc - mfb) * c1o2 + mfb * vv) * Kinverse + (mfa * Kinverse + c1) * (v2 - vv) * c1o2) * K; + LBMReal m1 = (((mfa - mfc) - c2 * mfb * vv) * Kinverse + (mfa * Kinverse + c1) * (-v2)) * K; + mfc = (((mfc + mfb) * c1o2 + mfb * vv) * Kinverse + (mfa * Kinverse + c1) * (v2 + vv) * c1o2) * K; + mfa = m0; + mfb = m1; +} +//////////////////////////////////////////////////////////////////////////////// +//! \brief forward chimera transformation \ref forwardChimera +//! Transformation from distributions to central moments according to Eq. (6)-(14) in +//! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a> +//! for \f$ K_{abc}=0 \f$. This is to avoid unnessary floating point operations. +//! Modified for lower round-off errors. +//////////////////////////////////////////////////////////////////////////////// +inline void IBcumulantK17LBMKernel::forwardChimera(LBMReal& mfa, LBMReal& mfb, LBMReal& mfc, LBMReal vv, LBMReal v2) +{ + using namespace UbMath; + LBMReal m1 = (mfa + mfc) + mfb; + LBMReal m2 = mfc - mfa; + mfc = (mfc + mfa) + (v2 * m1 - c2 * vv * m2); + mfb = m2 - vv * m1; + mfa = m1; +} +//////////////////////////////////////////////////////////////////////////////// +//! \brief backward chimera transformation \ref backwardChimera +//! Transformation from central moments to distributions according to Eq. (57)-(65) in +//! <a href="https://doi.org/10.1016/j.jcp.2017.05.040"><b>[ M. Geier et al. (2017), DOI:10.1016/j.jcp.2017.05.040 ]</b></a> +//! for \f$ K_{abc}=0 \f$. This is to avoid unnessary floating point operations. +//! Modified for lower round-off errors. +//////////////////////////////////////////////////////////////////////////////// +inline void IBcumulantK17LBMKernel::backwardChimera(LBMReal& mfa, LBMReal& mfb, LBMReal& mfc, LBMReal vv, LBMReal v2) +{ + using namespace UbMath; + LBMReal ma = (mfc + mfa * (v2 - vv)) * c1o2 + mfb * (vv - c1o2); + LBMReal mb = ((mfa - mfc) - mfa * v2) - c2 * mfb * vv; + mfc = (mfc + mfa * (v2 + vv)) * c1o2 + mfb * (vv + c1o2); + mfb = mb; + mfa = ma; +} + +#endif // IBcumulantK17LBMKernel_h__ \ No newline at end of file diff --git a/src/cpu/LiggghtsCoupling/IBdynamicsParticleData.h b/src/cpu/LiggghtsCoupling/IBdynamicsParticleData.h new file mode 100644 index 0000000000000000000000000000000000000000..28f11bf2eb84a509d59e6c098c0fbb69874f9517 --- /dev/null +++ b/src/cpu/LiggghtsCoupling/IBdynamicsParticleData.h @@ -0,0 +1,61 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ | +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids 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. +// +// VirtualFluids 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 VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file DataSet3D.h +//! \ingroup Data +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef IBdynamicsParticleData_h +#define IBdynamicsParticleData_h + +#include<array> + +constexpr auto SOLFRAC_MIN = 0.001; +constexpr auto SOLFRAC_MAX = 0.999; + +struct IBdynamicsParticleData { +public: + IBdynamicsParticleData() + : partId(0), solidFraction(0.) + { + uPart[0] = 0.; + uPart[1] = 0.; + uPart[2] = 0.; + + hydrodynamicForce[0] = 0.; + hydrodynamicForce[1] = 0.; + hydrodynamicForce[2] = 0.; + }; + int partId; + double solidFraction; + std::array<double, 3> uPart; + std::array<double, 3> hydrodynamicForce; +}; + +#endif diff --git a/src/cpu/LiggghtsCoupling/LiggghtsCouplingCoProcessor.cpp b/src/cpu/LiggghtsCoupling/LiggghtsCouplingCoProcessor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..da8c93296a333050c036f7fe084bbe23aa39ca23 --- /dev/null +++ b/src/cpu/LiggghtsCoupling/LiggghtsCouplingCoProcessor.cpp @@ -0,0 +1,413 @@ +#include "LiggghtsCouplingCoProcessor.h" +#include "GbSphere3D.h" +#include "MPICommunicator.h" +#include "CoProcessor.h" +#include "LiggghtsCouplingWrapper.h" +#include "Grid3D.h" +#include "Block3D.h" +#include "LBMKernel.h" +#include "DistributionArray3D.h" +#include "DataSet3D.h" +#include "IBcumulantK17LBMKernel.h" +#include "LBMUnitConverter.h" +#include "fix_lb_coupling_onetoone.h" + +LiggghtsCouplingCoProcessor::LiggghtsCouplingCoProcessor(SPtr<Grid3D> grid, SPtr<UbScheduler> s, + SPtr<Communicator> comm, LiggghtsCouplingWrapper &wrapper, int demSteps, SPtr<LBMUnitConverter> units) + : CoProcessor(grid, s), comm(comm), wrapper(wrapper), demSteps(demSteps), units(units) +{ + //gridRank = comm->getProcessID(); + //minInitLevel = this->grid->getCoarsestInitializedLevel(); + //maxInitLevel = this->grid->getFinestInitializedLevel(); + + //blockVector.resize(maxInitLevel + 1); + + //for (int level = minInitLevel; level <= maxInitLevel; level++) { + // grid->getBlocks(level, gridRank, true, blockVector[level]); + //} +} + +LiggghtsCouplingCoProcessor::~LiggghtsCouplingCoProcessor() +{ +} + +void LiggghtsCouplingCoProcessor::process(double actualTimeStep) +{ + std::cout << "step: " << actualTimeStep << "\n"; + + getForcesFromLattice(); + + wrapper.run(demSteps); + + setSpheresOnLattice(); +} + +void LiggghtsCouplingCoProcessor::setSpheresOnLattice() +{ + std::vector<int> excludeType; + + int nPart = wrapper.lmp->atom->nlocal + wrapper.lmp->atom->nghost; + + for (int iS = 0; iS < nPart; iS++) + { + int type = (int)wrapper.lmp->atom->type[iS]; + bool excludeFlag(false); + for (int iT = 0; iT < excludeType.size(); iT++) { + //std::cout << iS << " " << type << " " << excludeType[iT] << std::endl; + if (type == excludeType[iT]) { + excludeFlag = true; + break; + } + } + + if (excludeFlag) + continue; + + double x[3], v[3], omega[3]; + double r; + int id = wrapper.lmp->atom->tag[iS]; + + for (int i = 0; i < 3; i++) + { + x[i] = wrapper.lmp->atom->x[iS][i]; // * units->getFactorLentghWToLb(); // - 0.5; ???? + v[i] = wrapper.lmp->atom->v[iS][i] * units->getFactorVelocityWToLb(); + omega[i] = wrapper.lmp->atom->omega[iS][i] / units->getFactorTimeWToLb(); + } + + r = wrapper.lmp->atom->radius[iS]; // * units->getFactorLentghWToLb(); + + //std::cout << "x[0] = " << x[0] << ", x[1] = " << x[1] << ", x[2] = " << x[2] << std::endl; + //std::cout << "v[0] = " << v[0] << ", v[1] = " << v[1] << ", v[2] = " << v[2] << std::endl; + //std::cout << "omega[0] = " << omega[0] << ", omega[1] = " << omega[1] << ", omega[2] = " << omega[2] << std::endl; + //std::cout << "r = " << r << std::endl; + + setSingleSphere3D(x, v, omega, r, id); + } +} + +void LiggghtsCouplingCoProcessor::setSingleSphere3D(double *x, double *v, double *omega, /* double *com,*/ double r, + int id /*, bool initVelFlag*/) +{ + int level = 0; + //UbTupleInt3 bi = grid->getBlockIndexes(x[0], x[1], x[2], level); + //SPtr<Block3D> block = grid->getBlock(val<1>(bi), val<2>(bi), val<3>(bi), level); + + std::vector<SPtr<Block3D>> blocks; + grid->getBlocksByCuboid(level, x[0] - r, x[1] - r, x[2] - r, x[0] + r, x[1] + r, x[2] + r, blocks); + + + + + for (SPtr<Block3D> block : blocks) { + if (block) { + SPtr<ILBMKernel> kernel = block->getKernel(); + SPtr<DistributionArray3D> distributions = kernel->getDataSet()->getFdistributions(); + + CbArray3D<SPtr<IBdynamicsParticleData>, IndexerX3X2X1>::CbArray3DPtr particleData = + dynamicPointerCast<IBcumulantK17LBMKernel>(kernel)->getParticleData(); + + if (!particleData) + continue; + + int minX1 = 1; + int minX2 = 1; + int minX3 = 1; + + int maxX1 = (int)(distributions->getNX1()) - 1; + int maxX2 = (int)(distributions->getNX2()) - 1; + int maxX3 = (int)(distributions->getNX3()) - 1; + + for (int ix3 = minX3; ix3 < maxX3; ix3++) { + for (int ix2 = minX2; ix2 < maxX2; ix2++) { + for (int ix1 = minX1; ix1 < maxX1; ix1++) { + + //UbTupleInt3 blockNX = grid->getBlockNX(); + + //double const dx = val<1>(blockNX) * block->getX1() + ix1 - x[0]; + //double const dy = val<2>(blockNX) * block->getX2() + ix2 - x[1]; + //double const dz = val<3>(blockNX) * block->getX3() + ix3 - x[2]; + + Vector3D worldCoordinates = grid->getNodeCoordinates(block, ix1, ix2, ix3); + + double const dx = (worldCoordinates[0] - x[0]) * units->getFactorLentghWToLb(); + double const dy = (worldCoordinates[1] - x[1]) * units->getFactorLentghWToLb(); + double const dz = (worldCoordinates[2] - x[2]) * units->getFactorLentghWToLb(); + + double const sf = calcSolidFraction(dx, dy, dz, r * units->getFactorLentghWToLb()); + + double const sf_old = (*particleData)(ix1,ix2,ix3)->solidFraction; + int const id_old = (int)(*particleData)(ix1,ix2,ix3)->partId; + + int const decFlag = (sf > SOLFRAC_MIN) + 2 * (sf_old > SOLFRAC_MIN); + + switch (decFlag) { + case 0: // sf == 0 && sf_old == 0 + setToZero(*(*particleData)(ix1, ix2, ix3).get()); + break; // do nothing + case 1: // sf > 0 && sf_old == 0 + setValues(*(*particleData)(ix1, ix2, ix3).get(), id, sf, v, dx, dy, dz, omega); + break; + case 2: // sf == 0 && sf_old > 0 + if (id_old == id) // then particle has left this cell + setToZero(*(*particleData)(ix1, ix2, ix3).get()); + break; // else do nothing + case 3: // sf > 0 && sf_old > 0 + if (sf > sf_old || id_old == id) + setValues(*(*particleData)(ix1, ix2, ix3).get(), id, sf, v, dx, dy, dz, omega); + break; // else do nothing + } + // if desired, initialize interior of sphere with sphere velocity + // if (initVelFlag && sf > SOLFRAC_MAX) + // cell.defineVelocity(particleData->uPart); + + //if (sf > 0) { + // std::cout << "sf = " << sf << std::endl; + // std::cout << "ix1 = " << ix1 << ", ix2 = " << ix2 << ", ix3 = " << ix3 << std::endl; + //} + } + } + } + } + } + +} + +double LiggghtsCouplingCoProcessor::calcSolidFraction(double const dx_, double const dy_, double const dz_, + double const r_) +{ + static int const slicesPerDim = 5; + static double const sliceWidth = 1. / ((double)slicesPerDim); + static double const fraction = 1. / ((double)(slicesPerDim * slicesPerDim * slicesPerDim)); + + // should be sqrt(3.)/2. + // add a little to avoid roundoff errors + static const double sqrt3half = (double)sqrt(3.1) / 2.; + + double const dist = dx_ * dx_ + dy_ * dy_ + dz_ * dz_; + + double const r_p = r_ + sqrt3half; + if (dist > r_p * r_p) + return 0; + + double const r_m = r_ - sqrt3half; + if (dist < r_m * r_m) + return 1; + + double const r_sq = r_ * r_; + double dx_sq[slicesPerDim], dy_sq[slicesPerDim], dz_sq[slicesPerDim]; + + // pre-calculate d[xyz]_sq for efficiency + for (int i = 0; i < slicesPerDim; i++) { + double const delta = -0.5 + ((double)i + 0.5) * sliceWidth; + double const dx = dx_ + delta; + dx_sq[i] = dx * dx; + double const dy = dy_ + delta; + dy_sq[i] = dy * dy; + double const dz = dz_ + delta; + dz_sq[i] = dz * dz; + } + + unsigned int n(0); + for (int i = 0; i < slicesPerDim; i++) { + for (int j = 0; j < slicesPerDim; j++) { + for (int k = 0; k < slicesPerDim; k++) { + n += (dx_sq[i] + dy_sq[j] + dz_sq[k] < r_sq); + } + } + } + + return fraction * ((double)n); +} + + void LiggghtsCouplingCoProcessor::setValues(IBdynamicsParticleData &p, int const id, double const sf, double const *v, double const dx, double const dy, double const dz, double const *omega) +{ + p.uPart[0] = v[0]; + p.uPart[1] = v[1]; + p.uPart[2] = v[2]; + + if (omega != 0) { + p.uPart[0] += omega[1] * dz - omega[2] * dy; + p.uPart[1] += -omega[0] * dz + omega[2] * dx; + p.uPart[2] += omega[0] * dy - omega[1] * dx; + } + p.solidFraction = sf; + p.partId = id; +} + + +void LiggghtsCouplingCoProcessor::setToZero(IBdynamicsParticleData &p) +{ + p.uPart[0] = 0; + p.uPart[1] = 0; + p.uPart[2] = 0; + p.solidFraction = 0; + p.partId = 0; +} + +void LiggghtsCouplingCoProcessor::getForcesFromLattice() +{ + static std::vector<double> force, torque; + static typename ParticleData::ParticleDataArrayVector x_lb; + + int const nPart = wrapper.lmp->atom->nlocal + wrapper.lmp->atom->nghost; + int const n_force = nPart * 3; + + if (nPart == 0) + return; // no particles - no work + + if (nPart > x_lb.size()) { + for (int iPart = 0; iPart < x_lb.size(); iPart++) { + x_lb[iPart][0] = wrapper.lmp->atom->x[iPart][0]; + x_lb[iPart][1] = wrapper.lmp->atom->x[iPart][1]; + x_lb[iPart][2] = wrapper.lmp->atom->x[iPart][2]; + } + for (int iPart = x_lb.size(); iPart < nPart; iPart++) { + std::array<double, 3> ar = {wrapper.lmp->atom->x[iPart][0], + wrapper.lmp->atom->x[iPart][1], + wrapper.lmp->atom->x[iPart][2]}; + x_lb.push_back(ar); + } + + + } else { + for (int iPart = 0; iPart < nPart; iPart++) { + x_lb[iPart][0] = wrapper.lmp->atom->x[iPart][0]; + x_lb[iPart][1] = wrapper.lmp->atom->x[iPart][1]; + x_lb[iPart][2] = wrapper.lmp->atom->x[iPart][2]; + } + } + + if (n_force > force.size()) { + for (int i = 0; i < force.size(); i++) { + force[i] = 0; + torque[i] = 0; + } + for (int i = force.size(); i < n_force; i++) { + force.push_back(0.); + torque.push_back(0.); + } + } else { + for (int i = 0; i < n_force; i++) { + force[i] = 0; + torque[i] = 0; + } + } + + SumForceTorque3D(x_lb, &force.front(), &torque.front()); + + LAMMPS_NS::FixLbCouplingOnetoone *couplingFix = + dynamic_cast<LAMMPS_NS::FixLbCouplingOnetoone *>(wrapper.lmp->modify->find_fix_style("couple/lb/onetoone", 0)); + + double **f_liggghts = couplingFix->get_force_ptr(); + double **t_liggghts = couplingFix->get_torque_ptr(); + + for (int iPart = 0; iPart < nPart; iPart++) + for (int j = 0; j < 3; j++) { + f_liggghts[iPart][j] = 0; + t_liggghts[iPart][j] = 0; + } + + for (int iPart = 0; iPart < nPart; iPart++) { + int tag = wrapper.lmp->atom->tag[iPart]; + int liggghts_ind = wrapper.lmp->atom->map(tag); + + for (int j = 0; j < 3; j++) { + f_liggghts[liggghts_ind][j] += force[3 * iPart + j] * units->getFactorForceLbToW(); + t_liggghts[liggghts_ind][j] += torque[3 * iPart + j] * units->getFactorTorqueLbToW(); + } + } + couplingFix->comm_force_torque(); +} + +void LiggghtsCouplingCoProcessor::SumForceTorque3D(ParticleData::ParticleDataArrayVector &x, double *force, double *torque) +{ + int nx = grid->getNX1(), ny = grid->getNX2(), nz = grid->getNX3(); + + std::vector < SPtr < Block3D > > blocks; + int level = 0; + grid->getBlocks(level, gridRank, true, blocks); + + + for (SPtr<Block3D> block : blocks) { + if (block) { + SPtr<ILBMKernel> kernel = block->getKernel(); + SPtr<DistributionArray3D> distributions = kernel->getDataSet()->getFdistributions(); + + CbArray3D<SPtr<IBdynamicsParticleData>, IndexerX3X2X1>::CbArray3DPtr particleData = + dynamicPointerCast<IBcumulantK17LBMKernel>(kernel)->getParticleData(); + + if (!particleData) + continue; + + int minX1 = 1; + int minX2 = 1; + int minX3 = 1; + + int maxX1 = (int)(distributions->getNX1()) - 1; + int maxX2 = (int)(distributions->getNX2()) - 1; + int maxX3 = (int)(distributions->getNX3()) - 1; + + for (int ix3 = minX3; ix3 < maxX3; ix3++) { + for (int ix2 = minX2; ix2 < maxX2; ix2++) { + for (int ix1 = minX1; ix1 < maxX1; ix1++) { + + // LIGGGHTS indices start at 1 + int const id = (*particleData)(ix1, ix2, ix3)->partId; + if (id < 1) + continue; // no particle here + + int const ind = wrapper.lmp->atom->map(id); + + Vector3D worldCoordinates = grid->getNodeCoordinates(block, ix1, ix2, ix3); + + double dx = (worldCoordinates[0] - x[ind][0]) * units->getFactorLentghWToLb(); + double dy = (worldCoordinates[1] - x[ind][1]) * units->getFactorLentghWToLb(); + double dz = (worldCoordinates[2] - x[ind][2]) * units->getFactorLentghWToLb(); + + // minimum image convention, needed if + // (1) PBC are used and + // (2) both ends of PBC lie on the same processor + if (dx > nx / 2) + dx -= nx; + else if (dx < -nx / 2) + dx += nx; + if (dy > ny / 2) + dy -= ny; + else if (dy < -ny / 2) + dy += ny; + if (dz > nz / 2) + dz -= nz; + else if (dz < -nz / 2) + dz += nz; + + double const forceX = (*particleData)(ix1, ix2, ix3)->hydrodynamicForce[0]; + double const forceY = (*particleData)(ix1, ix2, ix3)->hydrodynamicForce[1]; + double const forceZ = (*particleData)(ix1, ix2, ix3)->hydrodynamicForce[2]; + + double const torqueX = dy * forceZ - dz * forceY; + double const torqueY = -dx * forceZ + dz * forceX; + double const torqueZ = dx * forceY - dy * forceX; + + addForce(ind, 0, forceX, force); + addForce(ind, 1, forceY, force); + addForce(ind, 2, forceZ, force); + + addTorque(ind, 0, torqueX, torque); + addTorque(ind, 1, torqueY, torque); + addTorque(ind, 2, torqueZ, torque); + } + } + } + } + } + } + +void LiggghtsCouplingCoProcessor::addForce(int const partId, int const coord, double const value, double *force) +{ + force[3 * partId + coord] += value; +} + +void LiggghtsCouplingCoProcessor::addTorque(int const partId, int const coord, double const value, double *torque) +{ + torque[3 * partId + coord] += value; +} \ No newline at end of file diff --git a/src/cpu/LiggghtsCoupling/LiggghtsCouplingCoProcessor.h b/src/cpu/LiggghtsCoupling/LiggghtsCouplingCoProcessor.h new file mode 100644 index 0000000000000000000000000000000000000000..dcaa6e16c0a46a69d64998285119e86077500b6b --- /dev/null +++ b/src/cpu/LiggghtsCoupling/LiggghtsCouplingCoProcessor.h @@ -0,0 +1,104 @@ +//======================================================================================= +// ____ ____ __ ______ __________ __ __ __ __ +// \ \ | | | | | _ \ |___ ___| | | | | / \ | | +// \ \ | | | | | |_) | | | | | | | / \ | | +// \ \ | | | | | _ / | | | | | | / /\ \ | | +// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____ +// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______| +// \ \ | | ________________________________________________________________ +// \ \ | | | ______________________________________________________________| +// \ \| | | | __ __ __ __ ______ _______ +// \ | | |_____ | | | | | | | | | _ \ / _____) +// \ | | _____| | | | | | | | | | | \ \ \_______ +// \ | | | | |_____ | \_/ | | | | |_/ / _____ | +// \ _____| |__| |________| \_______/ |__| |______/ (_______/ +// +// This file is part of VirtualFluids. VirtualFluids 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. +// +// VirtualFluids 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 VirtualFluids (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file LiggghtsCouplingCoProcessor.h +//! \ingroup LiggghtsCoupling +//! \author Konstantin Kutscher +//======================================================================================= + +#ifndef LiggghtsCouplingCoProcessor_h +#define LiggghtsCouplingCoProcessor_h + +#include "CoProcessor.h" + +#include "lammps.h" +#include "input.h" +#include "atom.h" +#include "modify.h" + +#include <memory> +#include <vector> + + +class CoProcessor; +class Communicator; +class LiggghtsCouplingWrapper; +class Grid3D; +class Block3D; +struct IBdynamicsParticleData; +class LBMUnitConverter; + +struct ParticleData { + typedef typename std::vector<std::array<double, 3>> ParticleDataArrayVector; + typedef typename std::vector<double> ParticleDataScalarVector; +}; + +class LiggghtsCouplingCoProcessor : public CoProcessor +{ +public: + LiggghtsCouplingCoProcessor(SPtr<Grid3D> grid, SPtr<UbScheduler> s, SPtr<Communicator> comm, + LiggghtsCouplingWrapper &wrapper, int demSteps, SPtr<LBMUnitConverter> units); + virtual ~LiggghtsCouplingCoProcessor(); + + void process(double actualTimeStep) override; + + +protected: + void setSpheresOnLattice(); + + void setSingleSphere3D(double *x, double *v, double *omega, double r, int id /*, bool initVelFlag*/); + + double calcSolidFraction(double const dx_, double const dy_, double const dz_, double const r_); + + void setValues(IBdynamicsParticleData &p, int const id, double const sf, double const *v, double const dx, double const dy, double const dz, double const *omega); + + void setToZero(IBdynamicsParticleData &p); + + void getForcesFromLattice(); + + void SumForceTorque3D(ParticleData::ParticleDataArrayVector &x, double *force, double *torque); + + void addForce(int const partId, int const coord, double const value, double *force); + + void addTorque(int const partId, int const coord, double const value, double *torque); + +private: + SPtr<Communicator> comm; + LiggghtsCouplingWrapper &wrapper; + SPtr<LBMUnitConverter> units; + int demSteps; + //std::vector<std::vector<SPtr<Block3D>>> blockVector; + //int minInitLevel; + //int maxInitLevel; + int gridRank; + + double *force, *torque; +}; + +#endif + diff --git a/src/cpu/LiggghtsCoupling/LiggghtsCouplingWrapper.cpp b/src/cpu/LiggghtsCoupling/LiggghtsCouplingWrapper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9be87887a26d654d03dc8a32ed9e456ec352fef2 --- /dev/null +++ b/src/cpu/LiggghtsCoupling/LiggghtsCouplingWrapper.cpp @@ -0,0 +1,85 @@ +/* + * This file is part of the LBDEMcoupling software. + * + * LBDEMcoupling 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, version 3. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + * + * Copyright 2014 Johannes Kepler University Linz + * + * Author: Philippe Seil (philippe.seil@jku.at) + */ + +#include "LiggghtsCouplingWrapper.h" +#include "mpi.h" +#include <iostream> +#include <sstream> + +LiggghtsCouplingWrapper::LiggghtsCouplingWrapper(char **argv, MPI_Comm communicator) + : lmp(0) +{ + // todo: get LAMMPS to recognize command line options + int argc_lmp = 1; + char **argv_lmp = 0; + argv_lmp = new char*[1]; + argv_lmp[0] = argv[0]; + + lmp = new LAMMPS_NS::LAMMPS(argc_lmp,argv_lmp,communicator); + + // delete[] argv_lmp[0]; + delete[] argv_lmp; +} +void LiggghtsCouplingWrapper::execFile(char* const fname) +{ + lmp->input->file(fname); +} +void LiggghtsCouplingWrapper::execCommand(std::stringstream const &cmd) +{ + lmp->input->one(cmd.str().c_str()); +} +void LiggghtsCouplingWrapper::execCommand(char* const cmd) +{ + lmp->input->one(cmd); +} +int LiggghtsCouplingWrapper::getNumParticles() +{ + return lammps_get_natoms(lmp); +} +void LiggghtsCouplingWrapper::setVariable(char const *name, double value) +{ + std::stringstream cmd; + cmd << "variable " << name << " equal " << value; + std::cout << cmd.str() << std::endl; + execCommand(cmd); +} +void LiggghtsCouplingWrapper::setVariable(char const *name, std::string &value) +{ + std::stringstream cmd; + cmd << "variable " << name << " string " << value; + std::cout << cmd.str() << std::endl; + execCommand(cmd); +} +void LiggghtsCouplingWrapper::run(int nSteps) +{ + std::stringstream cmd; + cmd << "run " << nSteps; + execCommand(cmd); +} +void LiggghtsCouplingWrapper::runUpto(int nSteps) +{ + std::stringstream cmd; + cmd << "run " << nSteps << " upto"; + execCommand(cmd); +} + + + + diff --git a/src/cpu/LiggghtsCoupling/LiggghtsCouplingWrapper.h b/src/cpu/LiggghtsCoupling/LiggghtsCouplingWrapper.h new file mode 100644 index 0000000000000000000000000000000000000000..a745a7e967ee7852a11cd37452012951e421c347 --- /dev/null +++ b/src/cpu/LiggghtsCoupling/LiggghtsCouplingWrapper.h @@ -0,0 +1,47 @@ +/* + * This file is part of the LBDEMcoupling software. + * + * LBDEMcoupling 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, version 3. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + * + * Copyright 2014 Johannes Kepler University Linz + * + * Author: Philippe Seil (philippe.seil@jku.at) + */ + +#ifndef LIGGGHTSCOUPLINGWRAPPER_H +#define LIGGGHTSCOUPLINGWRAPPER_H + +// necessary LAMMPS/LIGGGHTS includes + +#include "lammps.h" +#include "input.h" +#include "library.h" +#include "library_cfd_coupling.h" + +class LiggghtsCouplingWrapper { +public: + LiggghtsCouplingWrapper(char **argv, MPI_Comm communicator); + void execFile(char* const fname); + void execCommand(std::stringstream const &cmd); + void execCommand(char* const cmd); + void run(int nSteps); + void runUpto(int nSteps); + int getNumParticles(); + void setVariable(char const *name, double value); + void setVariable(char const *name, std::string &value); + + //private: + LAMMPS_NS::LAMMPS *lmp; +}; + +#endif /* LIGGGHTSCOUPLINGWRAPPER_H */ diff --git a/src/cpu/VirtualFluidsCore/CMakeLists.txt b/src/cpu/VirtualFluidsCore/CMakeLists.txt index 15cdceffd99515f84d60c4b6169e2da7e74ecfc3..5abe76be9ed986d773785a544eb1e29b9954944d 100644 --- a/src/cpu/VirtualFluidsCore/CMakeLists.txt +++ b/src/cpu/VirtualFluidsCore/CMakeLists.txt @@ -16,7 +16,6 @@ IF(${USE_CATALYST}) list(APPEND VF_LIBRARIES optimized vtkParallelMPI debug vtkParallelMPI ) ENDIF() - IF(${USE_DEM_COUPLING}) INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/../DemCoupling/DemCoupling.cmake) ENDIF() @@ -27,6 +26,11 @@ endif() vf_add_library(BUILDTYPE static PUBLIC_LINK basics muparser ${VF_LIBRARIES} PRIVATE_LINK lbm mpi logger) +IF(${USE_LIGGGHTS}) + list(APPEND VF_LIBRARIES optimized ${LIGGGHTS_RELEASE_LIBRARY} debug ${LIGGGHTS_DEBUG_LIBRARY}) +ENDIF() + +vf_add_library(BUILDTYPE static PUBLIC_LINK basics muparser MPI::MPI_CXX ${VF_LIBRARIES}) vf_get_library_name(library_name) @@ -47,6 +51,12 @@ IF(${USE_METIS} AND METIS_INCLUDEDIR) ENDIF() target_include_directories(${library_name} PRIVATE ${ZOLTAN_INCLUDEDIR}) + IF(${USE_VTK}) target_include_directories(${library_name} PRIVATE ${VTK_INCLUDE_DIRS}) ENDIF() + +IF(${USE_LIGGGHTS}) + target_include_directories(${library_name} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../LiggghtsCoupling) + target_include_directories(${library_name} PUBLIC ${LIGGGHTS_SOURCE_DIR}) +ENDIF() \ No newline at end of file diff --git a/src/cpu/VirtualFluidsCore/CoProcessors/InSituVTKCoProcessor.cpp b/src/cpu/VirtualFluidsCore/CoProcessors/InSituVTKCoProcessor.cpp index 73c0a2325953994c337934347e872223ba18452a..ed258864a4a87b473ca276064abf60ad5910828d 100644 --- a/src/cpu/VirtualFluidsCore/CoProcessors/InSituVTKCoProcessor.cpp +++ b/src/cpu/VirtualFluidsCore/CoProcessors/InSituVTKCoProcessor.cpp @@ -226,11 +226,11 @@ void InSituVTKCoProcessor::addData(SPtr<Block3D> block) UbSystem::toString(ix2) + "," + UbSystem::toString(ix3))); // vx3=999.0; - arrays[0]->InsertNextValue(rho * conv->getFactorDensityLbToW2()); - arrays[1]->InsertNextValue(vx1 * conv->getFactorVelocityLbToW2()); - arrays[2]->InsertNextValue(vx2 * conv->getFactorVelocityLbToW2()); - arrays[3]->InsertNextValue(vx3 * conv->getFactorVelocityLbToW2()); - arrays[4]->InsertNextValue(press * conv->getFactorPressureLbToW2()); + arrays[0]->InsertNextValue(rho * conv->getFactorDensityLbToW()); + arrays[1]->InsertNextValue(vx1 * conv->getFactorVelocityLbToW()); + arrays[2]->InsertNextValue(vx2 * conv->getFactorVelocityLbToW()); + arrays[3]->InsertNextValue(vx3 * conv->getFactorVelocityLbToW()); + arrays[4]->InsertNextValue(press * conv->getFactorPressureLbToW()); } } } diff --git a/src/cpu/VirtualFluidsCore/LBM/LBMUnitConverter.h b/src/cpu/VirtualFluidsCore/LBM/LBMUnitConverter.h index 40570cc3847f71a1942791afa7e95145daafb53b..7c4ef7372c3126378c8fbe258b5914cafae5500b 100644 --- a/src/cpu/VirtualFluidsCore/LBM/LBMUnitConverter.h +++ b/src/cpu/VirtualFluidsCore/LBM/LBMUnitConverter.h @@ -97,14 +97,6 @@ public: this->init(refLengthWorld, csWorld, rhoWorld, csWorld, refLengthLb, rhoLb, csLb); } - LBMUnitConverter(int /*dummy*/, double uReal, double uLB, double nuReal, double nuLB) - { - factorVelocityLbToW = uReal / uLB; - factorViscosityLbToW = nuReal / nuLB; - factorDensityLbToW = factorViscosityLbToW * factorVelocityLbToW * factorVelocityLbToW; - factorPressureLbToW = factorDensityLbToW; - } - virtual ~LBMUnitConverter() = default; double getRefRhoLb() { return refRhoLb; } @@ -124,10 +116,7 @@ public: double getFactorDensityLbToW() { return this->factorMassLbToW / std::pow(factorLengthLbToW, 3.0); } double getFactorDensityWToLb() { return 1.0 / this->getFactorDensityLbToW(); } - double getFactorPressureLbToW() - { - return this->factorMassLbToW / (std::pow(factorTimeLbToW, 2.0) * factorLengthLbToW); - } + double getFactorPressureLbToW(){ return this->factorMassLbToW / (factorLengthLbToW * factorTimeLbToW * factorTimeLbToW); } double getFactorPressureWToLb() { return 1.0 / this->getFactorPressureLbToW(); } double getFactorMassLbToW() { return this->factorMassLbToW; } @@ -136,14 +125,14 @@ public: double getFactorForceLbToW() { return factorMassLbToW * factorLengthLbToW / (factorTimeLbToW * factorTimeLbToW); } double getFactorForceWToLb() { return 1.0 / this->getFactorForceLbToW(); } + double getFactorTorqueLbToW() { return factorMassLbToW * factorLengthLbToW * factorLengthLbToW / (factorTimeLbToW * factorTimeLbToW);} + double getFactorTorqueWToLb() { return 1.0 / this->getFactorTorqueWToLb(); } + double getFactorAccLbToW() { return factorLengthLbToW / (factorTimeLbToW * factorTimeLbToW); } double getFactorAccWToLb() { return 1.0 / this->getFactorAccLbToW(); } double getFactorTimeLbToW(double deltaX) const { return factorTimeWithoutDx * deltaX; } - ////////////////////////////////////////////////////////////////////////// - double getFactorVelocityLbToW2() { return factorVelocityLbToW; } - double getFactorDensityLbToW2() { return factorDensityLbToW; } - double getFactorPressureLbToW2() { return factorPressureLbToW; } + /*==========================================================*/ friend inline std::ostream &operator<<(std::ostream &os, LBMUnitConverter c) @@ -212,11 +201,6 @@ protected: double factorMassLbToW{ 1.0 }; double refRhoLb{ 1.0 }; double factorTimeWithoutDx{ 0.0 }; - - double factorVelocityLbToW{ 1.0 }; - double factorViscosityLbToW{ 1.0 }; - double factorDensityLbToW{ 1.0 }; - double factorPressureLbToW{ 1.0 }; }; #endif // LBMUNITCONVERTER_H