merge from main

This commit is contained in:
HRN
2025-01-10 12:37:42 +03:30
682 changed files with 73362 additions and 20501 deletions

6
.gitignore vendored
View File

@ -1,6 +1,12 @@
# files
.clang-format
.vscode
.dependencygraph
# Prerequisites # Prerequisites
*.d *.d
# Compiled Object files # Compiled Object files
*.slo *.slo
*.lo *.lo

View File

@ -1,75 +1,73 @@
cmake_minimum_required(VERSION 3.16 FATAL_ERROR) cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
# set the project name and version # set the project name and version
project(phasicFlow VERSION 0.1 ) project(phasicFlow VERSION 1.0 )
set(CMAKE_CXX_STANDARD 17 CACHE STRING "" FORCE) set(CMAKE_CXX_STANDARD 17 CACHE STRING "" FORCE)
set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_INSTALL_PREFIX ${phasicFlow_SOURCE_DIR} CACHE PATH "Install path of phasicFlow" FORCE) set(CMAKE_INSTALL_PREFIX ${phasicFlow_SOURCE_DIR} CACHE PATH "Install path of phasicFlow" FORCE)
set(CMAKE_BUILD_TYPE Release CACHE STRING "build type" FORCE) set(CMAKE_BUILD_TYPE Debug CACHE STRING "build type" FORCE)
set(BUILD_SHARED_LIBS ON CACHE BOOL "Build using shared libraries" FORCE)
mark_as_advanced(FORCE var BUILD_SHARED_LIBS)
message(STATUS ${CMAKE_INSTALL_PREFIX}) message(STATUS ${CMAKE_INSTALL_PREFIX})
mark_as_advanced(FORCE var Kokkos_ENABLE_CUDA_LAMBDA) include(cmake/globals.cmake)
mark_as_advanced(FORCE var Kokkos_ENABLE_OPENMP)
mark_as_advanced(FORCE var Kokkos_ENABLE_SERIAL)
mark_as_advanced(FORCE var Kokkos_ENABLE_CUDA_LAMBDA)
mark_as_advanced(FORCE var BUILD_SHARED_LIBS)
option(USE_STD_PARALLEL_ALG "Use TTB std parallel algorithms" ON) #Kokkos directory to be included
set(Kokkos_Source_DIR)
if(DEFINED ENV{Kokkos_DIR})
set(Kokkos_Source_DIR $ENV{Kokkos_DIR})
else()
set(Kokkos_Source_DIR $ENV{HOME}/Kokkos/kokkos)
endif()
message(STATUS "Kokkos source directory is ${Kokkos_Source_DIR}")
add_subdirectory(${Kokkos_Source_DIR} ./kokkos)
Kokkos_cmake_settings()
option(pFlow_STD_Parallel_Alg "Use TTB std parallel algorithms" ON)
option(pFlow_Build_Serial "Build phasicFlow and backends for serial execution" OFF) option(pFlow_Build_Serial "Build phasicFlow and backends for serial execution" OFF)
option(pFlow_Build_OpenMP "Build phasicFlow and backends for OpenMP execution" OFF) option(pFlow_Build_OpenMP "Build phasicFlow and backends for OpenMP execution" OFF)
option(pFlow_Build_Cuda "Build phasicFlow and backends for Cuda execution" OFF) option(pFlow_Build_Cuda "Build phasicFlow and backends for Cuda execution" OFF)
option(pFlow_Build_Double "Build phasicFlow with double precision variables" ON) option(pFlow_Build_Double "Build phasicFlow with double precision floating-oint variables" ON)
option(pFlow_Build_MPI "Build for MPI parallelization. This will enable multi-gpu run, CPU run on clusters (distributed memory machine). Use this combination Cuda+MPI, OpenMP + MPI or Serial+MPI " OFF)
set(BUILD_SHARED_LIBS ON CACHE BOOL "Build using shared libraries" FORCE)
if(pFlow_Build_Serial) if(pFlow_Build_Serial)
set(Kokkos_ENABLE_SERIAL ON CACHE BOOL "Serial execution" FORCE) set(Kokkos_ENABLE_SERIAL ON CACHE BOOL "Serial execution" FORCE)
set(Kokkos_ENABLE_OPENMP OFF CACHE BOOL "OpenMP execution" FORCE) set(Kokkos_ENABLE_OPENMP OFF CACHE BOOL "OpenMP execution" FORCE)
set(Kokkos_ENABLE_CUDA OFF CACHE BOOL "Cuda execution" FORCE) set(Kokkos_ENABLE_CUDA OFF CACHE BOOL "Cuda execution" FORCE)
set(Kokkos_ENABLE_CUDA_LAMBDA OFF CACHE BOOL "Cuda execution" FORCE) set(Kokkos_ENABLE_CUDA_LAMBDA OFF CACHE BOOL "Cuda execution" FORCE)
set(Kokkos_ENABLE_CUDA_CONSTEXPR OFF CACHE BOOL "Enable constexpr on cuda code" FORCE)
elseif(pFlow_Build_OpenMP ) elseif(pFlow_Build_OpenMP )
set(Kokkos_ENABLE_SERIAL ON CACHE BOOL "Serial execution" FORCE) set(Kokkos_ENABLE_SERIAL ON CACHE BOOL "Serial execution" FORCE)
set(Kokkos_ENABLE_OPENMP ON CACHE BOOL "OpenMP execution" FORCE) set(Kokkos_ENABLE_OPENMP ON CACHE BOOL "OpenMP execution" FORCE)
set(Kokkos_ENABLE_CUDA OFF CACHE BOOL "Cuda execution" FORCE) set(Kokkos_ENABLE_CUDA OFF CACHE BOOL "Cuda execution" FORCE)
set(Kokkos_ENABLE_CUDA_LAMBDA OFF CACHE BOOL "Cuda execution" FORCE) set(Kokkos_ENABLE_CUDA_LAMBDA OFF CACHE BOOL "Cuda execution" FORCE)
set(Kokkos_DEFAULT_HOST_PARALLEL_EXECUTION_SPACE SERIAL CACHE STRING "" FORCE) set(Kokkos_DEFAULT_HOST_PARALLEL_EXECUTION_SPACE SERIAL CACHE STRING "" FORCE)
set(Kokkos_ENABLE_CUDA_CONSTEXPR OFF CACHE BOOL "Enable constexpr on cuda code" FORCE)
elseif(pFlow_Build_Cuda) elseif(pFlow_Build_Cuda)
set(Kokkos_ENABLE_SERIAL ON CACHE BOOL "Serial execution" FORCE) set(Kokkos_ENABLE_SERIAL ON CACHE BOOL "Serial execution" FORCE)
set(Kokkos_ENABLE_OPENMP OFF CACHE BOOL "OpenMP execution" FORCE) set(Kokkos_ENABLE_OPENMP OFF CACHE BOOL "OpenMP execution" FORCE)
set(Kokkos_ENABLE_CUDA ON CACHE BOOL "Cuda execution" FORCE) set(Kokkos_ENABLE_CUDA ON CACHE BOOL "Cuda execution" FORCE)
set(Kokkos_ENABLE_CUDA_LAMBDA ON CACHE BOOL "Cuda execution" FORCE) set(Kokkos_ENABLE_CUDA_LAMBDA ON CACHE BOOL "Cuda execution" FORCE)
set(Kokkos_ENABLE_CUDA_CONSTEXPR ON CACHE BOOL "Enable constexpr on cuda code" FORCE)
endif() endif()
if(pFlow_Build_MPI)
find_package(MPI REQUIRED)
include(cmake/globals.cmake) endif()
message(STATUS "Valid file extensions are ${validFiles}")
include(cmake/makeLibraryGlobals.cmake) include(cmake/makeLibraryGlobals.cmake)
include(cmake/makeExecutableGlobals.cmake) include(cmake/makeExecutableGlobals.cmake)
configure_file(phasicFlowConfig.H.in phasicFlowConfig.H) configure_file(phasicFlowConfig.H.in phasicFlowConfig.H)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
#add a global include directory #add a global include directory
include_directories(src/setHelpers src/demComponent "${PROJECT_BINARY_DIR}") include_directories(src/setHelpers src/demComponent "${PROJECT_BINARY_DIR}")
#main subdirectories of the code
set(Kokkos_Source_DIR)
if(DEFINED ENV{Kokkos_DIR})
set(Kokkos_Source_DIR $ENV{Kokkos_DIR})
# add_subdirectory($ENV{Kokkos_DIR} ${phasicFlow_BINARY_DIR}/kokkos)
# message(STATUS "Kokkos directory is $ENV{Kokkos_DIR}")
else()
# add_subdirectory($ENV{HOME}/Kokkos/kokkos ${phasicFlow_BINARY_DIR}/kokkos)
set(Kokkos_Source_DIR $ENV{HOME}/Kokkos/kokkos)
endif()
message(STATUS "Kokkos source directory is ${Kokkos_Source_DIR}")
add_subdirectory(${Kokkos_Source_DIR} ${phasicFlow_BINARY_DIR}/kokkos)
add_subdirectory(src) add_subdirectory(src)
add_subdirectory(solvers) add_subdirectory(solvers)
@ -77,12 +75,9 @@ add_subdirectory(solvers)
add_subdirectory(utilities) add_subdirectory(utilities)
add_subdirectory(DEMSystems) add_subdirectory(DEMSystems)
#add_subdirectory(testIO)
install(FILES "${PROJECT_BINARY_DIR}/phasicFlowConfig.H" install(FILES "${PROJECT_BINARY_DIR}/phasicFlowConfig.H"
DESTINATION include DESTINATION include)
)
include(InstallRequiredSystemLibraries) include(InstallRequiredSystemLibraries)
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")

View File

@ -1,9 +1,11 @@
set(SourceFiles set(SourceFiles
DEMSystem/DEMSystem.cpp
sphereDEMSystem/sphereDEMSystem.cpp
sphereDEMSystem/sphereFluidParticles.cpp
domainDistribute/domainDistribute.cpp domainDistribute/domainDistribute.cpp
DEMSystem/DEMSystem.cpp
sphereDEMSystem/sphereFluidParticles.cpp
sphereDEMSystem/sphereDEMSystem.cpp
grainDEMSystem/grainFluidParticles.cpp
grainDEMSystem/grainDEMSystem.cpp
) )
set(link_libs Kokkos::kokkos phasicFlow Particles Geometry Property Interaction Interaction Utilities) set(link_libs Kokkos::kokkos phasicFlow Particles Geometry Property Interaction Interaction Utilities)

View File

@ -34,13 +34,13 @@ pFlow::DEMSystem::DEMSystem(
{ {
REPORT(0)<<"Initializing host/device execution spaces . . . \n"; REPORT(0)<<"Initializing host/device execution spaces . . . \n";
REPORT(1)<<"Host execution space is "<< greenText(DefaultHostExecutionSpace::name())<<endREPORT; REPORT(1)<<"Host execution space is "<< Green_Text(DefaultHostExecutionSpace::name())<<END_REPORT;
REPORT(1)<<"Device execution space is "<<greenText(DefaultExecutionSpace::name())<<endREPORT; REPORT(1)<<"Device execution space is "<<Green_Text(DefaultExecutionSpace::name())<<END_REPORT;
// initialize Kokkos // initialize Kokkos
Kokkos::initialize( argc, argv ); Kokkos::initialize( argc, argv );
REPORT(0)<<"\nCreating Control repository . . ."<<endREPORT; REPORT(0)<<"\nCreating Control repository . . ."<<END_REPORT;
Control_ = makeUnique<systemControl>( Control_ = makeUnique<systemControl>(
ControlDict_.startTime(), ControlDict_.startTime(),
ControlDict_.endTime(), ControlDict_.endTime(),
@ -87,4 +87,3 @@ pFlow::uniquePtr<pFlow::DEMSystem>
return nullptr; return nullptr;
} }

View File

@ -25,6 +25,7 @@ Licence:
#include "types.hpp" #include "types.hpp"
#include "span.hpp" #include "span.hpp"
#include "box.hpp"
#include "virtualConstructor.hpp" #include "virtualConstructor.hpp"
#include "uniquePtr.hpp" #include "uniquePtr.hpp"
#include "systemControl.hpp" #include "systemControl.hpp"
@ -60,6 +61,7 @@ public:
DEMSystem(const DEMSystem&)=delete; DEMSystem(const DEMSystem&)=delete;
/// @brief no assignment
DEMSystem& operator = (const DEMSystem&)=delete; DEMSystem& operator = (const DEMSystem&)=delete;
create_vCtor( create_vCtor(
@ -111,19 +113,34 @@ public:
int32 numParInDomain(int32 di)const = 0; int32 numParInDomain(int32 di)const = 0;
virtual virtual
std::vector<int32> numParInDomain()const = 0; std::vector<int32> numParInDomains()const = 0;
virtual virtual
span<const int32> parIndexInDomain(int32 di)const = 0; span<const int32> parIndexInDomain(int32 domIndx)const = 0;
virtual virtual
span<real> parDiameter() = 0; span<real> diameter() = 0;
virtual virtual
span<realx3> parVelocity() = 0; span<real> courseGrainFactor() = 0;
virtual virtual
span<realx3> parPosition() = 0; span<realx3> acceleration()=0;
virtual
span<realx3> velocity() = 0;
virtual
span<realx3> position() = 0;
virtual
span<realx3> rAcceleration()=0;
virtual
span<realx3> rVelocity() = 0;
virtual
span<realx3> rPosition() = 0;
virtual virtual
span<realx3> parFluidForce() = 0; span<realx3> parFluidForce() = 0;
@ -153,7 +170,6 @@ public:
bool iterate(real upToTime) = 0; bool iterate(real upToTime) = 0;
static static
uniquePtr<DEMSystem> uniquePtr<DEMSystem>
create( create(
@ -162,8 +178,6 @@ public:
int argc, int argc,
char* argv[]); char* argv[]);
}; };

View File

@ -33,7 +33,7 @@ void pFlow::domainDistribute::clcDomains(const std::vector<box>& domains)
pFlow::domainDistribute::domainDistribute( pFlow::domainDistribute::domainDistribute(
const Vector<box>& domains, const std::vector<box>& domains,
real maxBoundingBox) real maxBoundingBox)
: :
numDomains_(domains.size()), numDomains_(domains.size()),
@ -47,10 +47,10 @@ maxBoundingBoxSize_(maxBoundingBox)
} }
bool pFlow::domainDistribute::locateParticles( bool pFlow::domainDistribute::locateParticles(
ViewType1D<realx3,HostSpace> points, includeMask mask) ViewType1D<realx3,HostSpace> points, const pFlagTypeHost& mask)
{ {
range activeRange = mask.activeRange(); const rangeU32 activeRange = mask.activeRange();
for(int32 di=0; di<numDomains_; di++) for(int32 di=0; di<numDomains_; di++)
@ -59,7 +59,7 @@ bool pFlow::domainDistribute::locateParticles(
} }
for(int32 i=activeRange.first; i<activeRange.second; i++) for(int32 i=activeRange.start(); i<activeRange.end(); i++)
{ {
if(mask(i)) if(mask(i))
{ {

View File

@ -43,19 +43,16 @@ protected:
int32Vector_H numParInDomain_; int32Vector_H numParInDomain_;
real maxBoundingBoxSize_; real maxBoundingBoxSize_;
real domainExtension_ = 1.0; real domainExtension_ = 1.0;
using includeMask = typename pointStructure::activePointsHost;
void clcDomains(const std::vector<box>& domains); void clcDomains(const std::vector<box>& domains);
public: public:
domainDistribute( domainDistribute(
const Vector<box>& domains, const std::vector<box>& domains,
real maxBoundingBox); real maxBoundingBox);
~domainDistribute()=default; ~domainDistribute()=default;
@ -78,7 +75,7 @@ public:
{ {
return return
span<const int32>( span<const int32>(
particlesInDomains_[di].hostVectorAll().data(), particlesInDomains_[di].hostViewAll().data(),
numParInDomain_[di] numParInDomain_[di]
); );
} }
@ -91,7 +88,7 @@ public:
//template<typename includeMask> //template<typename includeMask>
bool locateParticles( bool locateParticles(
ViewType1D<realx3,HostSpace> points, includeMask mask); ViewType1D<realx3,HostSpace> points, const pFlagTypeHost& mask);
}; };

View File

@ -0,0 +1,268 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
#include "grainDEMSystem.hpp"
#include "vocabs.hpp"
bool pFlow::grainDEMSystem::loop()
{
do
{
//
if(! insertion_().insertParticles(
Control().time().currentIter(),
Control().time().currentTime(),
Control().time().dt() ) )
{
fatalError<<
"particle insertion failed in grainDEMSystem.\n";
return false;
}
geometry_->beforeIteration();
interaction_->beforeIteration();
particles_->beforeIteration();
interaction_->iterate();
particles_->iterate();
geometry_->iterate();
particles_->afterIteration();
geometry_->afterIteration();
}while(Control()++);
return true;
}
pFlow::grainDEMSystem::grainDEMSystem(
word demSystemName,
const std::vector<box>& domains,
int argc,
char* argv[],
bool requireRVel)
:
DEMSystem(demSystemName, domains, argc, argv),
requireRVel_(requireRVel)
{
REPORT(0)<<"\nReading proprties . . . "<<END_REPORT;
property_ = makeUnique<property>(
propertyFile__,
Control().caseSetup().path());
REPORT(0)<< "\nCreating surface geometry for grainDEMSystem . . . "<<END_REPORT;
geometry_ = geometry::create(Control(), Property());
REPORT(0)<<"\nReading grain particles . . ."<<END_REPORT;
particles_ = makeUnique<grainFluidParticles>(Control(), Property());
insertion_ = makeUnique<grainInsertion>(
particles_(),
particles_().grains());
REPORT(0)<<"\nCreating interaction model for grain-grain contact and grain-wall contact . . ."<<END_REPORT;
interaction_ = interaction::create(
Control(),
Particles(),
Geometry());
auto maxD = maxBounndingSphereSize();
particleDistribution_ = makeUnique<domainDistribute>(domains, maxD);
}
pFlow::grainDEMSystem::~grainDEMSystem()
{
}
bool pFlow::grainDEMSystem::updateParticleDistribution(
real extentFraction,
const std::vector<box> domains)
{
if(!particleDistribution_->changeDomainsSize(
extentFraction,
maxBounndingSphereSize(),
domains))
{
fatalErrorInFunction<<
"cannot change the domain size"<<endl;
return false;
}
if(!particleDistribution_->locateParticles(
positionHost_,
particles_->pStruct().activePointsMaskHost()))
{
fatalErrorInFunction<<
"error in locating particles among sub-domains"<<endl;
return false;
}
return true;
}
pFlow::int32
pFlow::grainDEMSystem::numParInDomain(int32 di)const
{
return particleDistribution_().numParInDomain(di);
}
std::vector<pFlow::int32>
pFlow::grainDEMSystem::numParInDomains()const
{
const auto& distribute = particleDistribution_();
int32 numDomains = distribute.numDomains();
std::vector<int32> nums(numDomains);
for(int32 i=0; i<numDomains; i++)
{
nums[i] = distribute.numParInDomain(i);
}
return nums;
}
pFlow::span<const pFlow::int32>
pFlow::grainDEMSystem::parIndexInDomain(int32 di)const
{
return particleDistribution_->particlesInDomain(di);
}
pFlow::span<pFlow::real> pFlow::grainDEMSystem::diameter()
{
return span<real>(diameterHost_.data(), diameterHost_.size());
}
pFlow::span<pFlow::real> pFlow::grainDEMSystem::courseGrainFactor()
{
return span<real>(particles_->courseGrainFactorHost().data(), particles_->courseGrainFactorHost().size());
}
pFlow::span<pFlow::realx3> pFlow::grainDEMSystem::acceleration()
{
return span<realx3>(nullptr, 0);
}
pFlow::span<pFlow::realx3> pFlow::grainDEMSystem::velocity()
{
return span<realx3>(velocityHost_.data(), velocityHost_.size());
}
pFlow::span<pFlow::realx3> pFlow::grainDEMSystem::position()
{
return span<realx3>(positionHost_.data(), positionHost_.size());
}
pFlow::span<pFlow::realx3> pFlow::grainDEMSystem::rAcceleration()
{
return span<realx3>(nullptr, 0);
}
pFlow::span<pFlow::realx3> pFlow::grainDEMSystem::rVelocity()
{
return span<realx3>(rVelocityHost_.data(), rVelocityHost_.size());
}
pFlow::span<pFlow::realx3> pFlow::grainDEMSystem::rPosition()
{
return span<realx3>(nullptr, 0);
}
pFlow::span<pFlow::realx3> pFlow::grainDEMSystem::parFluidForce()
{
auto& hVec = particles_->fluidForceHost();
return span<realx3>(hVec.data(), hVec.size());
}
pFlow::span<pFlow::realx3> pFlow::grainDEMSystem::parFluidTorque()
{
auto& hVec = particles_->fluidTorqueHost();
return span<realx3>(hVec.data(), hVec.size());
}
bool pFlow::grainDEMSystem::sendFluidForceToDEM()
{
particles_->fluidForceHostUpdatedSync();
return true;
}
bool pFlow::grainDEMSystem::sendFluidTorqueToDEM()
{
particles_->fluidTorqueHostUpdatedSync();
return true;
}
bool pFlow::grainDEMSystem::beforeIteration()
{
velocityHost_ = std::as_const(particles_()).velocity().hostView();
positionHost_ = std::as_const(particles_()).pointPosition().hostView();
diameterHost_ = particles_->diameter().hostView();
if(requireRVel_)
rVelocityHost_ = std::as_const(particles_()).rVelocity().hostView();
return true;
}
bool pFlow::grainDEMSystem::iterate(
real upToTime,
real timeToWrite,
word timeName)
{
Control().time().setStopAt(upToTime);
Control().time().setOutputToFile(timeToWrite, timeName);
return loop();
return true;
}
bool pFlow::grainDEMSystem::iterate(real upToTime)
{
Control().time().setStopAt(upToTime);
return loop();
return true;
}
pFlow::real
pFlow::grainDEMSystem::maxBounndingSphereSize()const
{
real minD, maxD;
particles_->boundingSphereMinMax(minD, maxD);
return maxD;
}

View File

@ -0,0 +1,163 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
#ifndef __grainDEMSystem_hpp__
#define __grainDEMSystem_hpp__
#include "DEMSystem.hpp"
#include "property.hpp"
#include "uniquePtr.hpp"
#include "geometry.hpp"
#include "grainFluidParticles.hpp"
#include "interaction.hpp"
#include "Insertions.hpp"
#include "domainDistribute.hpp"
namespace pFlow
{
class grainDEMSystem
:
public DEMSystem
{
protected:
// protected members
uniquePtr<property> property_ = nullptr;
uniquePtr<geometry> geometry_ = nullptr;
uniquePtr<grainFluidParticles> particles_ = nullptr;
uniquePtr<grainInsertion> insertion_ = nullptr;
uniquePtr<interaction> interaction_ = nullptr;
uniquePtr<domainDistribute> particleDistribution_=nullptr;
// to be used for CPU communications
ViewType1D<realx3, HostSpace> velocityHost_;
ViewType1D<realx3, HostSpace> positionHost_;
ViewType1D<real, HostSpace> diameterHost_;
bool requireRVel_ = false;
ViewType1D<realx3, HostSpace> rVelocityHost_;
// protected member functions
auto& Property()
{
return property_();
}
auto& Geometry()
{
return geometry_();
}
auto& Particles()
{
return particles_();
}
auto& Interaction()
{
return interaction_();
}
bool loop();
public:
TypeInfo("grainDEMSystem");
grainDEMSystem(
word demSystemName,
const std::vector<box>& domains,
int argc,
char* argv[],
bool requireRVel=false);
virtual ~grainDEMSystem();
grainDEMSystem(const grainDEMSystem&)=delete;
grainDEMSystem& operator = (const grainDEMSystem&)=delete;
add_vCtor(
DEMSystem,
grainDEMSystem,
word);
bool updateParticleDistribution(real extentFraction, const std::vector<box> domains) override;
int32 numParInDomain(int32 di)const override;
std::vector<int32> numParInDomains()const override;
span<const int32> parIndexInDomain(int32 di)const override;
span<real> diameter() override;
span<real> courseGrainFactor() override;
span<realx3> acceleration() override;
span<realx3> velocity() override;
span<realx3> position() override;
span<realx3> rAcceleration() override;
span<realx3> rVelocity() override;
span<realx3> rPosition() override;
span<realx3> parFluidForce() override;
span<realx3> parFluidTorque() override;
bool sendFluidForceToDEM() override;
bool sendFluidTorqueToDEM() override;
bool beforeIteration() override;
bool iterate(
real upToTime,
real timeToWrite,
word timeName) override;
bool iterate(real upToTime) override;
real maxBounndingSphereSize()const override;
};
} // pFlow
#endif

View File

@ -0,0 +1,107 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
#include "grainFluidParticles.hpp"
#include "grainFluidParticlesKernels.hpp"
void pFlow::grainFluidParticles::checkHostMemory()
{
if(fluidForce_.size()!=fluidForceHost_.size())
{
resizeNoInit(fluidForceHost_, fluidForce_.size());
resizeNoInit(fluidTorqueHost_, fluidTorque_.size());
}
// copy the data (if required) from device to host
courseGrainFactorHost_ = coarseGrainFactor().hostView();
}
pFlow::grainFluidParticles::grainFluidParticles(
systemControl &control,
const property &prop)
: grainParticles(control, prop),
fluidForce_(
objectFile(
"fluidForce",
"",
objectFile::READ_IF_PRESENT,
objectFile::WRITE_ALWAYS),
dynPointStruct(),
zero3),
fluidTorque_(
objectFile(
"fluidTorque",
"",
objectFile::READ_IF_PRESENT,
objectFile::WRITE_NEVER),
dynPointStruct(),
zero3)
{
checkHostMemory();
}
bool pFlow::grainFluidParticles::beforeIteration()
{
grainParticles::beforeIteration();
checkHostMemory();
return true;
}
bool pFlow::grainFluidParticles::iterate()
{
accelerationTimer().start();
pFlow::grainFluidParticlesKernels::acceleration(
control().g(),
mass().deviceViewAll(),
contactForce().deviceViewAll(),
fluidForce_.deviceViewAll(),
I().deviceViewAll(),
contactTorque().deviceViewAll(),
fluidTorque_.deviceViewAll(),
pStruct().activePointsMaskDevice(),
accelertion().deviceViewAll(),
rAcceleration().deviceViewAll()
);
accelerationTimer().end();
intCorrectTimer().start();
dynPointStruct().correct(this->dt(), accelertion());
rVelIntegration().correct(this->dt(), rVelocity(), rAcceleration());
intCorrectTimer().end();
return true;
}
void pFlow::grainFluidParticles::fluidForceHostUpdatedSync()
{
copy(fluidForce_.deviceView(), fluidForceHost_);
return;
}
void pFlow::grainFluidParticles::fluidTorqueHostUpdatedSync()
{
copy(fluidTorque_.deviceView(), fluidTorqueHost_);
return;
}

View File

@ -0,0 +1,105 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
/*!
@class pFlow::grainFluidParticles
@brief Class for managing grain particles with fluid interactions
This is a top-level class that contains the essential components for
defining grain prticles with fluid interactions in a DEM simulation.
*/
#ifndef __grainFluidParticles_hpp__
#define __grainFluidParticles_hpp__
#include "grainParticles.hpp"
namespace pFlow
{
class grainFluidParticles
:
public grainParticles
{
protected:
/// pointField of rotational acceleration of particles on device
realx3PointField_D fluidForce_;
hostViewType1D<realx3> fluidForceHost_;
realx3PointField_D fluidTorque_;
hostViewType1D<realx3> fluidTorqueHost_;
hostViewType1D<real> courseGrainFactorHost_;
void checkHostMemory();
public:
/// construct from systemControl and property
grainFluidParticles(systemControl &control, const property& prop);
~grainFluidParticles() override = default;
/// before iteration step
bool beforeIteration() override;
/// iterate particles
bool iterate() override;
auto& fluidForce()
{
return fluidForce_;
}
auto& fluidTorque()
{
return fluidTorque_;
}
auto& fluidForceHost()
{
return fluidForceHost_;
}
auto& fluidTorqueHost()
{
return fluidTorqueHost_;
}
auto& courseGrainFactorHost()
{
return courseGrainFactorHost_;
}
void fluidForceHostUpdatedSync();
void fluidTorqueHostUpdatedSync();
}; //grainFluidParticles
} // pFlow
#endif //__sphereFluidParticles_hpp__

View File

@ -0,0 +1,79 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
#ifndef __grainFluidParticlesKernels_hpp__
#define __grainFluidParticlesKernels_hpp__
namespace pFlow::grainFluidParticlesKernels
{
using rpAcceleration = Kokkos::RangePolicy<
DefaultExecutionSpace,
Kokkos::Schedule<Kokkos::Static>,
Kokkos::IndexType<int32>
>;
template<typename IncludeFunctionType>
void acceleration(
realx3 g,
deviceViewType1D<real> mass,
deviceViewType1D<realx3> force,
deviceViewType1D<realx3> fluidForce,
deviceViewType1D<real> I,
deviceViewType1D<realx3> torque,
deviceViewType1D<realx3> fluidTorque,
IncludeFunctionType incld,
deviceViewType1D<realx3> lAcc,
deviceViewType1D<realx3> rAcc
)
{
auto activeRange = incld.activeRange();
if(incld.isAllActive())
{
Kokkos::parallel_for(
"pFlow::grainParticlesKernels::acceleration",
rpAcceleration(activeRange.first, activeRange.second),
LAMBDA_HD(int32 i){
lAcc[i] = (force[i]+fluidForce[i])/mass[i] + g;
rAcc[i] = (torque[i]+fluidTorque[i])/I[i];
});
}
else
{
Kokkos::parallel_for(
"pFlow::grainParticlesKernels::acceleration",
rpAcceleration(activeRange.first, activeRange.second),
LAMBDA_HD(int32 i){
if(incld(i))
{
lAcc[i] = (force[i]+fluidForce[i])/mass[i] + g;
rAcc[i] = (torque[i]+fluidTorque[i])/I[i];
}
});
}
Kokkos::fence();
}
}
#endif

View File

@ -19,6 +19,7 @@ Licence:
-----------------------------------------------------------------------------*/ -----------------------------------------------------------------------------*/
#include "sphereDEMSystem.hpp" #include "sphereDEMSystem.hpp"
#include "vocabs.hpp"
bool pFlow::sphereDEMSystem::loop() bool pFlow::sphereDEMSystem::loop()
{ {
@ -26,17 +27,16 @@ bool pFlow::sphereDEMSystem::loop()
do do
{ {
// //
if(! insertion_().insertParticles( if(! insertion_().insertParticles(
Control().time().currentIter(),
Control().time().currentTime(), Control().time().currentTime(),
Control().time().dt() ) ) Control().time().dt() ) )
{ {
fatalError<< fatalError<<
"particle insertion failed in sphereDFlow solver.\n"; "particle insertion failed in sphereDEMSystem.\n";
return false; return false;
} }
geometry_->beforeIteration(); geometry_->beforeIteration();
interaction_->beforeIteration(); interaction_->beforeIteration();
@ -63,29 +63,31 @@ pFlow::sphereDEMSystem::sphereDEMSystem(
word demSystemName, word demSystemName,
const std::vector<box>& domains, const std::vector<box>& domains,
int argc, int argc,
char* argv[]) char* argv[],
bool requireRVel)
: :
DEMSystem(demSystemName, domains, argc, argv) DEMSystem(demSystemName, domains, argc, argv),
requireRVel_(requireRVel)
{ {
REPORT(0)<<"\nReading proprties . . . "<<endREPORT; REPORT(0)<<"\nReading proprties . . . "<<END_REPORT;
property_ = makeUnique<property>( property_ = makeUnique<property>(
Control().caseSetup().path()+propertyFile__); propertyFile__,
Control().caseSetup().path());
REPORT(0)<< "\nCreating surface geometry for sphereDEMSystem . . . "<<endREPORT; REPORT(0)<< "\nCreating surface geometry for sphereDEMSystem . . . "<<END_REPORT;
geometry_ = geometry::create(Control(), Property()); geometry_ = geometry::create(Control(), Property());
REPORT(0)<<"\nReading sphere particles . . ."<<endREPORT; REPORT(0)<<"\nReading sphere particles . . ."<<END_REPORT;
particles_ = makeUnique<sphereFluidParticles>(Control(), Property()); particles_ = makeUnique<sphereFluidParticles>(Control(), Property());
insertion_ = makeUnique<sphereInsertion>( insertion_ = makeUnique<sphereInsertion>(
Control().caseSetup().path()+insertionFile__,
particles_(), particles_(),
particles_().shapes()); particles_().spheres());
REPORT(0)<<"\nCreating interaction model for sphere-sphere contact and sphere-wall contact . . ."<<endREPORT; REPORT(0)<<"\nCreating interaction model for sphere-sphere contact and sphere-wall contact . . ."<<END_REPORT;
interaction_ = interaction::create( interaction_ = interaction::create(
Control(), Control(),
Particles(), Particles(),
@ -98,6 +100,7 @@ pFlow::sphereDEMSystem::sphereDEMSystem(
} }
pFlow::sphereDEMSystem::~sphereDEMSystem() pFlow::sphereDEMSystem::~sphereDEMSystem()
{ {
@ -119,8 +122,8 @@ bool pFlow::sphereDEMSystem::updateParticleDistribution(
} }
if(!particleDistribution_->locateParticles( if(!particleDistribution_->locateParticles(
parPosition_, positionHost_,
particles_->pStruct().activePointsMaskH())) particles_->pStruct().activePointsMaskHost()))
{ {
fatalErrorInFunction<< fatalErrorInFunction<<
"error in locating particles among sub-domains"<<endl; "error in locating particles among sub-domains"<<endl;
@ -137,7 +140,7 @@ pFlow::int32
} }
std::vector<pFlow::int32> std::vector<pFlow::int32>
pFlow::sphereDEMSystem::numParInDomain()const pFlow::sphereDEMSystem::numParInDomains()const
{ {
const auto& distribute = particleDistribution_(); const auto& distribute = particleDistribution_();
int32 numDomains = distribute.numDomains(); int32 numDomains = distribute.numDomains();
@ -156,31 +159,56 @@ pFlow::sphereDEMSystem::parIndexInDomain(int32 di)const
return particleDistribution_->particlesInDomain(di); return particleDistribution_->particlesInDomain(di);
} }
pFlow::span<pFlow::real> pFlow::sphereDEMSystem::parDiameter() pFlow::span<pFlow::real> pFlow::sphereDEMSystem::diameter()
{ {
return span<real>(parDiameter_.data(), parDiameter_.size()); return span<real>(diameterHost_.data(), diameterHost_.size());
} }
pFlow::span<pFlow::realx3> pFlow::sphereDEMSystem::parVelocity() pFlow::span<pFlow::real> pFlow::sphereDEMSystem::courseGrainFactor()
{ {
return span<realx3>(parVelocity_.data(), parVelocity_.size()); return span<real>(nullptr, 0);
} }
pFlow::span<pFlow::realx3> pFlow::sphereDEMSystem::parPosition() pFlow::span<pFlow::realx3> pFlow::sphereDEMSystem::acceleration()
{ {
return span<realx3>(parPosition_.data(), parPosition_.size()); return span<realx3>(nullptr, 0);
}
pFlow::span<pFlow::realx3> pFlow::sphereDEMSystem::velocity()
{
return span<realx3>(velocityHost_.data(), velocityHost_.size());
}
pFlow::span<pFlow::realx3> pFlow::sphereDEMSystem::position()
{
return span<realx3>(positionHost_.data(), positionHost_.size());
}
pFlow::span<pFlow::realx3> pFlow::sphereDEMSystem::rAcceleration()
{
return span<realx3>(nullptr, 0);
}
pFlow::span<pFlow::realx3> pFlow::sphereDEMSystem::rVelocity()
{
return span<realx3>(rVelocityHost_.data(), rVelocityHost_.size());
}
pFlow::span<pFlow::realx3> pFlow::sphereDEMSystem::rPosition()
{
return span<realx3>(nullptr, 0);
} }
pFlow::span<pFlow::realx3> pFlow::sphereDEMSystem::parFluidForce() pFlow::span<pFlow::realx3> pFlow::sphereDEMSystem::parFluidForce()
{ {
auto& hVec = particles_->fluidForceHostAll(); auto& hVec = particles_->fluidForceHost();
return span<realx3>(hVec.data(), hVec.size()); return span<realx3>(hVec.data(), hVec.size());
} }
pFlow::span<pFlow::realx3> pFlow::sphereDEMSystem::parFluidTorque() pFlow::span<pFlow::realx3> pFlow::sphereDEMSystem::parFluidTorque()
{ {
auto& hVec = particles_->fluidTorqueHostAll(); auto& hVec = particles_->fluidTorqueHost();
return span<realx3>(hVec.data(), hVec.size()); return span<realx3>(hVec.data(), hVec.size());
} }
@ -198,9 +226,14 @@ bool pFlow::sphereDEMSystem::sendFluidTorqueToDEM()
bool pFlow::sphereDEMSystem::beforeIteration() bool pFlow::sphereDEMSystem::beforeIteration()
{ {
parVelocity_ = particles_->dynPointStruct().velocityHostAll(); velocityHost_ = std::as_const(particles_()).velocity().hostView();
parPosition_ = particles_->dynPointStruct().pointPositionHostAll(); positionHost_ = std::as_const(particles_()).pointPosition().hostView();
parDiameter_ = particles_->diameter().hostVectorAll(); diameterHost_ = particles_->diameter().hostView();
if(requireRVel_)
rVelocityHost_ = std::as_const(particles_()).rVelocity().hostView();
return true; return true;
} }

View File

@ -55,11 +55,16 @@ protected:
uniquePtr<domainDistribute> particleDistribution_=nullptr; uniquePtr<domainDistribute> particleDistribution_=nullptr;
// to be used for CPU communications // to be used for CPU communications
ViewType1D<realx3, HostSpace> parVelocity_; ViewType1D<realx3, HostSpace> velocityHost_;
ViewType1D<realx3, HostSpace> parPosition_; ViewType1D<realx3, HostSpace> positionHost_;
ViewType1D<real, HostSpace> diameterHost_;
bool requireRVel_ = false;
ViewType1D<realx3, HostSpace> rVelocityHost_;
ViewType1D<real, HostSpace> parDiameter_;
// protected member functions // protected member functions
auto& Property() auto& Property()
@ -92,7 +97,8 @@ public:
word demSystemName, word demSystemName,
const std::vector<box>& domains, const std::vector<box>& domains,
int argc, int argc,
char* argv[]); char* argv[],
bool requireRVel=false);
virtual ~sphereDEMSystem(); virtual ~sphereDEMSystem();
@ -110,15 +116,25 @@ public:
int32 numParInDomain(int32 di)const override; int32 numParInDomain(int32 di)const override;
std::vector<int32> numParInDomain()const override; std::vector<int32> numParInDomains()const override;
span<const int32> parIndexInDomain(int32 di)const override; span<const int32> parIndexInDomain(int32 di)const override;
span<real> parDiameter() override; span<real> diameter() override;
span<realx3> parVelocity() override; span<real> courseGrainFactor() override;
span<realx3> parPosition() override; span<realx3> acceleration() override;
span<realx3> velocity() override;
span<realx3> position() override;
span<realx3> rAcceleration() override;
span<realx3> rVelocity() override;
span<realx3> rPosition() override;
span<realx3> parFluidForce() override; span<realx3> parFluidForce() override;

View File

@ -21,42 +21,44 @@ Licence:
#include "sphereFluidParticles.hpp" #include "sphereFluidParticles.hpp"
#include "sphereFluidParticlesKernels.hpp" #include "sphereFluidParticlesKernels.hpp"
void pFlow::sphereFluidParticles::checkHostMemory()
{
if(fluidForce_.size()!=fluidForceHost_.size())
{
resizeNoInit(fluidForceHost_, fluidForce_.size());
resizeNoInit(fluidTorqueHost_, fluidTorque_.size());
}
}
pFlow::sphereFluidParticles::sphereFluidParticles( pFlow::sphereFluidParticles::sphereFluidParticles(
systemControl &control, systemControl &control,
const property& prop const property &prop)
) : sphereParticles(control, prop),
:
sphereParticles(control, prop),
fluidForce_( fluidForce_(
this->time().emplaceObject<realx3PointField_HD>(
objectFile( objectFile(
"fluidForce", "fluidForce",
"", "",
objectFile::READ_IF_PRESENT, objectFile::READ_IF_PRESENT,
objectFile::WRITE_ALWAYS objectFile::WRITE_ALWAYS),
), dynPointStruct(),
pStruct(), zero3),
zero3
)
),
fluidTorque_( fluidTorque_(
this->time().emplaceObject<realx3PointField_HD>(
objectFile( objectFile(
"fluidTorque", "fluidTorque",
"", "",
objectFile::READ_IF_PRESENT, objectFile::READ_IF_PRESENT,
objectFile::WRITE_ALWAYS objectFile::WRITE_NEVER),
), dynPointStruct(),
pStruct(), zero3)
zero3 {
) checkHostMemory();
) }
{}
bool pFlow::sphereFluidParticles::beforeIteration() bool pFlow::sphereFluidParticles::beforeIteration()
{ {
sphereParticles::beforeIteration(); sphereParticles::beforeIteration();
checkHostMemory();
return true; return true;
} }
@ -64,42 +66,40 @@ bool pFlow::sphereFluidParticles::beforeIteration()
bool pFlow::sphereFluidParticles::iterate() bool pFlow::sphereFluidParticles::iterate()
{ {
accelerationTimer_.start(); accelerationTimer().start();
pFlow::sphereFluidParticlesKernels::acceleration( pFlow::sphereFluidParticlesKernels::acceleration(
control().g(), control().g(),
mass().deviceVectorAll(), mass().deviceViewAll(),
contactForce().deviceVectorAll(), contactForce().deviceViewAll(),
fluidForce().deviceVectorAll(), fluidForce_.deviceViewAll(),
I().deviceVectorAll(), I().deviceViewAll(),
contactTorque().deviceVectorAll(), contactTorque().deviceViewAll(),
fluidTorque().deviceVectorAll(), fluidTorque_.deviceViewAll(),
pStruct().activePointsMaskD(), pStruct().activePointsMaskDevice(),
accelertion().deviceVectorAll(), accelertion().deviceViewAll(),
rAcceleration().deviceVectorAll() rAcceleration().deviceViewAll()
); );
accelerationTimer_.end(); accelerationTimer().end();
intCorrectTimer_.start(); intCorrectTimer().start();
dynPointStruct_.correct(this->dt(), accelertion_); dynPointStruct().correct(this->dt(), accelertion());
rVelIntegration_().correct(this->dt(), rVelocity_, rAcceleration_); rVelIntegration().correct(this->dt(), rVelocity(), rAcceleration());
intCorrectTimer_.end(); intCorrectTimer().end();
return true; return true;
} }
void pFlow::sphereFluidParticles::fluidForceHostUpdatedSync() void pFlow::sphereFluidParticles::fluidForceHostUpdatedSync()
{ {
fluidForce_.modifyOnHost(); copy(fluidForce_.deviceView(), fluidForceHost_);
fluidForce_.syncViews();
return; return;
} }
void pFlow::sphereFluidParticles::fluidTorqueHostUpdatedSync() void pFlow::sphereFluidParticles::fluidTorqueHostUpdatedSync()
{ {
fluidTorque_.modifyOnHost(); copy(fluidTorque_.deviceView(), fluidTorqueHost_);
fluidTorque_.syncViews();
return; return;
} }

View File

@ -43,12 +43,17 @@ class sphereFluidParticles
protected: protected:
/// pointField of rotational acceleration of particles on device /// pointField of rotational acceleration of particles on device
realx3PointField_HD& fluidForce_; realx3PointField_D fluidForce_;
realx3PointField_HD& fluidTorque_; hostViewType1D<realx3> fluidForceHost_;
realx3PointField_D fluidTorque_;
void zeroFluidForce_H() hostViewType1D<realx3> fluidTorqueHost_;
void checkHostMemory();
/*void zeroFluidForce_H()
{ {
fluidForce_.fillHost(zero3); fluidForce_.fillHost(zero3);
} }
@ -56,7 +61,7 @@ protected:
void zeroFluidTorque_H() void zeroFluidTorque_H()
{ {
fluidTorque_.fillHost(zero3); fluidTorque_.fillHost(zero3);
} }*/
public: public:
@ -81,17 +86,16 @@ public:
} }
auto& fluidForceHostAll() auto& fluidForceHost()
{ {
return fluidForce_.hostVectorAll(); return fluidForceHost_;
} }
auto& fluidTorqueHostAll() auto& fluidTorqueHost()
{ {
return fluidTorque_.hostVectorAll(); return fluidTorqueHost_;
} }
void fluidForceHostUpdatedSync(); void fluidForceHostUpdatedSync();
void fluidTorqueHostUpdatedSync(); void fluidTorqueHostUpdatedSync();

View File

@ -46,7 +46,7 @@ void acceleration(
{ {
auto activeRange = incld.activeRange(); auto activeRange = incld.activeRange();
if(incld.allActive()) if(incld.isAllActive())
{ {
Kokkos::parallel_for( Kokkos::parallel_for(
"pFlow::sphereParticlesKernels::acceleration", "pFlow::sphereParticlesKernels::acceleration",

View File

@ -3,10 +3,18 @@
</div> </div>
**PhasicFlow** is a parallel C++ code for performing DEM simulations. It can run on shared-memory multi-core computational units such as multi-core CPUs or GPUs (for now it works on CUDA-enabled GPUs). The parallelization method mainly relies on loop-level parallelization on a shared-memory computational unit. You can build and run PhasicFlow in serial mode on regular PCs, in parallel mode for multi-core CPUs, or build it for a GPU device to off-load computations to a GPU. In its current statues you can simulate millions of particles (up to 32M particles tested) on a single desktop computer. You can see the [performance tests of PhasicFlow](https://github.com/PhasicFlow/phasicFlow/wiki/Performance-of-phasicFlow) in the wiki page. **PhasicFlow** is a parallel C++ code for performing DEM simulations. It can run on shared-memory multi-core computational units such as multi-core CPUs or GPUs (for now it works on CUDA-enabled GPUs). The parallelization method mainly relies on loop-level parallelization on a shared-memory computational unit. You can build and run PhasicFlow in serial mode on regular PCs, in parallel mode for multi-core CPUs, or build it for a GPU device to off-load computations to a GPU. In its current statues you can simulate millions of particles (up to 80M particles tested) on a single desktop computer. You can see the [performance tests of PhasicFlow](https://github.com/PhasicFlow/phasicFlow/wiki/Performance-of-phasicFlow) in the wiki page.
**MPI** parallelization with dynamic load balancing is under development. With this level of parallelization, PhasicFlow can leverage the computational power of **multi-gpu** workstations or clusters with distributed memory CPUs.
In summary PhasicFlow can have 6 execution modes:
1. Serial on a single CPU core,
2. Parallel on a multi-core computer/node (using OpenMP),
3. Parallel on an nvidia-GPU (using Cuda),
4. Parallel on distributed memory workstation (Using MPI)
5. Parallel on distributed memory workstations with multi-core nodes (using MPI+OpenMP)
6. Parallel on workstations with multiple GPUs (using MPI+Cuda).
## How to build? ## How to build?
You can build PhasicFlow for CPU and GPU executions. [Here is a complete step-by-step procedure](https://github.com/PhasicFlow/phasicFlow/wiki/How-to-Build-PhasicFlow). You can build PhasicFlow for CPU and GPU executions. The latest release of PhasicFlow is v-0.1. [Here is a complete step-by-step procedure for building phasicFlow-v-0.1.](https://github.com/PhasicFlow/phasicFlow/wiki/How-to-Build-PhasicFlow).
## Online code documentation ## Online code documentation
You can find a full documentation of the code, its features, and other related materials on [online documentation of the code](https://phasicflow.github.io/phasicFlow/) You can find a full documentation of the code, its features, and other related materials on [online documentation of the code](https://phasicflow.github.io/phasicFlow/)
@ -22,3 +30,19 @@ PhasicFlowPlus is and extension to PhasicFlow for simulating particle-fluid syst
* [Kokkos](https://github.com/kokkos/kokkos) from National Technology & Engineering Solutions of Sandia, LLC (NTESS) * [Kokkos](https://github.com/kokkos/kokkos) from National Technology & Engineering Solutions of Sandia, LLC (NTESS)
* [CLI11 1.8](https://github.com/CLIUtils/CLI11) from University of Cincinnati. * [CLI11 1.8](https://github.com/CLIUtils/CLI11) from University of Cincinnati.
## How to cite PhasicFlow
If you are using PhasicFlow in your research or industrial work, cite the following [article](https://www.sciencedirect.com/science/article/pii/S0010465523001662):
```
@article{NOROUZI2023108821,
title = {PhasicFlow: A parallel, multi-architecture open-source code for DEM simulations},
journal = {Computer Physics Communications},
volume = {291},
pages = {108821},
year = {2023},
issn = {0010-4655},
doi = {https://doi.org/10.1016/j.cpc.2023.108821},
url = {https://www.sciencedirect.com/science/article/pii/S0010465523001662},
author = {H.R. Norouzi},
keywords = {Discrete element method, Parallel computing, CUDA, GPU, OpenMP, Granular flow}
}
```

33
cmake/autoComplete Normal file
View File

@ -0,0 +1,33 @@
PF_cFlags="--description --help --version"
_pFlowToVTK(){
if [ "$3" == "--time" ]; then
COMPREPLY=( $(ls) )
else
COMPREPLY=( $(compgen -W "$PF_cFlags --binary --no-geometry --no-particles --out-folder --time --separate-surfaces --fields" -- "$2") )
fi
}
complete -F _pFlowToVTK pFlowToVTK
_postprocessPhasicFlow(){
if [ "$3" == "--time" ]; then
COMPREPLY=( $(ls) )
else
COMPREPLY=( $(compgen -W "$PF_cFlags --out-folder --time --zeroFolder" -- "$2") )
fi
}
complete -F _postprocessPhasicFlow postprocessPhasicFlow
complete -W "$PF_cFlags --positionParticles-only --setFields-only --coupling" particlesPhasicFlow
complete -W "$PF_cFlags --coupling" geometryPhasicFlow
complete -W "$PF_cFlags --coupling" iterateGeometry
complete -W "$PF_cFlags" iterateSphereParticles
complete -W "$PF_cFlags" sphereGranFlow
complete -W "$PF_cFlags" grainGranFlow
complete -W "$PF_cFlags" checkPhasicFlow

View File

@ -1,8 +1,7 @@
export pFlow_PROJECT_VERSION=v0.1 export pFlow_PROJECT_VERSION=v-1.0
export pFlow_PROJECT=phasicFlow
export pFlow_PROJECT="phasicFlow-$pFlow_PROJECT_VERSION"
projectDir="$HOME/PhasicFlow" projectDir="$HOME/PhasicFlow"
kokkosDir="$HOME/Kokkos/kokkos" kokkosDir="$HOME/Kokkos/kokkos"
@ -20,6 +19,8 @@ export pFlow_SRC_DIR="$pFlow_PROJECT_DIR/src"
export Kokkos_DIR="$kokkosDir" export Kokkos_DIR="$kokkosDir"
export Zoltan_DIR="$projectDir/Zoltan"
# Cleanup variables (done as final statement for a clean exit code) # Cleanup variables (done as final statement for a clean exit code)
unset projectDir unset projectDir
@ -27,5 +28,7 @@ export PATH="$pFlow_BIN_DIR:$PATH"
export LD_LIBRARY_PATH="$pFlow_LIB_DIR:$LD_LIBRARY_PATH" export LD_LIBRARY_PATH="$pFlow_LIB_DIR:$LD_LIBRARY_PATH"
export LD_LIBRARY_PATH="$Zoltan_DIR/lib:$LD_LIBRARY_PATH"
source $pFlow_PROJECT_DIR/cmake/autoComplete
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------

View File

@ -2,3 +2,52 @@
set(validFiles) set(validFiles)
list(APPEND validFiles *.C *.cpp *.cxx *.c *.cu *.H *.hpp *.hxx *.h *.cuh) list(APPEND validFiles *.C *.cpp *.cxx *.c *.cu *.H *.hpp *.hxx *.h *.cuh)
macro(Kokkos_cmake_settings)
#mark_as_advanced(FORCE var Kokkos_ENABLE_CUDA_LAMBDA)
mark_as_advanced(FORCE var Kokkos_CXX_STANDARD)
#mark_as_advanced(FORCE var Kokkos_ENABLE_CUDA_CONSTEXPR)
mark_as_advanced(FORCE var Kokkos_ENABLE_OPENMP)
mark_as_advanced(FORCE var Kokkos_ENABLE_SERIAL)
mark_as_advanced(FORCE var Kokkos_ENABLE_CUDA)
mark_as_advanced(FORCE var Kokkos_ENABLE_HIP)
mark_as_advanced(FORCE var Kokkos_ENABLE_AGGRESSIVE_VECTORIZATION)
mark_as_advanced(FORCE var Kokkos_ENABLE_BENCHMARKS)
mark_as_advanced(FORCE var Kokkos_ENABLE_COMPILE_AS_CMAKE_LANGUAGE)
mark_as_advanced(FORCE var Kokkos_ENABLE_CUDA_LDG_INTRINSIC)
mark_as_advanced(FORCE var Kokkos_ENABLE_CUDA_RELOCATABLE_DEVICE_CODE)
mark_as_advanced(FORCE var Kokkos_ENABLE_CUDA_UVM)
mark_as_advanced(FORCE var Kokkos_ENABLE_DEPRECATED_CODE_3)
mark_as_advanced(FORCE var Kokkos_ENABLE_DEPRECATED_CODE_4)
mark_as_advanced(FORCE var Kokkos_ENABLE_DEPRECATION_WARNINGS)
mark_as_advanced(FORCE var Kokkos_ENABLE_DESUL_ATOMICS_EXTERNAL)
mark_as_advanced(FORCE var Kokkos_ENABLE_EXAMPLES)
mark_as_advanced(FORCE var Kokkos_ENABLE_HEADER_SELF_CONTAINMENT_TESTS)
mark_as_advanced(FORCE var Kokkos_ENABLE_HIP_MULTIPLE_KERNEL_INSTANTIATIONS)
mark_as_advanced(FORCE var Kokkos_ENABLE_HIP_RELOCATABLE_DEVICE_CODE)
mark_as_advanced(FORCE var Kokkos_ENABLE_HPX)
mark_as_advanced(FORCE var Kokkos_ENABLE_HWLOC)
mark_as_advanced(FORCE var Kokkos_ENABLE_IMPL_CUDA_MALLOC_ASYNC)
mark_as_advanced(FORCE var Kokkos_ENABLE_IMPL_HPX_ASYNC_DISPATCH)
mark_as_advanced(FORCE var Kokkos_ENABLE_LARGE_MEM_TESTS)
mark_as_advanced(FORCE var Kokkos_ENABLE_DEBUG_DUALVIEW_MODIFY_CHECK)
mark_as_advanced(FORCE var Kokkos_ENABLE_LIBQUADMATH)
mark_as_advanced(FORCE var Kokkos_ENABLE_LIBRT)
mark_as_advanced(FORCE var Kokkos_ENABLE_MEMKIND)
mark_as_advanced(FORCE var Kokkos_ENABLE_ONEDPL)
mark_as_advanced(FORCE var Kokkos_ENABLE_OPENACC)
mark_as_advanced(FORCE var Kokkos_ENABLE_OPENMPTARGET)
mark_as_advanced(FORCE var Kokkos_ENABLE_ROCM)
mark_as_advanced(FORCE var Kokkos_ENABLE_SYCL)
mark_as_advanced(FORCE var Kokkos_ENABLE_TESTS)
mark_as_advanced(FORCE var Kokkos_ENABLE_THREADS)
mark_as_advanced(FORCE var Kokkos_ENABLE_TUNING)
mark_as_advanced(FORCE var Kokkos_ENABLE_UNSUPPORTED_ARCHS)
mark_as_advanced(FORCE var Kokkos_HPX_DIR)
mark_as_advanced(FORCE var Kokkos_HWLOC_DIR)
mark_as_advanced(FORCE var Kokkos_MEMKIND_DIR)
mark_as_advanced(FORCE var Kokkos_ROCM_DIR)
mark_as_advanced(FORCE var Kokkos_THREADS_DIR)
endmacro()

View File

@ -31,8 +31,8 @@ target_include_directories(${target_name}
message(STATUS "\nCreating make file for executable ${target_name}") message(STATUS "\nCreating make file for executable ${target_name}")
message(STATUS " ${target_name} link libraries are: ${${target_link_libs}}") message(STATUS " ${target_name} link libraries are: ${${target_link_libs}}")
message(STATUS " ${target_name} source files are: ${source_files}") #message(STATUS " ${target_name} source files are: ${${source_files}}")
message(STATUS " ${target_name} include dirs are: ${includeDirs}\n") #message(STATUS " ${target_name} include dirs are: ${includeDirs}\n")
install(TARGETS ${target_name} DESTINATION bin) install(TARGETS ${target_name} DESTINATION bin)

View File

@ -41,8 +41,8 @@ target_include_directories(${target_name}
message(STATUS "\nCreating make file for library ${target_name}") message(STATUS "\nCreating make file for library ${target_name}")
message(STATUS " ${target_name} link libraries are: ${${target_link_libs}}") message(STATUS " ${target_name} link libraries are: ${${target_link_libs}}")
message(STATUS " ${target_name} source files are: ${source_files}") #message(STATUS " ${target_name} source files are: ${source_files}")
message(STATUS " ${target_name} include dirs are: ${includeDirs}\n") #message(STATUS " ${target_name} include dirs are: ${includeDirs}\n \n")
install(TARGETS ${target_name} DESTINATION lib) install(TARGETS ${target_name} DESTINATION lib)
install(FILES ${includeFiles} DESTINATION include/${target_name}) install(FILES ${includeFiles} DESTINATION include/${target_name})

View File

@ -5,5 +5,6 @@
#cmakedefine pFlow_Build_Serial #cmakedefine pFlow_Build_Serial
#cmakedefine pFlow_Build_OpenMP #cmakedefine pFlow_Build_OpenMP
#cmakedefine pFlow_Build_Cuda #cmakedefine pFlow_Build_Cuda
#cmakedefine USE_STD_PARALLEL_ALG #cmakedefine pFlow_STD_Parallel_Alg
#cmakedefine pFlow_Build_Double #cmakedefine pFlow_Build_Double
#cmakedefine pFlow_Build_MPI

View File

@ -1,7 +1,9 @@
#add_subdirectory(iterateSphereParticles) add_subdirectory(iterateSphereParticles)
add_subdirectory(iterateGeometry) add_subdirectory(iterateGeometry)
add_subdirectory(sphereGranFlow) add_subdirectory(sphereGranFlow)
add_subdirectory(grainGranFlow)

View File

@ -0,0 +1,7 @@
set(source_files
grainGranFlow.cpp
)
set(link_lib Kokkos::kokkos phasicFlow Particles Geometry Property Interaction Interaction Utilities)
pFlow_make_executable_install(grainGranFlow source_files link_lib)

View File

@ -0,0 +1,50 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
//
REPORT(0)<<"\nReading sphere particles . . ."<<END_REPORT;
pFlow::grainParticles grnParticles(Control, proprties);
//
REPORT(0)<<"\nCreating particle insertion object . . ."<<END_REPORT;
/*auto& sphInsertion =
Control.caseSetup().emplaceObject<sphereInsertion>(
objectFile(
insertionFile__,
"",
objectFile::READ_ALWAYS,
objectFile::WRITE_ALWAYS
),
sphParticles,
sphParticles.shapes()
);*/
auto grnInsertion = pFlow::grainInsertion(
grnParticles,
grnParticles.grains());
REPORT(0)<<"\nCreating interaction model for sphere-sphere contact and sphere-wall contact . . ."<<END_REPORT;
auto interactionPtr = pFlow::interaction::create(
Control,
grnParticles,
surfGeometry
);
auto& grnInteraction = interactionPtr();

View File

@ -0,0 +1,123 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
/**
* \file sphereGranFlow.cpp
* \brief sphereGranFlow solver
*
* This solver simulate granular flow of cohesion-less, spherical particles.
* Particle insertion can be activated in the solver to gradually insert
* particles into the simulation. Geometry can be defined generally with
* built-in features of the code or through ASCII stl files or a combination
* of both. For more information refer to [tutorials/sphereGranFlow/]
* (https://github.com/PhasicFlow/phasicFlow/tree/main/tutorials/sphereGranFlow) folder.
*/
#include "vocabs.hpp"
#include "phasicFlowKokkos.hpp"
#include "systemControl.hpp"
#include "commandLine.hpp"
#include "property.hpp"
#include "geometry.hpp"
#include "grainParticles.hpp"
#include "interaction.hpp"
#include "Insertions.hpp"
//#include "readControlDict.hpp"
/**
* DEM solver for simulating granular flow of cohesion-less particles.
*
* In the root case directory just simply enter the following command to
* run the simulation. For command line options use flag -h.
*/
int main( int argc, char* argv[])
{
pFlow::commandLine cmds(
"grainGranFlow",
"DEM solver for non-cohesive spherical grain particles with particle insertion "
"mechanism and moving geometry");
bool isCoupling = false;
if(!cmds.parse(argc, argv)) return 0;
// this should be palced in each main
pFlow::processors::initProcessors(argc, argv);
pFlow::initialize_pFlowProcessors();
#include "initialize_Control.hpp"
#include "setProperty.hpp"
#include "setSurfaceGeometry.hpp"
#include "createDEMComponents.hpp"
REPORT(0)<<"\nStart of time loop . . .\n"<<END_REPORT;
do
{
if(! grnInsertion.insertParticles(
Control.time().currentIter(),
Control.time().currentTime(),
Control.time().dt() ) )
{
fatalError<<
"particle insertion failed in grain DFlow solver.\n";
return 1;
}
// set force to zero
surfGeometry.beforeIteration();
// set force to zero, predict, particle deletion and etc.
grnParticles.beforeIteration();
grnInteraction.beforeIteration();
grnInteraction.iterate();
surfGeometry.iterate();
grnParticles.iterate();
grnInteraction.afterIteration();
surfGeometry.afterIteration();
grnParticles.afterIteration();
}while(Control++);
REPORT(0)<<"\nEnd of time loop.\n"<<END_REPORT;
// this should be palced in each main
#include "finalize.hpp"
pFlow::processors::finalizeProcessors();
}

View File

@ -29,17 +29,16 @@ Licence:
* folder. * folder.
*/ */
#include "vocabs.hpp"
#include "systemControl.hpp" #include "systemControl.hpp"
#include "geometryMotion.hpp" #include "geometry.hpp"
#include "commandLine.hpp" #include "commandLine.hpp"
#include "readControlDict.hpp" //#include "readControlDict.hpp"
using pFlow::commandLine;
int main( int argc, char* argv[] ) int main( int argc, char* argv[] )
{ {
commandLine cmds( pFlow::commandLine cmds(
"iterateGeometry", "iterateGeometry",
"Performs simulation without particles, only geometry is solved"); "Performs simulation without particles, only geometry is solved");
@ -54,6 +53,8 @@ commandLine cmds(
// this should be palced in each main // this should be palced in each main
pFlow::processors::initProcessors(argc, argv);
pFlow::initialize_pFlowProcessors();
#include "initialize_Control.hpp" #include "initialize_Control.hpp"
#include "setProperty.hpp" #include "setProperty.hpp"
@ -68,6 +69,7 @@ commandLine cmds(
// this should be palced in each main // this should be palced in each main
#include "finalize.hpp" #include "finalize.hpp"
pFlow::processors::finalizeProcessors();
} }

View File

@ -0,0 +1,7 @@
set(source_files
iterateSphereParticles.cpp
)
set(link_lib Particles)
pFlow_make_executable_install(iterateSphereParticles source_files link_lib)

View File

@ -18,10 +18,8 @@ Licence:
-----------------------------------------------------------------------------*/ -----------------------------------------------------------------------------*/
//
REPORT(0)<<"\nReading sphere particles . . ."<<END_REPORT;
pFlow::sphereParticles sphParticles(Control, proprties);
#include "peakableRegions.hpp" WARNING<<"Particle insertion has not been set yet!"<<END_WARNING;
#ifdef BUILD_SHARED_LIBS
#include "peakableRegionInstantiate.cpp"
#endif

View File

@ -0,0 +1,89 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
/**
* \file sphereGranFlow.cpp
* \brief sphereGranFlow solver
*
* This solver simulate granular flow of cohesion-less, spherical particles.
* Particle insertion can be activated in the solver to gradually insert
* particles into the simulation. Geometry can be defined generally with
* built-in features of the code or through ASCII stl files or a combination
* of both. For more information refer to [tutorials/sphereGranFlow/]
* (https://github.com/PhasicFlow/phasicFlow/tree/main/tutorials/sphereGranFlow) folder.
*/
#include "vocabs.hpp"
#include "property.hpp"
#include "sphereParticles.hpp"
#include "systemControl.hpp"
#include "commandLine.hpp"
/**
* DEM solver for simulating granular flow of cohesion-less particles.
*
* In the root case directory just simply enter the following command to
* run the simulation. For command line options use flag -h.
*/
int main( int argc, char* argv[])
{
pFlow::commandLine cmds(
"sphereGranFlow",
"DEM solver for non-cohesive spherical particles with particle insertion "
"mechanism and moving geometry");
bool isCoupling = false;
if(!cmds.parse(argc, argv)) return 0;
// this should be palced in each main
pFlow::processors::initProcessors(argc, argv);
pFlow::initialize_pFlowProcessors();
#include "initialize_Control.hpp"
#include "setProperty.hpp"
#include "createDEMComponents.hpp"
REPORT(0)<<"\nStart of time loop . . .\n"<<END_REPORT;
do
{
sphParticles.beforeIteration();
sphParticles.iterate();
sphParticles.afterIteration();
}while(Control++);
REPORT(0)<<"\nEnd of time loop.\n"<<END_REPORT;
// this should be palced in each main
#include "finalize.hpp"
pFlow::processors::finalizeProcessors();
}

View File

@ -19,11 +19,11 @@ Licence:
-----------------------------------------------------------------------------*/ -----------------------------------------------------------------------------*/
// //
REPORT(0)<<"\nReading sphere particles . . ."<<endREPORT; REPORT(0)<<"\nReading sphere particles . . ."<<END_REPORT;
sphereParticles sphParticles(Control, proprties); pFlow::sphereParticles sphParticles(Control, proprties);
// //
REPORT(0)<<"\nCreating particle insertion object . . ."<<endREPORT; REPORT(0)<<"\nCreating particle insertion object . . ."<<END_REPORT;
/*auto& sphInsertion = /*auto& sphInsertion =
Control.caseSetup().emplaceObject<sphereInsertion>( Control.caseSetup().emplaceObject<sphereInsertion>(
objectFile( objectFile(
@ -36,13 +36,12 @@ REPORT(0)<<"\nCreating particle insertion object . . ."<<endREPORT;
sphParticles.shapes() sphParticles.shapes()
);*/ );*/
auto sphInsertion = sphereInsertion( auto sphInsertion = pFlow::sphereInsertion(
Control.caseSetup().path()+insertionFile__,
sphParticles, sphParticles,
sphParticles.shapes()); sphParticles.spheres());
REPORT(0)<<"\nCreating interaction model for sphere-sphere contact and sphere-wall contact . . ."<<endREPORT; REPORT(0)<<"\nCreating interaction model for sphere-sphere contact and sphere-wall contact . . ."<<END_REPORT;
auto interactionPtr = interaction::create( auto interactionPtr = pFlow::interaction::create(
Control, Control,
sphParticles, sphParticles,
surfGeometry surfGeometry

View File

@ -30,29 +30,17 @@ Licence:
* (https://github.com/PhasicFlow/phasicFlow/tree/main/tutorials/sphereGranFlow) folder. * (https://github.com/PhasicFlow/phasicFlow/tree/main/tutorials/sphereGranFlow) folder.
*/ */
#include "vocabs.hpp"
#include "phasicFlowKokkos.hpp"
#include "systemControl.hpp"
#include "commandLine.hpp"
#include "property.hpp" #include "property.hpp"
#include "geometry.hpp" #include "geometry.hpp"
#include "sphereParticles.hpp" #include "sphereParticles.hpp"
#include "interaction.hpp"
#include "Insertions.hpp" #include "Insertions.hpp"
#include "systemControl.hpp"
#include "contactSearch.hpp"
#include "sphereInteraction.hpp"
#include "commandLine.hpp"
#include "readControlDict.hpp"
using pFlow::output;
using pFlow::endl;
using pFlow::property;
using pFlow::sphereParticles;
using pFlow::objectFile;
using pFlow::sphereInsertion;
using pFlow::insertionFile__;
using pFlow::interactionFile__;
using pFlow::contactSearch;
using pFlow::interaction;
using pFlow::commandLine;
//#include "readControlDict.hpp"
/** /**
* DEM solver for simulating granular flow of cohesion-less particles. * DEM solver for simulating granular flow of cohesion-less particles.
@ -63,7 +51,7 @@ using pFlow::commandLine;
int main( int argc, char* argv[]) int main( int argc, char* argv[])
{ {
commandLine cmds( pFlow::commandLine cmds(
"sphereGranFlow", "sphereGranFlow",
"DEM solver for non-cohesive spherical particles with particle insertion " "DEM solver for non-cohesive spherical particles with particle insertion "
"mechanism and moving geometry"); "mechanism and moving geometry");
@ -73,20 +61,22 @@ bool isCoupling = false;
if(!cmds.parse(argc, argv)) return 0; if(!cmds.parse(argc, argv)) return 0;
// this should be palced in each main // this should be palced in each main
pFlow::processors::initProcessors(argc, argv);
pFlow::initialize_pFlowProcessors();
#include "initialize_Control.hpp" #include "initialize_Control.hpp"
#include "setProperty.hpp" #include "setProperty.hpp"
#include "setSurfaceGeometry.hpp" #include "setSurfaceGeometry.hpp"
#include "createDEMComponents.hpp" #include "createDEMComponents.hpp"
REPORT(0)<<"\nStart of time loop . . .\n"<<endREPORT; REPORT(0)<<"\nStart of time loop . . .\n"<<END_REPORT;
do do
{ {
if(! sphInsertion.insertParticles( if(! sphInsertion.insertParticles(
Control.time().currentIter(),
Control.time().currentTime(), Control.time().currentTime(),
Control.time().dt() ) ) Control.time().dt() ) )
{ {
@ -95,30 +85,34 @@ if(!cmds.parse(argc, argv)) return 0;
return 1; return 1;
} }
// set force to zero
surfGeometry.beforeIteration(); surfGeometry.beforeIteration();
// set force to zero, predict, particle deletion and etc.
sphParticles.beforeIteration();
sphInteraction.beforeIteration(); sphInteraction.beforeIteration();
sphParticles.beforeIteration();
sphInteraction.iterate(); sphInteraction.iterate();
sphParticles.iterate();
surfGeometry.iterate(); surfGeometry.iterate();
sphParticles.afterIteration(); sphParticles.iterate();
sphInteraction.afterIteration();
surfGeometry.afterIteration(); surfGeometry.afterIteration();
sphParticles.afterIteration();
}while(Control++); }while(Control++);
REPORT(0)<<"\nEnd of time loop.\n"<<endREPORT; REPORT(0)<<"\nEnd of time loop.\n"<<END_REPORT;
// this should be palced in each main // this should be palced in each main
#include "finalize.hpp" #include "finalize.hpp"
pFlow::processors::finalizeProcessors();
} }

View File

@ -7,9 +7,9 @@ add_subdirectory(Property)
add_subdirectory(Particles) add_subdirectory(Particles)
add_subdirectory(Geometry)
add_subdirectory(Interaction) add_subdirectory(Interaction)
add_subdirectory(MotionModel) add_subdirectory(MotionModel)
add_subdirectory(Geometry)

View File

@ -19,32 +19,40 @@ Licence:
-----------------------------------------------------------------------------*/ -----------------------------------------------------------------------------*/
#include "geometry.hpp" #include "geometry.hpp"
#include "systemControl.hpp"
#include "vocabs.hpp" #include "vocabs.hpp"
bool pFlow::geometry::findPropertyId() bool pFlow::geometry::createPropertyId()
{ {
if(materialName_.size() != numSurfaces() )
int8Vector propId(0, surface().capacity(),RESERVE());
propId.clear();
uint32 pId;
ForAll(matI, materialName_)
{
if( !wallProperty_.nameToIndex( materialName_[matI], pId ) )
{ {
fatalErrorInFunction<< fatalErrorInFunction<<
"material name for the geometry is invalid: "<< materialName_[matI]<<endl; "number of subSurface and material names do not match"<<endl;
return false; return false;
} }
int32 surfSize = surface().surfNumTriangles(matI); uint32Vector propId(
"propId",
capacity(),
size(),
RESERVE());
for(int32 i=0; i<surfSize; i++) ForAll(i, materialName_)
{ {
propId.push_back(pId); uint32 pIdx =0;
if( !wallProperty_.nameToIndex(materialName_[i], pIdx) )
{
fatalErrorInFunction<<
"Property/material name is invalid "<<materialName_[i]<<
". A list of valid names are \n"<< wallProperty_.materials()<<endl;
return false;
} }
auto triRange = subSurfaceRange(i);
propId.fill(triRange.start(), triRange.end(), pIdx);
} }
propertyId_.assign(propId); propertyId_.assign(propId);
@ -53,83 +61,363 @@ bool pFlow::geometry::findPropertyId()
} }
void pFlow::geometry::zeroForce()
{
contactForceWall_.fill(zero3);
}
pFlow::geometry::geometry pFlow::geometry::geometry
( (
systemControl& control, systemControl& control,
const property& prop const property& prop
) )
: :
demGeometry(control), multiTriSurface
(
objectFile
(
triSurfaceFile__,
"",
objectFile::READ_ALWAYS,
objectFile::WRITE_ALWAYS
),
&control.geometry()
),
demComponent
(
"geometry",
control
),
wallProperty_(prop), wallProperty_(prop),
geometryRepository_(control.geometry()), propertyId_
triSurface_( (
control.geometry().emplaceObject<multiTriSurface>( objectFile
objectFile( (
"triSurface",
"",
objectFile::READ_ALWAYS,
objectFile::WRITE_ALWAYS
)
)
),
motionComponentName_(
control.geometry().emplaceObject<wordField>(
objectFile(
"motionComponentName",
"",
objectFile::READ_ALWAYS,
objectFile::WRITE_ALWAYS
),
"motionNamesList"
)
),
materialName_(
control.geometry().emplaceObject<wordField>(
objectFile(
"materialName",
"",
objectFile::READ_ALWAYS,
objectFile::WRITE_ALWAYS
),
"materialNamesList"
)
),
propertyId_(
control.geometry().emplaceObject<int8TriSurfaceField_D>(
objectFile(
"propertyId", "propertyId",
"", "",
objectFile::READ_NEVER, objectFile::READ_NEVER,
objectFile::WRITE_NEVER), objectFile::WRITE_NEVER
surface(), ),
0 ) ), *this,
contactForceWall_( 0u
control.geometry().emplaceObject<realx3TriSurfaceField_D>( ),
objectFile( contactForceWall_
"contactForceWall", (
objectFile
(
"contactForcWall",
"", "",
objectFile::READ_IF_PRESENT, objectFile::READ_IF_PRESENT,
objectFile::WRITE_ALWAYS), objectFile::WRITE_NEVER
surface(), ),
zero3) ), *this,
stressWall_( zero3
control.geometry().emplaceObject<realx3TriSurfaceField_D>( ),
objectFile( normalStressWall_
"stressWall", (
objectFile
(
"normalStressWall",
"", "",
objectFile::READ_IF_PRESENT, objectFile::READ_IF_PRESENT,
objectFile::WRITE_ALWAYS), objectFile::WRITE_NEVER
surface(), ),
zero3) ) *this,
zero3
),
shearStressWall_
(
objectFile
(
"shearStressWall",
"",
objectFile::READ_IF_PRESENT,
objectFile::WRITE_NEVER
),
*this,
zero3
)
{ {
if(!findPropertyId()) readWholeObject_ = false;
if( !IOobject::readObject() )
{
fatalErrorInFunction<<
"Error in reading from file "<<IOobject::path()<<endl;
fatalExit;
}
readWholeObject_ = true;
if( this->numSurfaces() != motionComponentName_.size() )
{
fatalErrorInFunction<<
"Number of surfaces is not equal to number of motion component names"<<endl;
fatalExit;
}
if(!createPropertyId())
{ {
fatalExit; fatalExit;
} }
} }
pFlow::geometry::geometry pFlow::geometry::geometry
(
systemControl &control,
const property &prop,
multiTriSurface &surf,
const wordVector &motionCompName,
const wordVector &materialName,
const dictionary& motionDict
)
:
multiTriSurface
(
objectFile
(
triSurfaceFile__,
"",
objectFile::READ_NEVER,
objectFile::WRITE_ALWAYS
),
&control.geometry(),
surf
),
demComponent
(
"geometry",
control
),
wallProperty_
(
prop
),
propertyId_
(
objectFile
(
"propertyId",
"",
objectFile::READ_NEVER,
objectFile::WRITE_NEVER
),
*this,
0u
),
contactForceWall_
(
objectFile
(
"contactForcWall",
"",
objectFile::READ_IF_PRESENT,
objectFile::WRITE_NEVER
),
*this,
zero3
),
normalStressWall_
(
objectFile
(
"normalStressWall",
"",
objectFile::READ_IF_PRESENT,
objectFile::WRITE_NEVER
),
*this,
zero3
),
shearStressWall_
(
objectFile
(
"shearStressWall",
"",
objectFile::READ_IF_PRESENT,
objectFile::WRITE_NEVER
),
*this,
zero3
)
{
motionComponentName_.assign(motionCompName);
materialName_.assign(materialName);
if( this->numSurfaces() != motionComponentName_.size() )
{
fatalErrorInFunction<<
"Number of surfaces ("<< this->numSurfaces() <<
") is not equal to number of motion component names("<<
motionComponentName_.size()<<")"<<endl;
fatalExit;
}
if(!createPropertyId())
{
fatalExit;
}
}
bool pFlow::geometry::beforeIteration()
{
zeroForce();
return true;
}
bool pFlow::geometry::iterate()
{
return true;
}
bool pFlow::geometry::afterIteration()
{
auto numTris = size();
auto& normalsD = normals().deviceViewAll();
auto& areaD = area().deviceViewAll();
auto& cForceD = contactForceWall_.deviceViewAll();
auto& sStressD = shearStressWall_.deviceViewAll();
auto& nStressD = normalStressWall_.deviceViewAll();
Kokkos::parallel_for(
"pFlow::geometry::afterIteration",
deviceRPolicyStatic(0, numTris),
LAMBDA_HD(uint32 i)
{
realx3 n = normalsD[i];
real A = max(areaD[i],smallValue);
realx3 nF = dot(cForceD[i],n)*n;
realx3 sF = cForceD[i] - nF;
nStressD[i] = nF/A;
sStressD[i] = sF/A;
});
Kokkos::fence();
return true;
}
bool pFlow::geometry::read(iIstream &is, const IOPattern &iop)
{
motionComponentName_.read(is, iop);
materialName_.read(is, iop);
if( readWholeObject_ )
{
return multiTriSurface::read(is, iop);
}
return true;
}
bool pFlow::geometry::write(iOstream &os, const IOPattern &iop) const
{
if( !motionComponentName_.write(os, iop) )
{
fatalErrorInFunction;
return false;
}
if( !materialName_.write(os,iop))
{
fatalErrorInFunction;
return false;
}
return multiTriSurface::write(os,iop);
}
pFlow::uniquePtr<pFlow::geometry>
pFlow::geometry::create
(
systemControl& control,
const property& prop
)
{
//
fileDictionary dict( motionModelFile__, control.time().geometry().path());
word model = dict.getVal<word>("motionModel");
auto geomModel = angleBracketsNames("geometry", model);
REPORT(1)<< "Selecting geometry model . . ."<<END_REPORT;
if( systemControlvCtorSelector_.search(geomModel) )
{
auto objPtr = systemControlvCtorSelector_[geomModel] (control, prop);
REPORT(2)<<"Model "<< Green_Text(geomModel)<<" is created.\n"<<END_REPORT;
return objPtr;
}
else
{
printKeys
(
fatalError << "Ctor Selector "<< Yellow_Text(geomModel) << " dose not exist. \n"
<<"Avaiable ones are: \n\n"
,
systemControlvCtorSelector_
);
fatalExit;
}
return nullptr;
}
pFlow::uniquePtr<pFlow::geometry>
pFlow::geometry::create
(
systemControl& control,
const property& prop,
multiTriSurface& surf,
const wordVector& motionCompName,
const wordVector& materialName,
const dictionary& motionDic
)
{
word model = motionDic.getVal<word>("motionModel");
auto geomModel = angleBracketsNames("geometry", model);
REPORT(1)<< "Selecting geometry model . . ."<<END_REPORT;
if( dictionaryvCtorSelector_.search(geomModel) )
{
auto objPtr = dictionaryvCtorSelector_[geomModel]
(
control,
prop,
surf,
motionCompName,
materialName,
motionDic
);
REPORT(2)<<"Model "<< Green_Text(geomModel)<<" is created.\n"<<END_REPORT;
return objPtr;
}
else
{
printKeys
(
fatalError << "Ctor Selector "<< Yellow_Text(geomModel) << " dose not exist. \n"
<<"Avaiable ones are: \n\n"
,
dictionaryvCtorSelector_
);
fatalExit;
}
return nullptr;
}
/*pFlow::geometry::geometry
( (
systemControl& control, systemControl& control,
const property& prop, const property& prop,
@ -224,52 +512,7 @@ pFlow::geometry::geometry
{} {}
pFlow::uniquePtr<pFlow::geometry>
pFlow::geometry::create
(
systemControl& control,
const property& prop
)
{
//motionModelFile__
auto motionDictPtr = IOobject::make<dictionary>
(
objectFile
(
motionModelFile__,
control.geometry().path(),
objectFile::READ_ALWAYS,
objectFile::WRITE_NEVER
),
motionModelFile__,
true
);
word model = motionDictPtr().getObject<dictionary>().getVal<word>("motionModel");
auto geomModel = angleBracketsNames("geometry", model);
REPORT(1)<< "Selecting geometry model . . ."<<endREPORT;
if( systemControlvCtorSelector_.search(geomModel) )
{
auto objPtr = systemControlvCtorSelector_[geomModel] (control, prop);
REPORT(2)<<"Model "<< greenText(geomModel)<<" is created.\n"<<endREPORT;
return objPtr;
}
else
{
printKeys
(
fatalError << "Ctor Selector "<< yellowText(geomModel) << " dose not exist. \n"
<<"Avaiable ones are: \n\n"
,
systemControlvCtorSelector_
);
fatalExit;
}
return nullptr;
}
bool pFlow::geometry::beforeIteration() bool pFlow::geometry::beforeIteration()
{ {
@ -296,48 +539,4 @@ bool pFlow::geometry::afterIteration()
Kokkos::fence(); Kokkos::fence();
return true; return true;
} }*/
pFlow::uniquePtr<pFlow::geometry>
pFlow::geometry::create(
systemControl& control,
const property& prop,
const dictionary& dict,
const multiTriSurface& triSurface,
const wordVector& motionCompName,
const wordVector& propName)
{
word model = dict.getVal<word>("motionModel");
auto geomModel = angleBracketsNames("geometry", model);
REPORT(1)<< "Selecting geometry model . . ."<<endREPORT;
if( dictionaryvCtorSelector_.search(geomModel) )
{
auto objPtr = dictionaryvCtorSelector_[geomModel]
(
control,
prop,
dict,
triSurface,
motionCompName,
propName
);
REPORT(2)<<"Model "<< greenText(geomModel)<<" is created.\n"<<endREPORT;
return objPtr;
}
else
{
printKeys
(
fatalError << "Ctor Selector "<< yellowText(geomModel) << " dose not exist. \n"
<<"Avaiable ones are: \n\n"
,
dictionaryvCtorSelector_
);
fatalExit;
}
return nullptr;
}

View File

@ -23,13 +23,14 @@ Licence:
#include "virtualConstructor.hpp" #include "virtualConstructor.hpp"
#include "demGeometry.hpp" #include "demComponent.hpp"
#include "property.hpp" #include "property.hpp"
#include "Fields.hpp"
#include "Vectors.hpp"
#include "multiTriSurface.hpp" #include "multiTriSurface.hpp"
#include "triSurfaceFields.hpp" #include "triSurfaceFields.hpp"
#include "dictionary.hpp" //#include "Fields.hpp"
//#include "Vectors.hpp"
namespace pFlow namespace pFlow
{ {
@ -42,48 +43,49 @@ namespace pFlow
*/ */
class geometry class geometry
: :
public demGeometry public multiTriSurface,
public demComponent
{ {
protected: private:
// - Protected members // - Protected members
/// Const reference to physical property of materials /// Const reference to physical property of materials
const property& wallProperty_; const property& wallProperty_;
/// Repository to store geometry data at each simulation moment
repository& geometryRepository_;
/// All triangles in the set of wall surfaces
multiTriSurface& triSurface_;
/// The name of motion component of each wall surface /// The name of motion component of each wall surface
wordField& motionComponentName_; wordField_H motionComponentName_{
"motionComponentName",
"motionComponentName"};
/// Material name of each wall surface /// Material name of each wall surface
wordField& materialName_; wordField_H materialName_{
"materialName",
"materialName"};
/// Property id of each triangle in the set of wall surfaces /// Property id of each triangle in the set of wall surfaces
int8TriSurfaceField_D& propertyId_; uint32TriSurfaceField_D propertyId_;
/// Contact force on each triangle in the set of wall surfaces /// Contact force on each triangle in the set of wall surfaces
realx3TriSurfaceField_D& contactForceWall_; realx3TriSurfaceField_D contactForceWall_;
/// Stress on ech triangle in the set of wall surfaces /// Stress on each triangle in the set of wall surfaces
realx3TriSurfaceField_D& stressWall_; realx3TriSurfaceField_D normalStressWall_;
/// Stress on each triangle in the set of wall surfaces
realx3TriSurfaceField_D shearStressWall_;
bool readWholeObject_ = true;
// - Protected member functions // - Protected member functions
/// Find property id of each triangle based on the supplied material name /// Find property id of each triangle based on the supplied material name
/// and the surface wall that the triangle belongs to. /// and the surface wall that the triangle belongs to.
bool findPropertyId(); bool createPropertyId();
/// Initialize contact force to zero /// Initialize contact force to zero
void zeroForce() void zeroForce();
{
contactForceWall_.fill(zero3);
}
public: public:
@ -95,8 +97,15 @@ public:
/// Construct from controlSystem and property, for reading from file /// Construct from controlSystem and property, for reading from file
geometry(systemControl& control, const property& prop); geometry(systemControl& control, const property& prop);
/// Construct from components
geometry(systemControl& control, geometry(systemControl& control,
const property& prop,
multiTriSurface& surf,
const wordVector& motionCompName,
const wordVector& materialName,
const dictionary& motionDict);
/// Construct from components
/*geometry(systemControl& control,
const property& prop, const property& prop,
const multiTriSurface& triSurface, const multiTriSurface& triSurface,
const wordVector& motionCompName, const wordVector& motionCompName,
@ -110,10 +119,10 @@ public:
const dictionary& dict, const dictionary& dict,
const multiTriSurface& triSurface, const multiTriSurface& triSurface,
const wordVector& motionCompName, const wordVector& motionCompName,
const wordVector& propName); const wordVector& propName);*/
/// Destructor /// Destructor
virtual ~geometry() = default; ~geometry()override = default;
/// Virtual constructor /// Virtual constructor
create_vCtor create_vCtor
@ -132,156 +141,96 @@ public:
( (
geometry, geometry,
dictionary, dictionary,
(systemControl& control, (
systemControl& control,
const property& prop, const property& prop,
const dictionary& dict, multiTriSurface& surf,
const multiTriSurface& triSurface,
const wordVector& motionCompName, const wordVector& motionCompName,
const wordVector& propName), const wordVector& materialName,
(control, prop, dict, triSurface, motionCompName, propName) const dictionary& motionDic),
(control, prop, surf, motionCompName, materialName, motionDic)
); );
//- Methods //- Methods
/// Size of tri-surface
inline inline
auto size()const const auto& motionComponentName()const
{ {
return triSurface_.size(); return motionComponentName_;
}
/// Number of points in the set of surface walls
inline
auto numPoints()const
{
return triSurface_.numPoints();
}
/// Number of triangles in the set of surface walls
inline
auto numTriangles()const
{
return size();
}
/// Access to the points
inline
const auto& points()const
{
return triSurface_.points();
}
/// Access to the vertices
inline
const auto& vertices()const
{
return triSurface_.vertices();
}
/// Obtain an object for accessing triangles
inline auto getTriangleAccessor()const
{
return triSurface_.getTriangleAccessor();
}
/// Surface
inline auto& surface()
{
return triSurface_;
}
/// Surface
inline const auto& surface()const
{
return triSurface_;
} }
/// Access to contact force /// Access to contact force
inline inline
realx3TriSurfaceField_D& contactForceWall() auto& contactForceWall()
{ {
return contactForceWall_; return contactForceWall_;
} }
/// Access to contact force /// Access to contact force
inline inline
const realx3TriSurfaceField_D& contactForceWall() const const auto& contactForceWall() const
{ {
return contactForceWall_; return contactForceWall_;
} }
/// Property ide of triangles
inline
const auto& propertyId()const
{
return propertyId_;
}
/// Access to property /// Access to property
inline const auto& wallProperty()const inline const auto& wallProperty()const
{ {
return wallProperty_; return wallProperty_;
} }
/// Owner repository
inline
const repository& owner()const
{
return geometryRepository_;
}
/// Owner repository
inline
repository& owner()
{
return geometryRepository_;
}
/// Path to the repository folder
inline auto path()
{
return owner().path();
}
/// The name of motion model /// The name of motion model
virtual virtual
word motionModelTypeName()const = 0; word motionModelTypeName()const = 0;
/// Motion model index of triangles /// Motion model index of triangles
virtual virtual
const int8Vector_HD& triMotionIndex() const =0; const uint32Field_D& triMotionIndex() const =0;
/// Motion model index of points /// Motion model index of points
virtual virtual
const int8Vector_HD& pointMotionIndex()const = 0; const uint32Field_D& pointMotionIndex()const = 0;
/// Property ide of triangles
const int8TriSurfaceField_D& propertyId() const
{
return propertyId_;
}
/// Operations before each iteration
bool beforeIteration() override; bool beforeIteration() override;
/// Operations after each iteration /// This is called in time loop. Perform the main calculations
/// when the component should evolve along time.
bool iterate() override;
/// This is called in time loop, after iterate.
bool afterIteration() override; bool afterIteration() override;
//- IO //- IO
bool read(iIstream& is, const IOPattern& iop) override;
/// write /// write
bool write()const bool write( iOstream& os, const IOPattern& iop )const override;
{
return owner().write();
}
//- Static members //- Static members
static static
uniquePtr<geometry> create(systemControl& control, const property& prop); uniquePtr<geometry> create(
systemControl& control,
const property& prop);
static static
uniquePtr<geometry> create( uniquePtr<geometry> create(
systemControl& control, systemControl& control,
const property& prop, const property& prop,
const dictionary& dict, multiTriSurface& surf,
const multiTriSurface& triSurface,
const wordVector& motionCompName, const wordVector& motionCompName,
const wordVector& propName); const wordVector& materialName,
const dictionary& motionDic);
}; };

View File

@ -21,41 +21,116 @@ Licence:
template<typename MotionModel> template<typename MotionModel>
bool pFlow::geometryMotion<MotionModel>::findMotionIndex() bool pFlow::geometryMotion<MotionModel>::findMotionIndex()
{ {
motionIndex_.clear();
triMotionIndex_.reserve( this->surface().capacity() );
triMotionIndex_.clear();
ForAll( surfI, motionComponentName_) if(motionComponentName().size() != numSurfaces() )
{ {
auto mName = motionComponentName_[surfI]; fatalErrorInFunction<<
auto mInd = motionModel_.nameToIndex(mName); "size of motion component names in the triSurface is not"<<
motionIndex_.push_back(mInd); " equal to size of number of sub-surfaces"<<endl;
// fill motionIndex for triangles of the surface return false;
int32 surfSize = this->surface().surfNumTriangles(surfI);
for(int32 i=0; i<surfSize; i++)
{
triMotionIndex_.push_back(mInd);
} }
}
motionIndex_.syncViews();
triMotionIndex_.syncViews();
pointMotionIndex_.reserve(triSurface_.numPoints()); uint32Vector surfMotionIndex("surfMotionIndex");
pointMotionIndex_.clear(); uint32Vector triMotionIndex("triMotionIndex");
uint32Vector pointMotionIndex("pointMotionIndex");
ForAll(surfI, motionIndex_) ForAll( surfI, motionComponentName())
{ {
auto nP = triSurface_.surfNumPoints(surfI); auto mName = motionComponentName()[surfI];
for(int32 i=0; i<nP; i++) uint32 mInd=0;
if( !motionModel_.nameToIndex(mName, mInd) )
{ {
pointMotionIndex_.push_back(motionIndex_[surfI]); fatalErrorInFunction<<
mName<< " does not exist in the list of motion names -> "<<
motionModel_.componentNames();
return false;
}
surfMotionIndex.push_back(mInd);
auto surfRange = subSurfaceRange(surfI);
for(uint32 i=0; i<surfRange.numElements(); i++)
{
triMotionIndex.push_back(mInd);
}
auto pointRange = subSurfacePointRange(surfI);
for(uint32 n=0; n<pointRange.numElements(); n++)
{
pointMotionIndex.push_back(mInd);
} }
} }
pointMotionIndex_.syncViews();
surfMotionIndex_.assign(surfMotionIndex);
triMotionIndex_.assign(triMotionIndex);
pointMotionIndex_.assign(pointMotionIndex);
return true; return true;
} }
namespace pFlow::GMotion
{
template<typename ModelInterface>
void moveGeometry(
real dt,
uint32 nPoints,
const ModelInterface& mModel,
const deviceViewType1D<uint32>& pointMIndexD,
const deviceViewType1D<realx3>& pointsD
)
{
Kokkos::parallel_for(
"geometryMotion<MotionModel>::movePoints",
deviceRPolicyStatic(0, nPoints),
LAMBDA_HD(uint32 i){
auto newPos = mModel.transferPoint(pointMIndexD[i], pointsD[i], dt);
pointsD[i] = newPos;
});
Kokkos::fence();
}
}
template<typename MotionModel>
bool pFlow::geometryMotion<MotionModel>::moveGeometry()
{
uint32 iter = this->currentIter();
real t = this->currentTime();
real dt = this->dt();
auto mModel = motionModel_.getModelInterface(iter, t, dt);
auto& pointMIndexD= pointMotionIndex_.deviceViewAll();
auto& pointsD = points().deviceViewAll();
pFlow::GMotion::moveGeometry(
dt,
numPoints(),
motionModel_.getModelInterface(iter, t, dt),
pointMotionIndex_.deviceViewAll(),
points().deviceViewAll()
);
/*Kokkos::parallel_for(
"geometryMotion<MotionModel>::movePoints",
deviceRPolicyStatic(0, numPoints()),
LAMBDA_HD(uint32 i){
auto newPos = mModel.transferPoint(pointMIndexD[i], pointsD[i], dt);
pointsD[i] = newPos;
});
Kokkos::fence();*/
// move the motion components
motionModel_.move(iter, t,dt);
// end of calculations
return true;
}
template<typename MotionModel> template<typename MotionModel>
pFlow::geometryMotion<MotionModel>::geometryMotion pFlow::geometryMotion<MotionModel>::geometryMotion
@ -65,96 +140,65 @@ pFlow::geometryMotion<MotionModel>::geometryMotion
) )
: :
geometry(control, prop), geometry(control, prop),
motionModel_( motionModel_
this->owner().template emplaceObject<MotionModel>( (
objectFile( objectFile
(
motionModelFile__, motionModelFile__,
"", "",
objectFile::READ_ALWAYS, objectFile::READ_ALWAYS,
objectFile::WRITE_ALWAYS objectFile::WRITE_ALWAYS
) ),
) owner()
), ),
moveGeomTimer_("move geometry", &this->timers()) moveGeomTimer_("move geometry", &this->timers())
{ {
findMotionIndex(); if(!findMotionIndex())
{
fatalExit;
}
} }
template<typename MotionModel> template <typename MotionModelType>
pFlow::geometryMotion<MotionModel>::geometryMotion pFlow::geometryMotion<MotionModelType>::geometryMotion
( (
systemControl &control, systemControl &control,
const property &prop, const property &prop,
const multiTriSurface& triSurface, multiTriSurface &surf,
const wordVector &motionCompName, const wordVector &motionCompName,
const wordVector& propName, const wordVector &materialName,
const MotionModel& motionModel const dictionary &motionDict
) )
: :
geometry( geometry
(
control, control,
prop, prop,
triSurface, surf,
motionCompName, motionCompName,
propName materialName,
motionDict
), ),
motionModel_( motionModel_
this->owner().template emplaceObject<MotionModel>( (
objectFile( objectFile
(
motionModelFile__, motionModelFile__,
"", "",
objectFile::READ_NEVER, objectFile::READ_NEVER,
objectFile::WRITE_ALWAYS objectFile::WRITE_ALWAYS
), ),
motionModel motionDict,
) owner()
), ),
moveGeomTimer_("move geometry", &this->timers()) moveGeomTimer_("move geometry", &this->timers())
{ {
findMotionIndex(); if(!findMotionIndex())
{
fatalExit;
}
} }
template<typename MotionModel>
pFlow::geometryMotion<MotionModel>::geometryMotion
(
systemControl& control,
const property& prop,
const dictionary& dict,
const multiTriSurface& triSurface,
const wordVector& motionCompName,
const wordVector& propName
)
:
geometry(
control,
prop,
dict,
triSurface,
motionCompName,
propName
),
motionModel_(
this->owner().template emplaceObject<MotionModel>(
objectFile(
motionModelFile__,
"",
objectFile::READ_NEVER,
objectFile::WRITE_ALWAYS
),
dict
)
),
moveGeomTimer_("move geometry", &this->timers())
{
findMotionIndex();
}
template<typename MotionModel>
bool pFlow::geometryMotion<MotionModel>::beforeIteration()
{
geometry::beforeIteration();
return true;
}
template<typename MotionModel> template<typename MotionModel>
bool pFlow::geometryMotion<MotionModel>::iterate() bool pFlow::geometryMotion<MotionModel>::iterate()
@ -163,46 +207,8 @@ bool pFlow::geometryMotion<MotionModel>::iterate()
{ {
moveGeomTimer_.start(); moveGeomTimer_.start();
moveGeometry(); moveGeometry();
this->calculateNormals();
moveGeomTimer_.end(); moveGeomTimer_.end();
} }
return true; return true;
} }
template<typename MotionModel>
bool pFlow::geometryMotion<MotionModel>::afterIteration()
{
geometry::afterIteration();
return true;
}
template<typename MotionModel>
bool pFlow::geometryMotion<MotionModel>::moveGeometry()
{
real dt = this->dt();
real t = this->currentTime();
auto pointMIndex= pointMotionIndex_.deviceVector();
auto mModel = motionModel_.getModel(t);
realx3* points = triSurface_.pointsData_D();
auto numPoints = triSurface_.numPoints();
Kokkos::parallel_for(
"geometryMotion<MotionModel>::movePoints",
numPoints,
LAMBDA_HD(int32 i){
auto newPos = mModel.transferPoint(pointMIndex[i], points[i], dt);
points[i] = newPos;
});
Kokkos::fence();
// move the motion components
motionModel_.move(t,dt);
// end of calculations
moveGeomTimer_.end();
return true;
}

View File

@ -20,9 +20,8 @@ Licence:
#ifndef __geometryMotion_hpp__ #ifndef __geometryMotion_hpp__
#define __geometryMotion_hpp__ #define __geometryMotion_hpp__
#include "vocabs.hpp"
#include "geometry.hpp" #include "geometry.hpp"
#include "VectorDuals.hpp"
namespace pFlow namespace pFlow
{ {
@ -41,19 +40,21 @@ public:
using MotionModel = MotionModelType; using MotionModel = MotionModelType;
protected: using ModelComponent = typename MotionModelType::ModelComponent;
private:
/// Ref to motion model /// Ref to motion model
MotionModel& motionModel_; MotionModelType motionModel_;
/// motion indext mapped on each surface /// motion indext mapped on each surface
int32Vector_HD motionIndex_; uint32Field_D surfMotionIndex_{"triMotionIndex"};
/// motion index mapped on each triangle /// motion index mapped on each triangle
int8Vector_HD triMotionIndex_; uint32Field_D triMotionIndex_ {"surfMotionIndex"};
/// motion index mapped on each point /// motion index mapped on each point
int8Vector_HD pointMotionIndex_; uint32Field_D pointMotionIndex_{"pointMotionIndex"};
/// timer for moveGeometry /// timer for moveGeometry
Timer moveGeomTimer_; Timer moveGeomTimer_;
@ -61,32 +62,25 @@ protected:
/// determine the motion index of each triangle /// determine the motion index of each triangle
bool findMotionIndex(); bool findMotionIndex();
/// Move geometry
bool moveGeometry();
public: public:
/// Type info /// Type info
TypeInfoTemplate("geometry", MotionModel); TypeInfoTemplate11("geometry", ModelComponent);
// - Constructors // - Constructors
geometryMotion(systemControl& control, const property& prop); geometryMotion(systemControl& control, const property& prop);
geometryMotion( geometryMotion(
systemControl& control, systemControl& control,
const property& prop, const property& prop,
const multiTriSurface& triSurface, multiTriSurface& surf,
const wordVector& motionCompName, const wordVector& motionCompName,
const wordVector& propName, const wordVector& materialName,
const MotionModel& motionModel); const dictionary& motionDict);
/// Construct from components and dictionary that contains
/// motionModel
geometryMotion(systemControl& control,
const property& prop,
const dictionary& dict,
const multiTriSurface& triSurface,
const wordVector& motionCompName,
const wordVector& propName);
/// Add virtual constructor /// Add virtual constructor
add_vCtor add_vCtor
@ -107,9 +101,9 @@ public:
// - Methods // - Methods
/// Obtain motion model at time t /// Obtain motion model at time t
auto getModel(real t)const auto getModel(uint32 iter, real t, real dt)const
{ {
return motionModel_.getModel(t); return motionModel_.getModelInterface(iter, t, dt);
} }
/// TypeName / TypeInfo of motion model /// TypeName / TypeInfo of motion model
@ -119,28 +113,21 @@ public:
} }
/// Access to motion model index of triangles /// Access to motion model index of triangles
const int8Vector_HD& triMotionIndex()const override const uint32Field_D& triMotionIndex()const override
{ {
return triMotionIndex_; return triMotionIndex_;
} }
/// Access to motion model index of points /// Access to motion model index of points
const int8Vector_HD& pointMotionIndex()const override const uint32Field_D& pointMotionIndex()const override
{ {
return pointMotionIndex_; return pointMotionIndex_;
} }
/// Operations before each iteration
bool beforeIteration() override;
/// Iterate geometry one time step /// Iterate geometry one time step
bool iterate() override ; bool iterate() override ;
/// Operations after each iteration
bool afterIteration() override;
/// Move geometry
bool moveGeometry();
}; };
@ -148,9 +135,6 @@ public:
#include "geometryMotion.cpp" #include "geometryMotion.cpp"
#ifndef BUILD_SHARED_LIBS
#include "geometryMotionsInstantiate.cpp"
#endif
#endif //__geometryMotion_hpp__ #endif //__geometryMotion_hpp__

View File

@ -17,9 +17,15 @@ Licence:
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/ -----------------------------------------------------------------------------*/
#include "geometryMotions.hpp" #include "geometryMotions.hpp"
#ifdef BUILD_SHARED_LIBS
#include "geometryMotionsInstantiate.cpp" template class pFlow::geometryMotion<pFlow::vibratingMotion>;
#endif
template class pFlow::geometryMotion<pFlow::rotatingAxisMotion>;
template class pFlow::geometryMotion<pFlow::stationaryWall>;
template class pFlow::geometryMotion<pFlow::conveyorBeltMotion>;
//template class pFlow::geometryMotion<pFlow::multiRotatingAxisMotion>;

View File

@ -22,22 +22,26 @@ Licence:
#define __geometryMotions_hpp__ #define __geometryMotions_hpp__
#include "geometryMotion.hpp" #include "geometryMotion.hpp"
#include "fixedWall.hpp" #include "stationaryWall.hpp"
#include "rotatingAxisMotion.hpp" #include "rotatingAxisMotion.hpp"
#include "multiRotatingAxisMotion.hpp" #include "conveyorBeltMotion.hpp"
//#include "multiRotatingAxisMotion.hpp"
#include "vibratingMotion.hpp" #include "vibratingMotion.hpp"
namespace pFlow namespace pFlow
{ {
typedef geometryMotion<vibratingMotion> vibratingMotionGeometry; using vibratingMotionGeometry = geometryMotion<vibratingMotion>;
typedef geometryMotion<rotatingAxisMotion> rotationAxisMotionGeometry; using rotationAxisMotionGeometry = geometryMotion<rotatingAxisMotion>;
typedef geometryMotion<multiRotatingAxisMotion> multiRotationAxisMotionGeometry; using stationaryGeometry = geometryMotion<stationaryWall>;
using conveyorBeltMotionGeometry = geometryMotion<conveyorBeltMotion>;
//typedef geometryMotion<multiRotatingAxisMotion> multiRotationAxisMotionGeometry;
typedef geometryMotion<fixedWall> fixedGeometry;

View File

@ -0,0 +1,63 @@
#ifndef __AB2Kernels_hpp__
#define __AB2Kernels_hpp__
#include "KokkosTypes.hpp"
#include "types.hpp"
namespace pFlow::AB2Kernels
{
inline
bool intAllActive(
const word& name,
real dt,
rangeU32 activeRng,
const deviceViewType1D<realx3>& y,
const deviceViewType1D<realx3>& dy,
const deviceViewType1D<realx3>& dy1
)
{
Kokkos::parallel_for(
name,
deviceRPolicyStatic (activeRng.start(), activeRng.end()),
LAMBDA_HD(uint32 i){
y[i] += dt*(static_cast<real>(1.5) * dy[i] - static_cast<real>(0.5) * dy1[i]);
dy1[i] = dy[i];
});
Kokkos::fence();
return true;
}
inline
bool intScattered
(
const word& name,
real dt,
const pFlagTypeDevice& activePoints,
const deviceViewType1D<realx3>& y,
const deviceViewType1D<realx3>& dy,
const deviceViewType1D<realx3>& dy1
)
{
Kokkos::parallel_for(
name,
deviceRPolicyStatic (activePoints.activeRange().start(), activePoints.activeRange().end()),
LAMBDA_HD(uint32 i){
if( activePoints(i))
{
y[i] += dt*(static_cast<real>(1.5) * dy[i] - static_cast<real>(0.5) * dy1[i]);
dy1[i] = dy[i];
}
});
Kokkos::fence();
return true;
}
}
#endif

View File

@ -19,61 +19,171 @@ Licence:
-----------------------------------------------------------------------------*/ -----------------------------------------------------------------------------*/
#include "AdamsBashforth2.hpp" #include "AdamsBashforth2.hpp"
#include "pointStructure.hpp"
#include "Time.hpp"
#include "vocabs.hpp"
//const real AB2_coef[] = { 3.0 / 2.0, 1.0 / 2.0}; namespace pFlow
{
/// Range policy for integration kernel (alias)
using rpIntegration = Kokkos::RangePolicy<
DefaultExecutionSpace,
Kokkos::Schedule<Kokkos::Static>,
Kokkos::IndexType<uint32>
>;
bool intAllActive(
real dt,
realx3Field_D& y,
realx3PointField_D& dy,
realx3PointField_D& dy1)
{
auto d_dy = dy.deviceView();
auto d_y = y.deviceView();
auto d_dy1= dy1.deviceView();
auto activeRng = dy1.activeRange();
Kokkos::parallel_for(
"AdamsBashforth2::correct",
rpIntegration (activeRng.start(), activeRng.end()),
LAMBDA_HD(uint32 i){
d_y[i] += dt*(static_cast<real>(1.5) * d_dy[i] - static_cast<real>(0.5) * d_dy1[i]);
d_dy1[i] = d_dy[i];
});
Kokkos::fence();
return true;
}
bool intScattered
(
real dt,
realx3Field_D& y,
realx3PointField_D& dy,
realx3PointField_D& dy1
)
{
auto d_dy = dy.deviceView();
auto d_y = y.deviceView();
auto d_dy1 = dy1.deviceView();
auto activeRng = dy1.activeRange();
const auto& activeP = dy1.activePointsMaskDevice();
Kokkos::parallel_for(
"AdamsBashforth2::correct",
rpIntegration (activeRng.start(), activeRng.end()),
LAMBDA_HD(uint32 i){
if( activeP(i))
{
d_y[i] += dt*(static_cast<real>(1.5) * d_dy[i] - static_cast<real>(0.5) * d_dy1[i]);
d_dy1[i] = d_dy[i];
}
});
Kokkos::fence();
return true;
}
}
pFlow::AdamsBashforth2::AdamsBashforth2 pFlow::AdamsBashforth2::AdamsBashforth2
( (
const word& baseName, const word& baseName,
repository& owner, pointStructure& pStruct,
const pointStructure& pStruct, const word& method,
const word& method const realx3Field_D& initialValField
) )
: :
integration(baseName, owner, pStruct, method), integration(baseName, pStruct, method, initialValField),
dy1_( realx3PointField_D
owner.emplaceObject<realx3PointField_D>( (
objectFile( objectFile
(
groupNames(baseName,"dy1"), groupNames(baseName,"dy1"),
"", pStruct.time().integrationFolder(),
objectFile::READ_IF_PRESENT, objectFile::READ_IF_PRESENT,
objectFile::WRITE_ALWAYS), objectFile::WRITE_ALWAYS
),
pStruct, pStruct,
zero3)) zero3,
{ zero3
),
boundaryList_(pStruct, method, *this)
{}
void pFlow::AdamsBashforth2::updateBoundariesSlaveToMasterIfRequested()
{
realx3PointField_D::updateBoundariesSlaveToMasterIfRequested();
}
bool pFlow::AdamsBashforth2::predict(
real UNUSED(dt),
realx3PointField_D &UNUSED(y),
realx3PointField_D &UNUSED(dy))
{
return true;
} }
bool pFlow::AdamsBashforth2::predict bool pFlow::AdamsBashforth2::predict
( (
real UNUSED(dt), real dt,
realx3Vector_D& UNUSED(y), realx3Field_D &y,
realx3Vector_D& UNUSED(dy) realx3PointField_D &dy
) )
{ {
return true; return true;
} }
bool pFlow::AdamsBashforth2::correct bool pFlow::AdamsBashforth2::correct
( (
real dt, real dt,
realx3Vector_D& y, realx3PointField_D& y,
realx3Vector_D& dy realx3PointField_D& dy
) )
{ {
if(this->pStruct().allActive()) auto& dy1l = dy1();
bool success = false;
if(dy1l.isAllActive())
{ {
return intAll(dt, y, dy, this->pStruct().activeRange()); success = intAllActive(dt, y.field(), dy, dy1l);
} }
else else
{ {
return intRange(dt, y, dy, this->pStruct().activePointsMaskD()); success = intScattered(dt, y.field(), dy, dy1l);
} }
return true; success = success && boundaryList_.correct(dt, y, dy);
return success;
} }
bool pFlow::AdamsBashforth2::correctPStruct(
real dt,
pointStructure &pStruct,
realx3PointField_D &vel)
{
auto& dy1l = dy1();
bool success = false;
if(dy1l.isAllActive())
{
success = intAllActive(dt, pStruct.pointPosition(), vel, dy1l);
}
else
{
success = intScattered(dt, pStruct.pointPosition(), vel, dy1l);
}
success = success && boundaryList_.correctPStruct(dt, pStruct, vel);
return success;
}
bool pFlow::AdamsBashforth2::setInitialVals( bool pFlow::AdamsBashforth2::setInitialVals(
const int32IndexContainer& newIndices, const int32IndexContainer& newIndices,
const realx3Vector& y) const realx3Vector& y)
@ -81,25 +191,3 @@ bool pFlow::AdamsBashforth2::setInitialVals(
return true; return true;
} }
bool pFlow::AdamsBashforth2::intAll(
real dt,
realx3Vector_D& y,
realx3Vector_D& dy,
range activeRng)
{
auto d_dy = dy.deviceVectorAll();
auto d_y = y.deviceVectorAll();
auto d_dy1= dy1_.deviceVectorAll();
Kokkos::parallel_for(
"AdamsBashforth2::correct",
rpIntegration (activeRng.first, activeRng.second),
LAMBDA_HD(int32 i){
d_y[i] += dt*(static_cast<real>(3.0 / 2.0) * d_dy[i] - static_cast<real>(1.0 / 2.0) * d_dy1[i]);
d_dy1[i] = d_dy[i];
});
Kokkos::fence();
return true;
}

View File

@ -17,13 +17,13 @@ Licence:
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/ -----------------------------------------------------------------------------*/
#ifndef __AdamsBashforth2_hpp__ #ifndef __AdamsBashforth2_hpp__
#define __AdamsBashforth2_hpp__ #define __AdamsBashforth2_hpp__
#include "integration.hpp" #include "integration.hpp"
#include "pointFields.hpp" #include "pointFields.hpp"
#include "boundaryIntegrationList.hpp"
namespace pFlow namespace pFlow
{ {
@ -36,41 +36,41 @@ namespace pFlow
*/ */
class AdamsBashforth2 class AdamsBashforth2
: :
public integration public integration,
public realx3PointField_D
{ {
protected: private:
/// dy at t-dt boundaryIntegrationList boundaryList_;
realx3PointField_D& dy1_;
/// Range policy for integration kernel (alias) friend class processorAB2BoundaryIntegration;
using rpIntegration = Kokkos::RangePolicy<
DefaultExecutionSpace, const auto& dy1()const
Kokkos::Schedule<Kokkos::Static>, {
Kokkos::IndexType<int32> return static_cast<const realx3PointField_D&>(*this);
>; }
auto& dy1()
{
return static_cast<realx3PointField_D&>(*this);
}
public: public:
/// Type info /// Class info
TypeInfo("AdamsBashforth2"); ClassInfo("AdamsBashforth2");
// - Constructors // - Constructors
/// Construct from components /// Construct from components
AdamsBashforth2( AdamsBashforth2(
const word& baseName, const word& baseName,
repository& owner, pointStructure& pStruct,
const pointStructure& pStruct, const word& method,
const word& method); const realx3Field_D& initialValField);
uniquePtr<integration> clone()const override
{
return makeUnique<AdamsBashforth2>(*this);
}
/// Destructor /// Destructor
virtual ~AdamsBashforth2()=default; ~AdamsBashforth2()final = default;
/// Add this to the virtual constructor table /// Add this to the virtual constructor table
add_vCtor( add_vCtor(
@ -81,70 +81,55 @@ public:
// - Methods // - Methods
void updateBoundariesSlaveToMasterIfRequested()override;
/// return integration method
word method()const override
{
return "AdamsBashforth2";
}
bool predict( bool predict(
real UNUSED(dt), real UNUSED(dt),
realx3Vector_D& UNUSED(y), realx3PointField_D& UNUSED(y),
realx3Vector_D& UNUSED(dy)) override; realx3PointField_D& UNUSED(dy)) final;
bool predict(
real dt,
realx3Field_D& y,
realx3PointField_D& dy) final;
bool correct( bool correct(
real dt, real dt,
realx3Vector_D& y, realx3PointField_D& y,
realx3Vector_D& dy) override; realx3PointField_D& dy) final;
bool correctPStruct(
real dt,
pointStructure& pStruct,
realx3PointField_D& vel) final;
/*bool hearChanges
(
real t,
real dt,
uint32 iter,
const message& msg,
const anyList& varList
) override;*/
bool setInitialVals( bool setInitialVals(
const int32IndexContainer& newIndices, const int32IndexContainer& newIndices,
const realx3Vector& y) override; const realx3Vector& y) final;
bool needSetInitialVals()const override bool needSetInitialVals()const final
{ {
return false; return false;
} }
/// Integrate on all points in the active range
bool intAll(
real dt,
realx3Vector_D& y,
realx3Vector_D& dy,
range activeRng);
/// Integrate on active points in the active range
template<typename activeFunctor>
bool intRange(
real dt,
realx3Vector_D& y,
realx3Vector_D& dy,
activeFunctor activeP );
}; };
template<typename activeFunctor>
bool pFlow::AdamsBashforth2::intRange(
real dt,
realx3Vector_D& y,
realx3Vector_D& dy,
activeFunctor activeP )
{
auto d_dy = dy.deviceVectorAll();
auto d_y = y.deviceVectorAll();
auto d_dy1= dy1_.deviceVectorAll();
auto activeRng = activeP.activeRange();
Kokkos::parallel_for(
"AdamsBashforth2::correct",
rpIntegration (activeRng.first, activeRng.second),
LAMBDA_HD(int32 i){
if( activeP(i))
{
d_y[i] += dt*(static_cast<real>(3.0 / 2.0) * d_dy[i] - static_cast<real>(1.0 / 2.0) * d_dy1[i]);
d_dy1[i] = d_dy[i];
}
});
Kokkos::fence();
return true;
}
} // pFlow } // pFlow

View File

@ -89,9 +89,9 @@ bool pFlow::AdamsBashforth3::intAll(
realx3Vector_D& dy, realx3Vector_D& dy,
range activeRng) range activeRng)
{ {
auto d_dy = dy.deviceVectorAll(); auto d_dy = dy.deviceViewAll();
auto d_y = y.deviceVectorAll(); auto d_y = y.deviceViewAll();
auto d_history = history_.deviceVectorAll(); auto d_history = history_.deviceViewAll();
Kokkos::parallel_for( Kokkos::parallel_for(
"AdamsBashforth3::correct", "AdamsBashforth3::correct",

View File

@ -160,9 +160,9 @@ bool pFlow::AdamsBashforth3::intRange(
realx3Vector_D& dy, realx3Vector_D& dy,
activeFunctor activeP ) activeFunctor activeP )
{ {
auto d_dy = dy.deviceVectorAll(); auto d_dy = dy.deviceViewAll();
auto d_y = y.deviceVectorAll(); auto d_y = y.deviceViewAll();
auto d_history = history_.deviceVectorAll(); auto d_history = history_.deviceViewAll();
auto activeRng = activeP.activeRange(); auto activeRng = activeP.activeRange();
Kokkos::parallel_for( Kokkos::parallel_for(

View File

@ -89,9 +89,9 @@ bool pFlow::AdamsBashforth4::intAll(
realx3Vector_D& dy, realx3Vector_D& dy,
range activeRng) range activeRng)
{ {
auto d_dy = dy.deviceVectorAll(); auto d_dy = dy.deviceViewAll();
auto d_y = y.deviceVectorAll(); auto d_y = y.deviceViewAll();
auto d_history = history_.deviceVectorAll(); auto d_history = history_.deviceViewAll();
Kokkos::parallel_for( Kokkos::parallel_for(
"AdamsBashforth4::correct", "AdamsBashforth4::correct",

View File

@ -165,9 +165,9 @@ bool pFlow::AdamsBashforth4::intRange(
realx3Vector_D& dy, realx3Vector_D& dy,
activeFunctor activeP ) activeFunctor activeP )
{ {
auto d_dy = dy.deviceVectorAll(); auto d_dy = dy.deviceViewAll();
auto d_y = y.deviceVectorAll(); auto d_y = y.deviceViewAll();
auto d_history = history_.deviceVectorAll(); auto d_history = history_.deviceViewAll();
auto activeRng = activeP.activeRange(); auto activeRng = activeP.activeRange();
Kokkos::parallel_for( Kokkos::parallel_for(

View File

@ -89,9 +89,9 @@ bool pFlow::AdamsBashforth5::intAll(
realx3Vector_D& dy, realx3Vector_D& dy,
range activeRng) range activeRng)
{ {
auto d_dy = dy.deviceVectorAll(); auto d_dy = dy.deviceViewAll();
auto d_y = y.deviceVectorAll(); auto d_y = y.deviceViewAll();
auto d_history = history_.deviceVectorAll(); auto d_history = history_.deviceViewAll();
Kokkos::parallel_for( Kokkos::parallel_for(
"AdamsBashforth5::correct", "AdamsBashforth5::correct",

View File

@ -165,9 +165,9 @@ bool pFlow::AdamsBashforth5::intRange(
realx3Vector_D& dy, realx3Vector_D& dy,
activeFunctor activeP ) activeFunctor activeP )
{ {
auto d_dy = dy.deviceVectorAll(); auto d_dy = dy.deviceViewAll();
auto d_y = y.deviceVectorAll(); auto d_y = y.deviceViewAll();
auto d_history = history_.deviceVectorAll(); auto d_history = history_.deviceViewAll();
auto activeRng = activeP.activeRange(); auto activeRng = activeP.activeRange();
Kokkos::parallel_for( Kokkos::parallel_for(

View File

@ -124,11 +124,11 @@ bool pFlow::AdamsMoulton3::predictAll(
range activeRng) range activeRng)
{ {
auto d_dy = dy.deviceVectorAll(); auto d_dy = dy.deviceViewAll();
auto d_y = y.deviceVectorAll(); auto d_y = y.deviceViewAll();
auto d_y0 = y0_.deviceVectorAll(); auto d_y0 = y0_.deviceViewAll();
auto d_dy0 = dy0_.deviceVectorAll(); auto d_dy0 = dy0_.deviceViewAll();
auto d_dy1= dy1_.deviceVectorAll(); auto d_dy1= dy1_.deviceViewAll();
Kokkos::parallel_for( Kokkos::parallel_for(
"AdamsMoulton3::predict", "AdamsMoulton3::predict",
@ -150,12 +150,12 @@ bool pFlow::AdamsMoulton3::intAll(
range activeRng) range activeRng)
{ {
auto d_dy = dy.deviceVectorAll(); auto d_dy = dy.deviceViewAll();
auto d_y = y.deviceVectorAll(); auto d_y = y.deviceViewAll();
auto d_dy0 = dy0_.deviceVectorAll(); auto d_dy0 = dy0_.deviceViewAll();
auto d_y0 = y0_.deviceVectorAll(); auto d_y0 = y0_.deviceViewAll();
auto d_dy1 = dy1_.deviceVectorAll(); auto d_dy1 = dy1_.deviceViewAll();
Kokkos::parallel_for( Kokkos::parallel_for(
"AdamsMoulton3::correct", "AdamsMoulton3::correct",

View File

@ -144,11 +144,11 @@ bool AdamsMoulton3::predictRange(
realx3Vector_D& dy, realx3Vector_D& dy,
activeFunctor activeP) activeFunctor activeP)
{ {
auto d_dy = dy.deviceVectorAll(); auto d_dy = dy.deviceViewAll();
auto d_y = y.deviceVectorAll(); auto d_y = y.deviceViewAll();
auto d_y0 = y0_.deviceVectorAll(); auto d_y0 = y0_.deviceViewAll();
auto d_dy0 = dy0_.deviceVectorAll(); auto d_dy0 = dy0_.deviceViewAll();
auto d_dy1= dy1_.deviceVectorAll(); auto d_dy1= dy1_.deviceViewAll();
auto activeRng = activeP.activeRange(); auto activeRng = activeP.activeRange();
@ -182,12 +182,12 @@ bool pFlow::AdamsMoulton3::intRange(
activeFunctor activeP) activeFunctor activeP)
{ {
auto d_dy = dy.deviceVectorAll(); auto d_dy = dy.deviceViewAll();
auto d_y = y.deviceVectorAll(); auto d_y = y.deviceViewAll();
auto d_dy0 = dy0_.deviceVectorAll(); auto d_dy0 = dy0_.deviceViewAll();
auto d_y0 = y0_.deviceVectorAll(); auto d_y0 = y0_.deviceViewAll();
auto d_dy1 = dy1_.deviceVectorAll(); auto d_dy1 = dy1_.deviceViewAll();
auto activeRng = activeP.activeRange(); auto activeRng = activeP.activeRange();

View File

@ -135,13 +135,13 @@ bool pFlow::AdamsMoulton4::predictAll(
range activeRng) range activeRng)
{ {
auto d_dy = dy.deviceVectorAll(); auto d_dy = dy.deviceViewAll();
auto d_y = y.deviceVectorAll(); auto d_y = y.deviceViewAll();
auto d_y0 = y0_.deviceVectorAll(); auto d_y0 = y0_.deviceViewAll();
auto d_dy0 = dy0_.deviceVectorAll(); auto d_dy0 = dy0_.deviceViewAll();
auto d_dy1 = dy1_.deviceVectorAll(); auto d_dy1 = dy1_.deviceViewAll();
auto d_dy2 = dy2_.deviceVectorAll(); auto d_dy2 = dy2_.deviceViewAll();
Kokkos::parallel_for( Kokkos::parallel_for(
"AdamsMoulton4::predict", "AdamsMoulton4::predict",
@ -165,13 +165,13 @@ bool pFlow::AdamsMoulton4::intAll(
range activeRng) range activeRng)
{ {
auto d_dy = dy.deviceVectorAll(); auto d_dy = dy.deviceViewAll();
auto d_y = y.deviceVectorAll(); auto d_y = y.deviceViewAll();
auto d_dy0 = dy0_.deviceVectorAll(); auto d_dy0 = dy0_.deviceViewAll();
auto d_y0 = y0_.deviceVectorAll(); auto d_y0 = y0_.deviceViewAll();
auto d_dy1 = dy1_.deviceVectorAll(); auto d_dy1 = dy1_.deviceViewAll();
auto d_dy2 = dy2_.deviceVectorAll(); auto d_dy2 = dy2_.deviceViewAll();
Kokkos::parallel_for( Kokkos::parallel_for(
"AdamsMoulton4::correct", "AdamsMoulton4::correct",

View File

@ -147,13 +147,13 @@ bool AdamsMoulton4::predictRange(
realx3Vector_D& dy, realx3Vector_D& dy,
activeFunctor activeP ) activeFunctor activeP )
{ {
auto d_dy = dy.deviceVectorAll(); auto d_dy = dy.deviceViewAll();
auto d_y = y.deviceVectorAll(); auto d_y = y.deviceViewAll();
auto d_y0 = y0_.deviceVectorAll(); auto d_y0 = y0_.deviceViewAll();
auto d_dy0 = dy0_.deviceVectorAll(); auto d_dy0 = dy0_.deviceViewAll();
auto d_dy1 = dy1_.deviceVectorAll(); auto d_dy1 = dy1_.deviceViewAll();
auto d_dy2 = dy2_.deviceVectorAll(); auto d_dy2 = dy2_.deviceViewAll();
auto activeRng = activeP.activeRange(); auto activeRng = activeP.activeRange();
@ -185,13 +185,13 @@ bool pFlow::AdamsMoulton4::intRange(
activeFunctor activeP ) activeFunctor activeP )
{ {
auto d_dy = dy.deviceVectorAll(); auto d_dy = dy.deviceViewAll();
auto d_y = y.deviceVectorAll(); auto d_y = y.deviceViewAll();
auto d_dy0 = dy0_.deviceVectorAll(); auto d_dy0 = dy0_.deviceViewAll();
auto d_y0 = y0_.deviceVectorAll(); auto d_y0 = y0_.deviceViewAll();
auto d_dy1 = dy1_.deviceVectorAll(); auto d_dy1 = dy1_.deviceViewAll();
auto d_dy2 = dy2_.deviceVectorAll(); auto d_dy2 = dy2_.deviceViewAll();
auto activeRng = activeP.activeRange(); auto activeRng = activeP.activeRange();

View File

@ -145,14 +145,14 @@ bool pFlow::AdamsMoulton5::predictAll(
range activeRng) range activeRng)
{ {
auto d_dy = dy.deviceVectorAll(); auto d_dy = dy.deviceViewAll();
auto d_y = y.deviceVectorAll(); auto d_y = y.deviceViewAll();
auto d_y0 = y0_.deviceVectorAll(); auto d_y0 = y0_.deviceViewAll();
auto d_dy0 = dy0_.deviceVectorAll(); auto d_dy0 = dy0_.deviceViewAll();
auto d_dy1 = dy1_.deviceVectorAll(); auto d_dy1 = dy1_.deviceViewAll();
auto d_dy2 = dy2_.deviceVectorAll(); auto d_dy2 = dy2_.deviceViewAll();
auto d_dy3 = dy3_.deviceVectorAll(); auto d_dy3 = dy3_.deviceViewAll();
Kokkos::parallel_for( Kokkos::parallel_for(
"AdamsMoulton5::predict", "AdamsMoulton5::predict",
@ -178,14 +178,14 @@ bool pFlow::AdamsMoulton5::intAll(
range activeRng) range activeRng)
{ {
auto d_dy = dy.deviceVectorAll(); auto d_dy = dy.deviceViewAll();
auto d_y = y.deviceVectorAll(); auto d_y = y.deviceViewAll();
auto d_dy0 = dy0_.deviceVectorAll(); auto d_dy0 = dy0_.deviceViewAll();
auto d_y0 = y0_.deviceVectorAll(); auto d_y0 = y0_.deviceViewAll();
auto d_dy1 = dy1_.deviceVectorAll(); auto d_dy1 = dy1_.deviceViewAll();
auto d_dy2 = dy2_.deviceVectorAll(); auto d_dy2 = dy2_.deviceViewAll();
auto d_dy3 = dy3_.deviceVectorAll(); auto d_dy3 = dy3_.deviceViewAll();
Kokkos::parallel_for( Kokkos::parallel_for(
"AdamsMoulton5::correct", "AdamsMoulton5::correct",

View File

@ -150,14 +150,14 @@ bool AdamsMoulton5::predictRange(
realx3Vector_D& dy, realx3Vector_D& dy,
activeFunctor activeP ) activeFunctor activeP )
{ {
auto d_dy = dy.deviceVectorAll(); auto d_dy = dy.deviceViewAll();
auto d_y = y.deviceVectorAll(); auto d_y = y.deviceViewAll();
auto d_y0 = y0_.deviceVectorAll(); auto d_y0 = y0_.deviceViewAll();
auto d_dy0 = dy0_.deviceVectorAll(); auto d_dy0 = dy0_.deviceViewAll();
auto d_dy1 = dy1_.deviceVectorAll(); auto d_dy1 = dy1_.deviceViewAll();
auto d_dy2 = dy2_.deviceVectorAll(); auto d_dy2 = dy2_.deviceViewAll();
auto d_dy3 = dy3_.deviceVectorAll(); auto d_dy3 = dy3_.deviceViewAll();
auto activeRng = activeP.activeRange(); auto activeRng = activeP.activeRange();
@ -189,14 +189,14 @@ bool pFlow::AdamsMoulton5::intRange(
activeFunctor activeP ) activeFunctor activeP )
{ {
auto d_dy = dy.deviceVectorAll(); auto d_dy = dy.deviceViewAll();
auto d_y = y.deviceVectorAll(); auto d_y = y.deviceViewAll();
auto d_dy0 = dy0_.deviceVectorAll(); auto d_dy0 = dy0_.deviceViewAll();
auto d_y0 = y0_.deviceVectorAll(); auto d_y0 = y0_.deviceViewAll();
auto d_dy1 = dy1_.deviceVectorAll(); auto d_dy1 = dy1_.deviceViewAll();
auto d_dy2 = dy2_.deviceVectorAll(); auto d_dy2 = dy2_.deviceViewAll();
auto d_dy3 = dy3_.deviceVectorAll(); auto d_dy3 = dy3_.deviceViewAll();
auto activeRng = activeP.activeRange(); auto activeRng = activeP.activeRange();

View File

@ -1,15 +1,22 @@
list(APPEND SourceFiles list(APPEND SourceFiles
integration/integration.cpp integration/integration.cpp
AdamsBashforth5/AdamsBashforth5.cpp boundaries/boundaryIntegration.cpp
AdamsBashforth4/AdamsBashforth4.cpp boundaries/boundaryIntegrationList.cpp
AdamsBashforth3/AdamsBashforth3.cpp
AdamsBashforth2/AdamsBashforth2.cpp AdamsBashforth2/AdamsBashforth2.cpp
AdamsMoulton3/AdamsMoulton3.cpp #AdamsBashforth5/AdamsBashforth5.cpp
AdamsMoulton4/AdamsMoulton4.cpp #AdamsBashforth4/AdamsBashforth4.cpp
AdamsMoulton5/AdamsMoulton5.cpp #AdamsBashforth3/AdamsBashforth3.cpp
#AdamsMoulton3/AdamsMoulton3.cpp
#AdamsMoulton4/AdamsMoulton4.cpp
#AdamsMoulton5/AdamsMoulton5.cpp
) )
if(pFlow_Build_MPI)
list(APPEND SourceFiles
AdamsBashforth2/processorAB2BoundaryIntegration.cpp)
endif()
set(link_libs Kokkos::kokkos phasicFlow) set(link_libs Kokkos::kokkos phasicFlow)
pFlow_add_library_install(Integration SourceFiles link_libs) pFlow_add_library_install(Integration SourceFiles link_libs)

View File

@ -0,0 +1,55 @@
#include "boundaryIntegration.hpp"
#include "pointStructure.hpp"
pFlow::boundaryIntegration::boundaryIntegration(
const boundaryBase &boundary,
const pointStructure &pStruct,
const word &method,
integration& intgrtn
)
:
generalBoundary(boundary, pStruct, "", method),
integration_(intgrtn)
{}
pFlow::uniquePtr<pFlow::boundaryIntegration> pFlow::boundaryIntegration::create(
const boundaryBase &boundary,
const pointStructure &pStruct,
const word &method,
integration& intgrtn
)
{
word bType = angleBracketsNames2(
"boundaryIntegration",
boundary.type(),
method);
word altBType{"boundaryIntegration<none>"};
if( boundaryBasevCtorSelector_.search(bType) )
{
pOutput.space(4)<<"Creating boundary "<< Green_Text(bType)<<
" for "<<boundary.name()<<endl;
return boundaryBasevCtorSelector_[bType](boundary, pStruct, method, intgrtn);
}
else if(boundaryBasevCtorSelector_.search(altBType))
{
pOutput.space(4)<<"Creating boundary "<< Green_Text(altBType)<<
" for "<<boundary.name()<<endl;
return boundaryBasevCtorSelector_[altBType](boundary, pStruct, method, intgrtn);
}
else
{
printKeys(
fatalError << "Ctor Selector "<< bType<<
" and "<< altBType << " do not exist. \n"
<<"Avaiable ones are: \n",
boundaryBasevCtorSelector_
);
fatalExit;
}
return nullptr;
}

View File

@ -0,0 +1,91 @@
#ifndef __boundaryIntegration_hpp__
#define __boundaryIntegration_hpp__
#include "generalBoundary.hpp"
#include "virtualConstructor.hpp"
#include "pointFields.hpp"
namespace pFlow
{
class integration;
class boundaryIntegration
:
public generalBoundary
{
private:
const integration& integration_;
public:
TypeInfo("boundaryIntegration<none>");
boundaryIntegration(
const boundaryBase& boundary,
const pointStructure& pStruct,
const word& method,
integration& intgrtn);
~boundaryIntegration()override = default;
create_vCtor(
boundaryIntegration,
boundaryBase,
(
const boundaryBase& boundary,
const pointStructure& pStruct,
const word& method,
integration& intgrtn
),
(boundary, pStruct, method, intgrtn)
);
add_vCtor(
boundaryIntegration,
boundaryIntegration,
boundaryBase
);
bool hearChanges(
real t,
real dt,
uint32 iter,
const message &msg,
const anyList &varList) override
{
return true;
}
const integration& Integration()const
{
return integration_;
}
virtual
bool correct(real dt, const realx3PointField_D& y, const realx3PointField_D& dy)
{
return true;
}
virtual
bool correctPStruct(real dt, const realx3PointField_D& vel)
{
return true;
}
static
uniquePtr<boundaryIntegration> create(
const boundaryBase& boundary,
const pointStructure& pStruct,
const word& method,
integration& intgrtn);
};
}
#endif

View File

@ -0,0 +1,59 @@
#include "boundaryIntegrationList.hpp"
#include "integration.hpp"
pFlow::boundaryIntegrationList::boundaryIntegrationList(
const pointStructure &pStruct,
const word &method,
integration &intgrtn
)
:
ListPtr<boundaryIntegration>(6),
boundaries_(pStruct.boundaries())
{
for(uint32 i=0; i<6; i++)
{
this->set(
i,
boundaryIntegration::create(
boundaries_[i],
pStruct,
method,
intgrtn
)
);
}
}
bool pFlow::boundaryIntegrationList::correct(real dt, realx3PointField_D &y, realx3PointField_D &dy)
{
for(auto& bndry:*this)
{
if(!bndry->correct(dt, y, dy))
{
fatalErrorInFunction<<"Error in correcting boundary "<<
bndry->boundaryName()<<endl;
return false;
}
}
return true;
}
bool pFlow::boundaryIntegrationList::correctPStruct(
real dt,
pointStructure &pStruct,
const realx3PointField_D &vel)
{
for(auto& bndry:*this)
{
if(!bndry->correctPStruct(dt, vel))
{
fatalErrorInFunction<<"Error in correcting boundary "<<
bndry->boundaryName()<<" in pointStructure."<<endl;
return false;
}
}
return true;
}

View File

@ -0,0 +1,51 @@
#ifndef __boundaryIntegrationList_hpp__
#define __boundaryIntegrationList_hpp__
#include "boundaryList.hpp"
#include "ListPtr.hpp"
#include "boundaryIntegration.hpp"
namespace pFlow
{
class integration;
class boundaryIntegrationList
:
public ListPtr<boundaryIntegration>
{
private:
const boundaryList& boundaries_;
public:
boundaryIntegrationList(
const pointStructure& pStruct,
const word& method,
integration& intgrtn
);
~boundaryIntegrationList()=default;
bool correct(
real dt,
realx3PointField_D& y,
realx3PointField_D& dy);
bool correctPStruct(
real dt,
pointStructure& pStruct,
const realx3PointField_D& vel);
};
}
#endif //__boundaryIntegrationList_hpp__

View File

@ -19,33 +19,35 @@ Licence:
-----------------------------------------------------------------------------*/ -----------------------------------------------------------------------------*/
#include "integration.hpp" #include "integration.hpp"
#include "pointStructure.hpp"
#include "repository.hpp"
pFlow::integration::integration pFlow::integration::integration
( (
const word& baseName, const word& baseName,
repository& owner, pointStructure& pStruct,
const pointStructure& pStruct, const word&,
const word& method const realx3Field_D&
) )
: :
owner_(owner), owner_(*pStruct.owner()),
baseName_(baseName), pStruct_(pStruct),
pStruct_(pStruct) baseName_(baseName)
{ {}
CONSUME_PARAM(method);
}
pFlow::uniquePtr<pFlow::integration> pFlow::uniquePtr<pFlow::integration>
pFlow::integration::create( pFlow::integration::create
(
const word& baseName, const word& baseName,
repository& owner, pointStructure& pStruct,
const pointStructure& pStruct, const word& method,
const word& method) const realx3Field_D& initialValField
)
{ {
if( wordvCtorSelector_.search(method) ) if( wordvCtorSelector_.search(method) )
{ {
return wordvCtorSelector_[method] (baseName, owner, pStruct, method); return wordvCtorSelector_[method] (baseName, pStruct, method, initialValField);
} }
else else
{ {

View File

@ -23,14 +23,16 @@ Licence:
#include "virtualConstructor.hpp" #include "virtualConstructor.hpp"
#include "Vectors.hpp" #include "pointFields.hpp"
#include "pointStructure.hpp"
#include "repository.hpp"
namespace pFlow namespace pFlow
{ {
// - Forward
class repository;
class pointStructure;
/** /**
* Base class for integrating the first order ODE (IVP) * Base class for integrating the first order ODE (IVP)
* *
@ -48,19 +50,19 @@ namespace pFlow
*/ */
class integration class integration
{ {
protected: private:
// - Protected data members // - Protected data members
/// The owner repository that all fields are storred in /// The owner repository that all fields are storred in
repository& owner_; repository& owner_;
/// The base name for integration
const word baseName_;
/// A reference to pointStructure /// A reference to pointStructure
const pointStructure& pStruct_; const pointStructure& pStruct_;
/// The base name for integration
const word baseName_;
public: public:
/// Type info /// Type info
@ -72,9 +74,9 @@ public:
/// Construct from components /// Construct from components
integration( integration(
const word& baseName, const word& baseName,
repository& owner, pointStructure& pStruct,
const pointStructure& pStruct, const word& method,
const word& method); const realx3Field_D& initialValField);
/// Copy constructor /// Copy constructor
integration(const integration&) = default; integration(const integration&) = default;
@ -88,22 +90,22 @@ public:
/// Move assignment /// Move assignment
integration& operator = (integration&&) = default; integration& operator = (integration&&) = default;
/// Polymorphic copy/cloning
virtual
uniquePtr<integration> clone()const=0;
/// Destructor /// Destructor
virtual ~integration()=default; virtual ~integration()=default;
/// Add a virtual constructor /// Add a virtual constructor
create_vCtor( create_vCtor
(
integration, integration,
word, word,
(const word& baseName, (
repository& owner, const word& baseName,
const pointStructure& pStruct, pointStructure& pStruct,
const word& method), const word& method,
(baseName, owner, pStruct, method) ); const realx3Field_D& initialValField
),
(baseName, pStruct, method, initialValField)
);
// - Methods // - Methods
@ -129,13 +131,25 @@ public:
return owner_; return owner_;
} }
virtual
void updateBoundariesSlaveToMasterIfRequested() = 0;
/// return integration method
virtual
word method()const = 0 ;
/// Prediction step in integration /// Prediction step in integration
virtual virtual
bool predict(real dt, realx3Vector_D& y, realx3Vector_D& dy) = 0; bool predict(real dt, realx3PointField_D& y, realx3PointField_D& dy) = 0;
virtual
bool predict(real dt, realx3Field_D& y, realx3PointField_D& dy) = 0;
/// Correction/main integration step /// Correction/main integration step
virtual virtual
bool correct(real dt, realx3Vector_D& y, realx3Vector_D& dy) = 0; bool correct(real dt, realx3PointField_D& y, realx3PointField_D& dy) = 0;
virtual
bool correctPStruct(real dt, pointStructure& pStruct, realx3PointField_D& vel) = 0;
/// Set the initial values for new indices /// Set the initial values for new indices
virtual virtual
@ -152,9 +166,9 @@ public:
static static
uniquePtr<integration> create( uniquePtr<integration> create(
const word& baseName, const word& baseName,
repository& owner, pointStructure& pStruct,
const pointStructure& pStruct, const word& method,
const word& method); const realx3Field_D& initialValField);
}; // integration }; // integration

View File

@ -1,11 +1,43 @@
set(SourceFiles set(SourceFiles
contactSearch/methods/cellBased/NBS/mapperNBS.cpp
contactSearch/methods/cellBased/NBS/mapperNBSKernels.cpp
contactSearch/methods/cellBased/NBS/NBSLevel0.cpp
contactSearch/methods/cellBased/NBS/NBS.cpp
contactSearch/methods/cellBased/NBS/cellsWallLevel0.cpp
contactSearch/boundaries/boundaryContactSearch/boundaryContactSearch.cpp
contactSearch/boundaries/periodicBoundaryContactSearch/ppwBndryContactSearchKernels.cpp
contactSearch/boundaries/periodicBoundaryContactSearch/ppwBndryContactSearch.cpp
contactSearch/boundaries/periodicBoundaryContactSearch/wallBoundaryContactSearch.cpp
contactSearch/boundaries/periodicBoundaryContactSearch/periodicBoundaryContactSearch.cpp
contactSearch/boundaries/boundaryContactSearchList.cpp
contactSearch/contactSearch/contactSearch.cpp contactSearch/contactSearch/contactSearch.cpp
contactSearch/ContactSearch/ContactSearchs.cpp contactSearch/ContactSearch/ContactSearchs.cpp
interaction/interaction.cpp interaction/interaction.cpp
sphereInteraction/sphereInteractions.cpp sphereInteraction/sphereInteractionsLinearModels.cpp
sphereInteraction/sphereInteractionsNonLinearModels.cpp
sphereInteraction/sphereInteractionsNonLinearModModels.cpp
grainInteraction/grainInteractionsLinearModels.cpp
grainInteraction/grainInteractionsNonLinearModels.cpp
grainInteraction/grainInteractionsNonLinearModModels.cpp
) )
if(pFlow_Build_MPI)
list(APPEND SourceFiles
contactSearch/boundaries/processorBoundaryContactSearch/processorBoundaryContactSearch.cpp
sphereInteraction/boundaries/processorBoundarySphereInteraction/processorBoundarySphereInteractions.cpp
contactSearch/boundaries/twoPartContactSearch/twoPartContactSearchKernels.cpp
contactSearch/boundaries/twoPartContactSearch/twoPartContactSearch.cpp
)
endif()
set(link_libs Kokkos::kokkos phasicFlow Property Particles Geometry) set(link_libs Kokkos::kokkos phasicFlow Property Particles Geometry)
pFlow_add_library_install(Interaction SourceFiles link_libs) pFlow_add_library_install(Interaction SourceFiles link_libs)

View File

@ -0,0 +1,350 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
#ifndef __cGAbsoluteLinearCF_hpp__
#define __cGAbsoluteLinearCF_hpp__
#include "types.hpp"
#include "symArrays.hpp"
namespace pFlow::cfModels
{
template<bool limited=true>
class cGAbsoluteLinear
{
public:
struct contactForceStorage
{
realx3 overlap_t_ = 0.0;
};
struct linearProperties
{
real kn_ = 1000.0;
real kt_ = 800.0;
real en_ = 0.0;
real ethat_ = 0.0;
real mu_ = 0.00001;
INLINE_FUNCTION_HD
linearProperties(){}
INLINE_FUNCTION_HD
linearProperties(real kn, real kt, real en, real etha_t, real mu ):
kn_(kn), kt_(kt), en_(en),ethat_(etha_t), mu_(mu)
{}
INLINE_FUNCTION_HD
linearProperties(const linearProperties&)=default;
INLINE_FUNCTION_HD
linearProperties& operator=(const linearProperties&)=default;
INLINE_FUNCTION_HD
~linearProperties() = default;
};
protected:
using LinearArrayType = symArray<linearProperties>;
int32 numMaterial_ = 0;
ViewType1D<real> rho_;
LinearArrayType linearProperties_;
int32 addDissipationModel_;
bool readLinearDictionary(const dictionary& dict)
{
auto kn = dict.getVal<realVector>("kn");
auto kt = dict.getVal<realVector>("kt");
auto en = dict.getVal<realVector>("en");
auto et = dict.getVal<realVector>("et");
auto mu = dict.getVal<realVector>("mu");
auto nElem = kn.size();
if(nElem != kt.size())
{
fatalErrorInFunction<<
"sizes of kn("<<nElem<<") and kt("<<kt.size()<<") do not match.\n";
return false;
}
if(nElem != kt.size())
{
fatalErrorInFunction<<
"sizes of kn("<<nElem<<") and kt("<<kt.size()<<") do not match.\n";
return false;
}
if(nElem != en.size())
{
fatalErrorInFunction<<
"sizes of kn("<<nElem<<") and en("<<en.size()<<") do not match.\n";
return false;
}
if(nElem != et.size())
{
fatalErrorInFunction<<
"sizes of kn("<<nElem<<") and et("<<et.size()<<") do not match.\n";
return false;
}
if(nElem != mu.size())
{
fatalErrorInFunction<<
"sizes of kn("<<nElem<<") and mu("<<mu.size()<<") do not match.\n";
return false;
}
// check if size of vector matchs a symetric array
uint32 nMat;
if( !LinearArrayType::getN(nElem, nMat) )
{
fatalErrorInFunction<<
"sizes of properties do not match a symetric array with size ("<<
numMaterial_<<"x"<<numMaterial_<<").\n";
return false;
}
else if( numMaterial_ != nMat)
{
fatalErrorInFunction<<
"size mismatch for porperties. \n"<<
"you supplied "<< numMaterial_<<" items in materials list and "<<
nMat << " for other properties.\n";
return false;
}
realVector etha_t("etha_t", nElem);
ForAll(i , kn)
{
etha_t[i] = -2.0*log( et[i])*sqrt(kt[i]*2/7) /
sqrt(log(pow(et[i],2.0))+ pow(Pi,2.0));
}
Vector<linearProperties> prop("prop", nElem);
ForAll(i,kn)
{
prop[i] = {kn[i], kt[i], en[i], etha_t[i], mu[i] };
}
linearProperties_.assign(prop);
auto adm = dict.getVal<word>("additionalDissipationModel");
if(adm == "none")
{
addDissipationModel_ = 1;
}
else if(adm == "LU")
{
addDissipationModel_ = 2;
}
else if (adm == "GB")
{
addDissipationModel_ = 3;
}
else
{
addDissipationModel_ = 1;
}
return true;
}
static const char* modelName()
{
if constexpr (limited)
{
return "cGAbsoluteLinearLimited";
}
else
{
return "cGAbsoluteLinearNonLimited";
}
return "";
}
public:
TypeInfoNV(modelName());
INLINE_FUNCTION_HD
cGAbsoluteLinear(){}
cGAbsoluteLinear(int32 nMaterial, const ViewType1D<real>& rho, const dictionary& dict)
:
numMaterial_(nMaterial),
rho_("rho",nMaterial),
linearProperties_("linearProperties",nMaterial)
{
Kokkos::deep_copy(rho_,rho);
if(!readLinearDictionary(dict))
{
fatalExit;
}
}
INLINE_FUNCTION_HD
cGAbsoluteLinear(const cGAbsoluteLinear&) = default;
INLINE_FUNCTION_HD
cGAbsoluteLinear(cGAbsoluteLinear&&) = default;
INLINE_FUNCTION_HD
cGAbsoluteLinear& operator=(const cGAbsoluteLinear&) = default;
INLINE_FUNCTION_HD
cGAbsoluteLinear& operator=(cGAbsoluteLinear&&) = default;
INLINE_FUNCTION_HD
~cGAbsoluteLinear()=default;
INLINE_FUNCTION_HD
int32 numMaterial()const
{
return numMaterial_;
}
//// - Methods
INLINE_FUNCTION_HD
void contactForce
(
const real dt,
const uint32 i,
const uint32 j,
const uint32 propId_i,
const uint32 propId_j,
const real Ri,
const real Rj,
const real cGFi,
const real cGFj,
const real ovrlp_n,
const realx3& Vr,
const realx3& Nij,
contactForceStorage& history,
realx3& FCn,
realx3& FCt
)const
{
auto prop = linearProperties_(propId_i,propId_j);
real f_ = ( cGFi + cGFj )/2 ;
real vrn = dot(Vr, Nij);
realx3 Vt = Vr - vrn*Nij;
history.overlap_t_ += Vt*dt;
real mi = 3*Pi/4*pow(Ri,3.0)*rho_[propId_i];
real mj = 3*Pi/4*pow(Rj,3.0)*rho_[propId_j];
real sqrt_meff = sqrt((mi*mj)/(mi+mj));
// disipation model
if (addDissipationModel_==2)
{
prop.en_ = sqrt(1+((pow(prop.en_,2)-1)*f_));
}
else if (addDissipationModel_==3)
{
auto pie =3.14;
prop.en_ = exp((pow(f_,1.5)*log(prop.en_)*sqrt( (1-((pow(log(prop.en_),2))/(pow(log(prop.en_),2)+pow(pie,2))))/(1-(pow(f_,3)*(pow(log(prop.en_),2))/(pow(log(prop.en_),2)+pow(pie,2)))) ) ));
}
real ethan_ = -2.0*log(prop.en_)*sqrt(prop.kn_)/
sqrt(pow(log(prop.en_),2.0)+ pow(Pi,2.0));
//REPORT(0)<<"\n en n is : "<<END_REPORT;
//REPORT(0)<< prop.en_ <<END_REPORT;
FCn = ( -pow(f_,3.0)*prop.kn_ * ovrlp_n - sqrt_meff * pow(f_,1.5) * ethan_ * vrn)*Nij;
FCt = ( -pow(f_,3.0)*prop.kt_ * history.overlap_t_ - sqrt_meff * pow(f_,1.5) * prop.ethat_*Vt);
real ft = length(FCt);
real ft_fric = prop.mu_ * length(FCn);
if(ft > ft_fric)
{
if( length(history.overlap_t_) >static_cast<real>(0.0))
{
if constexpr (limited)
{
FCt *= (ft_fric/ft);
history.overlap_t_ = - (FCt/prop.kt_);
}
else
{
FCt = (FCt/ft)*ft_fric;
}
//cout<<"friction is applied here \n";
}
else
{
FCt = 0.0;
}
}
}
};
} //pFlow::cfModels
#endif

View File

@ -0,0 +1,340 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
#ifndef __cGRelativeLinearCF_hpp__
#define __cGRelativeLinearCF_hpp__
#include "types.hpp"
#include "symArrays.hpp"
namespace pFlow::cfModels
{
template<bool limited=true>
class cGRelativeLinear
{
public:
struct contactForceStorage
{
realx3 overlap_t_ = 0.0;
};
struct linearProperties
{
real kn_ = 1000.0;
real kt_ = 800.0;
real en_ = 0.0;
real ethat_ = 0.0;
real mu_ = 0.00001;
INLINE_FUNCTION_HD
linearProperties(){}
INLINE_FUNCTION_HD
linearProperties(real kn, real kt, real en, real etha_t, real mu ):
kn_(kn), kt_(kt), en_(en),ethat_(etha_t), mu_(mu)
{}
INLINE_FUNCTION_HD
linearProperties(const linearProperties&)=default;
INLINE_FUNCTION_HD
linearProperties& operator=(const linearProperties&)=default;
INLINE_FUNCTION_HD
~linearProperties() = default;
};
protected:
using LinearArrayType = symArray<linearProperties>;
int32 numMaterial_ = 0;
ViewType1D<real> rho_;
LinearArrayType linearProperties_;
int32 addDissipationModel_;
bool readLinearDictionary(const dictionary& dict)
{
auto kn = dict.getVal<realVector>("kn");
auto kt = dict.getVal<realVector>("kt");
auto en = dict.getVal<realVector>("en");
auto et = dict.getVal<realVector>("et");
auto mu = dict.getVal<realVector>("mu");
auto nElem = kn.size();
if(nElem != kt.size())
{
fatalErrorInFunction<<
"sizes of kn("<<nElem<<") and kt("<<kt.size()<<") do not match.\n";
return false;
}
if(nElem != en.size())
{
fatalErrorInFunction<<
"sizes of kn("<<nElem<<") and en("<<en.size()<<") do not match.\n";
return false;
}
if(nElem != et.size())
{
fatalErrorInFunction<<
"sizes of kn("<<nElem<<") and et("<<et.size()<<") do not match.\n";
return false;
}
if(nElem != mu.size())
{
fatalErrorInFunction<<
"sizes of kn("<<nElem<<") and mu("<<mu.size()<<") do not match.\n";
return false;
}
// check if size of vector matchs a symetric array
uint32 nMat;
if( !LinearArrayType::getN(nElem, nMat) )
{
fatalErrorInFunction<<
"sizes of properties do not match a symetric array with size ("<<
numMaterial_<<"x"<<numMaterial_<<").\n";
return false;
}
else if( numMaterial_ != nMat)
{
fatalErrorInFunction<<
"size mismatch for porperties. \n"<<
"you supplied "<< numMaterial_<<" items in materials list and "<<
nMat << " for other properties.\n";
return false;
}
realVector etha_t("etha_t", nElem);
ForAll(i , kn)
{
etha_t[i] = -2.0*log( et[i])*sqrt(kt[i]*2/7) /
sqrt(log(pow(et[i],2.0))+ pow(Pi,2.0));
}
Vector<linearProperties> prop("prop", nElem);
ForAll(i,kn)
{
prop[i] = {kn[i], kt[i], en[i], etha_t[i], mu[i] };
}
linearProperties_.assign(prop);
auto adm = dict.getVal<word>("additionalDissipationModel");
if(adm == "none")
{
addDissipationModel_ = 1;
}
else if(adm == "LU")
{
addDissipationModel_ = 2;
}
else if (adm == "GB")
{
addDissipationModel_ = 3;
}
else
{
addDissipationModel_ = 1;
}
return true;
}
static const char* modelName()
{
if constexpr (limited)
{
return "cGRelativeLinearLimited";
}
else
{
return "cGRelativeLinearNonLimited";
}
return "";
}
public:
TypeInfoNV(modelName());
INLINE_FUNCTION_HD
cGRelativeLinear(){}
cGRelativeLinear(int32 nMaterial, const ViewType1D<real>& rho, const dictionary& dict)
:
numMaterial_(nMaterial),
rho_("rho",nMaterial),
linearProperties_("linearProperties",nMaterial)
{
Kokkos::deep_copy(rho_,rho);
if(!readLinearDictionary(dict))
{
fatalExit;
}
}
INLINE_FUNCTION_HD
cGRelativeLinear(const cGRelativeLinear&) = default;
INLINE_FUNCTION_HD
cGRelativeLinear(cGRelativeLinear&&) = default;
INLINE_FUNCTION_HD
cGRelativeLinear& operator=(const cGRelativeLinear&) = default;
INLINE_FUNCTION_HD
cGRelativeLinear& operator=(cGRelativeLinear&&) = default;
INLINE_FUNCTION_HD
~cGRelativeLinear()=default;
INLINE_FUNCTION_HD
int32 numMaterial()const
{
return numMaterial_;
}
//// - Methods
INLINE_FUNCTION_HD
void contactForce
(
const real dt,
const uint32 i,
const uint32 j,
const uint32 propId_i,
const uint32 propId_j,
const real Ri,
const real Rj,
const real cGFi,
const real cGFj,
const real ovrlp_n,
const realx3& Vr,
const realx3& Nij,
contactForceStorage& history,
realx3& FCn,
realx3& FCt
)const
{
auto prop = linearProperties_(propId_i,propId_j);
real f_ = ( cGFi + cGFj )/2 ;
real vrn = dot(Vr, Nij);
realx3 Vt = Vr - vrn*Nij;
history.overlap_t_ += Vt*dt;
real mi = 3*Pi/4*pow(Ri,3.0)*rho_[propId_i];
real mj = 3*Pi/4*pow(Rj,3.0)*rho_[propId_j];
real sqrt_meff = sqrt((mi*mj)/(mi+mj));
if (addDissipationModel_==2)
{
prop.en_ = sqrt(1+((pow(prop.en_,2)-1)*f_));
}
else if (addDissipationModel_==3)
{
auto pie =3.14;
prop.en_ = exp((pow(f_,1.5)*log(prop.en_)*sqrt( (1-((pow(log(prop.en_),2))/(pow(log(prop.en_),2)+pow(pie,2))))/(1-(pow(f_,3)*(pow(log(prop.en_),2))/(pow(log(prop.en_),2)+pow(pie,2)))) ) ));
}
real ethan_ = -2.0*log(prop.en_)*sqrt(prop.kn_)/
sqrt(pow(log(prop.en_),2.0)+ pow(Pi,2.0));
FCn = ( -pow(f_,1.0)*prop.kn_ * ovrlp_n - sqrt_meff * pow(f_,0.5) * ethan_ * vrn)*Nij;
FCt = ( -pow(f_,1.0)*prop.kt_ * history.overlap_t_ - sqrt_meff * pow(f_,0.5) * prop.ethat_*Vt);
real ft = length(FCt);
real ft_fric = prop.mu_ * length(FCn);
if(ft > ft_fric)
{
if( length(history.overlap_t_) >static_cast<real>(0.0))
{
if constexpr (limited)
{
FCt *= (ft_fric/ft);
history.overlap_t_ = - (FCt/prop.kt_);
}
else
{
FCt = (FCt/ft)*ft_fric;
}
//cout<<"friction is applied here \n";
}
else
{
FCt = 0.0;
}
}
}
};
} //pFlow::cfModels
#endif

View File

@ -133,8 +133,9 @@ protected:
return false; return false;
} }
realVector etha_n(nElem); realVector etha_n("etha_n", nElem);
realVector etha_t(nElem); realVector etha_t("etha_t", nElem);
ForAll(i , kn) ForAll(i , kn)
{ {
etha_n[i] = -2.0*log(en[i])*sqrt(kn[i])/ etha_n[i] = -2.0*log(en[i])*sqrt(kn[i])/
@ -144,7 +145,7 @@ protected:
sqrt(pow(log(et[i]),2.0)+ pow(Pi,2.0)); sqrt(pow(log(et[i]),2.0)+ pow(Pi,2.0));
} }
Vector<linearProperties> prop(nElem); Vector<linearProperties> prop("prop", nElem);
ForAll(i,kn) ForAll(i,kn)
{ {
prop[i] = {kn[i], kt[i], etha_n[i], etha_t[i], mu[i]}; prop[i] = {kn[i], kt[i], etha_n[i], etha_t[i], mu[i]};
@ -219,10 +220,10 @@ public:
void contactForce void contactForce
( (
const real dt, const real dt,
const int32 i, const uint32 i,
const int32 j, const uint32 j,
const int32 propId_i, const uint32 propId_i,
const int32 propId_j, const uint32 propId_j,
const real Ri, const real Ri,
const real Rj, const real Rj,
const real ovrlp_n, const real ovrlp_n,

View File

@ -121,7 +121,7 @@ protected:
} }
realVector etha_n(nElem); realVector etha_n("etha_n",nElem);
ForAll(i , en) ForAll(i , en)
{ {
@ -137,7 +137,7 @@ protected:
} }
Vector<nonLinearProperties> prop(nElem); Vector<nonLinearProperties> prop("prop",nElem);
ForAll(i,Yeff) ForAll(i,Yeff)
{ {
prop[i] = {Yeff[i], Geff[i], etha_n[i], mu[i]}; prop[i] = {Yeff[i], Geff[i], etha_n[i], mu[i]};
@ -214,10 +214,10 @@ public:
void contactForce void contactForce
( (
const real dt, const real dt,
const int32 i, const uint32 i,
const int32 j, const uint32 j,
const int32 propId_i, const uint32 propId_i,
const int32 propId_j, const uint32 propId_j,
const real Ri, const real Ri,
const real Rj, const real Rj,
const real ovrlp_n, const real ovrlp_n,

View File

@ -121,7 +121,7 @@ protected:
} }
Vector<nonLinearProperties> prop(nElem); Vector<nonLinearProperties> prop("prop",nElem);
ForAll(i,Yeff) ForAll(i,Yeff)
{ {
prop[i] = {Yeff[i], Geff[i], etha_n[i], mu[i]}; prop[i] = {Yeff[i], Geff[i], etha_n[i], mu[i]};
@ -198,10 +198,10 @@ public:
void contactForce void contactForce
( (
const real dt, const real dt,
const int32 i, const uint32 i,
const int32 j, const uint32 j,
const int32 propId_i, const uint32 propId_i,
const int32 propId_j, const uint32 propId_j,
const real Ri, const real Ri,
const real Rj, const real Rj,
const real ovrlp_n, const real ovrlp_n,

View File

@ -18,30 +18,28 @@ Licence:
-----------------------------------------------------------------------------*/ -----------------------------------------------------------------------------*/
#ifndef __grainContactForceModels_hpp__
#define __grainContactForceModels_hpp__
#ifndef __Control_hpp__ #include "cGAbsoluteLinearCF.hpp"
#define __Control_hpp__ #include "cGRelativeLinearCF.hpp"
#include "grainRolling.hpp"
// top-level entity repository for the whole application
// Each application that is executed in pFlow, should have
// settings/systemControl file in it.
// This repository holds two main repositories: Time and settings
#include "systemControl.hpp" namespace pFlow::cfModels
#include "timeFolder.hpp"
namespace pFlow
{ {
inline systemControl& Control() using limitedCGAbsoluteLinearGrainRolling = grainRolling<cGAbsoluteLinear<true>>;
{ using nonLimitedCGAbsoluteLinearGrainRolling = grainRolling<cGAbsoluteLinear<false>>;
static systemControl control_;
return control_; using limitedCGRelativeLinearGrainRolling = grainRolling<cGRelativeLinear<true>>;
using nonLimitedCGRelativeLinearGrainRolling = grainRolling<cGRelativeLinear<false>>;
} }
} // pFlow
#endif // __Control_hpp__ #endif //__grainContactForceModels_hpp__

View File

@ -0,0 +1,119 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
#ifndef __grainRolling_hpp__
#define __grainRolling_hpp__
namespace pFlow::cfModels
{
template<typename contactForceModel>
class grainRolling
:
public contactForceModel
{
public:
using contactForceStorage =
typename contactForceModel::contactForceStorage;
realSymArray_D mur_;
bool readGrainDict(const dictionary& dict)
{
auto mur = dict.getVal<realVector>("mur");
uint32 nMat;
if(!realSymArray_D::getN(mur.size(),nMat) || nMat != this->numMaterial())
{
fatalErrorInFunction<<
"wrong number of values supplied in mur. \n";
return false;
}
mur_.assign(mur);
return true;
}
public:
TypeInfoNV(word("normal<"+contactForceModel::TYPENAME()+">"));
grainRolling(int32 nMaterial, const ViewType1D<real>& rho, const dictionary& dict)
:
contactForceModel(nMaterial, rho, dict),
mur_("mur", nMaterial)
{
if(!readGrainDict(dict))
{
fatalExit;
}
}
INLINE_FUNCTION_HD
void rollingFriction
(
const real dt,
const uint32 i,
const uint32 j,
const uint32 propId_i,
const uint32 propId_j,
const real Ri,
const real Rj,
const real cGFi,
const real cGFj,
const realx3& wi,
const realx3& wj,
const realx3& Nij,
const realx3& FCn,
realx3& Mri,
realx3& Mrj
)const
{
realx3 w_hat = wi-wj;
real w_hat_mag = length(w_hat);
if( !equal(w_hat_mag,0.0) )
w_hat /= w_hat_mag;
else
w_hat = 0.0;
auto Reff = (Ri*Rj)/(Ri+Rj);
Mri = ( -mur_(propId_i,propId_j) *length(FCn) * Reff ) * w_hat ;
//removing the normal part
// Mri = Mri - ( (Mri .dot. nij)*nij )
Mrj = -Mri;
}
};
}
#endif

View File

@ -76,10 +76,10 @@ public:
void rollingFriction void rollingFriction
( (
const real dt, const real dt,
const int32 i, const uint32 i,
const int32 j, const uint32 j,
const int32 propId_i, const uint32 propId_i,
const int32 propId_j, const uint32 propId_j,
const real Ri, const real Ri,
const real Rj, const real Rj,
const realx3& wi, const realx3& wi,

View File

@ -53,7 +53,7 @@ protected:
ViewType1D<ValueType,ExecutionSpace> values_; ViewType1D<ValueType,ExecutionSpace> values_;
int32 size0_ = 0; uint32 size0_ = 0;
ViewType1D<PairType,ExecutionSpace> sortedPairs0_; ViewType1D<PairType,ExecutionSpace> sortedPairs0_;
@ -73,7 +73,7 @@ protected:
using rpReFillPairs = Kokkos::RangePolicy< using rpReFillPairs = Kokkos::RangePolicy<
ExecutionSpace, ExecutionSpace,
Kokkos::Schedule<Kokkos::Static>, Kokkos::Schedule<Kokkos::Static>,
Kokkos::IndexType<int32>, Kokkos::IndexType<uint32>,
TagReFillPairs>; TagReFillPairs>;
public: public:
@ -81,7 +81,7 @@ public:
TypeInfoNV("sortedContactList"); TypeInfoNV("sortedContactList");
sortedContactList(int32 initialSize =1) explicit sortedContactList(uint32 initialSize =1)
: :
SortedPairs(initialSize), SortedPairs(initialSize),
values_("values", SortedPairs::capacity()), values_("values", SortedPairs::capacity()),
@ -114,31 +114,31 @@ public:
} }
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
ValueType getValue(int32 idx)const ValueType getValue(uint32 idx)const
{ {
return values_[idx]; return values_[idx];
} }
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
void setValue(int32 idx, const ValueType& val)const void setValue(uint32 idx, const ValueType& val)const
{ {
values_[idx] = val; values_[idx] = val;
} }
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
void operator()(TagReFillPairs, int32 idx)const void operator()(TagReFillPairs, uint32 idx)const
{ {
auto searchLen = max(size0_/1000,10); uint32 searchLen = max(size0_/1000u,10u);
auto start = max(0,idx-searchLen); uint32 start = idx-min(searchLen,idx);
auto end = min(size0_,idx+searchLen); uint32 end = min(size0_,idx+searchLen);
auto newPair = this->sortedPairs_[idx]; auto newPair = this->sortedPairs_[idx];
if( auto idx0 = binarySearch( if( auto idx0 = binarySearch(
sortedPairs0_, sortedPairs0_,
start, start,
end, end,
newPair); newPair);
idx0>=0) idx0!=static_cast<uint32>(-1))
{ {
values_[idx] = values0_[idx0]; values_[idx] = values0_[idx0];
} }
@ -147,7 +147,7 @@ public:
start, start,
end, end,
newPair); newPair);
idx0>=0) idx0!= static_cast<uint32>(-1) )
{ {
values_[idx] = values0_[idx0]; values_[idx] = values0_[idx0];

View File

@ -52,24 +52,24 @@ public:
{ {
using PairType = typename sortedPairs::PairType; using PairType = typename sortedPairs::PairType;
int32 size_; uint32 size_;
ViewType1D<PairType,ExecutionSpace> sortedParis_; ViewType1D<PairType,ExecutionSpace> sortedParis_;
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
int32 size()const { return size_; } uint32 size()const { return size_; }
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
int32 loopCount()const { return size_; } uint32 loopCount()const { return size_; }
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
bool isValid(int32 i)const { return i<size_; } bool isValid(uint32 i)const { return i<size_; }
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
PairType getPair(int i)const { return sortedParis_[i]; } PairType getPair(uint32 i)const { return sortedParis_[i]; }
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
bool getPair(int32 i, PairType& pair)const { bool getPair(uint32 i, PairType& pair)const {
if(i<size_) { if(i<size_) {
pair = sortedParis_[i]; pair = sortedParis_[i];
return true; return true;
@ -85,22 +85,22 @@ public:
protected: protected:
/// size of pair list /// size of pair list
int32 size_ = 0; uint32 size_ = 0;
ViewType1D<int32,ExecutionSpace> flags_; ViewType1D<uint32,ExecutionSpace> flags_;
ViewType1D<PairType,ExecutionSpace> sortedPairs_; ViewType1D<PairType,ExecutionSpace> sortedPairs_;
using rpFillFlag = Kokkos::RangePolicy< using rpFillFlag = Kokkos::RangePolicy<
ExecutionSpace, ExecutionSpace,
Kokkos::Schedule<Kokkos::Static>, Kokkos::Schedule<Kokkos::Static>,
Kokkos::IndexType<int32>, Kokkos::IndexType<uint32>,
TagFillFlag >; TagFillFlag >;
using rpFillPairs = Kokkos::RangePolicy< using rpFillPairs = Kokkos::RangePolicy<
ExecutionSpace, ExecutionSpace,
Kokkos::Schedule<Kokkos::Static>, Kokkos::Schedule<Kokkos::Static>,
Kokkos::IndexType<int32>, Kokkos::IndexType<uint32>,
TagFillPairs>; TagFillPairs>;
public: public:
@ -110,7 +110,7 @@ public:
// constructors // constructors
sortedPairs(int32 initialSize =1) explicit sortedPairs(uint32 initialSize =1)
: :
UnsortedPairs(initialSize), UnsortedPairs(initialSize),
flags_("flags_",UnsortedPairs::capacity()+1), flags_("flags_",UnsortedPairs::capacity()+1),
@ -134,7 +134,7 @@ public:
// return the pair at index idx // return the pair at index idx
// perform no check for size and existance // perform no check for size and existance
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
PairType getPair(int32 idx)const PairType getPair(uint32 idx)const
{ {
return sortedPairs_[idx]; return sortedPairs_[idx];
} }
@ -142,7 +142,7 @@ public:
// - Device/host call // - Device/host call
// return the pair at index idx // return the pair at index idx
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
bool getPair(int32 idx, PairType& p)const bool getPair(uint32 idx, PairType& p)const
{ {
if(isValid(idx)) if(isValid(idx))
{ {
@ -156,7 +156,7 @@ public:
} }
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
bool isValid(int32 idx)const bool isValid(uint32 idx)const
{ {
return idx < size_; return idx < size_;
} }
@ -164,12 +164,12 @@ public:
//use this when the value of size_ is updated //use this when the value of size_ is updated
INLINE_FUNCTION_H INLINE_FUNCTION_H
int32 size()const uint32 size()const
{ {
return size_; return size_;
} }
int32 loopCount()const uint32 loopCount()const
{ {
return size_; return size_;
} }
@ -189,7 +189,7 @@ public:
void prepareSorted() void prepareSorted()
{ {
// first check the size of flags_ // first check the size of flags_
int32 capacity = UnsortedPairs::capacity(); uint32 capacity = UnsortedPairs::capacity();
if( capacity+1 > flags_.size() ) if( capacity+1 > flags_.size() )
{ {
@ -218,7 +218,7 @@ public:
if( size_>sortedPairs_.size() ) if( size_>sortedPairs_.size() )
{ {
// get more space to prevent reallocations in next iterations // get more space to prevent reallocations in next iterations
int32 len = size_*1.1+1; uint32 len = size_*1.1+1;
reallocNoInit(sortedPairs_, len); reallocNoInit(sortedPairs_, len);
} }
@ -235,7 +235,7 @@ public:
} }
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
void operator()(TagFillFlag, int32 i)const void operator()(TagFillFlag, uint32 i)const
{ {
if(this->container_.valid_at(i) ) if(this->container_.valid_at(i) )
flags_[i] = 1; flags_[i] = 1;
@ -244,7 +244,7 @@ public:
} }
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
void operator()(TagFillPairs, int32 i)const void operator()(TagFillPairs, uint32 i)const
{ {
auto fi = flags_[i]; auto fi = flags_[i];
if(fi!=flags_[i+1]) if(fi!=flags_[i+1])

View File

@ -17,10 +17,11 @@ Licence:
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/ -----------------------------------------------------------------------------*/
#ifndef __unsortedContactList_hpp__ #ifndef __unsortedContactList_hpp__
#define __unsortedContactList_hpp__ #define __unsortedContactList_hpp__
#include "unsortedPairs.hpp"
namespace pFlow namespace pFlow
{ {
@ -72,7 +73,7 @@ protected:
using rpFillPairs = Kokkos::RangePolicy< using rpFillPairs = Kokkos::RangePolicy<
ExecutionSpace, ExecutionSpace,
Kokkos::Schedule<Kokkos::Static>, Kokkos::Schedule<Kokkos::Static>,
Kokkos::IndexType<int32>, Kokkos::IndexType<uint32>,
TagReFillPairs>; TagReFillPairs>;
@ -80,7 +81,7 @@ public:
TypeInfoNV("unsortedContactList"); TypeInfoNV("unsortedContactList");
unsortedContactList(int32 capacity=1) explicit unsortedContactList(uint32 capacity=1)
: :
UnsortedPairs(capacity), UnsortedPairs(capacity),
values_("values", UnsortedPairs::capacity()), values_("values", UnsortedPairs::capacity()),
@ -94,7 +95,8 @@ public:
// swap conainer and values // swap conainer and values
swapViews(values0_, values_); swapViews(values0_, values_);
swapViews(container0_, this->container_); swapViews(container0_, this->container_);
return UnsortedPairs::beforeBroadSearch(); UnsortedPairs::beforeBroadSearch();
return true;
} }
bool afterBroadSearch() bool afterBroadSearch()
@ -122,7 +124,7 @@ public:
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
bool getValue(const PairType& p, ValueType& val)const bool getValue(const PairType& p, ValueType& val)const
{ {
if(auto idx = this->find(p); idx>=0) if(auto idx = this->find(p); idx!=static_cast<uint32>(-1))
{ {
val = getValue(idx); val = getValue(idx);
return true; return true;
@ -131,7 +133,7 @@ public:
} }
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
void setValue(int32 idx, const ValueType& val)const void setValue(uint32 idx, const ValueType& val)const
{ {
values_[idx] = val; values_[idx] = val;
} }
@ -139,7 +141,7 @@ public:
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
bool setValue(const PairType& p, const ValueType& val)const bool setValue(const PairType& p, const ValueType& val)const
{ {
if(auto idx = this->find(p); idx>=0) if(uint32 idx = this->find(p); idx!=static_cast<uint32>(-1))
{ {
setValue(idx, val); setValue(idx, val);
return true;; return true;;
@ -148,13 +150,13 @@ public:
} }
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
void operator()(TagReFillPairs, int32 idx)const void operator()(TagReFillPairs, uint32 idx)const
{ {
if( this->isValid(idx) ) if( this->isValid(idx) )
{ {
if( int32 idx0 = if( uint32 idx0 =
container0_.find(this->getPair(idx)); container0_.find(this->getPair(idx));
idx0>=0 ) idx0!= static_cast<uint32>(-1) )
{ {
values_[idx] = values0_[idx0]; values_[idx] = values0_[idx0];
} }

View File

@ -41,7 +41,7 @@ public:
using memory_space = typename ExecutionSpace::memory_space; using memory_space = typename ExecutionSpace::memory_space;
using PairType = kPair<idType,idType>; using PairType = Pair<idType,idType>;
using ContainerType = unorderedSet<PairType, ExecutionSpace>; using ContainerType = unorderedSet<PairType, ExecutionSpace>;
@ -52,19 +52,19 @@ public:
ContainerType Container_; ContainerType Container_;
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
int32 size()const { return Container_.size(); } uint32 size()const { return Container_.size(); }
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
int32 loopCount()const { return Container_.capacity(); } uint32 loopCount()const { return Container_.capacity(); }
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
bool isValid(int32 idx)const { return Container_.valid_at(idx); } bool isValid(uint32 idx)const { return Container_.valid_at(idx); }
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
PairType getPair(int idx)const { return Container_.key_at(idx); } PairType getPair(uint32 idx)const { return Container_.key_at(idx); }
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
bool getPair(int32 idx, PairType& pair)const { bool getPair(uint32 idx, PairType& pair)const {
if(Container_.valid_at(idx)) { if(Container_.valid_at(idx)) {
pair = Container_.key_at(idx); pair = Container_.key_at(idx);
return true; return true;
@ -84,7 +84,7 @@ public:
TypeInfoNV("unsorderedPairs"); TypeInfoNV("unsorderedPairs");
// constructor // constructor
unsortedPairs(int32 capacity=1) explicit unsortedPairs(uint32 capacity=1)
: :
container_(capacity) // the minimum capacity would be 128 container_(capacity) // the minimum capacity would be 128
{} {}
@ -102,20 +102,20 @@ public:
// - Device call // - Device call
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
int32 insert(idType i, idType j)const uint32 insert(idType i, idType j)const
{ {
if(auto insertResult = container_.insert(PairType(i,j)); insertResult.failed()) if(auto insertResult = container_.insert(PairType(i,j)); insertResult.failed())
return -1; return static_cast<uint32>(-1);
else else
return insertResult.index(); return insertResult.index();
} }
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
int32 insert(const PairType& p)const uint32 insert(const PairType& p)const
{ {
if(auto insertResult = container_.insert(p); insertResult.failed()) if(auto insertResult = container_.insert(p); insertResult.failed())
return -1; return static_cast<uint32>(-1);
else else
return insertResult.index(); return insertResult.index();
@ -125,7 +125,7 @@ public:
// return the pair at index idx // return the pair at index idx
// perform no check for size and existance // perform no check for size and existance
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
PairType getPair(int32 idx)const PairType getPair(uint32 idx)const
{ {
return container_.key_at(idx); return container_.key_at(idx);
} }
@ -133,7 +133,7 @@ public:
// - Device call // - Device call
// return the pair at index idx // return the pair at index idx
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
bool getPair(int32 idx, PairType& p)const bool getPair(uint32 idx, PairType& p)const
{ {
if(container_.valid_at(idx)) if(container_.valid_at(idx))
{ {
@ -148,36 +148,36 @@ public:
} }
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
int32 find(const PairType & p)const uint32 find(const PairType & p)const
{ {
if( auto idx = container_.find(p); if( auto idx = container_.find(p);
idx != Kokkos::UnorderedMapInvalidIndex ) idx != Kokkos::UnorderedMapInvalidIndex )
return idx; return idx;
else else
return -1; return static_cast<uint32>(-1);
} }
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
bool isValid(int32 idx)const bool isValid(uint32 idx)const
{ {
return container_.valid_at(idx); return container_.valid_at(idx);
} }
INLINE_FUNCTION_HD INLINE_FUNCTION_HD
int32 capacity() const uint32 capacity() const
{ {
return container_.capacity(); return container_.capacity();
} }
int32 loopCount()const uint32 loopCount()const
{ {
return container_.capacity(); return container_.capacity();
} }
//use this when the value of size_ is updated //use this when the value of size_ is updated
INLINE_FUNCTION_H INLINE_FUNCTION_H
int32 size()const uint32 size()const
{ {
return container_.size(); return container_.size();
} }
@ -190,7 +190,7 @@ public:
/// increase the capacity of the container by at-least len /// increase the capacity of the container by at-least len
/// the content will be erased. /// the content will be erased.
INLINE_FUNCTION_H INLINE_FUNCTION_H
void increaseCapacityBy(int32 len) void increaseCapacityBy(uint32 len)
{ {
uint newCap = container_.capacity()+len; uint newCap = container_.capacity()+len;
this->clear(); this->clear();

View File

@ -22,16 +22,18 @@ Licence:
#ifndef __ContactSearch_hpp__ #ifndef __ContactSearch_hpp__
#define __ContactSearch_hpp__ #define __ContactSearch_hpp__
#include "contactSearchGlobals.hpp"
#include "contactSearch.hpp" #include "contactSearch.hpp"
#include "box.hpp" #include "box.hpp"
#include "particles.hpp"
#include "geometry.hpp"
#include "boundaryContactSearchList.hpp"
namespace pFlow namespace pFlow
{ {
template< template<
template<class> class BaseMethod, class searchMethod
template<class> class WallMapping
> >
class ContactSearch class ContactSearch
: :
@ -39,206 +41,133 @@ class ContactSearch
{ {
public: public:
using IdType = typename contactSearch::IdType; using IdType = uint32;
using IndexType = typename contactSearch::IndexType; using ExecutionSpace = DefaultExecutionSpace;
using ExecutionSpace = typename contactSearch::ExecutionSpace; using SearchMethodType = searchMethod;
using PairContainerType = typename contactSearch::PairContainerType; private:
using ParticleContactSearchType = uniquePtr<SearchMethodType> ppwContactSearch_ = nullptr;
BaseMethod<
ExecutionSpace>;
using WallMappingType = boundaryContactSearchList csBoundaries_;
WallMapping<
ExecutionSpace>;
protected: bool BroadSearch(
const timeInfo& ti,
csPairContainerType& ppPairs,
csPairContainerType& pwPairs,
bool force = false) override
{
const auto& position = Particles().pointPosition().deviceViewAll();
const auto& flags = Particles().dynPointStruct().activePointsMaskDevice();
const auto& diam = Particles().boundingSphere().deviceViewAll();
uniquePtr<ParticleContactSearchType> particleContactSearch_ = nullptr; return ppwContactSearch_().broadSearch(
ti.iter(),
ti.t(),
ti.dt(),
ppPairs,
pwPairs,
position,
flags,
diam,
force
);
}
uniquePtr<WallMappingType> wallMapping_ = nullptr; bool BoundaryBroadSearch(
uint32 bndryIndex,
const timeInfo& ti,
csPairContainerType& ppPairs,
csPairContainerType& pwPairs,
bool force = false)override
{
return csBoundaries_[bndryIndex].broadSearch(
ti.iter(),
ti.t(),
ti.dt(),
ppPairs,
pwPairs,
force
);
}
public: public:
TypeInfoTemplate2("ContactSearch", ParticleContactSearchType, WallMappingType); TypeInfoTemplate11("ContactSearch", SearchMethodType);
ContactSearch( ContactSearch(
const dictionary& csDict, const dictionary& csDict,
const box& domain, const box& extDomain,
const particles& prtcl, const particles& prtcl,
const geometry& geom, const geometry& geom,
Timers& timers) Timers& timers)
: :
contactSearch(csDict, domain, prtcl, geom, timers) contactSearch(
csDict,
extDomain,
prtcl,
geom,
timers),
csBoundaries_(
csDict,
Particles().pStruct().boundaries(),
*this)
{ {
auto method = dict().getVal<word>("method"); real minD;
auto wmMethod = dict().getVal<word>("wallMapping"); real maxD;
auto nbDict = dict().subDict(method+"Info");
real minD, maxD;
this->Particles().boundingSphereMinMax(minD, maxD); this->Particles().boundingSphereMinMax(minD, maxD);
const auto& position = this->Particles().pointPosition().deviceVectorAll(); const auto& position = this->Particles().pointPosition().deviceViewAll();
const auto& diam = this->Particles().boundingSphere().deviceVectorAll(); const auto& flags = this->Particles().dynPointStruct().activePointsMaskDevice();
const auto& diam = this->Particles().boundingSphere().deviceViewAll();
particleContactSearch_ = uint32 wnPoints = this->Geometry().numPoints();
makeUnique<ParticleContactSearchType> uint32 wnTri = this->Geometry().size();
const auto& wPoints = this->Geometry().points().deviceViewAll();
const auto& wVertices = this->Geometry().vertices().deviceViewAll();
const auto& wNormals = this->Geometry().normals().deviceViewAll();
ppwContactSearch_ =
makeUnique<SearchMethodType>
( (
nbDict, dict(),
this->domain(), this->extendedDomainBox(),
minD, minD,
maxD, maxD,
position, position,
diam flags,
); diam,
REPORT(2)<<"Contact search algorithm for particle-particle is "<<
greenText(particleContactSearch_().typeName())<<endREPORT;
auto wmDict = dict().subDict(wmMethod+"Info");
int32 wnPoints = this->Geometry().numPoints();
int32 wnTri = this->Geometry().size();
const auto& wPoints = this->Geometry().points().deviceVectorAll();
const auto& wVertices = this->Geometry().vertices().deviceVectorAll();
wallMapping_ =
makeUnique<WallMappingType>(
wmDict,
particleContactSearch_().numLevels(),
particleContactSearch_().getCellsLevels(),
wnPoints, wnPoints,
wnTri, wnTri,
wPoints, wPoints,
wVertices wVertices,
wNormals
); );
REPORT(2)<<"Wall mapping algorithm for particle-wall is "<<
greenText(wallMapping_().typeName())<< endREPORT;
} }
add_vCtor( add_vCtor(
contactSearch, contactSearch,
ContactSearch, ContactSearch,
dictionary); dictionary);
bool broadSearch( bool enterBroadSearchBoundary(const timeInfo& ti, bool force=false)const override
PairContainerType& ppPairs,
PairContainerType& pwPairs,
bool force = false) override
{ {
return enterBroadSearch(ti, force) || csBoundaries_.boundariesUpdated();
if(particleContactSearch_)
{
auto activeRange = this->Particles().activeRange();
sphereSphereTimer_.start();
if(this->Particles().allActive())
{
particleContactSearch_().broadSearch(ppPairs, activeRange, force);
}
else
{
particleContactSearch_().broadSearch(ppPairs, activeRange, this->Particles().activePointsMaskD(), force);
} }
sphereSphereTimer_.end(); real sizeRatio()const override
}
else
return false;
if(wallMapping_)
{ {
sphereWallTimer_.start(); return ppwContactSearch_().sizeRatio();
wallMapping_().broadSearch(pwPairs, particleContactSearch_(), force);
sphereWallTimer_.end();
}
else
return false;
return true;
} }
real cellExtent()const override
bool ppEnterBroadSearch()const override
{ {
if(particleContactSearch_) return ppwContactSearch_().cellExtent();
{
return particleContactSearch_().enterBoadSearch();
} }
return false;
}
bool pwEnterBroadSearch()const override
{
if(wallMapping_)
{
return wallMapping_().enterBoadSearch();
}
return false;
}
bool ppPerformedBroadSearch()const override
{
if(particleContactSearch_)
{
return particleContactSearch_().performedSearch();
}
return false;
}
bool pwPerformedBroadSearch()const override
{
if(wallMapping_)
{
return wallMapping_().performedSearch();
}
return false;
}
/*bool update(const eventMessage& msg)
{
if(msg.isSizeChanged() )
{
auto newSize = this->prtcl().size();
if(!particleContactSearch_().objectSizeChanged(newSize))
{
fatalErrorInFunction<<
"erro in changing the size for particleContactSearch_ \n";
return false;
}
}
if(msg.isCapacityChanged() )
{
auto newSize = this->prtcl().capacity();
if(!particleContactSearch_().objectSizeChanged(newSize))
{
fatalErrorInFunction<<
"erro in changing the capacity for particleContactSearch_ \n";
return false;
}
}
return true;
}*/
}; };

View File

@ -20,11 +20,11 @@ Licence:
#include "ContactSearch.hpp" #include "ContactSearch.hpp"
#include "cellMapping.hpp" //#include "cellMapping.hpp"
#include "NBS.hpp" #include "NBS.hpp"
#include "multiGridNBS.hpp" //#include "multiGridNBS.hpp"
#include "multiGridMapping.hpp" //#include "multiGridMapping.hpp"
template class pFlow::ContactSearch<pFlow::NBS, pFlow::cellMapping>; template class pFlow::ContactSearch<pFlow::NBS>;
template class pFlow::ContactSearch<pFlow::multiGridNBS, pFlow::multiGridMapping>; //template class pFlow::ContactSearch<pFlow::multiGridNBS, pFlow::multiGridMapping>;

View File

@ -0,0 +1,77 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
#include "boundaryContactSearch.hpp"
#include "contactSearch.hpp"
pFlow::boundaryContactSearch::boundaryContactSearch(
const dictionary &dict,
const boundaryBase &boundary,
const contactSearch &cSearch)
: generalBoundary(
boundary,
cSearch.pStruct(),
"",
""),
contactSearch_(cSearch),
updateInterval_(dict.getVal<uint32>("updateInterval"))
{
}
pFlow::uniquePtr<pFlow::boundaryContactSearch>
pFlow::boundaryContactSearch::create(
const dictionary &dict,
const boundaryBase &boundary,
const contactSearch &cSearch)
{
word bType = angleBracketsNames2(
"boundaryContactSearch",
pFlowProcessors().localRunTypeName(),
boundary.type());
word altBType{"boundaryContactSearch<none>"};
if( boundaryBasevCtorSelector_.search(bType) )
{
pOutput.space(4)<<"Creating contact search boundary "<< Green_Text(bType)<<
" for "<<boundary.name()<<endl;
return boundaryBasevCtorSelector_[bType](dict, boundary, cSearch);
}
else if(boundaryBasevCtorSelector_.search(altBType))
{
pOutput.space(4)<<"Creating contact search boundary "<< Green_Text(altBType)<<
" for "<<boundary.name()<<endl;
return boundaryBasevCtorSelector_[altBType](dict, boundary, cSearch);
}
else
{
printKeys
(
fatalError << "Ctor Selector "<< bType<<
" and "<< altBType << " do not exist. \n"
<<"Avaiable ones are: \n"
,
boundaryBasevCtorSelector_
);
fatalExit;
}
return nullptr;
}

View File

@ -0,0 +1,109 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
#ifndef __boundaryContactSearch_hpp__
#define __boundaryContactSearch_hpp__
#include "generalBoundary.hpp"
#include "contactSearchGlobals.hpp"
#include "virtualConstructor.hpp"
namespace pFlow
{
class contactSearch;
class boundaryContactSearch
: public generalBoundary
{
private:
const contactSearch &contactSearch_;
/// @brief update interval in terms of iteration numebr
uint32 updateInterval_;
/// @brief last iteration number which contact search has been performed
uint32 lastUpdated_ = 0;
/// @brief performed search?
bool performedSearch_ = false;
public:
// type info
TypeInfo("boundaryContactSearch<none>");
boundaryContactSearch(
const dictionary &dict,
const boundaryBase &boundary,
const contactSearch &cSearch);
create_vCtor(
boundaryContactSearch,
boundaryBase,
(
const dictionary &dict,
const boundaryBase &boundary,
const contactSearch &cSearch),
(dict, boundary, cSearch));
add_vCtor(
boundaryContactSearch,
boundaryContactSearch,
boundaryBase);
const contactSearch &cSearch() const
{
return contactSearch_;
}
bool hearChanges(
real t,
real dt,
uint32 iter,
const message &msg,
const anyList &varList) override
{
if (msg.equivalentTo(message::BNDR_RESET))
{
// do nothing
}
return true;
}
virtual bool broadSearch(
uint32 iter,
real t,
real dt,
csPairContainerType &ppPairs,
csPairContainerType &pwPairs,
bool force = false)
{
return true;
}
static uniquePtr<boundaryContactSearch> create(
const dictionary &dict,
const boundaryBase &boundary,
const contactSearch &cSearch);
};
}
#endif //__boundaryContactSearch_hpp__

View File

@ -0,0 +1,32 @@
#include "boundaryContactSearchList.hpp"
#include "boundaryList.hpp"
void pFlow::boundaryContactSearchList::setList(
const dictionary &dict,
const contactSearch &cSearch)
{
for(auto i=0; i<boundaries_.size(); i++)
{
this->set
(
i,
boundaryContactSearch::create(dict, boundaries_[i], cSearch)
);
}
}
pFlow::boundaryContactSearchList::boundaryContactSearchList(
const dictionary &dict,
const boundaryList& bndrs,
const contactSearch &cSearch)
:
ListPtr(bndrs.size()),
boundaries_(bndrs)
{
setList(dict, cSearch);
}
bool pFlow::boundaryContactSearchList::boundariesUpdated() const
{
return boundaries_.boundariesUpdated();
}

View File

@ -0,0 +1,43 @@
#include "ListPtr.hpp"
#include "boundaryContactSearch.hpp"
namespace pFlow
{
class boundaryList;
class contactSearch;
class boundaryContactSearchList
:
public ListPtr<boundaryContactSearch>
{
private:
const boundaryList& boundaries_;
void setList(
const dictionary& dict,
const contactSearch& cSearch);
public:
TypeInfoNV("boundaryContactSearchList");
boundaryContactSearchList(
const dictionary& dict,
const boundaryList& bndrs,
const contactSearch& cSearch);
~boundaryContactSearchList()=default;
inline
const boundaryList& boundaries()const
{
return boundaries_;
}
bool boundariesUpdated()const;
};
}

View File

@ -0,0 +1,131 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
#include "periodicBoundaryContactSearch.hpp"
#include "contactSearch.hpp"
#include "particles.hpp"
#include "pointStructure.hpp"
#include "geometry.hpp"
void pFlow::periodicBoundaryContactSearch::setSearchBox()
{
auto db = pStruct().thisDomain().domainBox();
auto n1 = boundary().mirrorBoundary().boundaryPlane().normal();
auto l1 = boundary().mirrorBoundary().neighborLength();
auto n2 = boundary().boundaryPlane().normal();
auto l2 = boundary().neighborLength();
realx3 minP = db.minPoint() + (db.maxPoint()-db.minPoint())* n1+(n2*l2);
realx3 maxP = db.maxPoint() + (n1*l1);
searchBox_={minP, maxP};
}
pFlow::periodicBoundaryContactSearch::periodicBoundaryContactSearch(
const dictionary &dict,
const boundaryBase &boundary,
const contactSearch &cSearch)
:
boundaryContactSearch(dict, boundary, cSearch),
transferVec_(boundary.mirrorBoundary().displacementVectroToMirror()),
thisIndex_(thisBoundaryIndex()),
mirrorIndex_(mirrorBoundaryindex()),
diameter_(cSearch.Particles().boundingSphere())
{
if(thisIndex_%2==1)
{
masterSearch_ = true;
setSearchBox();
real minD;
real maxD;
cSearch.Particles().boundingSphereMinMax(minD, maxD);
ppContactSearch_ = makeUnique<ppwBndryContactSearch>(
searchBox_,
maxD);
const auto& geom = cSearch.Geometry();
pwContactSearch_ = makeUnique<wallBoundaryContactSearch>(
0.5,
geom.numPoints(),
geom.size(),
geom.points().deviceViewAll(),
geom.vertices().deviceViewAll(),
geom.normals().deviceViewAll());
}
else
{
masterSearch_ = false;
searchBox_={{0,0,0},{0,0,0}};
}
}
bool pFlow::periodicBoundaryContactSearch::broadSearch
(
uint32 iter,
real t,
real dt,
csPairContainerType &ppPairs,
csPairContainerType &pwPairs,
bool force
)
{
if(masterSearch_)
{
auto thisP = boundary().thisPoints();
auto thisDiams = diameter_.BoundaryField(thisIndex_).thisField();
auto mirrorP = mirrorBoundary().thisPoints();
auto mirrorDiams = diameter_.BoundaryField(mirrorIndex_).thisField();
ppContactSearch_().broadSearchPP(
ppPairs,
thisP,
thisDiams,
mirrorP,
mirrorDiams,
transferVec_);
/*pwContactSearch_().broadSearch(
pwPairs,
ppContactSearch_().searchCells(),
thisP,
thisDiams,
mirrorP,
mirrorDiams,
transferVec_,
ppContactSearch_().sizeRatio());*/
//output<<t<<" boundary pp size "<< ppPairs.size()<<endl;
//output<<t<<" boundary pw size "<< pwPairs.size()<<endl;
return true;
}else
{
return true;
}
}

View File

@ -0,0 +1,81 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
#ifndef __periodicBoundaryContactSearch_hpp__
#define __periodicBoundaryContactSearch_hpp__
#include "boundaryContactSearch.hpp"
#include "box.hpp"
#include "ppwBndryContactSearch.hpp"
#include "pointFields.hpp"
#include "wallBoundaryContactSearch.hpp"
namespace pFlow
{
class periodicBoundaryContactSearch
: public boundaryContactSearch
{
private:
box searchBox_;
realx3 transferVec_;
uint32 thisIndex_;
uint32 mirrorIndex_;
uniquePtr<ppwBndryContactSearch> ppContactSearch_ = nullptr;
uniquePtr<wallBoundaryContactSearch> pwContactSearch_ = nullptr;
const realPointField_D &diameter_;
bool masterSearch_ = false;
void setSearchBox();
public:
TypeInfo("boundaryContactSearch<regular,periodic>")
periodicBoundaryContactSearch(
const dictionary &dict,
const boundaryBase &boundary,
const contactSearch &cSearch);
~periodicBoundaryContactSearch() override = default;
add_vCtor(
boundaryContactSearch,
periodicBoundaryContactSearch,
boundaryBase);
bool broadSearch(
uint32 iter,
real t,
real dt,
csPairContainerType &ppPairs,
csPairContainerType &pwPairs,
bool force = false) override;
};
}
#endif //__periodicBoundaryContactSearch_hpp__

View File

@ -0,0 +1,109 @@
#include "ppwBndryContactSearch.hpp"
#include "ppwBndryContactSearchKernels.hpp"
#include "phasicFlowKokkos.hpp"
#include "streams.hpp"
void pFlow::ppwBndryContactSearch::checkAllocateNext(uint32 n)
{
if( nextCapacity_ < n)
{
nextCapacity_ = n;
reallocNoInit(next_, n);
}
}
void pFlow::ppwBndryContactSearch::nullifyHead()
{
fill(head_, static_cast<uint32>(-1));
}
void pFlow::ppwBndryContactSearch::nullifyNext(uint32 n)
{
fill(next_, 0u, n, static_cast<uint32>(-1));
}
void pFlow::ppwBndryContactSearch::buildList(
const deviceScatteredFieldAccess<realx3> &points)
{
if(points.empty())return;
uint32 n = points.size();
checkAllocateNext(n);
nullifyNext(n);
nullifyHead();
pFlow::pweBndryContactSearchKernels::buildNextHead(
points,
searchCells_,
head_,
next_
);
}
pFlow::ppwBndryContactSearch::ppwBndryContactSearch
(
const box &domain,
real cellSize,
real sizeRatio
)
:
searchCells_(domain, cellSize),
head_("periodic:head",searchCells_.nx(), searchCells_.ny(), searchCells_.nz()),
sizeRatio_(sizeRatio)
{
}
bool pFlow::ppwBndryContactSearch::broadSearchPP
(
csPairContainerType &ppPairs,
const deviceScatteredFieldAccess<realx3> &points,
const deviceScatteredFieldAccess<real>& diams,
const deviceScatteredFieldAccess<realx3> &mirrorPoints,
const deviceScatteredFieldAccess<real>& mirrorDiams,
const realx3& transferVec
)
{
buildList(points);
uint32 nNotInserted = 1;
// loop until the container size fits the numebr of contact pairs
while (nNotInserted > 0)
{
nNotInserted = pFlow::pweBndryContactSearchKernels::broadSearchPP
(
ppPairs,
points,
diams,
mirrorPoints,
mirrorDiams,
transferVec,
head_,
next_,
searchCells_,
sizeRatio_
);
if(nNotInserted)
{
// - resize the container
// note that getFull now shows the number of failed insertions.
uint32 len = max(nNotInserted,100u) ;
auto oldCap = ppPairs.capacity();
ppPairs.increaseCapacityBy(len);
INFORMATION<< "Particle-particle contact pair container capacity increased from "<<
oldCap << " to "<<ppPairs.capacity()<<" in peiodicBoundaryContactSearch."<<END_INFO;
}
}
return true;
}

View File

@ -0,0 +1,86 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
#ifndef __ppwBndryContactSearch_hpp__
#define __ppwBndryContactSearch_hpp__
#include "contactSearchGlobals.hpp"
#include "scatteredFieldAccess.hpp"
#include "cells.hpp"
namespace pFlow
{
class ppwBndryContactSearch
{
public:
using HeadType = deviceViewType3D<uint32>;
using NextType = deviceViewType1D<uint32>;
private:
cells searchCells_;
HeadType head_{ "periodic::head", 1, 1, 1 };
NextType next_{ "periodic::next", 1 };
real sizeRatio_ = 1.0;
uint32 nextCapacity_ = 0;
void checkAllocateNext(uint32 n);
void nullifyHead();
void nullifyNext(uint32 n);
void buildList(
const deviceScatteredFieldAccess<realx3> &points);
public:
ppwBndryContactSearch(
const box &domain,
real cellSize,
real sizeRatio = 1.0);
bool broadSearchPP(
csPairContainerType &ppPairs,
const deviceScatteredFieldAccess<realx3> &points,
const deviceScatteredFieldAccess<real> &diams,
const deviceScatteredFieldAccess<realx3> &mirrorPoints,
const deviceScatteredFieldAccess<real> &mirrorDiams,
const realx3 &transferVec);
const auto& searchCells()const
{
return searchCells_;
}
real sizeRatio()const
{
return sizeRatio_;
}
};
}
#endif //__ppwBndryContactSearch_hpp__

View File

@ -0,0 +1,105 @@
#include "ppwBndryContactSearchKernels.hpp"
INLINE_FUNCTION_HD
bool sphereSphereCheckB(const pFlow::realx3& p1, const pFlow::realx3 p2, pFlow::real d1, pFlow::real d2)
{
return pFlow::length(p2-p1) < 0.5*(d2+d1);
}
void pFlow::pweBndryContactSearchKernels::buildNextHead
(
const deviceScatteredFieldAccess<realx3> &points,
const cells &searchCells,
deviceViewType3D<uint32> &head,
deviceViewType1D<uint32> &next
)
{
if(points.empty())return;
uint32 n= points.size();
Kokkos::parallel_for(
"pFlow::ppwBndryContactSearch::buildList",
deviceRPolicyStatic(0,n),
LAMBDA_HD(uint32 i)
{
int32x3 ind;
if( searchCells.pointIndexInDomain(points[i], ind) )
{
// discards points out of searchCell
uint32 old = Kokkos::atomic_exchange(&head(ind.x(), ind.y(), ind.z()), i);
next[i] = old;
}
}
);
Kokkos::fence();
}
pFlow::uint32 pFlow::pweBndryContactSearchKernels::broadSearchPP
(
csPairContainerType &ppPairs,
const deviceScatteredFieldAccess<realx3> &points,
const deviceScatteredFieldAccess<real> &diams,
const deviceScatteredFieldAccess<realx3> &mirrorPoints,
const deviceScatteredFieldAccess<real> &mirrorDiams,
const realx3 &transferVec,
const deviceViewType3D<uint32> &head,
const deviceViewType1D<uint32> &next,
const cells &searchCells,
const real sizeRatio
)
{
if(points.empty()) return 0;
if(mirrorPoints.empty())return 0;
auto nMirror = mirrorPoints.size();
uint32 getFull = 0;
Kokkos::parallel_reduce(
"pFlow::pweBndryContactSearchKernels::broadSearchPP",
deviceRPolicyStatic(0, nMirror),
LAMBDA_HD(const uint32 mrrI, uint32 &getFullUpdate)
{
realx3 p_m = mirrorPoints(mrrI) + transferVec;
int32x3 ind_m;
if( !searchCells.pointIndexInDomain(p_m, ind_m))return;
real d_m = sizeRatio*mirrorDiams[mrrI];
for(int ii=-1; ii<2; ii++)
{
for(int jj=-1; jj<2; jj++)
{
for(int kk =-1; kk<2; kk++)
{
auto ind = ind_m + int32x3{ii,jj,kk};
if(!searchCells.inCellRange(ind))continue;
uint32 thisI = head(ind.x(),ind.y(),ind.z());
while (thisI!=static_cast<uint32>(-1))
{
auto d_n = sizeRatio*diams[thisI];
// first item is for this boundary and second itme, for mirror
if(sphereSphereCheckB(p_m, points[thisI], d_m, d_n)&&
ppPairs.insert(thisI,mrrI) == static_cast<uint32>(-1))
{
getFullUpdate++;
}
thisI = next(thisI);
}
}
}
}
},
getFull
);
return getFull;
}

View File

@ -0,0 +1,31 @@
#include "contactSearchGlobals.hpp"
#include "cells.hpp"
#include "contactSearchFunctions.hpp"
#include "scatteredFieldAccess.hpp"
namespace pFlow::pweBndryContactSearchKernels
{
void buildNextHead(
const deviceScatteredFieldAccess<realx3> &points,
const cells &searchCells,
deviceViewType3D<uint32> &head,
deviceViewType1D<uint32> &next );
uint32 broadSearchPP
(
csPairContainerType &ppPairs,
const deviceScatteredFieldAccess<realx3> &points,
const deviceScatteredFieldAccess<real> &diams,
const deviceScatteredFieldAccess<realx3> &mirrorPoints,
const deviceScatteredFieldAccess<real> &mirrorDiams,
const realx3 &transferVec,
const deviceViewType3D<uint32> &head,
const deviceViewType1D<uint32> &next,
const cells &searchCells,
real sizeRatio
);
}

View File

@ -0,0 +1,144 @@
#include "wallBoundaryContactSearch.hpp"
#include "streams.hpp"
pFlow::wallBoundaryContactSearch::wallBoundaryContactSearch
(
real cellExtent,
uint32 numPoints,
uint32 numElements,
const ViewType1D<realx3, memory_space> &points,
const ViewType1D<uint32x3, memory_space> &vertices,
const ViewType1D<realx3, memory_space> &normals
)
:
cellExtent_( max(cellExtent, 0.5 ) ),
numElements_(numElements),
numPoints_(numPoints),
vertices_(vertices),
points_(points),
normals_(normals)
{
allocateArrays();
}
bool pFlow::wallBoundaryContactSearch::build(const cells &searchBox, const realx3& transferVec)
{
Kokkos::parallel_for(
"pFlow::cellsWallLevel0::build",
deviceRPolicyStatic(0,numElements_),
CLASS_LAMBDA_HD(uint32 i)
{
auto v = vertices_[i];
auto p1 = points_[v.x()]+transferVec;
auto p2 = points_[v.y()]+transferVec;
auto p3 = points_[v.z()]+transferVec;
realx3 minP;
realx3 maxP;
searchBox.extendBox(p1, p2, p3, cellExtent_, minP, maxP);
elementBox_[i] = iBoxType(searchBox.pointIndex(minP), searchBox.pointIndex(maxP));
auto d = elementBox_[i].maxPoint()-elementBox_[i].minPoint();
validBox_[i] = (d.x()*d.y()*d.z())==0? 0:1;
});
Kokkos::fence();
return true;
}
bool pFlow::wallBoundaryContactSearch::broadSearch
(
csPairContainerType &pairs,
const cells &searchCells,
const deviceScatteredFieldAccess<realx3> &thisPoints,
const deviceScatteredFieldAccess<real> &thisDiams,
const deviceScatteredFieldAccess<realx3> &mirrorPoints,
const deviceScatteredFieldAccess<real> &mirroDiams,
const realx3 &transferVec,
real sizeRatio
)
{
uint32 nNotInserted = 1;
while (nNotInserted>0u)
{
build(searchCells,{0,0,0});
nNotInserted = findPairsElementRangeCount(
pairs,
searchCells,
thisPoints,
thisDiams,
{0,0,0},
0
);
build(searchCells, transferVec);
nNotInserted += findPairsElementRangeCount(
pairs,
searchCells,
mirrorPoints,
mirroDiams,
transferVec,
BASE_MIRROR_WALL_INDEX
);
if(nNotInserted>0u)
{
// note that getFull now shows the number of failed insertions.
uint32 incCap = max(nNotInserted,50u) ;
auto oldCap = pairs.capacity();
pairs.increaseCapacityBy(incCap);
INFORMATION<< "The contact pair container capacity increased from "<<
oldCap << " to "<<pairs.capacity()<<" in wallBoundaryContactSearch."<<END_INFO;
}
}
return true;
}
pFlow::uint32 pFlow::wallBoundaryContactSearch::findPairsElementRangeCount
(
csPairContainerType &pairs,
const cells &searchCells,
const deviceScatteredFieldAccess<realx3> &pPoints,
const deviceScatteredFieldAccess<real> &pDiams,
const realx3 &transferVec,
uint baseTriIndex
)
{
if(pPoints.empty())return 0u;
uint32 nNotInserted = 0;
uint32 nThis = pPoints.size();
const auto& numElements = numElements_;
const auto& elementBox = elementBox_;
const auto& validBox = validBox_;
Kokkos::parallel_reduce(
"pFlow::wallBoundaryContactSearch::findPairsElementRangeCount",
deviceRPolicyDynamic(0,nThis),
LAMBDA_HD(uint32 i, uint32 &notInsertedUpdate)
{
auto p = pPoints[i]+transferVec;
int32x3 ind;
if( searchCells.pointIndexInDomain(p, ind) )
{
for(uint32 nTri=0; nTri<numElements; nTri++)
{
if( validBox[nTri]== 0)continue;
if( elementBox[nTri].isInside(ind)&&
pairs.insert(i,nTri+baseTriIndex) == static_cast<uint32>(-1))
{
notInsertedUpdate++;
}
}
}
},
nNotInserted
);
return nNotInserted;
}

View File

@ -0,0 +1,131 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
#ifndef __wallBoundaryContactSearch_hpp__
#define __wallBoundaryContactSearch_hpp__
#include "contactSearchGlobals.hpp"
#include "contactSearchFunctions.hpp"
#include "scatteredFieldAccess.hpp"
#include "iBox.hpp"
#include "cells.hpp"
namespace pFlow
{
class wallBoundaryContactSearch
{
public:
using execution_space = csExecutionSpace;
using memory_space = typename execution_space::memory_space;
using iBoxType = iBox<int32>;
private:
// - box extent
real cellExtent_ = 0.5;
// - number of triangle elements
uint32 numElements_ = 0;
// - number of points
uint32 numPoints_ = 0;
// - ref to vectices (borrowed)
ViewType1D<uint32x3, memory_space> vertices_;
// - ref to points in the trisurface (borrowed)
ViewType1D<realx3, memory_space> points_;
// - ref to normal vectors of triangles (borrowed)
ViewType1D<realx3, memory_space> normals_;
// cell range of element/triangle bounding box
ViewType1D<iBoxType, memory_space> elementBox_;
ViewType1D<uint8, memory_space> validBox_;
FUNCTION_H
void allocateArrays()
{
reallocNoInit( elementBox_, numElements_);
reallocNoInit( validBox_, numElements_);
}
public:
TypeInfoNV("wallBoundaryContactSearch");
INLINE_FUNCTION_HD
wallBoundaryContactSearch()=default;
FUNCTION_H
wallBoundaryContactSearch(
real cellExtent,
uint32 numPoints,
uint32 numElements,
const ViewType1D<realx3,memory_space>& points,
const ViewType1D<uint32x3,memory_space>& vertices,
const ViewType1D<realx3, memory_space>& normals);
INLINE_FUNCTION_HD
uint32 numElements()const
{
return numElements_;
}
bool build(const cells& searchBox, const realx3& transferVec);
bool broadSearch(
csPairContainerType& pairs,
const cells &searchCells,
const deviceScatteredFieldAccess<realx3>& thisPoints,
const deviceScatteredFieldAccess<real>& thisDiams,
const deviceScatteredFieldAccess<realx3>& mirrorPoints,
const deviceScatteredFieldAccess<real>& mirroDiams,
const realx3& transferVec,
real sizeRatio);
uint32 findPairsElementRangeCount(
csPairContainerType &pairs,
const cells &searchCells,
const deviceScatteredFieldAccess<realx3> &pPoints,
const deviceScatteredFieldAccess<real> &pDiams,
const realx3 &transferVec,
uint baseTriIndex);
}; // wallBoundaryContactSearch
} // pFlow
#endif // __wallBoundaryContactSearch_hpp__

View File

@ -19,54 +19,124 @@ Licence:
-----------------------------------------------------------------------------*/ -----------------------------------------------------------------------------*/
#include "contactSearch.hpp" #include "contactSearch.hpp"
#include "streams.hpp"
#include "particles.hpp"
pFlow::contactSearch::contactSearch( pFlow::contactSearch::contactSearch(
const dictionary& dict, const dictionary& dict,
const box& domain, const box& extDomain,
const particles& prtcl, const particles& prtcl,
const geometry& geom, const geometry& geom,
Timers& timers) Timers& timers)
: :
interactionBase(prtcl, geom), extendedDomainBox_(extDomain),
domain_(domain), particles_(prtcl),
dict_(dict), geometry_(geom),
sphereSphereTimer_("particle-particle contact search", &timers), bTimer_("Boundary particles contact search", &timers),
sphereWallTimer_("particle-wall contact search", &timers) ppTimer_("Internal particles contact search", &timers),
dict_(dict)
{ {
} }
const pFlow::pointStructure &pFlow::contactSearch::pStruct() const
{
return particles_.pStruct();
}
bool pFlow::contactSearch::broadSearch
(
const timeInfo &ti,
csPairContainerType &ppPairs,
csPairContainerType &pwPairs,
bool force
)
{
if(enterBroadSearch(ti, force))
{
ppTimer_.start();
if( !BroadSearch(
ti,
ppPairs,
pwPairs,
force ) )
{
fatalErrorInFunction;
performedSearch_ = false;
return false;
}
ppTimer_.end();
performedSearch_ = true;
}
else
{
performedSearch_ = false;
}
return true;
}
bool pFlow::contactSearch::boundaryBroadSearch
(
uint32 bndryIndex,
const timeInfo &ti,
csPairContainerType &ppPairs,
csPairContainerType &pwPairs,
bool force
)
{
if(enterBroadSearchBoundary(ti, force))
{
bTimer_.start();
for(uint32 i=0u; i<6u; i++)
{
if(!BoundaryBroadSearch(
i,
ti,
ppPairs,
pwPairs,
force))
{
performedSearchBoundary_ = false;
return false;
}
}
bTimer_.end();
performedSearchBoundary_ = true;
}
else
{
performedSearchBoundary_ = false;
}
return true;
}
pFlow::uniquePtr<pFlow::contactSearch> pFlow::contactSearch::create( pFlow::uniquePtr<pFlow::contactSearch> pFlow::contactSearch::create(
const dictionary &dict, const dictionary &dict,
const box& domain, const box &extDomain,
const particles &prtcl, const particles &prtcl,
const geometry &geom, const geometry &geom,
Timers &timers) Timers &timers)
{ {
word baseMethName = dict.getVal<word>("method"); word baseMethName = dict.getVal<word>("method");
word wallMethod = dict.getVal<word>("wallMapping");
auto model = angleBracketsNames2("ContactSearch", baseMethName, wallMethod);
REPORT(1)<<"Selecting contact search model . . ."<<endREPORT;
auto model = angleBracketsNames("ContactSearch", baseMethName);
pOutput.space(2)<<"Selecting contact search model "<<Green_Text(model)<<endl;
if( dictionaryvCtorSelector_.search(model)) if( dictionaryvCtorSelector_.search(model))
{ {
auto objPtr = dictionaryvCtorSelector_[model] (dict, domain, prtcl, geom, timers); auto objPtr = dictionaryvCtorSelector_[model] (dict, extDomain, prtcl, geom, timers);
REPORT(2)<<"Model "<< greenText(model)<<" is created."<<endREPORT;
return objPtr; return objPtr;
} }
else else
{ {
printKeys printKeys
( (
fatalError << "Ctor Selector "<< model << " dose not exist. \n" fatalError << "Ctor Selector "<< model << " does not exist. \n"
<<"Avaiable ones are: \n\n" <<"Avaiable ones are: \n\n"
, ,
dictionaryvCtorSelector_ dictionaryvCtorSelector_

View File

@ -23,42 +23,68 @@ Licence:
#define __contactSearch_hpp__ #define __contactSearch_hpp__
#include "interactionBase.hpp" #include "contactSearchGlobals.hpp"
#include "unsortedPairs.hpp"
#include "box.hpp"
#include "dictionary.hpp" #include "dictionary.hpp"
#include "virtualConstructor.hpp"
#include "timeInfo.hpp"
#include "Timer.hpp"
namespace pFlow namespace pFlow
{ {
// - forward
class box;
class particles;
class geometry;
class pointStructure;
class contactSearch class contactSearch
:
public interactionBase
{ {
public: private:
using IdType = typename interactionBase::IdType;
using IndexType = typename interactionBase::IndexType; const box& extendedDomainBox_;
using ExecutionSpace = typename interactionBase::ExecutionSpace; /// @brief update interval in terms of iteration numebr
uint32 updateInterval_= 1;
using PairContainerType = unsortedPairs<ExecutionSpace, IdType>; /// @brief last iteration number which contact search has been performed
uint32 lastUpdated_ = 0;
protected: /// @brief performed search?
bool performedSearch_ = false;
const box& domain_; /// @brief performed search in boundaries
bool performedSearchBoundary_ = false;
/// const ref to particles
const particles& particles_;
/// const ref to geometry
const geometry& geometry_;
Timer bTimer_;
Timer ppTimer_;
dictionary dict_; dictionary dict_;
Timer sphereSphereTimer_; virtual
bool BroadSearch(
const timeInfo& ti,
csPairContainerType& ppPairs,
csPairContainerType& pwPairs,
bool force
)=0;
Timer sphereWallTimer_; virtual
bool BoundaryBroadSearch(
auto& dict() uint32 bndryIndex,
{ const timeInfo& ti,
return dict_; csPairContainerType& ppPairs,
} csPairContainerType& pwPairs,
bool force = false
)=0;
public: public:
@ -66,7 +92,7 @@ public:
contactSearch( contactSearch(
const dictionary& dict, const dictionary& dict,
const box& domain, const box& extDomain,
const particles& prtcl, const particles& prtcl,
const geometry& geom, const geometry& geom,
Timers& timers); Timers& timers);
@ -88,40 +114,103 @@ public:
(dict, domain, prtcl, geom, timers) (dict, domain, prtcl, geom, timers)
); );
const auto& domain()const inline
bool performedSearch()const
{ {
return domain_; return performedSearch_;
} }
const auto& dict()const inline
bool performedSearchBoundary()const
{
return performedSearchBoundary_;
}
inline
bool performSearch(uint32 iter, bool force = false)const
{
if((iter-lastUpdated_) % updateInterval_ == 0 || iter == 0 || force )
{
return true;
}
return false;
}
bool enterBroadSearch(const timeInfo& ti, bool force = false)const
{
return performSearch(ti.iter(), force);
}
virtual
bool enterBroadSearchBoundary(const timeInfo& ti, bool force=false)const = 0;
inline
uint32 updateInterval()const
{
return updateInterval_;
}
inline
const dictionary& dict()const
{ {
return dict_; return dict_;
} }
inline
const box& extendedDomainBox()const
{
return extendedDomainBox_;
}
inline
const particles& Particles()const
{
return particles_;
}
const pointStructure& pStruct()const;
inline
const geometry& Geometry()const
{
return geometry_;
}
inline
Timer& ppTimer()
{
return ppTimer_;
}
inline
Timer& bTimer()
{
return bTimer_;
}
virtual
bool broadSearch( bool broadSearch(
PairContainerType& ppPairs, const timeInfo& ti,
PairContainerType& pwPairs, csPairContainerType& ppPairs,
bool force = false) = 0; csPairContainerType& pwPairs,
bool force = false);
bool boundaryBroadSearch(
uint32 bndryIndex,
const timeInfo& ti,
csPairContainerType& ppPairs,
csPairContainerType& pwPairs,
bool force = false);
virtual virtual
bool ppEnterBroadSearch()const = 0; real sizeRatio()const = 0;
virtual virtual
bool pwEnterBroadSearch()const = 0; real cellExtent()const = 0;
virtual
bool ppPerformedBroadSearch()const = 0;
virtual
bool pwPerformedBroadSearch()const = 0;
static static
uniquePtr<contactSearch> create( uniquePtr<contactSearch> create(
const dictionary& dict, const dictionary& dict,
const box& domain, const box& extDomain,
const particles& prtcl, const particles& prtcl,
const geometry& geom, const geometry& geom,
Timers& timers); Timers& timers);

View File

@ -96,17 +96,6 @@ void indexToCell(const indexType idx, const iBox<cellIndexType>& box, triple<cel
cell+= box.minPoint(); cell+= box.minPoint();
} }
INLINE_FUNCTION_HD
bool sphereSphereCheck(const realx3& p1, const realx3 p2, real d1, real d2)
{
return length(p2-p1) < 0.5*(d2+d1);
}
} }
#endif //__broadSearchFunctions_hpp__ #endif //__broadSearchFunctions_hpp__

View File

@ -18,28 +18,24 @@ Licence:
-----------------------------------------------------------------------------*/ -----------------------------------------------------------------------------*/
#ifndef __interactionTypes_hpp__
#define __interactionTypes_hpp__
#include "types.hpp" #include "types.hpp"
#include "unsortedPairs.hpp"
#ifndef __contactSearchGlobals_hpp__
#define __contactSearchGlobals_hpp__
namespace pFlow namespace pFlow
{ {
using csExecutionSpace = DefaultExecutionSpace;
// always use signed types using csIdType = uint32;
using CELL_INDEX_TYPE = int32;
using ID_TYPE = int32; using csPairContainerType = unsortedPairs<DefaultExecutionSpace, uint32>;
//constexpr int32 minCellIndex = largestNegative<CELL_INDEX_TYPE>(); inline
const uint32 BASE_MIRROR_WALL_INDEX = 1000000;
//constexpr int32 maxCellIndex = largestPositive<CELL_INDEX_TYPE>();
} }
#endif
#endif //__interactionTypes_hpp__

View File

@ -1,209 +0,0 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
#ifndef __NBS_hpp__
#define __NBS_hpp__
#include "NBSLevel0.hpp"
namespace pFlow
{
template<typename executionSpace>
class NBS
{
public:
using NBSLevel0Type = NBSLevel0<executionSpace>;
using cellIterator = typename NBSLevel0Type::cellIterator;
using IdType = typename NBSLevel0Type::IdType;
using IndexType = typename NBSLevel0Type::IndexType;
using Cells = typename NBSLevel0Type::Cells;
using CellType = typename Cells::CellType;
using execution_space = typename NBSLevel0Type::execution_space;
using memory_space = typename NBSLevel0Type::memory_space;
protected:
real sizeRatio_ = 1.0;
int32 updateFrequency_= 1;
int32 currentIter_ = 0;
bool performedSearch_ = false;
NBSLevel0Type NBSLevel0_;
private:
bool performSearch()
{
if(currentIter_ % updateFrequency_ == 0)
{
currentIter_++;
return true;
}else
{
currentIter_++;
return false;
}
}
public:
TypeInfoNV("NBS");
NBS(
const dictionary& dict,
const box& domain,
real minSize,
real maxSize,
const ViewType1D<realx3, memory_space>& position,
const ViewType1D<real, memory_space>& diam)
:
sizeRatio_(
max(
dict.getValOrSet<real>("sizeRatio", 1.0),
1.0
)),
updateFrequency_(
max(
dict.getValOrSet<int32>("updateFrequency", 1),
1
)),
NBSLevel0_(
domain,
maxSize*sizeRatio_,
sizeRatio_,
position,
diam)
{}
INLINE_FUNCTION_HD
NBS(const NBS&) = default;
INLINE_FUNCTION_HD
NBS& operator = (const NBS&) = default;
INLINE_FUNCTION_HD
~NBS()=default;
//// - Methods
bool enterBoadSearch()const
{
return currentIter_%updateFrequency_==0;
}
bool performedSearch()const
{
return performedSearch_;
}
Vector<cellIterator> getCellIteratorLevels()
{
return Vector<cellIterator>("cellIterator", 1, NBSLevel0_.getCellIterator());
}
auto getCellIterator(int32 lvl)const
{
return NBSLevel0_.getCellIterator();
}
int32 numLevels()const
{
return 1;
}
Vector<Cells> getCellsLevels()const
{
return Vector<Cells>("Cells", 1, NBSLevel0_.getCells());
}
auto getCells()const
{
return NBSLevel0_.getCells();
}
bool objectSizeChanged(int32 newSize)
{
NBSLevel0_.checkAllocateNext(newSize);
return true;
}
// - Perform the broad search to find pairs
// with force = true, perform broad search regardless of
// updateFrequency_ value
// on all the points in the range of [0,numPoints_)
template<typename PairsContainer>
bool broadSearch(PairsContainer& pairs, range activeRange, bool force=false)
{
if(force) currentIter_ = 0;
performedSearch_ = false;
if( !performSearch() ) return true;
NBSLevel0_.build(activeRange);
NBSLevel0_.findPairs(pairs);
performedSearch_ = true;
return true;
}
// - Perform the broad search to find pairs,
// ignore particles with incld(i) = true,
// with force = true, perform broad search regardless of
// updateFrequency_ value
template<typename PairsContainer, typename IncludeFunction>
bool broadSearch(PairsContainer& pairs, range activeRange, IncludeFunction incld, bool force = false)
{
if(force) currentIter_ = 0;
performedSearch_ = false;
if( !performSearch() ) return true;
NBSLevel0_.build(activeRange, incld);
NBSLevel0_.findPairs(pairs);
performedSearch_ = true;
return true;
}
};
}
#endif

View File

@ -1,82 +0,0 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
int32 m = this->head_(i,j,k);
CellType currentCell(i,j,k);
int32 n = -1;
while( m > -1 )
{
auto p_m = this->pointPosition_[m];
auto d_m = this->sizeRatio_* this->diameter_[m];
int32x3 crossIndex = mapIndexLevels(
int32x3(i,j,k),
level_,
upperLevel.level());
for(int32 ii = -1; ii<2; ii++)
{
for(int32 jj=-1; jj<2; jj++)
{
int32 kk=-1;
while( kk < 2)
{
int32x3 nghbrCI = crossIndex + int32x3(ii,jj,kk);
if( upperLevel.isInRange(nghbrCI) )
{
n = upperLevel.head_(
nghbrCI.x(),
nghbrCI.y(),
nghbrCI.z());
while( n >-1)
{
auto p_n = this->pointPosition_[n];
auto d_n = this->sizeRatio_*this->diameter_[n];
if( sphereSphereCheck(p_m, p_n, d_m, d_n) )
{
auto ln = n;
auto lm = m;
if(lm>ln) this->Swap(lm,ln);
if( auto res = pairs.insert(lm,ln); res <0)
{
getFullUpdate++;
}
}
n = this->next_[n];
}
}
kk++;
}
}
}
m = this->next_[m];
}

View File

@ -1,127 +0,0 @@
#ifndef __NBSLevel_hpp__
#define __NBSLevel_hpp__
#include "NBSLevel0.hpp"
namespace pFlow
{
INLINE_FUNCTION_HD
int32x3 mapIndexLevels(const int32x3& ind, int32 lowerLevel, int32 upperLevel);
template<typename executionSpace>
class
NBSLevel
:
public NBSLevel0<executionSpace>
{
public:
using NBSLevel0Type = NBSLevel0<executionSpace>;
using cellIterator = typename NBSLevel0Type::cellIterator;
using IdType = typename NBSLevel0Type::IdType;
using IndexType = typename NBSLevel0Type::IndexType;
using Cells = typename NBSLevel0Type::Cells;
using CellType = typename Cells::CellType;
using execution_space = typename NBSLevel0Type::execution_space;
using memory_space = typename NBSLevel0Type::memory_space;
using mdrPolicyFindPairs = typename NBSLevel0Type::mdrPolicyFindPairs;
using HeadType = typename NBSLevel0Type::HeadType;
using NextType = typename NBSLevel0Type::NextType;
template<typename exeSpace>
friend class NBSLevels;
protected:
int32 level_ = 0;
public:
TypeInfoNV("NBSLevel0");
INLINE_FUNCTION_HD
NBSLevel(){}
NBSLevel(
int32 lvl,
const box& domain,
real cellSize,
real sizeRatio,
const ViewType1D<realx3, memory_space>& position,
const ViewType1D<real, memory_space>& diam)
:
NBSLevel0Type(
domain,
cellSize,
sizeRatio,
position,
diam,
lvl==0),
level_(lvl)
{}
INLINE_FUNCTION_HD
NBSLevel(const NBSLevel&) = default;
INLINE_FUNCTION_HD
NBSLevel& operator = (const NBSLevel&) = default;
INLINE_FUNCTION_HD
~NBSLevel() = default;
INLINE_FUNCTION_HD
auto level()const
{
return level_;
}
template<typename PairsContainer>
INLINE_FUNCTION_H
int32 findPairsCountCross(PairsContainer& pairs, NBSLevel& upperLevel)
{
mdrPolicyFindPairs
mdrPolicy(
{0,0,0},
{this->nx(),this->ny(),this->nz()} );
int32 notInsertedPairs;
Kokkos::parallel_reduce (
"NBSLevel::findPairsCountCross",
mdrPolicy,
CLASS_LAMBDA_HD(int32 i, int32 j, int32 k, int32& getFullUpdate){
#include "NBSCrossLoop.hpp"
}, notInsertedPairs);
return notInsertedPairs;
}
};
INLINE_FUNCTION_HD
int32x3 mapIndexLevels( const int32x3& ind, int32 lowerLevel, int32 upperLevel)
{
int32 a = pow(2, static_cast<int32>(upperLevel-lowerLevel));
return ind/a;
}
}
#endif

View File

@ -1,240 +0,0 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
#ifndef __NBSLevel0_hpp__
#define __NBSLevel0_hpp__
#include "mapperNBS.hpp"
namespace pFlow
{
template<typename executionSpace>
class NBSLevel0
:
public mapperNBS<executionSpace>
{
public:
using MapperType = mapperNBS<executionSpace>;
using cellIterator = typename MapperType::cellIterator;
using IdType = typename MapperType::IdType;
using IndexType = typename MapperType::IndexType;
using Cells = typename MapperType::Cells;
using CellType = typename Cells::CellType;
using execution_space = typename MapperType::execution_space;
using memory_space = typename MapperType::memory_space;
using HeadType = typename MapperType::HeadType;
using NextType = typename MapperType::NextType;
struct TagFindPairs{};
protected:
real sizeRatio_ = 1.0;
// borrowed ownership
ViewType1D<real, memory_space> diameter_;
using mdrPolicyFindPairs =
Kokkos::MDRangePolicy<
Kokkos::Rank<3>,
Kokkos::Schedule<Kokkos::Dynamic>,
execution_space>;
static INLINE_FUNCTION_HD
void Swap(int32& x, int32& y)
{
int32 tmp = x;
x = y;
y = tmp;
}
public:
TypeInfoNV("NBSLevel0");
INLINE_FUNCTION_HD
NBSLevel0(){}
NBSLevel0(
const box& domain,
real cellSize,
const ViewType1D<realx3, memory_space>& position,
const ViewType1D<real, memory_space>& diam)
:
MapperType(domain, cellSize, position),
diameter_(diam)
{}
NBSLevel0(
const box& domain,
int32 nx,
int32 ny,
int32 nz,
const ViewType1D<realx3, memory_space>& position,
const ViewType1D<real, memory_space>& diam)
:
MapperType(domain, nx, ny, nz, position),
diameter_(diam)
{ }
NBSLevel0(
const box& domain,
real cellSize,
real sizeRatio,
const ViewType1D<realx3, memory_space>& position,
const ViewType1D<real, memory_space>& diam,
bool nextOwner = true)
:
MapperType(domain, cellSize, position, nextOwner),
sizeRatio_(sizeRatio),
diameter_(diam)
{}
INLINE_FUNCTION_HD
NBSLevel0(const NBSLevel0&) = default;
INLINE_FUNCTION_HD
NBSLevel0& operator = (const NBSLevel0&) = default;
INLINE_FUNCTION_HD
~NBSLevel0()=default;
INLINE_FUNCTION_HD
auto sizeRatio()const
{
return sizeRatio_;
}
INLINE_FUNCTION_HD
auto& diameter()
{
return diameter_;
}
// - Perform the broad search to find pairs
// with force = true, perform broad search regardless of
// updateFrequency_ value
// on all the points in the range of [0,numPoints_)
template<typename PairsContainer>
bool broadSearch(PairsContainer& pairs, range activeRange)
{
this->build(activeRange);
findPairs(pairs);
return true;
}
// - Perform the broad search to find pairs,
// ignore particles with incld(i) = true,
// with force = true, perform broad search regardless of
// updateFrequency_ value
template<typename PairsContainer, typename IncludeFunction>
bool broadSearch(PairsContainer& pairs, range activeRange, IncludeFunction incld)
{
this->build(activeRange, incld);
findPairs(pairs);
return true;
}
template<typename PairsContainer>
INLINE_FUNCTION_H
bool findPairs(PairsContainer& pairs)
{
int32 getFull = 1;
// loop until the container size fits the numebr of contact pairs
while (getFull > 0)
{
getFull = findPairsCount(pairs);
if(getFull)
{
// - resize the container
// note that getFull now shows the number of failed insertions.
uint32 len = max(getFull,500) ;
auto oldCap = pairs.capacity();
pairs.increaseCapacityBy(len);
INFORMATION<< "The contact pair container capacity increased from "<<
oldCap << " to "<<pairs.capacity()<<" in NBSLevel0."<<endINFO;
}
Kokkos::fence();
}
return true;
}
template<typename PairsContainer>
INLINE_FUNCTION_H
int32 findPairsCount(PairsContainer& pairs)
{
mdrPolicyFindPairs
mdrPolicy(
{0,0,0},
{this->nx(),this->ny(),this->nz()} );
int32 notInsertedPairs;
Kokkos::parallel_reduce (
"NBSLevel0::findPairs",
mdrPolicy,
CLASS_LAMBDA_HD(int32 i, int32 j, int32 k, int32& getFullUpdate){
#include "NBSLoop.hpp"
}, notInsertedPairs);
return notInsertedPairs;
}
};
} // pFlow
#endif // __NBSLevel0_hpp__

View File

@ -1,438 +0,0 @@
#ifndef __NBSLevels_hpp__
#define __NBSLevels_hpp__
#include "NBSLevel.hpp"
#include "NBSLevel0.hpp"
#include "KokkosTypes.hpp"
namespace pFlow
{
template<typename executionSpace>
class NBSLevels
{
public:
using NBSLevelType = NBSLevel<executionSpace>;
using cellIterator = typename NBSLevelType::cellIterator;
using IdType = typename NBSLevelType::IdType;
using IndexType = typename NBSLevelType::IndexType;
using Cells = typename NBSLevelType::Cells;
using CellType = typename Cells::CellType;
using execution_space = typename NBSLevelType::execution_space;
using memory_space = typename NBSLevelType::memory_space;
using realRange = kPair<real,real>;
protected:
real minSize_;
real maxSize_;
int32 numLevels_=1;
Vector<NBSLevelType> nbsLevels_;
ViewType1D<realRange, memory_space> sizeRangeLevels_;
ViewType1D<realRange, HostSpace> sizeRangeLevelsHost_;
ViewType1D<real, memory_space> maxSizeLevels_;
ViewType1D<real, HostSpace> maxSizeLevelsHost_;
ViewType1D<int8, memory_space> particleLevel_;
range activeRange_{0,0};
using rangePolicyType =
Kokkos::RangePolicy<
Kokkos::IndexType<int32>,
Kokkos::Schedule<Kokkos::Static>,
execution_space>;
int32 setNumLevels()
{
int32 maxOvermin = static_cast<int32>(maxSize_/minSize_);
if (maxOvermin <=1)
return 1;
else if(maxOvermin<=3)
return 2;
else if(maxOvermin<=7)
return 3;
else if(maxOvermin<15)
return 4;
else if(maxOvermin<31)
return 5;
else if(maxOvermin<63)
return 6;
else if(maxOvermin <127)
return 7;
else
{
fatalErrorInFunction<<
"size ratio is not valid for multi-grid NBS "<< maxOvermin<<endl;
fatalExit;
}
return -1;
}
bool setDiameterRange(real sizeRatio)
{
real lvl_maxD = sizeRatio* maxSize_;
real lvl_minD = lvl_maxD/2.0;
for(int32 lvl=numLevels_-1; lvl>=0; lvl--)
{
if(lvl == 0 ) lvl_minD = 0.01*minSize_;
sizeRangeLevelsHost_[lvl] = {lvl_minD, lvl_maxD};
maxSizeLevelsHost_[lvl] = lvl_maxD;
lvl_maxD = lvl_minD;
lvl_minD /= 2.0;
}
copy(sizeRangeLevels_, sizeRangeLevelsHost_);
copy(maxSizeLevels_, maxSizeLevelsHost_);
REPORT(2)<<"Grids with "<< yellowText(numLevels_)<< " levels have been created."<<endREPORT;
for(int32 lvl=0; lvl<numLevels_; lvl++)
{
REPORT(3)<<"Cell gird No "<< yellowText(lvl)<<" with size range ("
<<sizeRangeLevelsHost_[lvl].first<<","<<sizeRangeLevelsHost_[lvl].second<<"]."<<endREPORT;
}
return true;
}
bool initLevels(
const box& domain,
real sizeRatio,
const ViewType1D<realx3, memory_space>& position,
const ViewType1D<real, memory_space>& diam)
{
for(int32 lvl = 0; lvl<numLevels_; lvl++)
{
nbsLevels_[lvl] = NBSLevelType(
lvl,
domain,
maxSizeLevelsHost_[lvl]*sizeRatio,
sizeRatio,
position,
diam );
}
auto next0 = nbsLevels_[0].next();
for(int32 lvl=1; lvl<numLevels_; lvl++)
{
nbsLevels_[lvl].setNext(next0);
}
return true;
}
void manageAllocateNext(range active)
{
activeRange_ = active;
if(activeRange_.second > nbsLevels_[0].capacity())
{
nbsLevels_[0].checkAllocateNext(activeRange_.second);
auto next0 = nbsLevels_[0].next();
for(int32 lvl=1; lvl<numLevels_; lvl++)
{
nbsLevels_[lvl].setNext(next0);
}
}
}
void nullify( range active)
{
for(int32 lvl=0; lvl<numLevels_; lvl++)
{
nbsLevels_[lvl].nullify(active);
}
}
public:
NBSLevels(
const box& domain,
real minSize,
real maxSize,
real sizeRatio,
const ViewType1D<realx3, memory_space>& position,
const ViewType1D<real, memory_space>& diam)
:
minSize_(minSize),
maxSize_(maxSize),
numLevels_(setNumLevels()),
nbsLevels_("nbsLevels", numLevels_, numLevels_, RESERVE()),
sizeRangeLevels_("sizeRangeLevels", numLevels_),
sizeRangeLevelsHost_("sizeRangeLevelsHost", numLevels_),
maxSizeLevels_("maxSizeLevels", numLevels_),
maxSizeLevelsHost_("maxSizeLevelsHost", numLevels_)
{
setDiameterRange(sizeRatio);
initLevels(domain, sizeRatio, position, diam);
}
auto getCellIterator(int32 lvl)const
{
return nbsLevels_[lvl].getCellIterator();
}
int32 numLevels()const
{
return numLevels_;
}
Cells getCells(int32 lvl)const
{
return nbsLevels_[lvl].getCells();
}
template<typename PairsContainer>
INLINE_FUNCTION_H
bool findPairs(PairsContainer& pairs)
{
int32 getFull = 1;
// loop until the container size fits the numebr of contact pairs
while (getFull > 0)
{
getFull = findPairsCount(pairs);
if(getFull)
{
// - resize the container
// note that getFull now shows the number of failed insertions.
uint32 len = max(getFull,100) ;
auto oldCap = pairs.capacity();
pairs.increaseCapacityBy(len);
INFORMATION<< "The contact pair container capacity increased from "<<
oldCap << " to "<<pairs.capacity()<<" in NBSLevels."<<endINFO;
}
Kokkos::fence();
}
return true;
}
template<typename PairsContainer>
INLINE_FUNCTION_H
int32 findPairsCount(PairsContainer& pairs)
{
int32 notInsertedCount = 0;
for(int32 lvl=0; lvl<numLevels_; lvl++)
{
// the same level
notInsertedCount+= nbsLevels_[lvl].findPairsCount(pairs);
for(int32 crsLvl = lvl+1; crsLvl<numLevels_; crsLvl++)
{
// cross levels
notInsertedCount+=
nbsLevels_[lvl].findPairsCountCross(pairs, nbsLevels_[crsLvl]);
}
}
return notInsertedCount;
}
INLINE_FUNCTION_H
void build(range activeRange)
{
// nullify next and heads
findParticleLevel(activeRange.first, activeRange.second);
manageAllocateNext(activeRange);
nullify(activeRange);
//
rangePolicyType rPolicy(activeRange.first, activeRange.second);
auto nbsLevel0 = nbsLevels_[0];
auto pointPosition = nbsLevel0.pointPosition();
auto particleLevel = particleLevel_;
auto next = nbsLevel0.next();
auto head0 = nbsLevel0.head();
typename NBSLevelType::HeadType head1, head2, head3, head4, head5, head6;
if(numLevels_>1) head1 = nbsLevels_[1].head();
if(numLevels_>2) head2 = nbsLevels_[2].head();
if(numLevels_>3) head3 = nbsLevels_[3].head();
if(numLevels_>4) head4 = nbsLevels_[4].head();
if(numLevels_>5) head5 = nbsLevels_[5].head();
if(numLevels_>6) head6 = nbsLevels_[6].head();
Kokkos::parallel_for(
"NBSLevels::build",
rPolicy,
LAMBDA_HD(int32 i){
int8 lvl = particleLevel[i];
auto ind = nbsLevel0.pointIndex(pointPosition[i]);
ind = mapIndexLevels(ind, 0, lvl);
int32 old;
if(lvl==0)
old =Kokkos::atomic_exchange(&head0(ind.x(), ind.y(), ind.z()),i);
else if(lvl==1)
old =Kokkos::atomic_exchange(&head1(ind.x(), ind.y(), ind.z()),i);
else if(lvl==2)
old =Kokkos::atomic_exchange(&head2(ind.x(), ind.y(), ind.z()),i);
else if(lvl==3)
old =Kokkos::atomic_exchange(&head3(ind.x(), ind.y(), ind.z()),i);
else if(lvl==4)
old =Kokkos::atomic_exchange(&head4(ind.x(), ind.y(), ind.z()),i);
else if(lvl==5)
old =Kokkos::atomic_exchange(&head5(ind.x(), ind.y(), ind.z()),i);
else if(lvl==6)
old =Kokkos::atomic_exchange(&head6(ind.x(), ind.y(), ind.z()),i);
next(i) = old;
});
Kokkos::fence();
}
template<typename IncludeFunction>
INLINE_FUNCTION_H
void build(range activeRange, IncludeFunction incld)
{
// nullify next and heads
findParticleLevel(activeRange.first, activeRange.second);
manageAllocateNext(activeRange);
nullify(activeRange);
rangePolicyType rPolicy(activeRange.first, activeRange.second);
auto nbsLevel0 = nbsLevels_[0];
auto pointPosition = nbsLevel0.pointPosition();
auto particleLevel = particleLevel_;
auto next = nbsLevel0.next();
auto head0 = nbsLevel0.head();
typename NBSLevelType::HeadType head1, head2, head3, head4, head5, head6;
if(numLevels_>1) head1 = nbsLevels_[1].head();
if(numLevels_>2) head2 = nbsLevels_[2].head();
if(numLevels_>3) head3 = nbsLevels_[3].head();
if(numLevels_>4) head4 = nbsLevels_[4].head();
if(numLevels_>5) head5 = nbsLevels_[5].head();
if(numLevels_>6) head6 = nbsLevels_[6].head();
Kokkos::parallel_for(
"NBSLevels::build",
rPolicy,
LAMBDA_HD(int32 i){
if(!incld(i)) return;
int8 lvl = particleLevel[i];
auto ind = nbsLevel0.pointIndex(pointPosition[i]);
ind = mapIndexLevels(ind, 0, lvl);
int32 old;
if(lvl==0)
old =Kokkos::atomic_exchange(&head0(ind.x(), ind.y(), ind.z()),i);
else if(lvl==1)
old =Kokkos::atomic_exchange(&head1(ind.x(), ind.y(), ind.z()),i);
else if(lvl==2)
old =Kokkos::atomic_exchange(&head2(ind.x(), ind.y(), ind.z()),i);
else if(lvl==3)
old =Kokkos::atomic_exchange(&head3(ind.x(), ind.y(), ind.z()),i);
else if(lvl==4)
old =Kokkos::atomic_exchange(&head4(ind.x(), ind.y(), ind.z()),i);
else if(lvl==5)
old =Kokkos::atomic_exchange(&head5(ind.x(), ind.y(), ind.z()),i);
else if(lvl==6)
old =Kokkos::atomic_exchange(&head6(ind.x(), ind.y(), ind.z()),i);
next(i) = old;
});
Kokkos::fence();
}
bool findParticleLevel(int32 first, int32 last)
{
if(last > particleLevel_.size())
{
reallocNoInit(particleLevel_,last);
}
auto diameter = nbsLevels_[0].diameter();
auto const maxSizes = maxSizeLevels_;
auto particleLevel = particleLevel_;
auto const sizeRatio = 0.999*nbsLevels_[0].sizeRatio();
int8 maxLvl = sizeRangeLevels_.size();
rangePolicyType rPolicy(first, last);
Kokkos::parallel_for(
"NBSLevels::findParticleLevel",
rPolicy,
LAMBDA_HD(int32 i)
{
for(int8 lvl = 0; lvl<maxLvl; lvl++)
{
if( sizeRatio*diameter[i]<= maxSizes[lvl] )
{
particleLevel[i] = lvl;
return;
}
}
particleLevel[i] = static_cast<int8>(-1);
});
Kokkos::fence();
return true;
}
}; //NBSLevels
}
#endif

View File

@ -1,101 +0,0 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
int32 m = this->head_(i,j,k);
CellType currentCell(i,j,k);
int32 n = -1;
while( m > -1 )
{
auto p_m = this->pointPosition_[m];
auto d_m = sizeRatio_* diameter_[m];
// the same cell
n = this->next_(m);
while(n >-1)
{
auto p_n = this->pointPosition_[n];
auto d_n = sizeRatio_*diameter_[n];
if( sphereSphereCheck(p_m, p_n, d_m, d_n) )
{
auto ln = n;
auto lm = m;
if(lm>ln) Swap(lm,ln);
if( auto res = pairs.insert(lm,ln); res <0)
{
getFullUpdate++;
}
}
n = this->next_(n);
}
// neighbor cells
CellType neighborCell;
for(int32 ni=0; ni<13; ni++)
{
if(ni==0) neighborCell = currentCell + CellType( 0, 0,-1);
else if(ni==1) neighborCell = currentCell + CellType(-1, 0,-1);
else if(ni==2) neighborCell = currentCell + CellType(-1, 0, 0);
else if(ni==3) neighborCell = currentCell + CellType(-1, 0, 1);
else if(ni==4) neighborCell = currentCell + CellType( 0,-1,-1);
else if(ni==5) neighborCell = currentCell + CellType( 0,-1, 0);
else if(ni==6) neighborCell = currentCell + CellType( 0,-1, 1);
else if(ni==7) neighborCell = currentCell + CellType(-1,-1,-1);
else if(ni==8) neighborCell = currentCell + CellType(-1,-1, 0);
else if(ni==9) neighborCell = currentCell + CellType(-1,-1, 1);
else if(ni==10) neighborCell = currentCell + CellType( 1,-1,-1);
else if(ni==11) neighborCell = currentCell + CellType( 1,-1, 0);
else if(ni==12) neighborCell = currentCell + CellType( 1,-1, 1);
if( this->isInRange(neighborCell) )
{
n = this->head_(neighborCell.x(), neighborCell.y(), neighborCell.z());
while( n>-1)
{
auto p_n = this->pointPosition_[n];
auto d_n = sizeRatio_*diameter_[n];
if(sphereSphereCheck(p_m, p_n, d_m, d_n))
{
auto ln = n;
auto lm = m;
if(lm>ln) Swap(lm,ln);
if( auto res = pairs.insert(lm,ln); res <0)
{
getFullUpdate++;
}
}
n = this->next_[n];
}
}
}
m = this->next_[m];
}

Some files were not shown because too many files have changed in this diff Show More