diff --git a/.gitignore b/.gitignore index 928da54c..3875287c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,12 @@ +# files +.clang-format +.vscode +.dependencygraph + # Prerequisites *.d + # Compiled Object files *.slo *.lo diff --git a/CMakeLists.txt b/CMakeLists.txt index f9740a90..fbb2eaf2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,75 +1,73 @@ cmake_minimum_required(VERSION 3.16 FATAL_ERROR) # 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_REQUIRED True) 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}) -mark_as_advanced(FORCE var Kokkos_ENABLE_CUDA_LAMBDA) -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) +include(cmake/globals.cmake) -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_OpenMP "Build phasicFlow and backends for OpenMP 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) set(Kokkos_ENABLE_SERIAL ON CACHE BOOL "Serial 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_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 ) set(Kokkos_ENABLE_SERIAL ON CACHE BOOL "Serial 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_LAMBDA OFF CACHE BOOL "Cuda execution" 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) set(Kokkos_ENABLE_SERIAL ON CACHE BOOL "Serial 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_LAMBDA ON CACHE BOOL "Cuda execution" FORCE) + set(Kokkos_ENABLE_CUDA_CONSTEXPR ON CACHE BOOL "Enable constexpr on cuda code" FORCE) endif() - - -include(cmake/globals.cmake) -message(STATUS "Valid file extensions are ${validFiles}") +if(pFlow_Build_MPI) + find_package(MPI REQUIRED) +endif() include(cmake/makeLibraryGlobals.cmake) include(cmake/makeExecutableGlobals.cmake) configure_file(phasicFlowConfig.H.in phasicFlowConfig.H) - +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) #add a global include directory 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(solvers) @@ -77,12 +75,9 @@ add_subdirectory(solvers) add_subdirectory(utilities) add_subdirectory(DEMSystems) -#add_subdirectory(testIO) - install(FILES "${PROJECT_BINARY_DIR}/phasicFlowConfig.H" - DESTINATION include -) + DESTINATION include) include(InstallRequiredSystemLibraries) set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") diff --git a/DEMSystems/CMakeLists.txt b/DEMSystems/CMakeLists.txt index 1a1a6f9c..6cc134e2 100644 --- a/DEMSystems/CMakeLists.txt +++ b/DEMSystems/CMakeLists.txt @@ -1,9 +1,11 @@ set(SourceFiles -DEMSystem/DEMSystem.cpp -sphereDEMSystem/sphereDEMSystem.cpp -sphereDEMSystem/sphereFluidParticles.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) diff --git a/DEMSystems/DEMSystem/DEMSystem.cpp b/DEMSystems/DEMSystem/DEMSystem.cpp index 85143431..7afd8b47 100644 --- a/DEMSystems/DEMSystem/DEMSystem.cpp +++ b/DEMSystems/DEMSystem/DEMSystem.cpp @@ -33,14 +33,14 @@ pFlow::DEMSystem::DEMSystem( ControlDict_() { - REPORT(0)<<"Initializing host/device execution spaces . . . \n"; - REPORT(1)<<"Host execution space is "<< greenText(DefaultHostExecutionSpace::name())<( ControlDict_.startTime(), ControlDict_.endTime(), @@ -87,4 +87,3 @@ pFlow::uniquePtr return nullptr; } - diff --git a/DEMSystems/DEMSystem/DEMSystem.hpp b/DEMSystems/DEMSystem/DEMSystem.hpp index 023b6481..23814d3e 100644 --- a/DEMSystems/DEMSystem/DEMSystem.hpp +++ b/DEMSystems/DEMSystem/DEMSystem.hpp @@ -25,6 +25,7 @@ Licence: #include "types.hpp" #include "span.hpp" +#include "box.hpp" #include "virtualConstructor.hpp" #include "uniquePtr.hpp" #include "systemControl.hpp" @@ -60,6 +61,7 @@ public: DEMSystem(const DEMSystem&)=delete; + /// @brief no assignment DEMSystem& operator = (const DEMSystem&)=delete; create_vCtor( @@ -111,19 +113,34 @@ public: int32 numParInDomain(int32 di)const = 0; virtual - std::vector numParInDomain()const = 0; + std::vector numParInDomains()const = 0; virtual - span parIndexInDomain(int32 di)const = 0; + span parIndexInDomain(int32 domIndx)const = 0; virtual - span parDiameter() = 0; + span diameter() = 0; + + virtual + span courseGrainFactor() = 0; virtual - span parVelocity() = 0; + span acceleration()=0; virtual - span parPosition() = 0; + span velocity() = 0; + + virtual + span position() = 0; + + virtual + span rAcceleration()=0; + + virtual + span rVelocity() = 0; + + virtual + span rPosition() = 0; virtual span parFluidForce() = 0; @@ -153,7 +170,6 @@ public: bool iterate(real upToTime) = 0; - static uniquePtr create( @@ -162,8 +178,6 @@ public: int argc, char* argv[]); - - }; diff --git a/DEMSystems/domainDistribute/domainDistribute.cpp b/DEMSystems/domainDistribute/domainDistribute.cpp index b6985243..8a595e2e 100644 --- a/DEMSystems/domainDistribute/domainDistribute.cpp +++ b/DEMSystems/domainDistribute/domainDistribute.cpp @@ -33,7 +33,7 @@ void pFlow::domainDistribute::clcDomains(const std::vector& domains) pFlow::domainDistribute::domainDistribute( - const Vector& domains, + const std::vector& domains, real maxBoundingBox) : numDomains_(domains.size()), @@ -47,10 +47,10 @@ maxBoundingBoxSize_(maxBoundingBox) } bool pFlow::domainDistribute::locateParticles( - ViewType1D points, includeMask mask) + ViewType1D points, const pFlagTypeHost& mask) { - range activeRange = mask.activeRange(); + const rangeU32 activeRange = mask.activeRange(); for(int32 di=0; di& domains); public: domainDistribute( - const Vector& domains, + const std::vector& domains, real maxBoundingBox); ~domainDistribute()=default; @@ -78,7 +75,7 @@ public: { return span( - particlesInDomains_[di].hostVectorAll().data(), + particlesInDomains_[di].hostViewAll().data(), numParInDomain_[di] ); } @@ -91,7 +88,7 @@ public: //template bool locateParticles( - ViewType1D points, includeMask mask); + ViewType1D points, const pFlagTypeHost& mask); }; diff --git a/DEMSystems/grainDEMSystem/grainDEMSystem.cpp b/DEMSystems/grainDEMSystem/grainDEMSystem.cpp new file mode 100644 index 00000000..0673012f --- /dev/null +++ b/DEMSystems/grainDEMSystem/grainDEMSystem.cpp @@ -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& domains, + int argc, + char* argv[], + bool requireRVel) +: + DEMSystem(demSystemName, domains, argc, argv), + requireRVel_(requireRVel) +{ + + REPORT(0)<<"\nReading proprties . . . "<( + propertyFile__, + Control().caseSetup().path()); + + REPORT(0)<< "\nCreating surface geometry for grainDEMSystem . . . "<(Control(), Property()); + + + insertion_ = makeUnique( + particles_(), + particles_().grains()); + + REPORT(0)<<"\nCreating interaction model for grain-grain contact and grain-wall contact . . ."<(domains, maxD); + +} + + +pFlow::grainDEMSystem::~grainDEMSystem() +{ + +} + +bool pFlow::grainDEMSystem::updateParticleDistribution( + real extentFraction, + const std::vector domains) +{ + + if(!particleDistribution_->changeDomainsSize( + extentFraction, + maxBounndingSphereSize(), + domains)) + { + fatalErrorInFunction<< + "cannot change the domain size"<locateParticles( + positionHost_, + particles_->pStruct().activePointsMaskHost())) + { + fatalErrorInFunction<< + "error in locating particles among sub-domains"< + pFlow::grainDEMSystem::numParInDomains()const +{ + const auto& distribute = particleDistribution_(); + int32 numDomains = distribute.numDomains(); + std::vector nums(numDomains); + for(int32 i=0; i +pFlow::grainDEMSystem::parIndexInDomain(int32 di)const +{ + return particleDistribution_->particlesInDomain(di); +} + +pFlow::span pFlow::grainDEMSystem::diameter() +{ + return span(diameterHost_.data(), diameterHost_.size()); +} + +pFlow::span pFlow::grainDEMSystem::courseGrainFactor() +{ + return span(particles_->courseGrainFactorHost().data(), particles_->courseGrainFactorHost().size()); +} + +pFlow::span pFlow::grainDEMSystem::acceleration() +{ + return span(nullptr, 0); +} + +pFlow::span pFlow::grainDEMSystem::velocity() +{ + return span(velocityHost_.data(), velocityHost_.size()); +} + +pFlow::span pFlow::grainDEMSystem::position() +{ + return span(positionHost_.data(), positionHost_.size()); +} + +pFlow::span pFlow::grainDEMSystem::rAcceleration() +{ + return span(nullptr, 0); +} + +pFlow::span pFlow::grainDEMSystem::rVelocity() +{ + return span(rVelocityHost_.data(), rVelocityHost_.size()); +} + +pFlow::span pFlow::grainDEMSystem::rPosition() +{ + return span(nullptr, 0); +} + +pFlow::span pFlow::grainDEMSystem::parFluidForce() +{ + auto& hVec = particles_->fluidForceHost(); + + return span(hVec.data(), hVec.size()); +} + +pFlow::span pFlow::grainDEMSystem::parFluidTorque() +{ + auto& hVec = particles_->fluidTorqueHost(); + return span(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; +} \ No newline at end of file diff --git a/DEMSystems/grainDEMSystem/grainDEMSystem.hpp b/DEMSystems/grainDEMSystem/grainDEMSystem.hpp new file mode 100644 index 00000000..07451942 --- /dev/null +++ b/DEMSystems/grainDEMSystem/grainDEMSystem.hpp @@ -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_ = nullptr; + + uniquePtr geometry_ = nullptr; + + uniquePtr particles_ = nullptr; + + uniquePtr insertion_ = nullptr; + + uniquePtr interaction_ = nullptr; + + uniquePtr particleDistribution_=nullptr; + + // to be used for CPU communications + ViewType1D velocityHost_; + + ViewType1D positionHost_; + + ViewType1D diameterHost_; + + bool requireRVel_ = false; + + ViewType1D 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& 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 domains) override; + + int32 numParInDomain(int32 di)const override; + + std::vector numParInDomains()const override; + + span parIndexInDomain(int32 di)const override; + + span diameter() override; + + span courseGrainFactor() override; + + span acceleration() override; + + span velocity() override; + + span position() override; + + span rAcceleration() override; + + span rVelocity() override; + + span rPosition() override; + + span parFluidForce() override; + + span 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 \ No newline at end of file diff --git a/DEMSystems/grainDEMSystem/grainFluidParticles.cpp b/DEMSystems/grainDEMSystem/grainFluidParticles.cpp new file mode 100644 index 00000000..e58ab65b --- /dev/null +++ b/DEMSystems/grainDEMSystem/grainFluidParticles.cpp @@ -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; +} \ No newline at end of file diff --git a/DEMSystems/grainDEMSystem/grainFluidParticles.hpp b/DEMSystems/grainDEMSystem/grainFluidParticles.hpp new file mode 100644 index 00000000..ba547556 --- /dev/null +++ b/DEMSystems/grainDEMSystem/grainFluidParticles.hpp @@ -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 fluidForceHost_; + + realx3PointField_D fluidTorque_; + + hostViewType1D fluidTorqueHost_; + + hostViewType1D 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__ diff --git a/DEMSystems/grainDEMSystem/grainFluidParticlesKernels.hpp b/DEMSystems/grainDEMSystem/grainFluidParticlesKernels.hpp new file mode 100644 index 00000000..da82e5ed --- /dev/null +++ b/DEMSystems/grainDEMSystem/grainFluidParticlesKernels.hpp @@ -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::IndexType + >; + +template +void acceleration( + realx3 g, + deviceViewType1D mass, + deviceViewType1D force, + deviceViewType1D fluidForce, + deviceViewType1D I, + deviceViewType1D torque, + deviceViewType1D fluidTorque, + IncludeFunctionType incld, + deviceViewType1D lAcc, + deviceViewType1D 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 diff --git a/DEMSystems/sphereDEMSystem/sphereDEMSystem.cpp b/DEMSystems/sphereDEMSystem/sphereDEMSystem.cpp index 37f7529f..29e2fff4 100644 --- a/DEMSystems/sphereDEMSystem/sphereDEMSystem.cpp +++ b/DEMSystems/sphereDEMSystem/sphereDEMSystem.cpp @@ -19,6 +19,7 @@ Licence: -----------------------------------------------------------------------------*/ #include "sphereDEMSystem.hpp" +#include "vocabs.hpp" bool pFlow::sphereDEMSystem::loop() { @@ -26,16 +27,15 @@ bool pFlow::sphereDEMSystem::loop() do { // - if(! insertion_().insertParticles( + Control().time().currentIter(), Control().time().currentTime(), Control().time().dt() ) ) { fatalError<< - "particle insertion failed in sphereDFlow solver.\n"; + "particle insertion failed in sphereDEMSystem.\n"; return false; - } - + } geometry_->beforeIteration(); @@ -63,29 +63,31 @@ pFlow::sphereDEMSystem::sphereDEMSystem( word demSystemName, const std::vector& domains, int argc, - char* argv[]) + char* argv[], + bool requireRVel) : - DEMSystem(demSystemName, domains, argc, argv) + DEMSystem(demSystemName, domains, argc, argv), + requireRVel_(requireRVel) { - REPORT(0)<<"\nReading proprties . . . "<( - Control().caseSetup().path()+propertyFile__); + propertyFile__, + Control().caseSetup().path()); - REPORT(0)<< "\nCreating surface geometry for sphereDEMSystem . . . "<(Control(), Property()); - insertion_ = makeUnique( - Control().caseSetup().path()+insertionFile__, + insertion_ = makeUnique( particles_(), - particles_().shapes()); + particles_().spheres()); - REPORT(0)<<"\nCreating interaction model for sphere-sphere contact and sphere-wall contact . . ."<locateParticles( - parPosition_, - particles_->pStruct().activePointsMaskH())) + positionHost_, + particles_->pStruct().activePointsMaskHost())) { fatalErrorInFunction<< "error in locating particles among sub-domains"< - pFlow::sphereDEMSystem::numParInDomain()const + pFlow::sphereDEMSystem::numParInDomains()const { const auto& distribute = particleDistribution_(); int32 numDomains = distribute.numDomains(); @@ -156,31 +159,56 @@ pFlow::sphereDEMSystem::parIndexInDomain(int32 di)const return particleDistribution_->particlesInDomain(di); } -pFlow::span pFlow::sphereDEMSystem::parDiameter() +pFlow::span pFlow::sphereDEMSystem::diameter() { - return span(parDiameter_.data(), parDiameter_.size()); + return span(diameterHost_.data(), diameterHost_.size()); } -pFlow::span pFlow::sphereDEMSystem::parVelocity() +pFlow::span pFlow::sphereDEMSystem::courseGrainFactor() { - return span(parVelocity_.data(), parVelocity_.size()); + return span(nullptr, 0); } -pFlow::span pFlow::sphereDEMSystem::parPosition() +pFlow::span pFlow::sphereDEMSystem::acceleration() { - return span(parPosition_.data(), parPosition_.size()); + return span(nullptr, 0); +} + +pFlow::span pFlow::sphereDEMSystem::velocity() +{ + return span(velocityHost_.data(), velocityHost_.size()); +} + +pFlow::span pFlow::sphereDEMSystem::position() +{ + return span(positionHost_.data(), positionHost_.size()); +} + +pFlow::span pFlow::sphereDEMSystem::rAcceleration() +{ + return span(nullptr, 0); +} + +pFlow::span pFlow::sphereDEMSystem::rVelocity() +{ + return span(rVelocityHost_.data(), rVelocityHost_.size()); +} + +pFlow::span pFlow::sphereDEMSystem::rPosition() +{ + return span(nullptr, 0); } pFlow::span pFlow::sphereDEMSystem::parFluidForce() { - auto& hVec = particles_->fluidForceHostAll(); + auto& hVec = particles_->fluidForceHost(); return span(hVec.data(), hVec.size()); } pFlow::span pFlow::sphereDEMSystem::parFluidTorque() { - auto& hVec = particles_->fluidTorqueHostAll(); + auto& hVec = particles_->fluidTorqueHost(); return span(hVec.data(), hVec.size()); } @@ -198,9 +226,14 @@ bool pFlow::sphereDEMSystem::sendFluidTorqueToDEM() bool pFlow::sphereDEMSystem::beforeIteration() { - parVelocity_ = particles_->dynPointStruct().velocityHostAll(); - parPosition_ = particles_->dynPointStruct().pointPositionHostAll(); - parDiameter_ = particles_->diameter().hostVectorAll(); + 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; } diff --git a/DEMSystems/sphereDEMSystem/sphereDEMSystem.hpp b/DEMSystems/sphereDEMSystem/sphereDEMSystem.hpp index a7015a36..b2092490 100644 --- a/DEMSystems/sphereDEMSystem/sphereDEMSystem.hpp +++ b/DEMSystems/sphereDEMSystem/sphereDEMSystem.hpp @@ -42,24 +42,29 @@ protected: // protected members - uniquePtr property_ = nullptr; + uniquePtr property_ = nullptr; - uniquePtr geometry_ = nullptr; + uniquePtr geometry_ = nullptr; - uniquePtr particles_ = nullptr; + uniquePtr particles_ = nullptr; - uniquePtr insertion_ = nullptr; + uniquePtr insertion_ = nullptr; - uniquePtr interaction_ = nullptr; + uniquePtr interaction_ = nullptr; - uniquePtr particleDistribution_=nullptr; + uniquePtr particleDistribution_=nullptr; // to be used for CPU communications - ViewType1D parVelocity_; + ViewType1D velocityHost_; - ViewType1D parPosition_; + ViewType1D positionHost_; + + ViewType1D diameterHost_; + + bool requireRVel_ = false; + + ViewType1D rVelocityHost_; - ViewType1D parDiameter_; // protected member functions auto& Property() @@ -92,7 +97,8 @@ public: word demSystemName, const std::vector& domains, int argc, - char* argv[]); + char* argv[], + bool requireRVel=false); virtual ~sphereDEMSystem(); @@ -110,15 +116,25 @@ public: int32 numParInDomain(int32 di)const override; - std::vector numParInDomain()const override; + std::vector numParInDomains()const override; span parIndexInDomain(int32 di)const override; - span parDiameter() override; + span diameter() override; - span parVelocity() override; + span courseGrainFactor() override; - span parPosition() override; + span acceleration() override; + + span velocity() override; + + span position() override; + + span rAcceleration() override; + + span rVelocity() override; + + span rPosition() override; span parFluidForce() override; diff --git a/DEMSystems/sphereDEMSystem/sphereFluidParticles.cpp b/DEMSystems/sphereDEMSystem/sphereFluidParticles.cpp index e1dfd357..11c9df24 100644 --- a/DEMSystems/sphereDEMSystem/sphereFluidParticles.cpp +++ b/DEMSystems/sphereDEMSystem/sphereFluidParticles.cpp @@ -21,42 +21,44 @@ Licence: #include "sphereFluidParticles.hpp" #include "sphereFluidParticlesKernels.hpp" +void pFlow::sphereFluidParticles::checkHostMemory() +{ + if(fluidForce_.size()!=fluidForceHost_.size()) + { + resizeNoInit(fluidForceHost_, fluidForce_.size()); + resizeNoInit(fluidTorqueHost_, fluidTorque_.size()); + } +} pFlow::sphereFluidParticles::sphereFluidParticles( - systemControl &control, - const property& prop -) -: - sphereParticles(control, prop), - fluidForce_( - this->time().emplaceObject( - objectFile( - "fluidForce", - "", - objectFile::READ_IF_PRESENT, - objectFile::WRITE_ALWAYS - ), - pStruct(), - zero3 - ) - ), - fluidTorque_( - this->time().emplaceObject( - objectFile( - "fluidTorque", - "", - objectFile::READ_IF_PRESENT, - objectFile::WRITE_ALWAYS - ), - pStruct(), - zero3 - ) - ) -{} + systemControl &control, + const property &prop) + : sphereParticles(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::sphereFluidParticles::beforeIteration() { sphereParticles::beforeIteration(); + checkHostMemory(); + return true; } @@ -64,42 +66,40 @@ bool pFlow::sphereFluidParticles::beforeIteration() bool pFlow::sphereFluidParticles::iterate() { - accelerationTimer_.start(); + accelerationTimer().start(); pFlow::sphereFluidParticlesKernels::acceleration( control().g(), - mass().deviceVectorAll(), - contactForce().deviceVectorAll(), - fluidForce().deviceVectorAll(), - I().deviceVectorAll(), - contactTorque().deviceVectorAll(), - fluidTorque().deviceVectorAll(), - pStruct().activePointsMaskD(), - accelertion().deviceVectorAll(), - rAcceleration().deviceVectorAll() + mass().deviceViewAll(), + contactForce().deviceViewAll(), + fluidForce_.deviceViewAll(), + I().deviceViewAll(), + contactTorque().deviceViewAll(), + fluidTorque_.deviceViewAll(), + pStruct().activePointsMaskDevice(), + accelertion().deviceViewAll(), + 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; } void pFlow::sphereFluidParticles::fluidForceHostUpdatedSync() { - fluidForce_.modifyOnHost(); - fluidForce_.syncViews(); + copy(fluidForce_.deviceView(), fluidForceHost_); return; } void pFlow::sphereFluidParticles::fluidTorqueHostUpdatedSync() { - fluidTorque_.modifyOnHost(); - fluidTorque_.syncViews(); + copy(fluidTorque_.deviceView(), fluidTorqueHost_); return; } \ No newline at end of file diff --git a/DEMSystems/sphereDEMSystem/sphereFluidParticles.hpp b/DEMSystems/sphereDEMSystem/sphereFluidParticles.hpp index 9890dac8..d8ae9f58 100644 --- a/DEMSystems/sphereDEMSystem/sphereFluidParticles.hpp +++ b/DEMSystems/sphereDEMSystem/sphereFluidParticles.hpp @@ -43,12 +43,17 @@ class sphereFluidParticles protected: /// pointField of rotational acceleration of particles on device - realx3PointField_HD& fluidForce_; + realx3PointField_D fluidForce_; - realx3PointField_HD& fluidTorque_; + hostViewType1D fluidForceHost_; + realx3PointField_D fluidTorque_; - void zeroFluidForce_H() + hostViewType1D fluidTorqueHost_; + + void checkHostMemory(); + + /*void zeroFluidForce_H() { fluidForce_.fillHost(zero3); } @@ -56,7 +61,7 @@ protected: void zeroFluidTorque_H() { fluidTorque_.fillHost(zero3); - } + }*/ 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 fluidTorqueHostUpdatedSync(); diff --git a/DEMSystems/sphereDEMSystem/sphereFluidParticlesKernels.hpp b/DEMSystems/sphereDEMSystem/sphereFluidParticlesKernels.hpp index a8277894..b6743819 100644 --- a/DEMSystems/sphereDEMSystem/sphereFluidParticlesKernels.hpp +++ b/DEMSystems/sphereDEMSystem/sphereFluidParticlesKernels.hpp @@ -46,7 +46,7 @@ void acceleration( { auto activeRange = incld.activeRange(); - if(incld.allActive()) + if(incld.isAllActive()) { Kokkos::parallel_for( "pFlow::sphereParticlesKernels::acceleration", diff --git a/README.md b/README.md index 1bad11e2..e1281936 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,18 @@ -**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? -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 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) * [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} +} +``` diff --git a/cmake/autoComplete b/cmake/autoComplete new file mode 100644 index 00000000..57de5139 --- /dev/null +++ b/cmake/autoComplete @@ -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 diff --git a/cmake/bashrc b/cmake/bashrc index 50f8fa60..e905df58 100644 --- a/cmake/bashrc +++ b/cmake/bashrc @@ -1,8 +1,7 @@ -export pFlow_PROJECT_VERSION=v0.1 - -export pFlow_PROJECT=phasicFlow +export pFlow_PROJECT_VERSION=v-1.0 +export pFlow_PROJECT="phasicFlow-$pFlow_PROJECT_VERSION" projectDir="$HOME/PhasicFlow" kokkosDir="$HOME/Kokkos/kokkos" @@ -20,6 +19,8 @@ export pFlow_SRC_DIR="$pFlow_PROJECT_DIR/src" export Kokkos_DIR="$kokkosDir" +export Zoltan_DIR="$projectDir/Zoltan" + # Cleanup variables (done as final statement for a clean exit code) 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="$Zoltan_DIR/lib:$LD_LIBRARY_PATH" +source $pFlow_PROJECT_DIR/cmake/autoComplete #------------------------------------------------------------------------------ diff --git a/cmake/globals.cmake b/cmake/globals.cmake index b3158dd8..34c075b4 100644 --- a/cmake/globals.cmake +++ b/cmake/globals.cmake @@ -2,3 +2,52 @@ set(validFiles) 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() + diff --git a/cmake/makeExecutableGlobals.cmake b/cmake/makeExecutableGlobals.cmake index 24eb6e0f..45d77e4e 100644 --- a/cmake/makeExecutableGlobals.cmake +++ b/cmake/makeExecutableGlobals.cmake @@ -31,8 +31,8 @@ target_include_directories(${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} source files are: ${source_files}") -message(STATUS " ${target_name} include dirs are: ${includeDirs}\n") +#message(STATUS " ${target_name} source files are: ${${source_files}}") +#message(STATUS " ${target_name} include dirs are: ${includeDirs}\n") install(TARGETS ${target_name} DESTINATION bin) diff --git a/cmake/makeLibraryGlobals.cmake b/cmake/makeLibraryGlobals.cmake index b5e30156..95d52a47 100644 --- a/cmake/makeLibraryGlobals.cmake +++ b/cmake/makeLibraryGlobals.cmake @@ -41,8 +41,8 @@ target_include_directories(${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} source files are: ${source_files}") -message(STATUS " ${target_name} include dirs are: ${includeDirs}\n") +#message(STATUS " ${target_name} source files are: ${source_files}") +#message(STATUS " ${target_name} include dirs are: ${includeDirs}\n \n") install(TARGETS ${target_name} DESTINATION lib) install(FILES ${includeFiles} DESTINATION include/${target_name}) diff --git a/phasicFlowConfig.H.in b/phasicFlowConfig.H.in index 919867e4..0f1b3224 100644 --- a/phasicFlowConfig.H.in +++ b/phasicFlowConfig.H.in @@ -5,5 +5,6 @@ #cmakedefine pFlow_Build_Serial #cmakedefine pFlow_Build_OpenMP #cmakedefine pFlow_Build_Cuda -#cmakedefine USE_STD_PARALLEL_ALG -#cmakedefine pFlow_Build_Double \ No newline at end of file +#cmakedefine pFlow_STD_Parallel_Alg +#cmakedefine pFlow_Build_Double +#cmakedefine pFlow_Build_MPI diff --git a/solvers/CMakeLists.txt b/solvers/CMakeLists.txt index 45bc40aa..5ecf3fb5 100644 --- a/solvers/CMakeLists.txt +++ b/solvers/CMakeLists.txt @@ -1,7 +1,9 @@ -#add_subdirectory(iterateSphereParticles) +add_subdirectory(iterateSphereParticles) add_subdirectory(iterateGeometry) add_subdirectory(sphereGranFlow) + +add_subdirectory(grainGranFlow) diff --git a/solvers/grainGranFlow/CMakeLists.txt b/solvers/grainGranFlow/CMakeLists.txt new file mode 100755 index 00000000..afd35eb4 --- /dev/null +++ b/solvers/grainGranFlow/CMakeLists.txt @@ -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) diff --git a/solvers/grainGranFlow/createDEMComponents.hpp b/solvers/grainGranFlow/createDEMComponents.hpp new file mode 100755 index 00000000..a92ed5c4 --- /dev/null +++ b/solvers/grainGranFlow/createDEMComponents.hpp @@ -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 . . ."<( + 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 . . ."<( objectFile( @@ -36,13 +36,12 @@ REPORT(0)<<"\nCreating particle insertion object . . ."<( - objectFile( - "triSurface", - "", - objectFile::READ_ALWAYS, - objectFile::WRITE_ALWAYS - ) - ) + propertyId_ + ( + objectFile + ( + "propertyId", + "", + objectFile::READ_NEVER, + objectFile::WRITE_NEVER ), - motionComponentName_( - control.geometry().emplaceObject( - objectFile( - "motionComponentName", - "", - objectFile::READ_ALWAYS, - objectFile::WRITE_ALWAYS - ), - "motionNamesList" - ) + *this, + 0u + ), + contactForceWall_ + ( + objectFile + ( + "contactForcWall", + "", + objectFile::READ_IF_PRESENT, + objectFile::WRITE_NEVER ), - materialName_( - control.geometry().emplaceObject( - objectFile( - "materialName", - "", - objectFile::READ_ALWAYS, - objectFile::WRITE_ALWAYS - ), - "materialNamesList" - ) + *this, + zero3 + ), + normalStressWall_ + ( + objectFile + ( + "normalStressWall", + "", + objectFile::READ_IF_PRESENT, + objectFile::WRITE_NEVER ), - propertyId_( - control.geometry().emplaceObject( - objectFile( - "propertyId", - "", - objectFile::READ_NEVER, - objectFile::WRITE_NEVER), - surface(), - 0 ) ), - contactForceWall_( - control.geometry().emplaceObject( - objectFile( - "contactForceWall", - "", - objectFile::READ_IF_PRESENT, - objectFile::WRITE_ALWAYS), - surface(), - zero3) ), - stressWall_( - control.geometry().emplaceObject( - objectFile( - "stressWall", - "", - objectFile::READ_IF_PRESENT, - objectFile::WRITE_ALWAYS), - 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 "<numSurfaces() != motionComponentName_.size() ) + { + fatalErrorInFunction<< + "Number of surfaces is not equal to number of motion component names"<numSurfaces() != motionComponentName_.size() ) + { + fatalErrorInFunction<< + "Number of surfaces ("<< this->numSurfaces() << + ") is not equal to number of motion component names("<< + motionComponentName_.size()<<")"< + pFlow::geometry::create +( + systemControl& control, + const property& prop +) +{ + + // + fileDictionary dict( motionModelFile__, control.time().geometry().path()); + + word model = dict.getVal("motionModel"); + + auto geomModel = angleBracketsNames("geometry", model); + + REPORT(1)<< "Selecting geometry model . . ."< + pFlow::geometry::create + ( + systemControl& control, + const property& prop, + multiTriSurface& surf, + const wordVector& motionCompName, + const wordVector& materialName, + const dictionary& motionDic + ) +{ + + word model = motionDic.getVal("motionModel"); + + auto geomModel = angleBracketsNames("geometry", model); + + REPORT(1)<< "Selecting geometry model . . ."< - pFlow::geometry::create -( - systemControl& control, - const property& prop -) -{ - //motionModelFile__ - auto motionDictPtr = IOobject::make - ( - objectFile - ( - motionModelFile__, - control.geometry().path(), - objectFile::READ_ALWAYS, - objectFile::WRITE_NEVER - ), - motionModelFile__, - true - ); - word model = motionDictPtr().getObject().getVal("motionModel"); - - auto geomModel = angleBracketsNames("geometry", model); - - REPORT(1)<< "Selecting geometry model . . ."< - pFlow::geometry::create( - systemControl& control, - const property& prop, - const dictionary& dict, - const multiTriSurface& triSurface, - const wordVector& motionCompName, - const wordVector& propName) -{ - - word model = dict.getVal("motionModel"); - - auto geomModel = angleBracketsNames("geometry", model); - - REPORT(1)<< "Selecting geometry model . . ."< create(systemControl& control, const property& prop); + uniquePtr create( + systemControl& control, + const property& prop); static uniquePtr create( - systemControl& control, - const property& prop, - const dictionary& dict, - const multiTriSurface& triSurface, - const wordVector& motionCompName, - const wordVector& propName); + systemControl& control, + const property& prop, + multiTriSurface& surf, + const wordVector& motionCompName, + const wordVector& materialName, + const dictionary& motionDic); }; diff --git a/src/Geometry/geometryMotion/geometryMotion.cpp b/src/Geometry/geometryMotion/geometryMotion.cpp index ece859df..22124c47 100644 --- a/src/Geometry/geometryMotion/geometryMotion.cpp +++ b/src/Geometry/geometryMotion/geometryMotion.cpp @@ -21,41 +21,116 @@ Licence: template bool pFlow::geometryMotion::findMotionIndex() { - motionIndex_.clear(); - triMotionIndex_.reserve( this->surface().capacity() ); - triMotionIndex_.clear(); - - ForAll( surfI, motionComponentName_) + + if(motionComponentName().size() != numSurfaces() ) { - auto mName = motionComponentName_[surfI]; - auto mInd = motionModel_.nameToIndex(mName); - motionIndex_.push_back(mInd); - // fill motionIndex for triangles of the surface - int32 surfSize = this->surface().surfNumTriangles(surfI); - for(int32 i=0; i "<< + motionModel_.componentNames(); + return false; + } + surfMotionIndex.push_back(mInd); + + auto surfRange = subSurfaceRange(surfI); + + for(uint32 i=0; i + void moveGeometry( + real dt, + uint32 nPoints, + const ModelInterface& mModel, + const deviceViewType1D& pointMIndexD, + const deviceViewType1D& pointsD + ) + { + Kokkos::parallel_for( + "geometryMotion::movePoints", + deviceRPolicyStatic(0, nPoints), + LAMBDA_HD(uint32 i){ + auto newPos = mModel.transferPoint(pointMIndexD[i], pointsD[i], dt); + pointsD[i] = newPos; + }); + + Kokkos::fence(); + } +} + +template + bool pFlow::geometryMotion::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::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 pFlow::geometryMotion::geometryMotion @@ -65,144 +140,75 @@ pFlow::geometryMotion::geometryMotion ) : geometry(control, prop), - motionModel_( - this->owner().template emplaceObject( - objectFile( - motionModelFile__, - "", - objectFile::READ_ALWAYS, - objectFile::WRITE_ALWAYS - ) - ) + motionModel_ + ( + objectFile + ( + motionModelFile__, + "", + objectFile::READ_ALWAYS, + objectFile::WRITE_ALWAYS ), + owner() + ), moveGeomTimer_("move geometry", &this->timers()) { - findMotionIndex(); -} - -template -pFlow::geometryMotion::geometryMotion -( - systemControl& control, - const property& prop, - const multiTriSurface& triSurface, - const wordVector& motionCompName, - const wordVector& propName, - const MotionModel& motionModel -) -: - geometry( - control, - prop, - triSurface, - motionCompName, - propName - ), - motionModel_( - this->owner().template emplaceObject( - objectFile( - motionModelFile__, - "", - objectFile::READ_NEVER, - objectFile::WRITE_ALWAYS - ), - motionModel - ) - ), - moveGeomTimer_("move geometry", &this->timers()) -{ - findMotionIndex(); -} - -template -pFlow::geometryMotion::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( - objectFile( - motionModelFile__, - "", - objectFile::READ_NEVER, - objectFile::WRITE_ALWAYS - ), - dict - ) - ), - moveGeomTimer_("move geometry", &this->timers()) -{ - findMotionIndex(); -} - -template -bool pFlow::geometryMotion::beforeIteration() -{ - geometry::beforeIteration(); - return true; -} - -template -bool pFlow::geometryMotion::iterate() -{ - if( motionModel_.isMoving() ) + if(!findMotionIndex()) { - moveGeomTimer_.start(); - moveGeometry(); - moveGeomTimer_.end(); + fatalExit; } - return true; } -template -bool pFlow::geometryMotion::afterIteration() +template +pFlow::geometryMotion::geometryMotion +( + systemControl &control, + const property &prop, + multiTriSurface &surf, + const wordVector &motionCompName, + const wordVector &materialName, + const dictionary &motionDict +) +: + geometry + ( + control, + prop, + surf, + motionCompName, + materialName, + motionDict + ), + motionModel_ + ( + objectFile + ( + motionModelFile__, + "", + objectFile::READ_NEVER, + objectFile::WRITE_ALWAYS + ), + motionDict, + owner() + ), + moveGeomTimer_("move geometry", &this->timers()) { - geometry::afterIteration(); - return true; -} - -template -bool pFlow::geometryMotion::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(); + if(!findMotionIndex()) + { + fatalExit; + } +} - Kokkos::parallel_for( - "geometryMotion::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; -} \ No newline at end of file + template + bool pFlow::geometryMotion::iterate() + { + if( motionModel_.isMoving() ) + { + moveGeomTimer_.start(); + moveGeometry(); + this->calculateNormals(); + moveGeomTimer_.end(); + } + return true; + } diff --git a/src/Geometry/geometryMotion/geometryMotion.hpp b/src/Geometry/geometryMotion/geometryMotion.hpp index cf47c613..157c05e0 100644 --- a/src/Geometry/geometryMotion/geometryMotion.hpp +++ b/src/Geometry/geometryMotion/geometryMotion.hpp @@ -20,9 +20,8 @@ Licence: #ifndef __geometryMotion_hpp__ #define __geometryMotion_hpp__ - +#include "vocabs.hpp" #include "geometry.hpp" -#include "VectorDuals.hpp" namespace pFlow { @@ -39,21 +38,23 @@ class geometryMotion { public: - using MotionModel = MotionModelType; + using MotionModel = MotionModelType; -protected: + using ModelComponent = typename MotionModelType::ModelComponent; + +private: /// Ref to motion model - MotionModel& motionModel_; + MotionModelType motionModel_; /// motion indext mapped on each surface - int32Vector_HD motionIndex_; + uint32Field_D surfMotionIndex_{"triMotionIndex"}; /// motion index mapped on each triangle - int8Vector_HD triMotionIndex_; + uint32Field_D triMotionIndex_ {"surfMotionIndex"}; /// motion index mapped on each point - int8Vector_HD pointMotionIndex_; + uint32Field_D pointMotionIndex_{"pointMotionIndex"}; /// timer for moveGeometry Timer moveGeomTimer_; @@ -61,32 +62,25 @@ protected: /// determine the motion index of each triangle bool findMotionIndex(); + /// Move geometry + bool moveGeometry(); + public: /// Type info - TypeInfoTemplate("geometry", MotionModel); + TypeInfoTemplate11("geometry", ModelComponent); // - Constructors geometryMotion(systemControl& control, const property& prop); - geometryMotion( - systemControl& control, + systemControl& control, const property& prop, - const multiTriSurface& triSurface, + multiTriSurface& surf, const wordVector& motionCompName, - const wordVector& propName, - const MotionModel& motionModel); - - /// 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); + const wordVector& materialName, + const dictionary& motionDict); /// Add virtual constructor add_vCtor @@ -107,9 +101,9 @@ public: // - Methods /// 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 @@ -119,28 +113,21 @@ public: } /// Access to motion model index of triangles - const int8Vector_HD& triMotionIndex()const override + const uint32Field_D& triMotionIndex()const override { return triMotionIndex_; } /// Access to motion model index of points - const int8Vector_HD& pointMotionIndex()const override + const uint32Field_D& pointMotionIndex()const override { return pointMotionIndex_; } - /// Operations before each iteration - bool beforeIteration() override; - /// Iterate geometry one time step bool iterate() override ; - /// Operations after each iteration - bool afterIteration() override; - - /// Move geometry - bool moveGeometry(); + }; @@ -148,9 +135,6 @@ public: #include "geometryMotion.cpp" -#ifndef BUILD_SHARED_LIBS - #include "geometryMotionsInstantiate.cpp" -#endif #endif //__geometryMotion_hpp__ diff --git a/src/Geometry/geometryMotion/geometryMotions.cpp b/src/Geometry/geometryMotion/geometryMotions.cpp index 4eaa179a..6cdb4a3b 100644 --- a/src/Geometry/geometryMotion/geometryMotions.cpp +++ b/src/Geometry/geometryMotion/geometryMotions.cpp @@ -17,9 +17,15 @@ Licence: implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -----------------------------------------------------------------------------*/ - #include "geometryMotions.hpp" -#ifdef BUILD_SHARED_LIBS -#include "geometryMotionsInstantiate.cpp" -#endif + +template class pFlow::geometryMotion; + +template class pFlow::geometryMotion; + +template class pFlow::geometryMotion; + +template class pFlow::geometryMotion; + +//template class pFlow::geometryMotion; diff --git a/src/Geometry/geometryMotion/geometryMotions.hpp b/src/Geometry/geometryMotion/geometryMotions.hpp index cd636ae6..3b0a2867 100644 --- a/src/Geometry/geometryMotion/geometryMotions.hpp +++ b/src/Geometry/geometryMotion/geometryMotions.hpp @@ -22,22 +22,26 @@ Licence: #define __geometryMotions_hpp__ #include "geometryMotion.hpp" -#include "fixedWall.hpp" +#include "stationaryWall.hpp" #include "rotatingAxisMotion.hpp" -#include "multiRotatingAxisMotion.hpp" +#include "conveyorBeltMotion.hpp" +//#include "multiRotatingAxisMotion.hpp" #include "vibratingMotion.hpp" namespace pFlow { -typedef geometryMotion vibratingMotionGeometry; +using vibratingMotionGeometry = geometryMotion; -typedef geometryMotion rotationAxisMotionGeometry; +using rotationAxisMotionGeometry = geometryMotion; -typedef geometryMotion multiRotationAxisMotionGeometry; +using stationaryGeometry = geometryMotion; + +using conveyorBeltMotionGeometry = geometryMotion; + +//typedef geometryMotion multiRotationAxisMotionGeometry; -typedef geometryMotion fixedGeometry; diff --git a/src/Integration/AdamsBashforth2/AB2Kernels.hpp b/src/Integration/AdamsBashforth2/AB2Kernels.hpp new file mode 100644 index 00000000..578cf07e --- /dev/null +++ b/src/Integration/AdamsBashforth2/AB2Kernels.hpp @@ -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& y, + const deviceViewType1D& dy, + const deviceViewType1D& dy1 +) +{ + Kokkos::parallel_for( + name, + deviceRPolicyStatic (activeRng.start(), activeRng.end()), + LAMBDA_HD(uint32 i){ + y[i] += dt*(static_cast(1.5) * dy[i] - static_cast(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& y, + const deviceViewType1D& dy, + const deviceViewType1D& dy1 +) +{ + + Kokkos::parallel_for( + name, + deviceRPolicyStatic (activePoints.activeRange().start(), activePoints.activeRange().end()), + LAMBDA_HD(uint32 i){ + if( activePoints(i)) + { + y[i] += dt*(static_cast(1.5) * dy[i] - static_cast(0.5) * dy1[i]); + dy1[i] = dy[i]; + } + }); + Kokkos::fence(); + + + return true; +} + +} + +#endif \ No newline at end of file diff --git a/src/Integration/AdamsBashforth2/AdamsBashforth2.cpp b/src/Integration/AdamsBashforth2/AdamsBashforth2.cpp index 09a4eaa0..7969b184 100644 --- a/src/Integration/AdamsBashforth2/AdamsBashforth2.cpp +++ b/src/Integration/AdamsBashforth2/AdamsBashforth2.cpp @@ -19,61 +19,171 @@ Licence: -----------------------------------------------------------------------------*/ #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::IndexType + >; + +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(1.5) * d_dy[i] - static_cast(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(1.5) * d_dy[i] - static_cast(0.5) * d_dy1[i]); + d_dy1[i] = d_dy[i]; + } + }); + Kokkos::fence(); + + + return true; +} + +} pFlow::AdamsBashforth2::AdamsBashforth2 ( const word& baseName, - repository& owner, - const pointStructure& pStruct, - const word& method + pointStructure& pStruct, + const word& method, + const realx3Field_D& initialValField ) : - integration(baseName, owner, pStruct, method), - dy1_( - owner.emplaceObject( - objectFile( - groupNames(baseName,"dy1"), - "", - objectFile::READ_IF_PRESENT, - objectFile::WRITE_ALWAYS), - pStruct, - zero3)) -{ + integration(baseName, pStruct, method, initialValField), + realx3PointField_D + ( + objectFile + ( + groupNames(baseName,"dy1"), + pStruct.time().integrationFolder(), + objectFile::READ_IF_PRESENT, + objectFile::WRITE_ALWAYS + ), + pStruct, + 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 ( - real UNUSED(dt), - realx3Vector_D& UNUSED(y), - realx3Vector_D& UNUSED(dy) + real dt, + realx3Field_D &y, + realx3PointField_D &dy ) { - - return true; + return true; } bool pFlow::AdamsBashforth2::correct ( real dt, - realx3Vector_D& y, - realx3Vector_D& dy + realx3PointField_D& y, + 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 { - 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( const int32IndexContainer& newIndices, const realx3Vector& y) @@ -81,25 +191,3 @@ bool pFlow::AdamsBashforth2::setInitialVals( 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(3.0 / 2.0) * d_dy[i] - static_cast(1.0 / 2.0) * d_dy1[i]); - d_dy1[i] = d_dy[i]; - }); - Kokkos::fence(); - - return true; -} \ No newline at end of file diff --git a/src/Integration/AdamsBashforth2/AdamsBashforth2.hpp b/src/Integration/AdamsBashforth2/AdamsBashforth2.hpp index 6e2a8892..e8abc026 100644 --- a/src/Integration/AdamsBashforth2/AdamsBashforth2.hpp +++ b/src/Integration/AdamsBashforth2/AdamsBashforth2.hpp @@ -17,13 +17,13 @@ Licence: implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -----------------------------------------------------------------------------*/ - #ifndef __AdamsBashforth2_hpp__ #define __AdamsBashforth2_hpp__ #include "integration.hpp" #include "pointFields.hpp" +#include "boundaryIntegrationList.hpp" namespace pFlow { @@ -36,41 +36,41 @@ namespace pFlow */ class AdamsBashforth2 : - public integration + public integration, + public realx3PointField_D { -protected: +private: - /// dy at t-dt - realx3PointField_D& dy1_; + boundaryIntegrationList boundaryList_; - /// Range policy for integration kernel (alias) - using rpIntegration = Kokkos::RangePolicy< - DefaultExecutionSpace, - Kokkos::Schedule, - Kokkos::IndexType - >; + friend class processorAB2BoundaryIntegration; + const auto& dy1()const + { + return static_cast(*this); + } + + auto& dy1() + { + return static_cast(*this); + } + public: - /// Type info - TypeInfo("AdamsBashforth2"); + /// Class info + ClassInfo("AdamsBashforth2"); // - Constructors /// Construct from components AdamsBashforth2( const word& baseName, - repository& owner, - const pointStructure& pStruct, - const word& method); - - uniquePtr clone()const override - { - return makeUnique(*this); - } + pointStructure& pStruct, + const word& method, + const realx3Field_D& initialValField); /// Destructor - virtual ~AdamsBashforth2()=default; + ~AdamsBashforth2()final = default; /// Add this to the virtual constructor table add_vCtor( @@ -81,70 +81,55 @@ public: // - Methods + void updateBoundariesSlaveToMasterIfRequested()override; + + /// return integration method + word method()const override + { + return "AdamsBashforth2"; + } + bool predict( real UNUSED(dt), - realx3Vector_D& UNUSED(y), - realx3Vector_D& UNUSED(dy)) override; + realx3PointField_D& UNUSED(y), + realx3PointField_D& UNUSED(dy)) final; + + bool predict( + real dt, + realx3Field_D& y, + realx3PointField_D& dy) final; bool correct( real dt, - realx3Vector_D& y, - realx3Vector_D& dy) override; + realx3PointField_D& y, + 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( const int32IndexContainer& newIndices, - const realx3Vector& y) override; + const realx3Vector& y) final; - bool needSetInitialVals()const override + bool needSetInitialVals()const final { 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 - bool intRange( - real dt, - realx3Vector_D& y, - realx3Vector_D& dy, - activeFunctor activeP ); }; -template -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(3.0 / 2.0) * d_dy[i] - static_cast(1.0 / 2.0) * d_dy1[i]); - d_dy1[i] = d_dy[i]; - } - }); - Kokkos::fence(); - - - return true; -} } // pFlow diff --git a/src/Integration/AdamsBashforth3/AdamsBashforth3.cpp b/src/Integration/AdamsBashforth3/AdamsBashforth3.cpp index 040a9e40..f8ec6b5a 100644 --- a/src/Integration/AdamsBashforth3/AdamsBashforth3.cpp +++ b/src/Integration/AdamsBashforth3/AdamsBashforth3.cpp @@ -89,9 +89,9 @@ bool pFlow::AdamsBashforth3::intAll( realx3Vector_D& dy, range activeRng) { - auto d_dy = dy.deviceVectorAll(); - auto d_y = y.deviceVectorAll(); - auto d_history = history_.deviceVectorAll(); + auto d_dy = dy.deviceViewAll(); + auto d_y = y.deviceViewAll(); + auto d_history = history_.deviceViewAll(); Kokkos::parallel_for( "AdamsBashforth3::correct", diff --git a/src/Integration/AdamsBashforth3/AdamsBashforth3.hpp b/src/Integration/AdamsBashforth3/AdamsBashforth3.hpp index 6bd47b11..279fdcda 100644 --- a/src/Integration/AdamsBashforth3/AdamsBashforth3.hpp +++ b/src/Integration/AdamsBashforth3/AdamsBashforth3.hpp @@ -160,9 +160,9 @@ bool pFlow::AdamsBashforth3::intRange( realx3Vector_D& dy, activeFunctor activeP ) { - auto d_dy = dy.deviceVectorAll(); - auto d_y = y.deviceVectorAll(); - auto d_history = history_.deviceVectorAll(); + auto d_dy = dy.deviceViewAll(); + auto d_y = y.deviceViewAll(); + auto d_history = history_.deviceViewAll(); auto activeRng = activeP.activeRange(); Kokkos::parallel_for( diff --git a/src/Integration/AdamsBashforth4/AdamsBashforth4.cpp b/src/Integration/AdamsBashforth4/AdamsBashforth4.cpp index 547de93f..23bad29b 100644 --- a/src/Integration/AdamsBashforth4/AdamsBashforth4.cpp +++ b/src/Integration/AdamsBashforth4/AdamsBashforth4.cpp @@ -89,9 +89,9 @@ bool pFlow::AdamsBashforth4::intAll( realx3Vector_D& dy, range activeRng) { - auto d_dy = dy.deviceVectorAll(); - auto d_y = y.deviceVectorAll(); - auto d_history = history_.deviceVectorAll(); + auto d_dy = dy.deviceViewAll(); + auto d_y = y.deviceViewAll(); + auto d_history = history_.deviceViewAll(); Kokkos::parallel_for( "AdamsBashforth4::correct", diff --git a/src/Integration/AdamsBashforth4/AdamsBashforth4.hpp b/src/Integration/AdamsBashforth4/AdamsBashforth4.hpp index 4f4a2914..cf1f50d8 100644 --- a/src/Integration/AdamsBashforth4/AdamsBashforth4.hpp +++ b/src/Integration/AdamsBashforth4/AdamsBashforth4.hpp @@ -165,9 +165,9 @@ bool pFlow::AdamsBashforth4::intRange( realx3Vector_D& dy, activeFunctor activeP ) { - auto d_dy = dy.deviceVectorAll(); - auto d_y = y.deviceVectorAll(); - auto d_history = history_.deviceVectorAll(); + auto d_dy = dy.deviceViewAll(); + auto d_y = y.deviceViewAll(); + auto d_history = history_.deviceViewAll(); auto activeRng = activeP.activeRange(); Kokkos::parallel_for( diff --git a/src/Integration/AdamsBashforth5/AdamsBashforth5.cpp b/src/Integration/AdamsBashforth5/AdamsBashforth5.cpp index 580f0c06..7b87a4a3 100644 --- a/src/Integration/AdamsBashforth5/AdamsBashforth5.cpp +++ b/src/Integration/AdamsBashforth5/AdamsBashforth5.cpp @@ -89,9 +89,9 @@ bool pFlow::AdamsBashforth5::intAll( realx3Vector_D& dy, range activeRng) { - auto d_dy = dy.deviceVectorAll(); - auto d_y = y.deviceVectorAll(); - auto d_history = history_.deviceVectorAll(); + auto d_dy = dy.deviceViewAll(); + auto d_y = y.deviceViewAll(); + auto d_history = history_.deviceViewAll(); Kokkos::parallel_for( "AdamsBashforth5::correct", diff --git a/src/Integration/AdamsBashforth5/AdamsBashforth5.hpp b/src/Integration/AdamsBashforth5/AdamsBashforth5.hpp index 99261588..16b55927 100644 --- a/src/Integration/AdamsBashforth5/AdamsBashforth5.hpp +++ b/src/Integration/AdamsBashforth5/AdamsBashforth5.hpp @@ -165,9 +165,9 @@ bool pFlow::AdamsBashforth5::intRange( realx3Vector_D& dy, activeFunctor activeP ) { - auto d_dy = dy.deviceVectorAll(); - auto d_y = y.deviceVectorAll(); - auto d_history = history_.deviceVectorAll(); + auto d_dy = dy.deviceViewAll(); + auto d_y = y.deviceViewAll(); + auto d_history = history_.deviceViewAll(); auto activeRng = activeP.activeRange(); Kokkos::parallel_for( diff --git a/src/Integration/AdamsMoulton3/AdamsMoulton3.cpp b/src/Integration/AdamsMoulton3/AdamsMoulton3.cpp index cb819c7c..4fb030bf 100644 --- a/src/Integration/AdamsMoulton3/AdamsMoulton3.cpp +++ b/src/Integration/AdamsMoulton3/AdamsMoulton3.cpp @@ -124,11 +124,11 @@ bool pFlow::AdamsMoulton3::predictAll( range activeRng) { - auto d_dy = dy.deviceVectorAll(); - auto d_y = y.deviceVectorAll(); - auto d_y0 = y0_.deviceVectorAll(); - auto d_dy0 = dy0_.deviceVectorAll(); - auto d_dy1= dy1_.deviceVectorAll(); + auto d_dy = dy.deviceViewAll(); + auto d_y = y.deviceViewAll(); + auto d_y0 = y0_.deviceViewAll(); + auto d_dy0 = dy0_.deviceViewAll(); + auto d_dy1= dy1_.deviceViewAll(); Kokkos::parallel_for( "AdamsMoulton3::predict", @@ -150,12 +150,12 @@ bool pFlow::AdamsMoulton3::intAll( range activeRng) { - auto d_dy = dy.deviceVectorAll(); - auto d_y = y.deviceVectorAll(); + auto d_dy = dy.deviceViewAll(); + auto d_y = y.deviceViewAll(); - auto d_dy0 = dy0_.deviceVectorAll(); - auto d_y0 = y0_.deviceVectorAll(); - auto d_dy1 = dy1_.deviceVectorAll(); + auto d_dy0 = dy0_.deviceViewAll(); + auto d_y0 = y0_.deviceViewAll(); + auto d_dy1 = dy1_.deviceViewAll(); Kokkos::parallel_for( "AdamsMoulton3::correct", diff --git a/src/Integration/AdamsMoulton3/AdamsMoulton3.hpp b/src/Integration/AdamsMoulton3/AdamsMoulton3.hpp index 349d62b2..3193a819 100644 --- a/src/Integration/AdamsMoulton3/AdamsMoulton3.hpp +++ b/src/Integration/AdamsMoulton3/AdamsMoulton3.hpp @@ -144,11 +144,11 @@ bool AdamsMoulton3::predictRange( realx3Vector_D& dy, activeFunctor activeP) { - auto d_dy = dy.deviceVectorAll(); - auto d_y = y.deviceVectorAll(); - auto d_y0 = y0_.deviceVectorAll(); - auto d_dy0 = dy0_.deviceVectorAll(); - auto d_dy1= dy1_.deviceVectorAll(); + auto d_dy = dy.deviceViewAll(); + auto d_y = y.deviceViewAll(); + auto d_y0 = y0_.deviceViewAll(); + auto d_dy0 = dy0_.deviceViewAll(); + auto d_dy1= dy1_.deviceViewAll(); auto activeRng = activeP.activeRange(); @@ -182,12 +182,12 @@ bool pFlow::AdamsMoulton3::intRange( activeFunctor activeP) { - auto d_dy = dy.deviceVectorAll(); - auto d_y = y.deviceVectorAll(); + auto d_dy = dy.deviceViewAll(); + auto d_y = y.deviceViewAll(); - auto d_dy0 = dy0_.deviceVectorAll(); - auto d_y0 = y0_.deviceVectorAll(); - auto d_dy1 = dy1_.deviceVectorAll(); + auto d_dy0 = dy0_.deviceViewAll(); + auto d_y0 = y0_.deviceViewAll(); + auto d_dy1 = dy1_.deviceViewAll(); auto activeRng = activeP.activeRange(); diff --git a/src/Integration/AdamsMoulton4/AdamsMoulton4.cpp b/src/Integration/AdamsMoulton4/AdamsMoulton4.cpp index ec735ac8..3cdbbc8f 100644 --- a/src/Integration/AdamsMoulton4/AdamsMoulton4.cpp +++ b/src/Integration/AdamsMoulton4/AdamsMoulton4.cpp @@ -135,13 +135,13 @@ bool pFlow::AdamsMoulton4::predictAll( range activeRng) { - auto d_dy = dy.deviceVectorAll(); - auto d_y = y.deviceVectorAll(); + auto d_dy = dy.deviceViewAll(); + auto d_y = y.deviceViewAll(); - auto d_y0 = y0_.deviceVectorAll(); - auto d_dy0 = dy0_.deviceVectorAll(); - auto d_dy1 = dy1_.deviceVectorAll(); - auto d_dy2 = dy2_.deviceVectorAll(); + auto d_y0 = y0_.deviceViewAll(); + auto d_dy0 = dy0_.deviceViewAll(); + auto d_dy1 = dy1_.deviceViewAll(); + auto d_dy2 = dy2_.deviceViewAll(); Kokkos::parallel_for( "AdamsMoulton4::predict", @@ -165,13 +165,13 @@ bool pFlow::AdamsMoulton4::intAll( range activeRng) { - auto d_dy = dy.deviceVectorAll(); - auto d_y = y.deviceVectorAll(); + auto d_dy = dy.deviceViewAll(); + auto d_y = y.deviceViewAll(); - auto d_dy0 = dy0_.deviceVectorAll(); - auto d_y0 = y0_.deviceVectorAll(); - auto d_dy1 = dy1_.deviceVectorAll(); - auto d_dy2 = dy2_.deviceVectorAll(); + auto d_dy0 = dy0_.deviceViewAll(); + auto d_y0 = y0_.deviceViewAll(); + auto d_dy1 = dy1_.deviceViewAll(); + auto d_dy2 = dy2_.deviceViewAll(); Kokkos::parallel_for( "AdamsMoulton4::correct", diff --git a/src/Integration/AdamsMoulton4/AdamsMoulton4.hpp b/src/Integration/AdamsMoulton4/AdamsMoulton4.hpp index c0da0f62..3950798a 100644 --- a/src/Integration/AdamsMoulton4/AdamsMoulton4.hpp +++ b/src/Integration/AdamsMoulton4/AdamsMoulton4.hpp @@ -147,13 +147,13 @@ bool AdamsMoulton4::predictRange( realx3Vector_D& dy, activeFunctor activeP ) { - auto d_dy = dy.deviceVectorAll(); - auto d_y = y.deviceVectorAll(); + auto d_dy = dy.deviceViewAll(); + auto d_y = y.deviceViewAll(); - auto d_y0 = y0_.deviceVectorAll(); - auto d_dy0 = dy0_.deviceVectorAll(); - auto d_dy1 = dy1_.deviceVectorAll(); - auto d_dy2 = dy2_.deviceVectorAll(); + auto d_y0 = y0_.deviceViewAll(); + auto d_dy0 = dy0_.deviceViewAll(); + auto d_dy1 = dy1_.deviceViewAll(); + auto d_dy2 = dy2_.deviceViewAll(); auto activeRng = activeP.activeRange(); @@ -185,13 +185,13 @@ bool pFlow::AdamsMoulton4::intRange( activeFunctor activeP ) { - auto d_dy = dy.deviceVectorAll(); - auto d_y = y.deviceVectorAll(); + auto d_dy = dy.deviceViewAll(); + auto d_y = y.deviceViewAll(); - auto d_dy0 = dy0_.deviceVectorAll(); - auto d_y0 = y0_.deviceVectorAll(); - auto d_dy1 = dy1_.deviceVectorAll(); - auto d_dy2 = dy2_.deviceVectorAll(); + auto d_dy0 = dy0_.deviceViewAll(); + auto d_y0 = y0_.deviceViewAll(); + auto d_dy1 = dy1_.deviceViewAll(); + auto d_dy2 = dy2_.deviceViewAll(); auto activeRng = activeP.activeRange(); diff --git a/src/Integration/AdamsMoulton5/AdamsMoulton5.cpp b/src/Integration/AdamsMoulton5/AdamsMoulton5.cpp index c3f62f18..37629649 100644 --- a/src/Integration/AdamsMoulton5/AdamsMoulton5.cpp +++ b/src/Integration/AdamsMoulton5/AdamsMoulton5.cpp @@ -145,14 +145,14 @@ bool pFlow::AdamsMoulton5::predictAll( range activeRng) { - auto d_dy = dy.deviceVectorAll(); - auto d_y = y.deviceVectorAll(); + auto d_dy = dy.deviceViewAll(); + auto d_y = y.deviceViewAll(); - auto d_y0 = y0_.deviceVectorAll(); - auto d_dy0 = dy0_.deviceVectorAll(); - auto d_dy1 = dy1_.deviceVectorAll(); - auto d_dy2 = dy2_.deviceVectorAll(); - auto d_dy3 = dy3_.deviceVectorAll(); + auto d_y0 = y0_.deviceViewAll(); + auto d_dy0 = dy0_.deviceViewAll(); + auto d_dy1 = dy1_.deviceViewAll(); + auto d_dy2 = dy2_.deviceViewAll(); + auto d_dy3 = dy3_.deviceViewAll(); Kokkos::parallel_for( "AdamsMoulton5::predict", @@ -178,14 +178,14 @@ bool pFlow::AdamsMoulton5::intAll( range activeRng) { - auto d_dy = dy.deviceVectorAll(); - auto d_y = y.deviceVectorAll(); + auto d_dy = dy.deviceViewAll(); + auto d_y = y.deviceViewAll(); - auto d_dy0 = dy0_.deviceVectorAll(); - auto d_y0 = y0_.deviceVectorAll(); - auto d_dy1 = dy1_.deviceVectorAll(); - auto d_dy2 = dy2_.deviceVectorAll(); - auto d_dy3 = dy3_.deviceVectorAll(); + auto d_dy0 = dy0_.deviceViewAll(); + auto d_y0 = y0_.deviceViewAll(); + auto d_dy1 = dy1_.deviceViewAll(); + auto d_dy2 = dy2_.deviceViewAll(); + auto d_dy3 = dy3_.deviceViewAll(); Kokkos::parallel_for( "AdamsMoulton5::correct", diff --git a/src/Integration/AdamsMoulton5/AdamsMoulton5.hpp b/src/Integration/AdamsMoulton5/AdamsMoulton5.hpp index 2e381d4a..451ff81f 100644 --- a/src/Integration/AdamsMoulton5/AdamsMoulton5.hpp +++ b/src/Integration/AdamsMoulton5/AdamsMoulton5.hpp @@ -150,14 +150,14 @@ bool AdamsMoulton5::predictRange( realx3Vector_D& dy, activeFunctor activeP ) { - auto d_dy = dy.deviceVectorAll(); - auto d_y = y.deviceVectorAll(); + auto d_dy = dy.deviceViewAll(); + auto d_y = y.deviceViewAll(); - auto d_y0 = y0_.deviceVectorAll(); - auto d_dy0 = dy0_.deviceVectorAll(); - auto d_dy1 = dy1_.deviceVectorAll(); - auto d_dy2 = dy2_.deviceVectorAll(); - auto d_dy3 = dy3_.deviceVectorAll(); + auto d_y0 = y0_.deviceViewAll(); + auto d_dy0 = dy0_.deviceViewAll(); + auto d_dy1 = dy1_.deviceViewAll(); + auto d_dy2 = dy2_.deviceViewAll(); + auto d_dy3 = dy3_.deviceViewAll(); auto activeRng = activeP.activeRange(); @@ -189,14 +189,14 @@ bool pFlow::AdamsMoulton5::intRange( activeFunctor activeP ) { - auto d_dy = dy.deviceVectorAll(); - auto d_y = y.deviceVectorAll(); + auto d_dy = dy.deviceViewAll(); + auto d_y = y.deviceViewAll(); - auto d_dy0 = dy0_.deviceVectorAll(); - auto d_y0 = y0_.deviceVectorAll(); - auto d_dy1 = dy1_.deviceVectorAll(); - auto d_dy2 = dy2_.deviceVectorAll(); - auto d_dy3 = dy3_.deviceVectorAll(); + auto d_dy0 = dy0_.deviceViewAll(); + auto d_y0 = y0_.deviceViewAll(); + auto d_dy1 = dy1_.deviceViewAll(); + auto d_dy2 = dy2_.deviceViewAll(); + auto d_dy3 = dy3_.deviceViewAll(); auto activeRng = activeP.activeRange(); diff --git a/src/Integration/CMakeLists.txt b/src/Integration/CMakeLists.txt index f3a03112..32c3c558 100644 --- a/src/Integration/CMakeLists.txt +++ b/src/Integration/CMakeLists.txt @@ -1,15 +1,22 @@ list(APPEND SourceFiles -integration/integration.cpp -AdamsBashforth5/AdamsBashforth5.cpp -AdamsBashforth4/AdamsBashforth4.cpp -AdamsBashforth3/AdamsBashforth3.cpp +integration/integration.cpp +boundaries/boundaryIntegration.cpp +boundaries/boundaryIntegrationList.cpp AdamsBashforth2/AdamsBashforth2.cpp -AdamsMoulton3/AdamsMoulton3.cpp -AdamsMoulton4/AdamsMoulton4.cpp -AdamsMoulton5/AdamsMoulton5.cpp +#AdamsBashforth5/AdamsBashforth5.cpp +#AdamsBashforth4/AdamsBashforth4.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) pFlow_add_library_install(Integration SourceFiles link_libs) diff --git a/src/Integration/boundaries/boundaryIntegration.cpp b/src/Integration/boundaries/boundaryIntegration.cpp new file mode 100644 index 00000000..e13a5624 --- /dev/null +++ b/src/Integration/boundaries/boundaryIntegration.cpp @@ -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::create( + const boundaryBase &boundary, + const pointStructure &pStruct, + const word &method, + integration& intgrtn +) +{ + + word bType = angleBracketsNames2( + "boundaryIntegration", + boundary.type(), + method); + + word altBType{"boundaryIntegration"}; + + if( boundaryBasevCtorSelector_.search(bType) ) + { + pOutput.space(4)<<"Creating boundary "<< Green_Text(bType)<< + " for "<"); + + 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 create( + const boundaryBase& boundary, + const pointStructure& pStruct, + const word& method, + integration& intgrtn); + +}; + +} + +#endif \ No newline at end of file diff --git a/src/Integration/boundaries/boundaryIntegrationList.cpp b/src/Integration/boundaries/boundaryIntegrationList.cpp new file mode 100644 index 00000000..9dfa1538 --- /dev/null +++ b/src/Integration/boundaries/boundaryIntegrationList.cpp @@ -0,0 +1,59 @@ +#include "boundaryIntegrationList.hpp" +#include "integration.hpp" + +pFlow::boundaryIntegrationList::boundaryIntegrationList( + const pointStructure &pStruct, + const word &method, + integration &intgrtn +) +: + ListPtr(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()<correctPStruct(dt, vel)) + { + fatalErrorInFunction<<"Error in correcting boundary "<< + bndry->boundaryName()<<" in pointStructure."< +{ +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__ \ No newline at end of file diff --git a/src/Integration/integration/integration.cpp b/src/Integration/integration/integration.cpp index 6e48ddaf..f3126e1e 100644 --- a/src/Integration/integration/integration.cpp +++ b/src/Integration/integration/integration.cpp @@ -19,33 +19,35 @@ Licence: -----------------------------------------------------------------------------*/ #include "integration.hpp" +#include "pointStructure.hpp" +#include "repository.hpp" pFlow::integration::integration ( const word& baseName, - repository& owner, - const pointStructure& pStruct, - const word& method + pointStructure& pStruct, + const word&, + const realx3Field_D& ) : - owner_(owner), - baseName_(baseName), - pStruct_(pStruct) -{ - CONSUME_PARAM(method); -} + owner_(*pStruct.owner()), + pStruct_(pStruct), + baseName_(baseName) +{} pFlow::uniquePtr - pFlow::integration::create( + pFlow::integration::create +( const word& baseName, - repository& owner, - const pointStructure& pStruct, - const word& method) + pointStructure& pStruct, + const word& method, + const realx3Field_D& initialValField +) { if( wordvCtorSelector_.search(method) ) { - return wordvCtorSelector_[method] (baseName, owner, pStruct, method); + return wordvCtorSelector_[method] (baseName, pStruct, method, initialValField); } else { diff --git a/src/Integration/integration/integration.hpp b/src/Integration/integration/integration.hpp index 3cca58c2..2c95813e 100644 --- a/src/Integration/integration/integration.hpp +++ b/src/Integration/integration/integration.hpp @@ -23,14 +23,16 @@ Licence: #include "virtualConstructor.hpp" -#include "Vectors.hpp" -#include "pointStructure.hpp" -#include "repository.hpp" +#include "pointFields.hpp" namespace pFlow { +// - Forward +class repository; +class pointStructure; + /** * Base class for integrating the first order ODE (IVP) * @@ -48,19 +50,19 @@ namespace pFlow */ class integration { -protected: +private: // - Protected data members /// The owner repository that all fields are storred in repository& owner_; - /// The base name for integration - const word baseName_; - /// A reference to pointStructure const pointStructure& pStruct_; + /// The base name for integration + const word baseName_; + public: /// Type info @@ -72,9 +74,9 @@ public: /// Construct from components integration( const word& baseName, - repository& owner, - const pointStructure& pStruct, - const word& method); + pointStructure& pStruct, + const word& method, + const realx3Field_D& initialValField); /// Copy constructor integration(const integration&) = default; @@ -88,22 +90,22 @@ public: /// Move assignment integration& operator = (integration&&) = default; - /// Polymorphic copy/cloning - virtual - uniquePtr clone()const=0; - /// Destructor virtual ~integration()=default; /// Add a virtual constructor - create_vCtor( + create_vCtor + ( integration, word, - (const word& baseName, - repository& owner, - const pointStructure& pStruct, - const word& method), - (baseName, owner, pStruct, method) ); + ( + const word& baseName, + pointStructure& pStruct, + const word& method, + const realx3Field_D& initialValField + ), + (baseName, pStruct, method, initialValField) + ); // - Methods @@ -129,13 +131,25 @@ public: return owner_; } + virtual + void updateBoundariesSlaveToMasterIfRequested() = 0; + /// return integration method + virtual + word method()const = 0 ; + /// Prediction step in integration 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 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 virtual @@ -152,9 +166,9 @@ public: static uniquePtr create( const word& baseName, - repository& owner, - const pointStructure& pStruct, - const word& method); + pointStructure& pStruct, + const word& method, + const realx3Field_D& initialValField); }; // integration diff --git a/src/Interaction/CMakeLists.txt b/src/Interaction/CMakeLists.txt index 25d43014..c75f8239 100644 --- a/src/Interaction/CMakeLists.txt +++ b/src/Interaction/CMakeLists.txt @@ -1,11 +1,43 @@ 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/ContactSearchs.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) pFlow_add_library_install(Interaction SourceFiles link_libs) diff --git a/src/Interaction/Models/contactForce/cGAbsoluteLinearCF.hpp b/src/Interaction/Models/contactForce/cGAbsoluteLinearCF.hpp new file mode 100755 index 00000000..25180208 --- /dev/null +++ b/src/Interaction/Models/contactForce/cGAbsoluteLinearCF.hpp @@ -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 +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; + + int32 numMaterial_ = 0; + + ViewType1D rho_; + + LinearArrayType linearProperties_; + + int32 addDissipationModel_; + + + bool readLinearDictionary(const dictionary& dict) + { + + + auto kn = dict.getVal("kn"); + auto kt = dict.getVal("kt"); + auto en = dict.getVal("en"); + auto et = dict.getVal("et"); + auto mu = dict.getVal("mu"); + + auto nElem = kn.size(); + + if(nElem != kt.size()) + { + fatalErrorInFunction<< + "sizes of kn("< 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("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& 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 : "< ft_fric) + { + if( length(history.overlap_t_) >static_cast(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 diff --git a/src/Interaction/Models/contactForce/cGRelativeLinearCF.hpp b/src/Interaction/Models/contactForce/cGRelativeLinearCF.hpp new file mode 100755 index 00000000..48a77884 --- /dev/null +++ b/src/Interaction/Models/contactForce/cGRelativeLinearCF.hpp @@ -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 +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; + + int32 numMaterial_ = 0; + + ViewType1D rho_; + + LinearArrayType linearProperties_; + + int32 addDissipationModel_; + + + bool readLinearDictionary(const dictionary& dict) + { + + + auto kn = dict.getVal("kn"); + auto kt = dict.getVal("kt"); + auto en = dict.getVal("en"); + auto et = dict.getVal("et"); + auto mu = dict.getVal("mu"); + + + auto nElem = kn.size(); + + + if(nElem != kt.size()) + { + fatalErrorInFunction<< + "sizes of kn("< 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("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& 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(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 diff --git a/src/Interaction/Models/contactForce/linearCF.hpp b/src/Interaction/Models/contactForce/linearCF.hpp index 5ef6da3e..88bf2108 100644 --- a/src/Interaction/Models/contactForce/linearCF.hpp +++ b/src/Interaction/Models/contactForce/linearCF.hpp @@ -133,8 +133,9 @@ protected: return false; } - realVector etha_n(nElem); - realVector etha_t(nElem); + realVector etha_n("etha_n", nElem); + realVector etha_t("etha_t", nElem); + ForAll(i , kn) { 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)); } - Vector prop(nElem); + Vector prop("prop", nElem); ForAll(i,kn) { prop[i] = {kn[i], kt[i], etha_n[i], etha_t[i], mu[i]}; @@ -219,10 +220,10 @@ public: void contactForce ( const real dt, - const int32 i, - const int32 j, - const int32 propId_i, - const int32 propId_j, + const uint32 i, + const uint32 j, + const uint32 propId_i, + const uint32 propId_j, const real Ri, const real Rj, const real ovrlp_n, diff --git a/src/Interaction/Models/contactForce/nonLinearCF.hpp b/src/Interaction/Models/contactForce/nonLinearCF.hpp index b9f42d69..3ba1c5c5 100644 --- a/src/Interaction/Models/contactForce/nonLinearCF.hpp +++ b/src/Interaction/Models/contactForce/nonLinearCF.hpp @@ -121,7 +121,7 @@ protected: } - realVector etha_n(nElem); + realVector etha_n("etha_n",nElem); ForAll(i , en) { @@ -137,7 +137,7 @@ protected: } - Vector prop(nElem); + Vector prop("prop",nElem); ForAll(i,Yeff) { prop[i] = {Yeff[i], Geff[i], etha_n[i], mu[i]}; @@ -214,10 +214,10 @@ public: void contactForce ( const real dt, - const int32 i, - const int32 j, - const int32 propId_i, - const int32 propId_j, + const uint32 i, + const uint32 j, + const uint32 propId_i, + const uint32 propId_j, const real Ri, const real Rj, const real ovrlp_n, diff --git a/src/Interaction/Models/contactForce/nonLinearMod.hpp b/src/Interaction/Models/contactForce/nonLinearMod.hpp index 3bfbd29b..9a771970 100644 --- a/src/Interaction/Models/contactForce/nonLinearMod.hpp +++ b/src/Interaction/Models/contactForce/nonLinearMod.hpp @@ -121,7 +121,7 @@ protected: } - Vector prop(nElem); + Vector prop("prop",nElem); ForAll(i,Yeff) { prop[i] = {Yeff[i], Geff[i], etha_n[i], mu[i]}; @@ -198,10 +198,10 @@ public: void contactForce ( const real dt, - const int32 i, - const int32 j, - const int32 propId_i, - const int32 propId_j, + const uint32 i, + const uint32 j, + const uint32 propId_i, + const uint32 propId_j, const real Ri, const real Rj, const real ovrlp_n, diff --git a/src/phasicFlow/repository/systemControl/Control.hpp b/src/Interaction/Models/grainContactForceModels.hpp old mode 100644 new mode 100755 similarity index 63% rename from src/phasicFlow/repository/systemControl/Control.hpp rename to src/Interaction/Models/grainContactForceModels.hpp index 58df40a4..908117f5 --- a/src/phasicFlow/repository/systemControl/Control.hpp +++ b/src/Interaction/Models/grainContactForceModels.hpp @@ -18,30 +18,28 @@ Licence: -----------------------------------------------------------------------------*/ +#ifndef __grainContactForceModels_hpp__ +#define __grainContactForceModels_hpp__ -#ifndef __Control_hpp__ -#define __Control_hpp__ +#include "cGAbsoluteLinearCF.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" -#include "timeFolder.hpp" - -namespace pFlow +namespace pFlow::cfModels { -inline systemControl& Control() -{ - static systemControl control_; - return control_; +using limitedCGAbsoluteLinearGrainRolling = grainRolling>; +using nonLimitedCGAbsoluteLinearGrainRolling = grainRolling>; + +using limitedCGRelativeLinearGrainRolling = grainRolling>; +using nonLimitedCGRelativeLinearGrainRolling = grainRolling>; + } -} // pFlow -#endif // __Control_hpp__ +#endif //__grainContactForceModels_hpp__ diff --git a/src/Interaction/Models/rolling/grainRolling.hpp b/src/Interaction/Models/rolling/grainRolling.hpp new file mode 100755 index 00000000..b8eff130 --- /dev/null +++ b/src/Interaction/Models/rolling/grainRolling.hpp @@ -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 +class grainRolling +: + public contactForceModel +{ +public: + + using contactForceStorage = + typename contactForceModel::contactForceStorage; + + + realSymArray_D mur_; + + bool readGrainDict(const dictionary& dict) + { + auto mur = dict.getVal("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& 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 diff --git a/src/Interaction/Models/rolling/normalRolling.hpp b/src/Interaction/Models/rolling/normalRolling.hpp index de850e3c..80b8e321 100644 --- a/src/Interaction/Models/rolling/normalRolling.hpp +++ b/src/Interaction/Models/rolling/normalRolling.hpp @@ -76,10 +76,10 @@ public: void rollingFriction ( const real dt, - const int32 i, - const int32 j, - const int32 propId_i, - const int32 propId_j, + const uint32 i, + const uint32 j, + const uint32 propId_i, + const uint32 propId_j, const real Ri, const real Rj, const realx3& wi, diff --git a/src/Interaction/contactLists/sortedContactList.hpp b/src/Interaction/contactLists/sortedContactList.hpp index 45c8e4b0..4f41caac 100644 --- a/src/Interaction/contactLists/sortedContactList.hpp +++ b/src/Interaction/contactLists/sortedContactList.hpp @@ -53,7 +53,7 @@ protected: ViewType1D values_; - int32 size0_ = 0; + uint32 size0_ = 0; ViewType1D sortedPairs0_; @@ -73,7 +73,7 @@ protected: using rpReFillPairs = Kokkos::RangePolicy< ExecutionSpace, Kokkos::Schedule, - Kokkos::IndexType, + Kokkos::IndexType, TagReFillPairs>; public: @@ -81,7 +81,7 @@ public: TypeInfoNV("sortedContactList"); - sortedContactList(int32 initialSize =1) + explicit sortedContactList(uint32 initialSize =1) : SortedPairs(initialSize), values_("values", SortedPairs::capacity()), @@ -114,31 +114,31 @@ public: } INLINE_FUNCTION_HD - ValueType getValue(int32 idx)const + ValueType getValue(uint32 idx)const { return values_[idx]; } INLINE_FUNCTION_HD - void setValue(int32 idx, const ValueType& val)const + void setValue(uint32 idx, const ValueType& val)const { values_[idx] = val; } INLINE_FUNCTION_HD - void operator()(TagReFillPairs, int32 idx)const + void operator()(TagReFillPairs, uint32 idx)const { - auto searchLen = max(size0_/1000,10); - auto start = max(0,idx-searchLen); - auto end = min(size0_,idx+searchLen); + uint32 searchLen = max(size0_/1000u,10u); + uint32 start = idx-min(searchLen,idx); + uint32 end = min(size0_,idx+searchLen); auto newPair = this->sortedPairs_[idx]; if( auto idx0 = binarySearch( sortedPairs0_, start, end, newPair); - idx0>=0) + idx0!=static_cast(-1)) { values_[idx] = values0_[idx0]; } @@ -147,7 +147,7 @@ public: start, end, newPair); - idx0>=0) + idx0!= static_cast(-1) ) { values_[idx] = values0_[idx0]; diff --git a/src/Interaction/contactLists/sortedPairs.hpp b/src/Interaction/contactLists/sortedPairs.hpp index d8b74a50..12593810 100644 --- a/src/Interaction/contactLists/sortedPairs.hpp +++ b/src/Interaction/contactLists/sortedPairs.hpp @@ -52,24 +52,24 @@ public: { using PairType = typename sortedPairs::PairType; - int32 size_; + uint32 size_; ViewType1D sortedParis_; INLINE_FUNCTION_HD - int32 size()const { return size_; } + uint32 size()const { return size_; } INLINE_FUNCTION_HD - int32 loopCount()const { return size_; } + uint32 loopCount()const { return size_; } INLINE_FUNCTION_HD - bool isValid(int32 i)const { return i flags_; + ViewType1D flags_; ViewType1D sortedPairs_; using rpFillFlag = Kokkos::RangePolicy< ExecutionSpace, Kokkos::Schedule, - Kokkos::IndexType, + Kokkos::IndexType, TagFillFlag >; using rpFillPairs = Kokkos::RangePolicy< ExecutionSpace, Kokkos::Schedule, - Kokkos::IndexType, + Kokkos::IndexType, TagFillPairs>; public: @@ -110,7 +110,7 @@ public: // constructors - sortedPairs(int32 initialSize =1) + explicit sortedPairs(uint32 initialSize =1) : UnsortedPairs(initialSize), flags_("flags_",UnsortedPairs::capacity()+1), @@ -134,7 +134,7 @@ public: // return the pair at index idx // perform no check for size and existance INLINE_FUNCTION_HD - PairType getPair(int32 idx)const + PairType getPair(uint32 idx)const { return sortedPairs_[idx]; } @@ -142,7 +142,7 @@ public: // - Device/host call // return the pair at index idx INLINE_FUNCTION_HD - bool getPair(int32 idx, PairType& p)const + bool getPair(uint32 idx, PairType& p)const { if(isValid(idx)) { @@ -156,7 +156,7 @@ public: } INLINE_FUNCTION_HD - bool isValid(int32 idx)const + bool isValid(uint32 idx)const { return idx < size_; } @@ -164,12 +164,12 @@ public: //use this when the value of size_ is updated INLINE_FUNCTION_H - int32 size()const + uint32 size()const { return size_; } - int32 loopCount()const + uint32 loopCount()const { return size_; } @@ -189,7 +189,7 @@ public: void prepareSorted() { // first check the size of flags_ - int32 capacity = UnsortedPairs::capacity(); + uint32 capacity = UnsortedPairs::capacity(); if( capacity+1 > flags_.size() ) { @@ -218,7 +218,7 @@ public: if( size_>sortedPairs_.size() ) { // get more space to prevent reallocations in next iterations - int32 len = size_*1.1+1; + uint32 len = size_*1.1+1; reallocNoInit(sortedPairs_, len); } @@ -235,7 +235,7 @@ public: } INLINE_FUNCTION_HD - void operator()(TagFillFlag, int32 i)const + void operator()(TagFillFlag, uint32 i)const { if(this->container_.valid_at(i) ) flags_[i] = 1; @@ -244,7 +244,7 @@ public: } INLINE_FUNCTION_HD - void operator()(TagFillPairs, int32 i)const + void operator()(TagFillPairs, uint32 i)const { auto fi = flags_[i]; if(fi!=flags_[i+1]) diff --git a/src/Interaction/contactLists/unsortedContactList.hpp b/src/Interaction/contactLists/unsortedContactList.hpp index f2200fd9..7aa98237 100644 --- a/src/Interaction/contactLists/unsortedContactList.hpp +++ b/src/Interaction/contactLists/unsortedContactList.hpp @@ -17,10 +17,11 @@ Licence: implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -----------------------------------------------------------------------------*/ - #ifndef __unsortedContactList_hpp__ #define __unsortedContactList_hpp__ +#include "unsortedPairs.hpp" + namespace pFlow { @@ -72,7 +73,7 @@ protected: using rpFillPairs = Kokkos::RangePolicy< ExecutionSpace, Kokkos::Schedule, - Kokkos::IndexType, + Kokkos::IndexType, TagReFillPairs>; @@ -80,7 +81,7 @@ public: TypeInfoNV("unsortedContactList"); - unsortedContactList(int32 capacity=1) + explicit unsortedContactList(uint32 capacity=1) : UnsortedPairs(capacity), values_("values", UnsortedPairs::capacity()), @@ -94,7 +95,8 @@ public: // swap conainer and values swapViews(values0_, values_); swapViews(container0_, this->container_); - return UnsortedPairs::beforeBroadSearch(); + UnsortedPairs::beforeBroadSearch(); + return true; } bool afterBroadSearch() @@ -109,7 +111,7 @@ public: rpFillPairs(0,this->capacity()), *this); Kokkos::fence(); - + return true; } @@ -122,7 +124,7 @@ public: INLINE_FUNCTION_HD 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(-1)) { val = getValue(idx); return true; @@ -131,7 +133,7 @@ public: } INLINE_FUNCTION_HD - void setValue(int32 idx, const ValueType& val)const + void setValue(uint32 idx, const ValueType& val)const { values_[idx] = val; } @@ -139,7 +141,7 @@ public: INLINE_FUNCTION_HD 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(-1)) { setValue(idx, val); return true;; @@ -148,13 +150,13 @@ public: } INLINE_FUNCTION_HD - void operator()(TagReFillPairs, int32 idx)const + void operator()(TagReFillPairs, uint32 idx)const { if( this->isValid(idx) ) { - if( int32 idx0 = + if( uint32 idx0 = container0_.find(this->getPair(idx)); - idx0>=0 ) + idx0!= static_cast(-1) ) { values_[idx] = values0_[idx0]; } diff --git a/src/Interaction/contactLists/unsortedPairs.hpp b/src/Interaction/contactLists/unsortedPairs.hpp index e9434751..fb622bdb 100644 --- a/src/Interaction/contactLists/unsortedPairs.hpp +++ b/src/Interaction/contactLists/unsortedPairs.hpp @@ -41,7 +41,7 @@ public: using memory_space = typename ExecutionSpace::memory_space; - using PairType = kPair; + using PairType = Pair; using ContainerType = unorderedSet; @@ -52,19 +52,19 @@ public: ContainerType Container_; INLINE_FUNCTION_HD - int32 size()const { return Container_.size(); } + uint32 size()const { return Container_.size(); } INLINE_FUNCTION_HD - int32 loopCount()const { return Container_.capacity(); } + uint32 loopCount()const { return Container_.capacity(); } 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 - PairType getPair(int idx)const { return Container_.key_at(idx); } + PairType getPair(uint32 idx)const { return Container_.key_at(idx); } INLINE_FUNCTION_HD - bool getPair(int32 idx, PairType& pair)const { + bool getPair(uint32 idx, PairType& pair)const { if(Container_.valid_at(idx)) { pair = Container_.key_at(idx); return true; @@ -84,7 +84,7 @@ public: TypeInfoNV("unsorderedPairs"); // constructor - unsortedPairs(int32 capacity=1) + explicit unsortedPairs(uint32 capacity=1) : container_(capacity) // the minimum capacity would be 128 {} @@ -102,20 +102,20 @@ public: // - Device call 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()) - return -1; + return static_cast(-1); else return insertResult.index(); } INLINE_FUNCTION_HD - int32 insert(const PairType& p)const + uint32 insert(const PairType& p)const { if(auto insertResult = container_.insert(p); insertResult.failed()) - return -1; + return static_cast(-1); else return insertResult.index(); @@ -125,7 +125,7 @@ public: // return the pair at index idx // perform no check for size and existance INLINE_FUNCTION_HD - PairType getPair(int32 idx)const + PairType getPair(uint32 idx)const { return container_.key_at(idx); } @@ -133,7 +133,7 @@ public: // - Device call // return the pair at index idx INLINE_FUNCTION_HD - bool getPair(int32 idx, PairType& p)const + bool getPair(uint32 idx, PairType& p)const { if(container_.valid_at(idx)) { @@ -148,36 +148,36 @@ public: } INLINE_FUNCTION_HD - int32 find(const PairType & p)const + uint32 find(const PairType & p)const { if( auto idx = container_.find(p); idx != Kokkos::UnorderedMapInvalidIndex ) return idx; else - return -1; + return static_cast(-1); } INLINE_FUNCTION_HD - bool isValid(int32 idx)const + bool isValid(uint32 idx)const { return container_.valid_at(idx); } INLINE_FUNCTION_HD - int32 capacity() const + uint32 capacity() const { return container_.capacity(); } - int32 loopCount()const + uint32 loopCount()const { return container_.capacity(); } //use this when the value of size_ is updated INLINE_FUNCTION_H - int32 size()const + uint32 size()const { return container_.size(); } @@ -190,7 +190,7 @@ public: /// increase the capacity of the container by at-least len /// the content will be erased. INLINE_FUNCTION_H - void increaseCapacityBy(int32 len) + void increaseCapacityBy(uint32 len) { uint newCap = container_.capacity()+len; this->clear(); diff --git a/src/Interaction/contactSearch/ContactSearch/ContactSearch.hpp b/src/Interaction/contactSearch/ContactSearch/ContactSearch.hpp index d6428064..e024295c 100644 --- a/src/Interaction/contactSearch/ContactSearch/ContactSearch.hpp +++ b/src/Interaction/contactSearch/ContactSearch/ContactSearch.hpp @@ -22,16 +22,18 @@ Licence: #ifndef __ContactSearch_hpp__ #define __ContactSearch_hpp__ - +#include "contactSearchGlobals.hpp" #include "contactSearch.hpp" #include "box.hpp" +#include "particles.hpp" +#include "geometry.hpp" +#include "boundaryContactSearchList.hpp" namespace pFlow { template< - template class BaseMethod, - template class WallMapping + class searchMethod > class ContactSearch : @@ -39,207 +41,134 @@ class ContactSearch { 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; - - using ParticleContactSearchType = - BaseMethod< - ExecutionSpace>; - - using WallMappingType = - WallMapping< - ExecutionSpace>; - -protected: +private: + uniquePtr ppwContactSearch_ = nullptr; - uniquePtr particleContactSearch_ = nullptr; + boundaryContactSearchList csBoundaries_; - uniquePtr wallMapping_ = nullptr; + 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(); + + return ppwContactSearch_().broadSearch( + ti.iter(), + ti.t(), + ti.dt(), + ppPairs, + pwPairs, + position, + flags, + diam, + force + ); + } + + 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: - TypeInfoTemplate2("ContactSearch", ParticleContactSearchType, WallMappingType); + TypeInfoTemplate11("ContactSearch", SearchMethodType); ContactSearch( const dictionary& csDict, - const box& domain, + const box& extDomain, const particles& prtcl, const geometry& geom, Timers& timers) : - contactSearch(csDict, domain, prtcl, geom, timers) - + contactSearch( + csDict, + extDomain, + prtcl, + geom, + timers), + csBoundaries_( + csDict, + Particles().pStruct().boundaries(), + *this) { - auto method = dict().getVal("method"); - auto wmMethod = dict().getVal("wallMapping"); - - auto nbDict = dict().subDict(method+"Info"); - - real minD, maxD; + real minD; + real maxD; this->Particles().boundingSphereMinMax(minD, maxD); - const auto& position = this->Particles().pointPosition().deviceVectorAll(); - const auto& diam = this->Particles().boundingSphere().deviceVectorAll(); + const auto& position = this->Particles().pointPosition().deviceViewAll(); + const auto& flags = this->Particles().dynPointStruct().activePointsMaskDevice(); + const auto& diam = this->Particles().boundingSphere().deviceViewAll(); - particleContactSearch_ = - makeUnique + uint32 wnPoints = this->Geometry().numPoints(); + 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 ( - nbDict, - this->domain(), + dict(), + this->extendedDomainBox(), minD, maxD, position, - diam - ); - REPORT(2)<<"Contact search algorithm for particle-particle is "<< - greenText(particleContactSearch_().typeName())<Geometry().numPoints(); - int32 wnTri = this->Geometry().size(); - - const auto& wPoints = this->Geometry().points().deviceVectorAll(); - const auto& wVertices = this->Geometry().vertices().deviceVectorAll(); - - wallMapping_ = - makeUnique( - wmDict, - particleContactSearch_().numLevels(), - particleContactSearch_().getCellsLevels(), + flags, + diam, wnPoints, - wnTri, + wnTri, wPoints, - wVertices - ); - REPORT(2)<<"Wall mapping algorithm for particle-wall is "<< - greenText(wallMapping_().typeName())<< endREPORT; - + wVertices, + wNormals + ); } - add_vCtor( contactSearch, ContactSearch, dictionary); - - bool broadSearch( - PairContainerType& ppPairs, - PairContainerType& pwPairs, - bool force = false) override + + bool enterBroadSearchBoundary(const timeInfo& ti, bool force=false)const override { - - - 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(); - - } - else - return false; - - if(wallMapping_) - { - sphereWallTimer_.start(); - wallMapping_().broadSearch(pwPairs, particleContactSearch_(), force); - sphereWallTimer_.end(); - } - else - return false; - - - - return true; + return enterBroadSearch(ti, force) || csBoundaries_.boundariesUpdated(); } - - bool ppEnterBroadSearch()const override + real sizeRatio()const override { - if(particleContactSearch_) - { - return particleContactSearch_().enterBoadSearch(); - } - return false; + return ppwContactSearch_().sizeRatio(); } - bool pwEnterBroadSearch()const override + real cellExtent()const override { - if(wallMapping_) - { - return wallMapping_().enterBoadSearch(); - } - return false; + return ppwContactSearch_().cellExtent(); } - - 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; - }*/ - - }; } diff --git a/src/Interaction/contactSearch/ContactSearch/ContactSearchs.cpp b/src/Interaction/contactSearch/ContactSearch/ContactSearchs.cpp index 043e9b78..61024220 100644 --- a/src/Interaction/contactSearch/ContactSearch/ContactSearchs.cpp +++ b/src/Interaction/contactSearch/ContactSearch/ContactSearchs.cpp @@ -20,11 +20,11 @@ Licence: #include "ContactSearch.hpp" -#include "cellMapping.hpp" +//#include "cellMapping.hpp" #include "NBS.hpp" -#include "multiGridNBS.hpp" -#include "multiGridMapping.hpp" +//#include "multiGridNBS.hpp" +//#include "multiGridMapping.hpp" -template class pFlow::ContactSearch; -template class pFlow::ContactSearch; +template class pFlow::ContactSearch; +//template class pFlow::ContactSearch; diff --git a/src/Interaction/contactSearch/boundaries/boundaryContactSearch/boundaryContactSearch.cpp b/src/Interaction/contactSearch/boundaries/boundaryContactSearch/boundaryContactSearch.cpp new file mode 100644 index 00000000..d0d31a61 --- /dev/null +++ b/src/Interaction/contactSearch/boundaries/boundaryContactSearch/boundaryContactSearch.cpp @@ -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("updateInterval")) +{ +} + +pFlow::uniquePtr +pFlow::boundaryContactSearch::create( + const dictionary &dict, + const boundaryBase &boundary, + const contactSearch &cSearch) +{ + + word bType = angleBracketsNames2( + "boundaryContactSearch", + pFlowProcessors().localRunTypeName(), + boundary.type()); + word altBType{"boundaryContactSearch"}; + + if( boundaryBasevCtorSelector_.search(bType) ) + { + pOutput.space(4)<<"Creating contact search boundary "<< Green_Text(bType)<< + " for "<"); + + 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 create( + const dictionary &dict, + const boundaryBase &boundary, + const contactSearch &cSearch); +}; + +} + +#endif //__boundaryContactSearch_hpp__ diff --git a/src/Interaction/contactSearch/boundaries/boundaryContactSearchList.cpp b/src/Interaction/contactSearch/boundaries/boundaryContactSearchList.cpp new file mode 100644 index 00000000..ae86d7ab --- /dev/null +++ b/src/Interaction/contactSearch/boundaries/boundaryContactSearchList.cpp @@ -0,0 +1,32 @@ +#include "boundaryContactSearchList.hpp" +#include "boundaryList.hpp" + +void pFlow::boundaryContactSearchList::setList( + const dictionary &dict, + const contactSearch &cSearch) +{ + for(auto i=0; iset + ( + 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(); +} diff --git a/src/Interaction/contactSearch/boundaries/boundaryContactSearchList.hpp b/src/Interaction/contactSearch/boundaries/boundaryContactSearchList.hpp new file mode 100644 index 00000000..9f1951b8 --- /dev/null +++ b/src/Interaction/contactSearch/boundaries/boundaryContactSearchList.hpp @@ -0,0 +1,43 @@ +#include "ListPtr.hpp" +#include "boundaryContactSearch.hpp" + +namespace pFlow +{ + +class boundaryList; +class contactSearch; + +class boundaryContactSearchList +: + public ListPtr +{ +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; + +}; + + +} \ No newline at end of file diff --git a/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/periodicBoundaryContactSearch.cpp b/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/periodicBoundaryContactSearch.cpp new file mode 100644 index 00000000..7dfcd1b5 --- /dev/null +++ b/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/periodicBoundaryContactSearch.cpp @@ -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( + searchBox_, + maxD); + + const auto& geom = cSearch.Geometry(); + + pwContactSearch_ = makeUnique( + 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< ppContactSearch_ = nullptr; + + uniquePtr pwContactSearch_ = nullptr; + + const realPointField_D &diameter_; + + bool masterSearch_ = false; + + void setSearchBox(); + +public: + TypeInfo("boundaryContactSearch") + + 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__ \ No newline at end of file diff --git a/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/ppwBndryContactSearch.cpp b/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/ppwBndryContactSearch.cpp new file mode 100644 index 00000000..ba6928a5 --- /dev/null +++ b/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/ppwBndryContactSearch.cpp @@ -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(-1)); +} + +void pFlow::ppwBndryContactSearch::nullifyNext(uint32 n) +{ + fill(next_, 0u, n, static_cast(-1)); +} + +void pFlow::ppwBndryContactSearch::buildList( + const deviceScatteredFieldAccess &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 &points, + const deviceScatteredFieldAccess& diams, + const deviceScatteredFieldAccess &mirrorPoints, + const deviceScatteredFieldAccess& 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 "<; + + using NextType = deviceViewType1D; + +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 &points); + +public: + ppwBndryContactSearch( + const box &domain, + real cellSize, + real sizeRatio = 1.0); + + bool broadSearchPP( + csPairContainerType &ppPairs, + const deviceScatteredFieldAccess &points, + const deviceScatteredFieldAccess &diams, + const deviceScatteredFieldAccess &mirrorPoints, + const deviceScatteredFieldAccess &mirrorDiams, + const realx3 &transferVec); + + const auto& searchCells()const + { + return searchCells_; + } + + real sizeRatio()const + { + return sizeRatio_; + } +}; + +} + +#endif //__ppwBndryContactSearch_hpp__ \ No newline at end of file diff --git a/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/ppwBndryContactSearchKernels.cpp b/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/ppwBndryContactSearchKernels.cpp new file mode 100644 index 00000000..a0d47e78 --- /dev/null +++ b/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/ppwBndryContactSearchKernels.cpp @@ -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 &points, + const cells &searchCells, + deviceViewType3D &head, + deviceViewType1D &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 &points, + const deviceScatteredFieldAccess &diams, + const deviceScatteredFieldAccess &mirrorPoints, + const deviceScatteredFieldAccess &mirrorDiams, + const realx3 &transferVec, + const deviceViewType3D &head, + const deviceViewType1D &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(-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(-1)) + { + getFullUpdate++; + } + + thisI = next(thisI); + } + } + } + } + }, + getFull + ); + + return getFull; +} diff --git a/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/ppwBndryContactSearchKernels.hpp b/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/ppwBndryContactSearchKernels.hpp new file mode 100644 index 00000000..78c4a125 --- /dev/null +++ b/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/ppwBndryContactSearchKernels.hpp @@ -0,0 +1,31 @@ + +#include "contactSearchGlobals.hpp" +#include "cells.hpp" +#include "contactSearchFunctions.hpp" +#include "scatteredFieldAccess.hpp" + +namespace pFlow::pweBndryContactSearchKernels +{ + +void buildNextHead( + const deviceScatteredFieldAccess &points, + const cells &searchCells, + deviceViewType3D &head, + deviceViewType1D &next ); + + +uint32 broadSearchPP +( + csPairContainerType &ppPairs, + const deviceScatteredFieldAccess &points, + const deviceScatteredFieldAccess &diams, + const deviceScatteredFieldAccess &mirrorPoints, + const deviceScatteredFieldAccess &mirrorDiams, + const realx3 &transferVec, + const deviceViewType3D &head, + const deviceViewType1D &next, + const cells &searchCells, + real sizeRatio +); + +} \ No newline at end of file diff --git a/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/wallBoundaryContactSearch.cpp b/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/wallBoundaryContactSearch.cpp new file mode 100644 index 00000000..acfad226 --- /dev/null +++ b/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/wallBoundaryContactSearch.cpp @@ -0,0 +1,144 @@ +#include "wallBoundaryContactSearch.hpp" +#include "streams.hpp" + +pFlow::wallBoundaryContactSearch::wallBoundaryContactSearch +( + real cellExtent, + uint32 numPoints, + uint32 numElements, + const ViewType1D &points, + const ViewType1D &vertices, + const ViewType1D &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 &thisPoints, + const deviceScatteredFieldAccess &thisDiams, + const deviceScatteredFieldAccess &mirrorPoints, + const deviceScatteredFieldAccess &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 "< &pPoints, + const deviceScatteredFieldAccess &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 ¬InsertedUpdate) + { + auto p = pPoints[i]+transferVec; + int32x3 ind; + if( searchCells.pointIndexInDomain(p, ind) ) + { + for(uint32 nTri=0; nTri(-1)) + { + notInsertedUpdate++; + } + } + } + }, + nNotInserted + ); + + return nNotInserted; +} diff --git a/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/wallBoundaryContactSearch.hpp b/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/wallBoundaryContactSearch.hpp new file mode 100644 index 00000000..540b793e --- /dev/null +++ b/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/wallBoundaryContactSearch.hpp @@ -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; + +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 vertices_; + + // - ref to points in the trisurface (borrowed) + ViewType1D points_; + + // - ref to normal vectors of triangles (borrowed) + ViewType1D normals_; + + // cell range of element/triangle bounding box + ViewType1D elementBox_; + + ViewType1D 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& points, + const ViewType1D& vertices, + const ViewType1D& 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& thisPoints, + const deviceScatteredFieldAccess& thisDiams, + const deviceScatteredFieldAccess& mirrorPoints, + const deviceScatteredFieldAccess& mirroDiams, + const realx3& transferVec, + real sizeRatio); + + uint32 findPairsElementRangeCount( + csPairContainerType &pairs, + const cells &searchCells, + const deviceScatteredFieldAccess &pPoints, + const deviceScatteredFieldAccess &pDiams, + const realx3 &transferVec, + uint baseTriIndex); + + + +}; // wallBoundaryContactSearch + +} // pFlow + + +#endif // __wallBoundaryContactSearch_hpp__ diff --git a/src/Interaction/contactSearch/contactSearch/contactSearch.cpp b/src/Interaction/contactSearch/contactSearch/contactSearch.cpp index 17c1dbd3..7394e295 100644 --- a/src/Interaction/contactSearch/contactSearch/contactSearch.cpp +++ b/src/Interaction/contactSearch/contactSearch/contactSearch.cpp @@ -19,54 +19,124 @@ Licence: -----------------------------------------------------------------------------*/ #include "contactSearch.hpp" - +#include "streams.hpp" +#include "particles.hpp" pFlow::contactSearch::contactSearch( const dictionary& dict, - const box& domain, + const box& extDomain, const particles& prtcl, const geometry& geom, Timers& timers) : - interactionBase(prtcl, geom), - domain_(domain), - dict_(dict), - sphereSphereTimer_("particle-particle contact search", &timers), - sphereWallTimer_("particle-wall contact search", &timers) + extendedDomainBox_(extDomain), + particles_(prtcl), + geometry_(geom), + bTimer_("Boundary particles contact search", &timers), + ppTimer_("Internal particles contact search", &timers), + dict_(dict) { } +const pFlow::pointStructure &pFlow::contactSearch::pStruct() const +{ + return particles_.pStruct(); +} -pFlow::uniquePtr pFlow::contactSearch::create( - const dictionary& dict, - const box& domain, - const particles& prtcl, - const geometry& geom, - Timers& timers) +bool pFlow::contactSearch::broadSearch +( + const timeInfo &ti, + csPairContainerType &ppPairs, + csPairContainerType &pwPairs, + bool force +) { - word baseMethName = dict.getVal("method"); - word wallMethod = dict.getVal("wallMapping"); + if(enterBroadSearch(ti, force)) + { + ppTimer_.start(); + if( !BroadSearch( + ti, + ppPairs, + pwPairs, + force ) ) + { + fatalErrorInFunction; + performedSearch_ = false; + return false; + } + ppTimer_.end(); + performedSearch_ = true; + } + else + { + performedSearch_ = false; + } - auto model = angleBracketsNames2("ContactSearch", baseMethName, wallMethod); + 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 + { - REPORT(1)<<"Selecting contact search model . . ."< pFlow::contactSearch::create( + const dictionary &dict, + const box &extDomain, + const particles &prtcl, + const geometry &geom, + Timers &timers) +{ + word baseMethName = dict.getVal("method"); + + auto model = angleBracketsNames("ContactSearch", baseMethName); - + pOutput.space(2)<<"Selecting contact search model "<; + /// @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_; - Timer sphereSphereTimer_; + virtual + bool BroadSearch( + const timeInfo& ti, + csPairContainerType& ppPairs, + csPairContainerType& pwPairs, + bool force + )=0; - Timer sphereWallTimer_; + virtual + bool BoundaryBroadSearch( + uint32 bndryIndex, + const timeInfo& ti, + csPairContainerType& ppPairs, + csPairContainerType& pwPairs, + bool force = false + )=0; - auto& dict() - { - return dict_; - } - public: TypeInfo("contactSearch"); contactSearch( const dictionary& dict, - const box& domain, + const box& extDomain, const particles& prtcl, const geometry& geom, Timers& timers); @@ -88,40 +114,103 @@ public: (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_; } + inline + const box& extendedDomainBox()const + { + return extendedDomainBox_; + } - virtual + 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_; + } + bool broadSearch( - PairContainerType& ppPairs, - PairContainerType& pwPairs, - bool force = false) = 0; - - virtual - bool ppEnterBroadSearch()const = 0; - - virtual - bool pwEnterBroadSearch()const = 0; - - virtual - bool ppPerformedBroadSearch()const = 0; - - virtual - bool pwPerformedBroadSearch()const = 0; + const timeInfo& ti, + csPairContainerType& ppPairs, + csPairContainerType& pwPairs, + bool force = false); + bool boundaryBroadSearch( + uint32 bndryIndex, + const timeInfo& ti, + csPairContainerType& ppPairs, + csPairContainerType& pwPairs, + bool force = false); + virtual + real sizeRatio()const = 0; + + virtual + real cellExtent()const = 0; + static uniquePtr create( const dictionary& dict, - const box& domain, + const box& extDomain, const particles& prtcl, const geometry& geom, Timers& timers); diff --git a/src/Interaction/contactSearch/contactSearchFunctions.hpp b/src/Interaction/contactSearch/contactSearchFunctions.hpp index 55879c95..96ee9596 100644 --- a/src/Interaction/contactSearch/contactSearchFunctions.hpp +++ b/src/Interaction/contactSearch/contactSearchFunctions.hpp @@ -96,17 +96,6 @@ void indexToCell(const indexType idx, const iBox& box, triple; -//constexpr int32 minCellIndex = largestNegative(); - -//constexpr int32 maxCellIndex = largestPositive(); +inline +const uint32 BASE_MIRROR_WALL_INDEX = 1000000; } - -#endif //__interactionTypes_hpp__ +#endif diff --git a/src/Interaction/contactSearch/methods/NBS.hpp b/src/Interaction/contactSearch/methods/NBS.hpp deleted file mode 100644 index fb3cc4f8..00000000 --- a/src/Interaction/contactSearch/methods/NBS.hpp +++ /dev/null @@ -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 -class NBS -{ -public: - - using NBSLevel0Type = NBSLevel0; - - 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& position, - const ViewType1D& diam) - : - sizeRatio_( - max( - dict.getValOrSet("sizeRatio", 1.0), - 1.0 - )), - updateFrequency_( - max( - dict.getValOrSet("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 getCellIteratorLevels() - { - return Vector("cellIterator", 1, NBSLevel0_.getCellIterator()); - } - - auto getCellIterator(int32 lvl)const - { - return NBSLevel0_.getCellIterator(); - } - - int32 numLevels()const - { - return 1; - } - - Vector getCellsLevels()const - { - return Vector("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 - 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 - 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 diff --git a/src/Interaction/contactSearch/methods/NBSCrossLoop.hpp b/src/Interaction/contactSearch/methods/NBSCrossLoop.hpp deleted file mode 100644 index adce7409..00000000 --- a/src/Interaction/contactSearch/methods/NBSCrossLoop.hpp +++ /dev/null @@ -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]; -} - diff --git a/src/Interaction/contactSearch/methods/NBSLevel.hpp b/src/Interaction/contactSearch/methods/NBSLevel.hpp deleted file mode 100644 index f355d566..00000000 --- a/src/Interaction/contactSearch/methods/NBSLevel.hpp +++ /dev/null @@ -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 -class -NBSLevel -: - public NBSLevel0 -{ -public: - - using NBSLevel0Type = NBSLevel0; - - 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 - 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& position, - const ViewType1D& 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 - 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(upperLevel-lowerLevel)); - return ind/a; -} - - -} - -#endif diff --git a/src/Interaction/contactSearch/methods/NBSLevel0.hpp b/src/Interaction/contactSearch/methods/NBSLevel0.hpp deleted file mode 100644 index d9ae2f83..00000000 --- a/src/Interaction/contactSearch/methods/NBSLevel0.hpp +++ /dev/null @@ -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 -class NBSLevel0 -: - public mapperNBS -{ -public: - - using MapperType = mapperNBS; - - 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 diameter_; - - - using mdrPolicyFindPairs = - Kokkos::MDRangePolicy< - Kokkos::Rank<3>, - Kokkos::Schedule, - 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& position, - const ViewType1D& diam) - : - MapperType(domain, cellSize, position), - diameter_(diam) - {} - - NBSLevel0( - const box& domain, - int32 nx, - int32 ny, - int32 nz, - const ViewType1D& position, - const ViewType1D& diam) - : - MapperType(domain, nx, ny, nz, position), - diameter_(diam) - { } - - NBSLevel0( - const box& domain, - real cellSize, - real sizeRatio, - const ViewType1D& position, - const ViewType1D& 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 - 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 - bool broadSearch(PairsContainer& pairs, range activeRange, IncludeFunction incld) - { - - this->build(activeRange, incld); - - findPairs(pairs); - - return true; - } - - template - 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 "< - 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__ diff --git a/src/Interaction/contactSearch/methods/NBSLevels.hpp b/src/Interaction/contactSearch/methods/NBSLevels.hpp deleted file mode 100644 index 30603bd3..00000000 --- a/src/Interaction/contactSearch/methods/NBSLevels.hpp +++ /dev/null @@ -1,438 +0,0 @@ -#ifndef __NBSLevels_hpp__ -#define __NBSLevels_hpp__ - -#include "NBSLevel.hpp" -#include "NBSLevel0.hpp" -#include "KokkosTypes.hpp" - -namespace pFlow -{ - -template -class NBSLevels -{ - -public: - - using NBSLevelType = NBSLevel; - - 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; - -protected: - - real minSize_; - - real maxSize_; - - int32 numLevels_=1; - - Vector nbsLevels_; - - ViewType1D sizeRangeLevels_; - - ViewType1D sizeRangeLevelsHost_; - - ViewType1D maxSizeLevels_; - - ViewType1D maxSizeLevelsHost_; - - ViewType1D particleLevel_; - - range activeRange_{0,0}; - - using rangePolicyType = - Kokkos::RangePolicy< - Kokkos::IndexType, - Kokkos::Schedule, - execution_space>; - - int32 setNumLevels() - { - - int32 maxOvermin = static_cast(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<=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."<& position, - const ViewType1D& diam) - { - - - for(int32 lvl = 0; lvl nbsLevels_[0].capacity()) - { - nbsLevels_[0].checkAllocateNext(activeRange_.second); - - auto next0 = nbsLevels_[0].next(); - - for(int32 lvl=1; lvl& position, - const ViewType1D& 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 - 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 "< - INLINE_FUNCTION_H - int32 findPairsCount(PairsContainer& pairs) - { - - int32 notInsertedCount = 0; - - for(int32 lvl=0; lvl1) 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 - 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(-1); - }); - Kokkos::fence(); - - return true; - } - - -}; //NBSLevels - -} - -#endif diff --git a/src/Interaction/contactSearch/methods/NBSLoop.hpp b/src/Interaction/contactSearch/methods/NBSLoop.hpp deleted file mode 100644 index 8aed3e26..00000000 --- a/src/Interaction/contactSearch/methods/NBSLoop.hpp +++ /dev/null @@ -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]; -} - diff --git a/src/Interaction/contactSearch/methods/cellBased/NBS/NBS.cpp b/src/Interaction/contactSearch/methods/cellBased/NBS/NBS.cpp new file mode 100644 index 00000000..733313b4 --- /dev/null +++ b/src/Interaction/contactSearch/methods/cellBased/NBS/NBS.cpp @@ -0,0 +1,69 @@ +/*------------------------------- 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 "NBS.hpp" + +pFlow::NBS::NBS +( + const dictionary& dict, + const box& domainBox, + real minBSSize, + real maxBSSize, + const deviceViewType1D &position, + const pFlagTypeDevice &flags, + const deviceViewType1D &diam, + uint32 nWallPoints, + uint32 nWallElements, + const ViewType1D& wallPoints, + const ViewType1D& wallVertices, + const ViewType1D& wallNormals +) +: + particleWallContactSearchs( + dict, + domainBox, + minBSSize, + maxBSSize, + position, + flags, + diam), + sizeRatio_(max(dict.getVal("sizeRatio"), 1.0)), + cellExtent_(max(dict.getVal("cellExtent"), 0.5)), + adjustableBox_(dict.getVal("adjustableBox")), + NBSLevel0_ + ( + this->domainBox_, + maxBSSize, + sizeRatio_, + position, + flags, + adjustableBox_() + ), + cellsWallLevel0_ + ( + cellExtent_, + nWallPoints, + nWallElements, + wallPoints, + wallVertices, + wallNormals + ) +{ +} diff --git a/src/Interaction/contactSearch/methods/cellBased/NBS/NBS.hpp b/src/Interaction/contactSearch/methods/cellBased/NBS/NBS.hpp new file mode 100644 index 00000000..9cd5ab6f --- /dev/null +++ b/src/Interaction/contactSearch/methods/cellBased/NBS/NBS.hpp @@ -0,0 +1,162 @@ +/*------------------------------- 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 "particleWallContactSearchs.hpp" +#include "NBSLevel0.hpp" +#include "cellsWallLevel0.hpp" +#include "Vector.hpp" + +namespace pFlow +{ + + +class NBS +: + public particleWallContactSearchs +{ +public: + + using CellIterator = typename NBSLevel0::CellIterator; + +private: + + real sizeRatio_ = 1.0; + + real cellExtent_ = 0.5; + + Logical adjustableBox_; + + NBSLevel0 NBSLevel0_; + + cellsWallLevel0 cellsWallLevel0_; + +protected: + + friend particleWallContactSearchs; + + bool impl_broadSearch + ( + csPairContainerType& ppPairs, + csPairContainerType& pwPairs, + const deviceViewType1D& pointPos, + const pFlagTypeDevice& flags, + const deviceViewType1D& diameter + ) + { + bool searchBoxChanged; + if( !NBSLevel0_.broadSearch( + ppPairs, + pointPos, + flags, + diameter, + searchBoxChanged)) + { + fatalErrorInFunction<< + "Error in broadSearch for NBS (particle-particle)"< &position, + const pFlagTypeDevice &flags, + const deviceViewType1D &diam, + uint32 nWallPoints, + uint32 nWallElements, + const ViewType1D& wallPoints, + const ViewType1D& wallVertices, + const ViewType1D& wallNormals ); + + + INLINE_FUNCTION_HD + NBS(const NBS&) = default; + + INLINE_FUNCTION_HD + NBS(NBS&&) = default; + + INLINE_FUNCTION_HD + NBS& operator = (const NBS&) = default; + + INLINE_FUNCTION_HD + NBS& operator = (NBS&&) = default; + + INLINE_FUNCTION_HD + ~NBS()=default; + + + //// - Methods + + uint32 numLevels()const + { + return 1; + } + + real sizeRatio()const + { + return sizeRatio_; + } + + real cellExtent()const + { + return cellExtent_; + } + + auto getCellIterator([[maybe_unused]] uint32 lvl)const + { + return NBSLevel0_.getCellIterator(); + } + + Vector getDomainCellsLevels()const + { + return Vector("Cells", 1, NBSLevel0_.getDomainCells()); + } + +}; + +} + +#endif diff --git a/src/Interaction/contactSearch/methods/cellBased/NBS/NBSLevel0.cpp b/src/Interaction/contactSearch/methods/cellBased/NBS/NBSLevel0.cpp new file mode 100644 index 00000000..8e43c35f --- /dev/null +++ b/src/Interaction/contactSearch/methods/cellBased/NBS/NBSLevel0.cpp @@ -0,0 +1,117 @@ +/*------------------------------- 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 "NBSLevel0.hpp" +#include "streams.hpp" + +bool pFlow::NBSLevel0::findPairs +( + csPairContainerType &pairs, + const deviceViewType1D &pointPos, + const pFlagTypeDevice &flags, + const deviceViewType1D &diameter +) +{ + uint32 getFull = 1; + + // loop until the container size fits the numebr of contact pairs + while (getFull > 0) + { + + getFull = pFlow::NBSLevel0Kernels::findPairsCount + ( + pairs, + sizeRatio_, + pointPos, + flags, + diameter, + getCellIterator() + ); + + if(getFull) + { + // - resize the container + // note that getFull now shows the number of failed insertions. + uint32 len = max(getFull,500u) ; + + auto oldCap = pairs.capacity(); + + pairs.increaseCapacityBy(len); + + INFORMATION<< "The contact pair container capacity increased from "<< + oldCap << " to "<& pointPos, + const pFlagTypeDevice& flags, + bool adjustableBox +) +: + mapperNBS + ( + domain, + cellSize, + pointPos, + flags, + adjustableBox, + true + ), + sizeRatio_(sizeRatio) +{ + +} + +bool pFlow::NBSLevel0::broadSearch +( + csPairContainerType &pairs, + const deviceViewType1D &pointPos, + const pFlagTypeDevice &flags, + const deviceViewType1D &diameter, + bool& searchBoxChanged +) +{ + if(!build(pointPos, flags, searchBoxChanged)) + { + fatalErrorInFunction; + return false; + } + + if(!findPairs(pairs, pointPos, flags, diameter)) + { + fatalErrorInFunction; + return false; + } + + return true; +} + + diff --git a/src/Interaction/contactSearch/methods/cellBased/NBS/NBSLevel0.hpp b/src/Interaction/contactSearch/methods/cellBased/NBS/NBSLevel0.hpp new file mode 100644 index 00000000..2f87c151 --- /dev/null +++ b/src/Interaction/contactSearch/methods/cellBased/NBS/NBSLevel0.hpp @@ -0,0 +1,98 @@ +/*------------------------------- 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 "NBSLevel0Kernels.hpp" +#include "mapperNBS.hpp" + +namespace pFlow +{ + + +class NBSLevel0 +: + public mapperNBS +{ +public: + + using MapperType = mapperNBS; + + using CellIterator = typename MapperType::CellIterator; + + using HeadType = typename MapperType::HeadType; + + using NextType = typename MapperType::NextType; + + +private: + + real sizeRatio_ = 1.0; + + bool findPairs + ( + csPairContainerType& pairs, + const deviceViewType1D& pointPos, + const pFlagTypeDevice& flags, + const deviceViewType1D& diameter + ); + +public: + + TypeInfoNV("NBSLevel0"); + + INLINE_FUNCTION_HD + NBSLevel0() = default; + + NBSLevel0( + const box& domain, + real cellSize, + real sizeRatio, + const deviceViewType1D& pointPos, + const pFlagTypeDevice& flags, + bool adjustableBox); + + INLINE_FUNCTION_HD + NBSLevel0(const NBSLevel0&) = default; + + INLINE_FUNCTION_HD + NBSLevel0& operator = (const NBSLevel0&) = default; + + INLINE_FUNCTION_HD + ~NBSLevel0()=default; + + + bool broadSearch( + csPairContainerType& pairs, + const deviceViewType1D& pointPos, + const pFlagTypeDevice& flags, + const deviceViewType1D& diameter, + bool& searchBoxChanged); + + + + +}; + +} // pFlow + +#endif // __NBSLevel0_hpp__ diff --git a/src/Interaction/contactSearch/methods/cellBased/NBS/NBSLevel0Kernels.hpp b/src/Interaction/contactSearch/methods/cellBased/NBS/NBSLevel0Kernels.hpp new file mode 100644 index 00000000..31df063c --- /dev/null +++ b/src/Interaction/contactSearch/methods/cellBased/NBS/NBSLevel0Kernels.hpp @@ -0,0 +1,83 @@ +/*------------------------------- 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 "mapperNBS.hpp" +#include "contactSearchGlobals.hpp" + +#include "streams.hpp" + +namespace pFlow::NBSLevel0Kernels +{ + +using mdrPolicyFindPairs = + Kokkos::MDRangePolicy< + Kokkos::IndexType, + Kokkos::Rank<3>, + Kokkos::Schedule, + DefaultExecutionSpace>; + +template +INLINE_FUNCTION_HD +void Swap(T& x, T& y) +{ + T tmp = x; + x = y; + y = tmp; +} + +INLINE_FUNCTION_HD +bool sphereSphereCheck(const realx3& p1, const realx3 p2, real d1, real d2) +{ + return length(p2-p1) < 0.5*(d2+d1); +} + +inline +uint32 findPairsCount +( + csPairContainerType& pairs, + real sizeRatio, + const deviceViewType1D& pointPos, + const pFlagTypeDevice& flags, + const deviceViewType1D& diameter, + mapperNBS::CellIterator cellIter +) +{ + + auto nCells = cellIter.numCells(); + + mdrPolicyFindPairs + mdrPolicy( + {0,0,0}, + {nCells.x(), nCells.y(), nCells.z()} ); + + uint32 notInsertedPairs = 0u; + + + Kokkos::parallel_reduce ( + "pFlow::NBSLevel0Kernels::findPairsCount", + mdrPolicy, + LAMBDA_HD(uint32 i, uint32 j, uint32 k, uint32& getFullUpdate){ + #include "NBSLoop.hpp" + }, notInsertedPairs); + + return notInsertedPairs; +} + +} \ No newline at end of file diff --git a/src/Interaction/contactSearch/methods/cellBased/NBS/NBSLoop.hpp b/src/Interaction/contactSearch/methods/cellBased/NBS/NBSLoop.hpp new file mode 100644 index 00000000..ecbc63e5 --- /dev/null +++ b/src/Interaction/contactSearch/methods/cellBased/NBS/NBSLoop.hpp @@ -0,0 +1,100 @@ +/*------------------------------- 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. + +-----------------------------------------------------------------------------*/ + + +uint32 m = cellIter.start(i,j,k); +int32x3 currentCell(i,j,k); +uint32 n = mapperNBS::NoPos; + +while( m != mapperNBS::NoPos) +{ + + auto p_m = pointPos[m]; + auto d_m = sizeRatio* diameter[m]; + + // the same cell + n = cellIter.getNext(m); + + while(n != mapperNBS::NoPos) + { + auto p_n = pointPos[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( pairs.insert(lm,ln) == static_cast(-1)) + { + getFullUpdate++; + } + } + + n = cellIter.getNext(n);; + } + + // neighbor cells + int32x3 neighborCell; + for(uint32 ni=0u; ni<13; ni++) + { + if(ni==0) neighborCell = currentCell + int32x3( 0, 0,-1); + else if(ni==1) neighborCell = currentCell + int32x3(-1, 0,-1); + else if(ni==2) neighborCell = currentCell + int32x3(-1, 0, 0); + else if(ni==3) neighborCell = currentCell + int32x3(-1, 0, 1); + else if(ni==4) neighborCell = currentCell + int32x3( 0,-1,-1); + else if(ni==5) neighborCell = currentCell + int32x3( 0,-1, 0); + else if(ni==6) neighborCell = currentCell + int32x3( 0,-1, 1); + else if(ni==7) neighborCell = currentCell + int32x3(-1,-1,-1); + else if(ni==8) neighborCell = currentCell + int32x3(-1,-1, 0); + else if(ni==9) neighborCell = currentCell + int32x3(-1,-1, 1); + else if(ni==10) neighborCell = currentCell + int32x3( 1,-1,-1); + else if(ni==11) neighborCell = currentCell + int32x3( 1,-1, 0); + else if(ni==12) neighborCell = currentCell + int32x3( 1,-1, 1); + + if( neighborCell.x()>=0 && neighborCell.y()>=0 && neighborCell.z()>=0 && + neighborCell.x()ln) Swap(lm,ln); + if( pairs.insert(lm,ln) == static_cast(-1)) + { + getFullUpdate++; + } + } + n = cellIter.next(n); + } + } + } + m = cellIter.next(m); +} + diff --git a/src/Interaction/contactSearch/methods/cellBased/NBS/cellsWallLevel0.cpp b/src/Interaction/contactSearch/methods/cellBased/NBS/cellsWallLevel0.cpp new file mode 100644 index 00000000..e1b6e3a7 --- /dev/null +++ b/src/Interaction/contactSearch/methods/cellBased/NBS/cellsWallLevel0.cpp @@ -0,0 +1,220 @@ +/*------------------------------- 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 "cellsWallLevel0.hpp" +#include "streams.hpp" + +pFlow::cellsWallLevel0::cellsWallLevel0 +( + real cellExtent, + uint32 numPoints, + uint32 numElements, + const ViewType1D &points, + const ViewType1D &vertices, + const ViewType1D& normals +) +: + cellExtent_( max(cellExtent, 0.5 ) ), + numElements_(numElements), + numPoints_(numPoints), + vertices_(vertices), + points_(points), + normals_(normals) +{ + allocateArrays(); +} + +bool pFlow::cellsWallLevel0::resetElements +( + uint32 numElements, + uint32 numPoints, + const ViewType1D& points, + const ViewType1D& vertices, + const ViewType1D& normals +) +{ + + numElements_ = numElements; + numPoints_ = numPoints; + points_ = points; + vertices_ = vertices; + normals_ = normals; + + allocateArrays(); + + return true; +} + +bool pFlow::cellsWallLevel0::broadSearch +( + csPairContainerType &pairs, + const cells& searchBox, + const mapperNBS::CellIterator &particleMap, + const deviceViewType1D& pPoints, + const deviceViewType1D& pDiams, + real sizeRatio +) +{ + + // map walls onto the cells + + this->build(searchBox); + + this->particleWallFindPairs(pairs, particleMap, pPoints, pDiams, sizeRatio); + + return true; +} + +bool pFlow::cellsWallLevel0::build(const cells & searchBox) +{ + + const auto& points = points_; + const auto& vertices = vertices_; + const auto& elementBox = elementBox_; + const auto cellExtent = cellExtent_; + + Kokkos::parallel_for( + "pFlow::cellsWallLevel0::build", + deviceRPolicyStatic(0,numElements_), + LAMBDA_HD(uint32 i) + { + auto v = vertices[i]; + auto p1 = points[v.x()]; + auto p2 = points[v.y()]; + auto p3 = points[v.z()]; + + realx3 minP; + realx3 maxP; + + searchBox.extendBox(p1, p2, p3, cellExtent, minP, maxP); + elementBox[i] = iBoxType(searchBox.pointIndex(minP), searchBox.pointIndex(maxP)); + }); + Kokkos::fence(); + + return true; +} + +bool pFlow::cellsWallLevel0::particleWallFindPairs +( + csPairContainerType &pairs, + const mapperNBS::CellIterator &particleMap, + const deviceViewType1D& pPoints, + const deviceViewType1D& pDiams, + real sizeRatio +) +{ + + uint32 getFull = 1; + + while (getFull) + { + + getFull = findPairsElementRangeCount(pairs, particleMap, pPoints, pDiams, sizeRatio); + + if(getFull) + { + // - resize the container + // note that getFull now shows the number of failed insertions. + uint32 len = max(getFull, 50u); + auto oldCap = pairs.capacity(); + pairs.increaseCapacityBy(len); + + INFORMATION<<"Contact pair container capacity increased from "<< + oldCap << " to " + << pairs.capacity() <<" in cellsWallLevel0."<& pPoints, + const deviceViewType1D& pDiams, + real sizeRatio +) +{ + uint32 getFull =0; + + const auto& elementBox = elementBox_; + const auto& normals = normals_; + const auto& points = points_; + const auto& vertices = vertices_; + const auto cellExtent = cellExtent_; + + Kokkos::parallel_reduce( + "pFlow::cellsWallLevel0::findPairsElementRangeCount", + tpPWContactSearch(numElements_, Kokkos::AUTO), + LAMBDA_HD( + const typename tpPWContactSearch::member_type & teamMember, + uint32& valueToUpdate){ + + const uint32 iTri = teamMember.league_rank(); + + const auto triBox = elementBox[iTri]; + const auto triPlane = infinitePlane( + normals[iTri], + points[vertices[iTri].x()]); + + uint32 getFull2 = 0; + + auto bExtent = boxExtent(triBox); + uint32 numCellBox = bExtent.x()*bExtent.y()*bExtent.z(); + + Kokkos::parallel_reduce( + Kokkos::TeamThreadRange( teamMember, numCellBox ), + [&] ( const uint32 linIndex, uint32 &innerUpdate ) + { + + int32x3 cell; + indexToCell(linIndex, triBox, cell); + + uint32 n = particleMap.start(cell.x(),cell.y(),cell.z()); + + while( n != particleMap.NoPos) + { + // id is wall id the pair is (particle id, wall id) + if( abs(triPlane.pointFromPlane(pPoints[n]))< pDiams[n]*sizeRatio*cellExtent) + { + if( pairs.insert( + static_cast(n), + static_cast(iTri) ) == static_cast(-1) + ) + innerUpdate++; + } + n = particleMap.next(n); + + } + + }, + getFull2 + ); + + if ( teamMember.team_rank() == 0 ) valueToUpdate += getFull2; + }, + getFull + ); + return getFull; +} \ No newline at end of file diff --git a/src/Interaction/contactSearch/methods/cellBased/NBS/cellsWallLevel0.hpp b/src/Interaction/contactSearch/methods/cellBased/NBS/cellsWallLevel0.hpp new file mode 100644 index 00000000..da7d77d1 --- /dev/null +++ b/src/Interaction/contactSearch/methods/cellBased/NBS/cellsWallLevel0.hpp @@ -0,0 +1,153 @@ +/*------------------------------- 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 __cellsWallLevel0_hpp__ +#define __cellsWallLevel0_hpp__ + +#include "contactSearchGlobals.hpp" +#include "contactSearchFunctions.hpp" +#include "mapperNBS.hpp" +#include "iBox.hpp" + + + +namespace pFlow +{ + +class cellsWallLevel0 +{ +public: + + using execution_space = csExecutionSpace; + + using memory_space = typename execution_space::memory_space; + + using iBoxType = iBox; + + class TagFindCellRange2{}; + +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 vertices_; + + // - ref to points in the trisurface (borrowed) + ViewType1D points_; + + // - ref to normal vectors of triangles (borrowed) + ViewType1D normals_; + + // cell range of element/triangle bounding box + ViewType1D elementBox_; + + + using tpPWContactSearch = Kokkos::TeamPolicy< + execution_space, + Kokkos::Schedule, + Kokkos::IndexType>; + + FUNCTION_H + void allocateArrays() + { + reallocNoInit( elementBox_, numElements_); + } + +public: + + TypeInfoNV("cellsWallLevel0"); + + INLINE_FUNCTION_HD + cellsWallLevel0(){} + + FUNCTION_H + cellsWallLevel0( + real cellExtent, + uint32 numPoints, + uint32 numElements, + const ViewType1D& points, + const ViewType1D& vertices, + const ViewType1D& normals); + + + + // - host call + // reset triangle elements if they have changed + bool resetElements( + uint32 numElements, + uint32 numPoints, + const ViewType1D& points, + const ViewType1D& vertices, + const ViewType1D& normals); + + + INLINE_FUNCTION_HD + iBoxType elementBox(uint32 i)const + { + return elementBox_[i]; + } + + INLINE_FUNCTION_HD + uint32 numElements()const + { + return numElements_; + } + + bool broadSearch( + csPairContainerType& pairs, + const cells& searchBox, + const mapperNBS::CellIterator& particleMap, + const deviceViewType1D& pPoints, + const deviceViewType1D& pDiams, + real sizeRatio); + + + bool build(const cells& searchBox); + + bool particleWallFindPairs( + csPairContainerType& pairs, + const mapperNBS::CellIterator& particleMap, + const deviceViewType1D& pPoints, + const deviceViewType1D& pDiams, + real sizeRatio); + + int32 findPairsElementRangeCount( + csPairContainerType& pairs, + const mapperNBS::CellIterator& particleMap, + const deviceViewType1D& pPoints, + const deviceViewType1D& pDiams, + real sizeRatio); + + + +}; // cellsWallLevel0 + +} // pFlow + + +#endif // __cellsWallLevel0_hpp__ diff --git a/src/Interaction/contactSearch/methods/cellBased/NBS/mapperNBS.cpp b/src/Interaction/contactSearch/methods/cellBased/NBS/mapperNBS.cpp new file mode 100644 index 00000000..b0f16804 --- /dev/null +++ b/src/Interaction/contactSearch/methods/cellBased/NBS/mapperNBS.cpp @@ -0,0 +1,194 @@ +/*------------------------------- 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 "mapperNBS.hpp" +#include "mapperNBSKernels.hpp" +#include "streams.hpp" + +pFlow::uint32 pFlow::mapperNBS::checkInterval_ = 1000; +pFlow::real pFlow::mapperNBS::enlargementFactor_ = 1.1; + +bool pFlow::mapperNBS::setSearchBox +( + const deviceViewType1D &pointPos, + const pFlagTypeDevice &flags, + real cellSize +) +{ + box domainBox = domainCells_.domainBox(); + + + if(adjustableBox_) + { + lastCheckForBox_ = buildCount_; + + realx3 minP; + realx3 maxP; + pFlow::mapperNBSKernels::findPointExtends + ( + pointPos, + flags, + minP, maxP + ); + + minP = max( minP - enlargementFactor_*cellSize, domainBox.minPoint()); + maxP = min( maxP + enlargementFactor_*cellSize, domainBox.maxPoint()); + + box searchBox = {minP, maxP}; + searchCells_ = cells(searchBox, cellSize); + INFORMATION<<"Search box for contact search has changed: "<< + "search box is ["< &pointPos, + const pFlagTypeDevice &flags, + bool adjustableBox, + bool nextOwner +) +: + domainCells_(domain, cellSize), + searchCells_(domain, cellSize), + adjustableBox_(adjustableBox), + nextOwner_(nextOwner) +{ + setSearchBox(pointPos, flags, cellSize); + + allocateArrays(flags.activeRange()); +} + +bool pFlow::mapperNBS::build +( + const deviceViewType1D& pointPos, + const pFlagTypeDevice & flags, + bool& searchBoxChanged +) +{ + auto aRange = flags.activeRange(); + buildCount_++; + if(adjustableBox_ && buildCount_%checkInterval_ == 0) + { + + if(searchBoxChanged = + setSearchBox(pointPos, flags, searchCells_.cellSize());searchBoxChanged) + { + allocateArrays(aRange); + } + + } + else + { + checkAllocateNext(aRange); + nullifyHead(); + nullifyNext(aRange); + } + + if( adjustableBox_ ) + { + if(!pFlow::mapperNBSKernels::buildListsReduce( + searchCells_, + head_, + next_, + pointPos, + flags) ) + { + + buildCount_++; + setSearchBox(pointPos, flags, searchCells_.cellSize()); + + searchBoxChanged = true; + + allocateArrays(flags.activeRange()); + + if(!pFlow::mapperNBSKernels::buildListsReduce( + searchCells_, + head_, + next_, + pointPos, + flags)) + { + fatalErrorInFunction<<"failed to build list in anjustable search box mode!"<; + + using NextType = deviceViewType1D; + + + static constexpr uint32 NoPos = 0xFFFFFFFF; + + class CellIterator + { + private: + HeadType head_; + + NextType next_; + + public: + + CellIterator(const HeadType& head, const NextType& next) + : + head_(head), + next_(next) + {} + + static constexpr uint32 NoPos = 0xFFFFFFFF; + + INLINE_FUNCTION_HD + int32x3 numCells()const { + return int32x3(head_.extent(0), head_.extent(1), head_.extent(2));} + + INLINE_FUNCTION_HD + uint32 start(int32 i, int32 j, int32 k)const { + return head_(i,j,k); } + + INLINE_FUNCTION_HD + uint32 getNext(uint32 n)const { + if(n == NoPos ) return NoPos; + return next_(n); } + + INLINE_FUNCTION_HD + uint32 next(uint32 n)const{ + return next_(n);} + }; + +private: + + cells domainCells_; + + cells searchCells_; + + HeadType head_{"NBS::head",1,1,1}; + + NextType next_{"NBS::next", 1}; + + uint32 nextCapacity_ = 0; + + uint32 lastCheckForBox_ = 0; + + uint32 buildCount_ = 0; + + bool adjustableBox_ = false; + + bool nextOwner_ = true; + + static uint32 checkInterval_; + + static real enlargementFactor_; + + bool setSearchBox( + const deviceViewType1D& pointPos, + const pFlagTypeDevice& flags, + real cellSize + ); + + void allocateArrays(rangeU32 nextRng); + + void checkAllocateNext(rangeU32 nextRng); + + void nullifyHead(); + + void nullifyNext(rangeU32 nextRng); + +public: + + TypeInfoNV("mapperNBS"); + + INLINE_FUNCTION_HD + mapperNBS() = default; + + mapperNBS( + const box& domain, + real cellSize, + const deviceViewType1D& pointPos, + const pFlagTypeDevice& flags, + bool adjustableBox, + bool nextOwner = true); + + INLINE_FUNCTION_HD + mapperNBS(const mapperNBS&) = default; + + INLINE_FUNCTION_HD + mapperNBS(mapperNBS&&) = default; + + INLINE_FUNCTION_HD + mapperNBS& operator = (const mapperNBS&) = default; + + INLINE_FUNCTION_HD + mapperNBS& operator = (mapperNBS&&) = default; + + INLINE_FUNCTION_HD + ~mapperNBS()=default; + + //// - Methods + + auto getCellIterator()const + { + return CellIterator(head_, next_); + } + + const auto& getDomainCells()const + { + return domainCells_; + } + + const auto& getSearchCells()const + { + return searchCells_; + } + + bool build( + const deviceViewType1D& pointPos, + const pFlagTypeDevice& flags, + bool& searchBoxChanged); + + + + +}; + +} // pFlow + +#endif // __mapperNBS_hpp__ + + + + +/* +INLINE_FUNCTION_HD + auto& head() + { + return head_; + } + + INLINE_FUNCTION_HD + auto& next() + { + return next_; + } + + INLINE_FUNCTION_HD + const auto& head()const + { + return head_; + } + + INLINE_FUNCTION_HD + const auto& next()const + { + return next_; + } + + INLINE_FUNCTION_HD + auto& pointPosition() + { + return pointPosition_; + } +*/ \ No newline at end of file diff --git a/src/Interaction/contactSearch/methods/cellBased/NBS/mapperNBSKernels.cpp b/src/Interaction/contactSearch/methods/cellBased/NBS/mapperNBSKernels.cpp new file mode 100644 index 00000000..01141eac --- /dev/null +++ b/src/Interaction/contactSearch/methods/cellBased/NBS/mapperNBSKernels.cpp @@ -0,0 +1,192 @@ + + +/*------------------------------- 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 "mapperNBSKernels.hpp" + + +void pFlow::mapperNBSKernels::findPointExtends +( + const deviceViewType1D& points, + const pFlagTypeDevice& flags, + realx3& minPoint, + realx3& maxPoint +) +{ + if(flags.numActive() == 0) + { + minPoint = {0,0,0}; + maxPoint = {0,0,0}; + return; + } + + real minX; + real minY; + real minZ; + real maxX; + real maxY; + real maxZ; + auto aRange = flags.activeRange(); + Kokkos::parallel_reduce( + "pFlow::mapperNBSKernels::findPointExtends", + deviceRPolicyStatic(aRange.start(), aRange.end()), + LAMBDA_HD( + uint32 i, + real& minXUpdate, + real& minYUpdate, + real& minZUpdate, + real& maxXUpdate, + real& maxYUpdate, + real& maxZUpdate) + { + if(flags(i)) + { + auto p = points(i); + minXUpdate = min(p.x(), minXUpdate); + minYUpdate = min(p.y(), minYUpdate); + minZUpdate = min(p.z(), minZUpdate); + maxXUpdate = max(p.x(), maxXUpdate); + maxYUpdate = max(p.y(), maxYUpdate); + maxZUpdate = max(p.z(), maxZUpdate); + } + + }, + Kokkos::Min(minX), + Kokkos::Min(minY), + Kokkos::Min(minZ), + Kokkos::Max(maxX), + Kokkos::Max(maxY), + Kokkos::Max(maxZ) + ); + + minPoint = {minX, minY, minZ}; + maxPoint = {maxX, maxY, maxZ}; +} + +bool pFlow::mapperNBSKernels::buildListsReduce +( + const cells &searchCell, + const deviceViewType3D &head, + const deviceViewType1D &next, + const deviceViewType1D &points, + const pFlagTypeDevice &flags +) +{ + uint32 numOut = 0; + auto aRange = flags.activeRange(); + + if(flags.isAllActive()) + { + Kokkos::parallel_reduce + ( + "pFlow::mapperNBSKernels::buildListsReduce", + deviceRPolicyStatic(aRange.start(), aRange.end()), + LAMBDA_HD(uint32 i, uint32& valToUpdate) + { + int32x3 ind; + if( searchCell.pointIndexInDomain(points[i], ind) ) + { + uint32 old = Kokkos::atomic_exchange(&head(ind.x(), ind.y(), ind.z()), i); + next[i] = old; + } + else + { + valToUpdate++; + } + }, + numOut + ); + } + else + { + Kokkos::parallel_reduce + ( + "pFlow::mapperNBSKernels::buildListsReduce", + deviceRPolicyStatic(aRange.start(), aRange.end()), + LAMBDA_HD(uint32 i, uint32& valToUpdate) + { + int32x3 ind; + if( flags(i) ) + { + if( searchCell.pointIndexInDomain(points[i], ind) ) + { + uint32 old = Kokkos::atomic_exchange(&head(ind.x(), ind.y(), ind.z()), i); + next[i] = old; + } + else + { + valToUpdate++; + } + } + }, + numOut + ); + } + + return numOut == 0u ; +} + +bool pFlow::mapperNBSKernels::buildLists +( + const cells &searchCell, + const deviceViewType3D &head, + const deviceViewType1D &next, + const deviceViewType1D &points, + const pFlagTypeDevice &flags +) +{ + auto aRange = flags.activeRange(); + if(flags.isAllActive() ) + { + Kokkos::parallel_for + ( + "pFlow::mapperNBSKernels::buildLists", + deviceRPolicyStatic(aRange.start(), aRange.end()), + LAMBDA_HD(uint32 i) + { + auto ind = searchCell.pointIndex(points[i]); + uint32 old = Kokkos::atomic_exchange(&head(ind.x(), ind.y(), ind.z()), i); + next[i] = old; + } + ); + Kokkos::fence(); + } + else + { + Kokkos::parallel_for + ( + "pFlow::mapperNBSKernels::buildLists", + deviceRPolicyStatic(aRange.start(), aRange.end()), + LAMBDA_HD(uint32 i) + { + if( flags(i) ) + { + auto ind = searchCell.pointIndex(points[i]); + uint32 old = Kokkos::atomic_exchange(&head(ind.x(), ind.y(), ind.z()), i); + next[i] = old; + } + } + ); + Kokkos::fence(); + } + + return true; +} diff --git a/src/Interaction/contactSearch/methods/cellBased/NBS/mapperNBSKernels.hpp b/src/Interaction/contactSearch/methods/cellBased/NBS/mapperNBSKernels.hpp new file mode 100644 index 00000000..6730ff22 --- /dev/null +++ b/src/Interaction/contactSearch/methods/cellBased/NBS/mapperNBSKernels.hpp @@ -0,0 +1,49 @@ +/*------------------------------- 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 "phasicFlowKokkos.hpp" +#include "cells.hpp" +#include "pointFlag.hpp" + + +namespace pFlow::mapperNBSKernels +{ + +void findPointExtends( + const deviceViewType1D& points, + const pFlagTypeDevice& flags, + realx3& minPoint, + realx3& maxPoint); + +bool buildListsReduce( + const cells& searchCell, + const deviceViewType3D& head, + const deviceViewType1D& next, + const deviceViewType1D& points, + const pFlagTypeDevice& flags); + +bool buildLists( + const cells& searchCell, + const deviceViewType3D& head, + const deviceViewType1D& next, + const deviceViewType1D& points, + const pFlagTypeDevice& flags); + +} \ No newline at end of file diff --git a/src/Interaction/contactSearch/cells.hpp b/src/Interaction/contactSearch/methods/cellBased/cells.hpp similarity index 62% rename from src/Interaction/contactSearch/cells.hpp rename to src/Interaction/contactSearch/methods/cellBased/cells.hpp index c77b1a69..c4b50813 100644 --- a/src/Interaction/contactSearch/cells.hpp +++ b/src/Interaction/contactSearch/methods/cellBased/cells.hpp @@ -28,58 +28,40 @@ Licence: namespace pFlow { -template class cells { -public: - - using CellType = triple; - -protected: +private: // - domain - box domain_{realx3(0.0), realx3(1.0)}; + box domainBox_{realx3(0.0), realx3(1.0)}; // - cell size - realx3 cellSize_{1,1,1}; - - CellType numCells_{1,1,1}; + real celldx_{1}; + int32x3 numCells_{1,1,1}; // - protected methods INLINE_FUNCTION_H void calculate() { - numCells_ = (domain_.maxPoint()-domain_.minPoint())/cellSize_ + realx3(1.0); - numCells_ = max( numCells_ , CellType(static_cast(1)) ); + numCells_ = (domainBox_.maxPoint()-domainBox_.minPoint())/celldx_ + realx3(1.0); + numCells_ = max( numCells_ , int32x3(1) ); } public: INLINE_FUNCTION_HD - cells() - {} + cells() = default; INLINE_FUNCTION_H cells(const box& domain, real cellSize) : - domain_(domain), - cellSize_(cellSize) + domainBox_(domain), + celldx_(cellSize) { calculate(); } - - INLINE_FUNCTION_H - cells(const box& domain, int32 nx, int32 ny, int32 nz) - : - domain_(domain), - cellSize_( - (domain_.maxPoint() - domain_.minPoint())/realx3(nx, ny, nz) - ), - numCells_(nx, ny, nz) - {} - INLINE_FUNCTION_HD cells(const cells&) = default; @@ -100,43 +82,36 @@ public: INLINE_FUNCTION_H void setCellSize(real cellSize) { - cellSize_ = cellSize; - calculate(); - } - - INLINE_FUNCTION_H - void setCellSize(realx3 cellSize) - { - cellSize_ = cellSize; + celldx_ = cellSize; calculate(); } INLINE_FUNCTION_HD - realx3 cellSize()const + real cellSize()const { - return cellSize_; + return celldx_; } INLINE_FUNCTION_HD - const CellType& numCells()const + const int32x3& numCells()const { return numCells_; } INLINE_FUNCTION_HD - indexType nx()const + int32 nx()const { return numCells_.x(); } INLINE_FUNCTION_HD - indexType ny()const + int32 ny()const { return numCells_.y(); } INLINE_FUNCTION_HD - indexType nz()const + int32 nz()const { return numCells_.z(); } @@ -149,22 +124,21 @@ public: static_cast(numCells_.z()); } - const auto& domain()const + const auto& domainBox()const { - return domain_; + return domainBox_; } INLINE_FUNCTION_HD - CellType pointIndex(const realx3& p)const + int32x3 pointIndex(const realx3& p)const { - return CellType( (p - domain_.minPoint())/cellSize_ ); + return int32x3( (p - domainBox_.minPoint())/celldx_ ); } INLINE_FUNCTION_HD - bool pointIndexInDomain(const realx3 p, CellType& index)const + bool pointIndexInDomain(const realx3 p, int32x3& index)const { - if( !domain_.isInside(p) ) return false; - + if(!inDomain(p))return false; index = this->pointIndex(p); return true; } @@ -172,11 +146,11 @@ public: INLINE_FUNCTION_HD bool inDomain(const realx3& p)const { - return domain_.isInside(p); + return domainBox_.isInside(p); } INLINE_FUNCTION_HD - bool isInRange(const CellType& cell)const + bool inCellRange(const int32x3& cell)const { if(cell.x()<0)return false; if(cell.y()<0)return false; @@ -188,7 +162,7 @@ public: } INLINE_FUNCTION_HD - bool isInRange(indexType i, indexType j, indexType k)const + bool inCellRange(int32 i, int32 j, int32 k)const { if(i<0)return false; if(j<0)return false; @@ -199,22 +173,7 @@ public: return true; } - INLINE_FUNCTION_HD - void extendBox( - const CellType& p1, - const CellType& p2, - const CellType& p3, - indexType extent, - CellType& minP, - CellType& maxP)const - { - minP = min( min( p1, p2), p3)-extent; - maxP = max( max( p1, p2), p3)+extent; - - minP = bound(minP); - maxP = bound(maxP); - } - + INLINE_FUNCTION_HD void extendBox( const realx3& p1, @@ -224,17 +183,17 @@ public: realx3& minP, realx3& maxP)const { - minP = min(min(p1,p2),p3) - extent*cellSize_ ; - maxP = max(max(p1,p2),p3) + extent*cellSize_ ; + minP = min(min(p1,p2),p3) - extent*celldx_ ; + maxP = max(max(p1,p2),p3) + extent*celldx_ ; minP = bound(minP); maxP = bound(maxP); } INLINE_FUNCTION_HD - CellType bound(CellType p)const + int32x3 bound(int32x3 p)const { - return CellType( + return int32x3( min( numCells_.x()-1, max(0,p.x())), min( numCells_.y()-1, max(0,p.y())), min( numCells_.z()-1, max(0,p.z())) @@ -245,9 +204,9 @@ public: realx3 bound(realx3 p)const { return realx3( - min( domain_.maxPoint().x(), max(domain_.minPoint().x(),p.x())), - min( domain_.maxPoint().y(), max(domain_.minPoint().y(),p.y())), - min( domain_.maxPoint().z(), max(domain_.minPoint().z(),p.z())) + min( domainBox_.maxPoint().x(), max(domainBox_.minPoint().x(),p.x())), + min( domainBox_.maxPoint().y(), max(domainBox_.minPoint().y(),p.y())), + min( domainBox_.maxPoint().z(), max(domainBox_.minPoint().z(),p.z())) ); } }; diff --git a/src/Interaction/contactSearch/methods/mapperNBS.hpp b/src/Interaction/contactSearch/methods/mapperNBS.hpp deleted file mode 100644 index 41b47068..00000000 --- a/src/Interaction/contactSearch/methods/mapperNBS.hpp +++ /dev/null @@ -1,389 +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 __mapperNBS_hpp__ -#define __mapperNBS_hpp__ - -#include "cells.hpp" -#include "contactSearchFunctions.hpp" -#include "baseAlgorithms.hpp" -#include "ViewAlgorithms.hpp" - -namespace pFlow -{ - -template -class mapperNBS -: - public cells -{ -public: - - using IdType = int32; - - using IndexType = int32; - - using Cells = cells; - - using CellType = typename Cells::CellType; - - using execution_space = executionSpace; - - using memory_space = typename execution_space::memory_space; - - using HeadType = ViewType3D; - - using NextType = ViewType1D; - - class cellIterator - { - private: - HeadType head_; - - NextType next_; - - public: - - cellIterator(ViewType3D head, ViewType1D next) - : - head_(head), - next_(next) - {} - - INLINE_FUNCTION_HD - Cells cellsSize()const { - return Cells(head_.extent(0), head_.extent(1), head_.extent(2));} - - INLINE_FUNCTION_HD - int32 start(IndexType i, IndexType j, IndexType k)const { - return head_(i,j,k); } - - INLINE_FUNCTION_HD - int32 getNext(int32 n)const { - if(n<0) return n; - return next_(n); } - }; - -protected: - - int32 capacity_ = 1; - - ViewType3D head_; - - ViewType1D next_; - - bool nextOwner_ = true; - - // borrowed ownership - ViewType1D pointPosition_; - - using rangePolicyType = - Kokkos::RangePolicy< - Kokkos::IndexType, - Kokkos::Schedule, - execution_space>; - - INLINE_FUNCTION_H - void nullifyHead() - { - fill( - head_, - range(0,this->nx()), - range(0,this->ny()), - range(0,this->nz()), - static_cast(-1) - ); - } - - void nullifyNext(range nextRng) - { - if(!nextOwner_)return; - fill( - next_, - nextRng, - static_cast(-1) - ); - } - - void nullify() - { - nullifyHead(); - - nullifyNext(range(0,capacity_)); - } - - void nullify(range nextRng) - { - nullifyHead(); - - nullifyNext(nextRng); - } - - - void checkAllocateNext(int newCap) - { - if( capacity_ < newCap) - { - capacity_ = newCap; - if(!nextOwner_)return; - reallocNoInit(next_, capacity_); - } - } - - void allocateHead() - { - reallocNoInit(head_, this->nx(), this->ny(), this->nz()); - } - - - -public: - - TypeInfoNV("mapperNBS"); - - INLINE_FUNCTION_HD - mapperNBS(){} - - mapperNBS( - const box& domain, - real cellSize, - const ViewType1D& position, - bool nextOwner = true) - : - Cells(domain, cellSize), - pointPosition_(position), - head_( - "mapperNBS::head_", - this->nx(), - this->ny(), - this->nz() - ), - next_("mapperNBS::next_",1), //,position.size()), - nextOwner_(nextOwner) - { - checkAllocateNext(pointPosition_.size()); - } - - mapperNBS( - const box& domain, - int32 nx, - int32 ny, - int32 nz, - const ViewType1D& position, - bool nextOwner = true) - : - Cells(domain, nx, ny, nz), - pointPosition_(position), - head_("mapperNBS::head_",nx,ny,nz), - next_("mapperNBS::next_",1), - nextOwner_(nextOwner) - { - checkAllocateNext(pointPosition_.size()); - } - - - INLINE_FUNCTION_HD - mapperNBS(const mapperNBS&) = default; - - INLINE_FUNCTION_HD - mapperNBS& operator = (const mapperNBS&) = default; - - INLINE_FUNCTION_HD - ~mapperNBS()=default; - - //// - Methods - INLINE_FUNCTION_HD - auto capacity()const - { - return capacity_; - } - - cellIterator getCellIterator()const - { - return cellIterator(head_, next_); - } - - bool particlesCapcityChanged(int32 newCap) - { - checkAllocateNext(newCap); - return true; - } - - INLINE_FUNCTION_HD - auto& head() - { - return head_; - } - - INLINE_FUNCTION_HD - auto& next() - { - return next_; - } - - INLINE_FUNCTION_HD - const auto& head()const - { - return head_; - } - - INLINE_FUNCTION_HD - const auto& next()const - { - return next_; - } - - INLINE_FUNCTION_HD - auto& pointPosition() - { - return pointPosition_; - } - - INLINE_FUNCTION_H - void setNext(ViewType1D& next) - { - if(!nextOwner_) - { - next_ = next; - capacity_ = next.size(); - } - } - - - - // - build based on all points in active range - INLINE_FUNCTION_H - void build(range activeRange) - { - checkAllocateNext(activeRange.second); - nullify(activeRange); - - Cells cellIndex = static_cast(*this); - auto points = pointPosition_; - auto next = next_; - auto head = head_; - - rangePolicyType rPolicy(activeRange.first, activeRange.second); - - Kokkos::parallel_for( - "mapperNBS::build", - rPolicy, - LAMBDA_HD(int32 i){ - CellType ind = cellIndex.pointIndex(points[i]); - int32 old = Kokkos::atomic_exchange(&head(ind.x(), ind.y(), ind.z()), i); - next[i] = old; - }); - Kokkos::fence(); - } - - - template - INLINE_FUNCTION_H - void build(range activeRange, IncludeFunction incld) - { - checkAllocateNext(activeRange.second); - nullify(activeRange); - - Cells cellIndex = static_cast(*this); - auto points = pointPosition_; - auto next = next_; - auto head = head_; - - rangePolicyType rPolicy(activeRange.first, activeRange.second); - - Kokkos::parallel_for( - "mapperNBS::build_Include", - rPolicy, - LAMBDA_HD(int32 i){ - if( incld(i) ) - { - CellType ind = cellIndex.pointIndex(points[i]); - auto old = Kokkos::atomic_exchange(&head(ind.x(), ind.y(), ind.z()), i); - next[i] = old; - } - }); - Kokkos::fence(); - - } - - - INLINE_FUNCTION_H - void buildCheckInDomain(range activeRange) - { - checkAllocateNext(activeRange.second); - nullify(activeRange); - - Cells cellIndex = static_cast(*this); - auto points = pointPosition_; - auto next = next_; - auto head = head_; - - rangePolicyType rPolicy(activeRange.first, activeRange.second); - - Kokkos::parallel_for( - "mapperNBS::buildCheckInDomain", - rPolicy, - LAMBDA_HD(int32 i){ - CellType ind; - if( cellIndex.pointIndexInDomain(points[i], ind) ) - { - int32 old = Kokkos::atomic_exchange(&head(ind.x(), ind.y(), ind.z()), i); - next[i] = old; - } - }); - - Kokkos::fence(); - - } - - template - INLINE_FUNCTION_H - void buildCheckInDomain(range activeRange, IncludeFunction incld) - { - checkAllocateNext(activeRange.second); - nullify(activeRange); - - Cells cellIndex = static_cast(*this); - auto points = pointPosition_; - auto next = next_; - auto head = head_; - - rangePolicyType rPolicy(activeRange.first, activeRange.second); - - Kokkos::parallel_for( - "mapperNBS::buildCheckInDomain_Include", - rPolicy, - LAMBDA_HD(int32 i){ - CellType ind; - if( incld(i) && cellIndex.pointIndexInDomain(points[i], ind) ) - { - auto old = Kokkos::atomic_exchange(&head(ind.x(), ind.y(), ind.z()), i); - next[i] = old; - } - }); - Kokkos::fence(); - } - -}; - -} // pFlow - -#endif // __mapperNBS_hpp__ \ No newline at end of file diff --git a/src/Interaction/contactSearch/methods/multiGridNBS.hpp b/src/Interaction/contactSearch/methods/multiGridNBS.hpp deleted file mode 100644 index dbce390b..00000000 --- a/src/Interaction/contactSearch/methods/multiGridNBS.hpp +++ /dev/null @@ -1,213 +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 __multiGridNBS_hpp__ -#define __multiGridNBS_hpp__ - -#include "NBSLevels.hpp" - -namespace pFlow -{ - - -template -class multiGridNBS -{ -public: - - using NBSLevelsType = NBSLevels; - - using cellIterator = typename NBSLevelsType::cellIterator; - - using IdType = typename NBSLevelsType::IdType; - - using IndexType = typename NBSLevelsType::IndexType; - - using Cells = typename NBSLevelsType::Cells; - - using CellType = typename Cells::CellType; - - using execution_space = typename NBSLevelsType::execution_space; - - using memory_space = typename NBSLevelsType::memory_space; - - -protected: - - real sizeRatio_ = 1.0; - - int32 updateFrequency_= 1; - - int32 currentIter_ = 0; - - bool performedSearch_ = false; - - NBSLevelsType NBSLevels_; - -private: - - bool performSearch() - { - if(currentIter_ % updateFrequency_ == 0) - { - currentIter_++; - return true; - - }else - { - currentIter_++; - return false; - } - } - -public: - - TypeInfoNV("multiGridNBS"); - - multiGridNBS( - const dictionary& dict, - const box& domain, - real minSize, - real maxSize, - const ViewType1D& position, - const ViewType1D& diam) - : - sizeRatio_( - max( - dict.getVal("sizeRatio"), - 1.0 - )), - updateFrequency_( - max( - dict.getVal("updateFrequency"), - 1 - )), - NBSLevels_( - domain, - minSize, - maxSize, - sizeRatio_, - position, - diam) - {} - - INLINE_FUNCTION_HD - multiGridNBS(const multiGridNBS&) = default; - - INLINE_FUNCTION_HD - multiGridNBS& operator = (const multiGridNBS&) = default; - - INLINE_FUNCTION_HD - ~multiGridNBS()=default; - - //// - Methods - - bool enterBoadSearch()const - { - return currentIter_%updateFrequency_==0; - } - - bool performedSearch()const - { - return performedSearch_; - } - - int32 numLevels()const - { - return NBSLevels_.numLevels(); - } - - auto getCellsLevels()const - { - Vector cellsLvl("cells", numLevels(), numLevels(), RESERVE()); - - for(int32 lvl=0; lvl - bool broadSearch(PairsContainer& pairs, range activeRange, bool force=false) - { - - if(force) currentIter_ = 0; - performedSearch_ = false; - - if( !performSearch() ) return true; - - - NBSLevels_.build(activeRange); - - NBSLevels_.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 - bool broadSearch(PairsContainer& pairs, range activeRange, IncludeFunction incld, bool force = false) - { - if(force) currentIter_ = 0; - performedSearch_ = false; - - if( !performSearch() ) return true; - - NBSLevels_.build(activeRange, incld); - - NBSLevels_.findPairs(pairs); - - performedSearch_ = true; - return true; - } - -}; - -} - -#endif diff --git a/src/Interaction/contactSearch/methods/particleWallContactSearchs.cpp b/src/Interaction/contactSearch/methods/particleWallContactSearchs.cpp new file mode 100644 index 00000000..95a37309 --- /dev/null +++ b/src/Interaction/contactSearch/methods/particleWallContactSearchs.cpp @@ -0,0 +1,66 @@ +/*------------------------------- 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. + +-----------------------------------------------------------------------------*/ + + +template +pFlow::particleWallContactSearchs::particleWallContactSearchs +( + const dictionary &dict, + const box &domain, + real minSize, + real maxSize, + const ViewType1D &position, + const pFlagTypeDevice &flags, + const ViewType1D &diam +) +: + domainBox_(domain) +{} + +template +bool pFlow::particleWallContactSearchs::broadSearch +( + uint32 iter, + real t, + real dt, + csPairContainerType& ppPairs, + csPairContainerType& pwPairs, + const deviceViewType1D& pointPos, + const pFlagTypeDevice& flags, + const deviceViewType1D& diameter, + bool force +) +{ + + if(!getMethod().impl_broadSearch( + ppPairs, + pwPairs, + pointPos, + flags, + diameter)) + { + fatalErrorInFunction<< + "Error in performing particle-particle broadSearch in method"<< + getMethod().typeName()< +class particleWallContactSearchs +{ +public: + + using MethodType = method; + + using IndexType = uint32; + + using execution_space = DefaultExecutionSpace; + + using memory_space = typename execution_space::memory_space; + +private: + + // friend + friend MethodType; + + /// @brief box enclosing the simulation domain (local to processor) + box domainBox_; + +protected: + + inline + auto& getMethod() + { + return static_cast(*this); + } + + inline + const auto& getMethod()const + { + return static_cast(*this); + } + +public: + + particleWallContactSearchs( + const dictionary& dict, + const box& domain, + real minSize, + real maxSize, + const ViewType1D& position, + const pFlagTypeDevice &flags, + const ViewType1D& diam + ); + + bool broadSearch + ( + uint32 iter, + real t, + real dt, + csPairContainerType& ppPairs, + csPairContainerType& pwPairs, + const deviceViewType1D& pointPos, + const pFlagTypeDevice& flags, + const deviceViewType1D& diameter, + bool force = false + ); + + real sizeRatio()const + { + return getMethod().sizeRatio(); + } + + real cellExtent()const + { + return getMethod().cellExtent(); + } + +}; + + +} // pFlow + +#include "particleWallContactSearchs.cpp" + +#endif //__particleWallContactSearchs_hpp__ \ No newline at end of file diff --git a/src/Interaction/contactSearch/wallMappings/cellMapping.hpp b/src/Interaction/contactSearch/wallMappings/cellMapping.hpp deleted file mode 100644 index 5a10c248..00000000 --- a/src/Interaction/contactSearch/wallMappings/cellMapping.hpp +++ /dev/null @@ -1,150 +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 __cellMapping_hpp__ -#define __cellMapping_hpp__ - -#include "cellsWallLevel0.hpp" -#include "dictionary.hpp" - - -namespace pFlow -{ - -template< - typename executionSpace - > -class cellMapping -{ -public: - - using cellsWallLevel0Type = cellsWallLevel0; - - using IdType = typename cellsWallLevel0Type::IdType; - - using IndexType = typename cellsWallLevel0Type::IndexType; - - using Cells = typename cellsWallLevel0Type::Cells; - - using CellType = typename Cells::CellType; - - using execution_space = typename cellsWallLevel0Type::execution_space; - - using memory_space = typename cellsWallLevel0Type::memory_space; - - using iBoxType = iBox; - - -protected: - - // - update frequency - int32 updateFrequency_=1; - - real cellExtent_; - - int32 currentIter_ = 0; - - /// a broad search has been occured during last pass? - bool performedSearch_ = false; - - cellsWallLevel0Type cellsWallLevle_; - -private: - - bool performSearch() - { - if(currentIter_ % updateFrequency_ == 0) - { - currentIter_++; - return true; - - }else - { - currentIter_++; - return false; - } - } - -public: - - TypeInfoNV("cellMapping"); - - cellMapping( - const dictionary& dict, - int32 numLevels, - const Vector& ppCells, - int32 numPoints, - int32 numElements, - const ViewType1D& points, - const ViewType1D& vertices - ) - : - updateFrequency_( - max( - dict.getValOrSet( - "updateFrequency", - 1), - 1)), - cellExtent_( - max( - dict.getValOrSet( - "cellExtent", - 0.5), - 0.5)), - cellsWallLevle_( - ppCells[0], - cellExtent_, - numPoints, - numElements, - points, - vertices - ) - {} - - - bool enterBoadSearch()const - { - return currentIter_%updateFrequency_==0; - } - - bool performedSearch()const - { - return performedSearch_; - } - - template - bool broadSearch(PairsContainer& pairs, particleMapType& particleMap, bool force=false) - { - if(force) currentIter_ = 0; - performedSearch_= false; - if(!performSearch())return true; - - cellsWallLevle_.broadSearch(pairs, particleMap); - - performedSearch_ = true; - return true; - } - -}; // cellMapping - -} // pFlow - - -#endif diff --git a/src/Interaction/contactSearch/wallMappings/cellsWallLevel0.hpp b/src/Interaction/contactSearch/wallMappings/cellsWallLevel0.hpp deleted file mode 100644 index 65034507..00000000 --- a/src/Interaction/contactSearch/wallMappings/cellsWallLevel0.hpp +++ /dev/null @@ -1,285 +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 __cellsWallLevel0_hpp__ -#define __cellsWallLevel0_hpp__ - -#include "types.hpp" -#include "KokkosTypes.hpp" -#include "cells.hpp" -#include "iBox.hpp" - - - -namespace pFlow -{ - -template< - typename executionSpace - > -class cellsWallLevel0 -: - public cells -{ -public: - - using IdType = int32; - - using IndexType = int32; - - using Cells = cells; - - using CellType = typename Cells::CellType; - - using execution_space = executionSpace; - - using memory_space = typename execution_space::memory_space; - - using iBoxType = iBox; - - class TagFindCellRange2{}; - -protected: - - // - box extent - real cellExtent_ = 0.5; - - // - number of triangle elements - int32 numElements_ = 0; - - // - number of points - int32 numPoints_ = 0; - - // - ref to vectices (borrowed) - ViewType1D vertices_; - - // - ref to points in the trisurface (borrowed) - ViewType1D points_; - - // cell range of element/triangle bounding box - ViewType1D elementBox_; - - - using tpPWContactSearch = Kokkos::TeamPolicy< - execution_space, - Kokkos::Schedule, - Kokkos::IndexType - >; - - using rpFindCellRange2Type = - Kokkos::RangePolicy>; - - - FUNCTION_H - void allocateArrays() - { - reallocNoInit( elementBox_, numElements_); - } - -public: - - TypeInfoNV("cellsWallLevel0"); - - INLINE_FUNCTION_HD - cellsWallLevel0(){} - - FUNCTION_H - cellsWallLevel0( - const Cells& ppCells, - real cellExtent, - int32 numPoints, - int32 numElements, - const ViewType1D& points, - const ViewType1D& vertices - ) - : - Cells(ppCells), - cellExtent_( max(cellExtent, 0.5 ) ), - numElements_(numElements), - numPoints_(numPoints), - vertices_(vertices), - points_(points) - { - - allocateArrays(); - } - - - // - host call - // reset triangle elements if they have changed - bool resetElements( - int32 numElements, - int32 numPoints, - ViewType1D& points, - ViewType1D& vertices ) - { - - numElements_ = numElements; - numPoints_ = numPoints; - points_ = points; - vertices_ = vertices; - - allocateArrays(); - - return true; - } - - INLINE_FUNCTION_HD - iBoxType elementBox(int32 i)const - { - return elementBox_[i]; - } - - INLINE_FUNCTION_HD - int32 numElements()const - { - return numElements_; - } - - - - template - bool broadSearch(PairsContainer& pairs, particleMapType& particleMap) - { - - // map walls onto the cells - this->build(); - - this->particleWallFindPairs(pairs, particleMap); - - return true; - } - - bool build() - { - Kokkos::parallel_for( - "cellsSimple::findcellrange2", - rpFindCellRange2Type(0,numElements_), - *this); - Kokkos::fence(); - return true; - } - - template - bool particleWallFindPairs(PairsContainer& pairs, particleMapType& particleMap) - { - - int32 getFull = 1; - - while (getFull) - { - - getFull = findPairsElementRangeCount(pairs, particleMap.getCellIterator(0)); - - if(getFull) - { - // - resize the container - // note that getFull now shows the number of failed insertions. - uint32 len = max(getFull, 50); - auto oldCap = pairs.capacity(); - pairs.increaseCapacityBy(len); - - INFORMATION<<"Contact pair container capacity increased from "<< - oldCap << " to " - << pairs.capacity() <<" in cellsWallLevel0."< - int32 findPairsElementRangeCount(PairsContainer& pairs, CellIteratorType cellIter) - { - int32 getFull =0; - - const auto pwPairs = pairs; - const auto elementBox = elementBox_; - - Kokkos::parallel_reduce( - "cellsSimple::findPairsElementRangeModified2", - tpPWContactSearch(numElements_, Kokkos::AUTO), - LAMBDA_HD( - const typename tpPWContactSearch::member_type & teamMember, - int32& valueToUpdate){ - - const int32 iTri = teamMember.league_rank(); - - const auto triBox = elementBox[iTri]; - - int32 getFull2 = 0; - - auto bExtent = boxExtent(triBox); - int32 numCellBox = bExtent.x()*bExtent.y()*bExtent.z(); - - Kokkos::parallel_reduce( - Kokkos::TeamThreadRange( teamMember, numCellBox ), - [&] ( const int32 linIndex, int32 &innerUpdate ) - { - - CellType cell; - indexToCell(linIndex, triBox, cell); - - int32 n = cellIter.start(cell.x(),cell.y(),cell.z()); - - while( n>-1) - { - // id is wall id the pair is (particle id, wall id) - if( pairs.insert(static_cast(n), iTri) < 0 ) - innerUpdate++; - n = cellIter.getNext(n); - } - - }, - getFull2 - ); - - if ( teamMember.team_rank() == 0 ) valueToUpdate += getFull2; - }, - getFull - ); - - return getFull; - } - - INLINE_FUNCTION_HD - void operator()(TagFindCellRange2, int32 i) const - { - auto v = vertices_[i]; - auto p1 = points_[v.x()]; - auto p2 = points_[v.y()]; - auto p3 = points_[v.z()]; - - realx3 minP, maxP; - - this->extendBox(p1, p2, p3, cellExtent_, minP, maxP); - elementBox_[i] = iBoxType(this->pointIndex(minP), this->pointIndex(maxP)); - - } - -}; // cellsWallLevel0 - -} // pFlow - - -#endif // __cellsWallLevel0_hpp__ diff --git a/src/Interaction/contactSearch/wallMappings/cellsWallLevels.hpp b/src/Interaction/contactSearch/wallMappings/cellsWallLevels.hpp deleted file mode 100644 index 9f2c80ec..00000000 --- a/src/Interaction/contactSearch/wallMappings/cellsWallLevels.hpp +++ /dev/null @@ -1,152 +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 __cellsWallLevels_hpp__ -#define __cellsWallLevels_hpp__ - -#include "cellsWallLevel0.hpp" - -namespace pFlow -{ - -template< - typename executionSpace - > -class cellsWallLevels -{ -public: - - using cellsWallLevel0Type = cellsWallLevel0; - - using IdType = typename cellsWallLevel0Type::IdType; - - using IndexType = typename cellsWallLevel0Type::IndexType; - - using Cells = typename cellsWallLevel0Type::Cells; - - using CellType = typename Cells::CellType; - - using execution_space = typename cellsWallLevel0Type::execution_space; - - using memory_space = typename cellsWallLevel0Type::memory_space; - - using iBoxType = iBox; - -protected: - - int32 numLevles_=1; - - - Vector cellsWallLevels_; - -public: - - TypeInfoNV("cellsWallLevels"); - - FUNCTION_H - cellsWallLevels( - int32 numLevels, - const Vector& cellsLevels, - real cellExtent, - int32 numPoints, - int32 numElements, - const ViewType1D& points, - const ViewType1D& vertices - ) - : - numLevles_(numLevels), - cellsWallLevels_("cellsWallLevels",numLevels, numLevels, RESERVE()) - { - - - - for(int32 lvl=0; lvl - bool broadSearch(PairsContainer& pairs, particleMapType& particleMap) - { - - // map walls onto the cells - for(int32 lvl=0; lvlparticleWallFindPairs(pairs, particleMap); - - return true; - } - - template - bool particleWallFindPairs(PairsContainer& pairs, particleMapType& particleMap) - { - - int32 getFull = 1; - - while (getFull) - { - getFull = 0; - for(int32 lvl=0; lvl -class multiGridMapping -{ -public: - - using CellsWallLevelType = cellsWallLevels; - - using IdType = typename CellsWallLevelType::IdType; - - using IndexType = typename CellsWallLevelType::IndexType; - - using Cells = typename CellsWallLevelType::Cells; - - using CellType = typename Cells::CellType; - - using execution_space = typename CellsWallLevelType::execution_space; - - using memory_space = typename CellsWallLevelType::memory_space; - - using iBoxType = iBox; - - -protected: - - // - update frequency - int32 updateFrequency_=1; - - real cellExtent_; - - int32 currentIter_ = 0; - - /// a broad search has been occured during last pass? - bool performedSearch_ = false; - - CellsWallLevelType cellsWallLevle_; - -private: - - bool performSearch() - { - if(currentIter_ % updateFrequency_ == 0) - { - currentIter_++; - return true; - - }else - { - currentIter_++; - return false; - } - } - -public: - - TypeInfoNV("multiGridMapping"); - - multiGridMapping( - const dictionary& dict, - int32 numLevels, - const Vector& ppCells, - int32 numPoints, - int32 numElements, - const ViewType1D& points, - const ViewType1D& vertices - ) - : - updateFrequency_( - max( - dict.getVal("updateFrequency"), - 1)), - cellExtent_( - max( - dict.getVal("cellExtent"), - 0.5)), - cellsWallLevle_( - numLevels, - ppCells, - cellExtent_, - numPoints, - numElements, - points, - vertices - ) - { - - REPORT(3)<<"Multi-grid wall mapping with "<< - yellowText(numLevels)<<" levels has been created."< - bool broadSearch(PairsContainer& pairs, particleMapType& particleMap, bool force=false) - { - if(force) currentIter_ = 0; - performedSearch_= false; - if(!performSearch())return true; - - - cellsWallLevle_.broadSearch(pairs, particleMap); - - - performedSearch_ = true; - return true; - } - -}; // multiGridMapping - -} // pFlow - - -#endif diff --git a/src/Interaction/grainInteraction/boundaries/boundaryGrainInteraction/boundaryGrainInteraction.cpp b/src/Interaction/grainInteraction/boundaries/boundaryGrainInteraction/boundaryGrainInteraction.cpp new file mode 100644 index 00000000..a2949227 --- /dev/null +++ b/src/Interaction/grainInteraction/boundaries/boundaryGrainInteraction/boundaryGrainInteraction.cpp @@ -0,0 +1,104 @@ +#include "boundarySphereInteraction.hpp" +/*------------------------------- 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. + +-----------------------------------------------------------------------------*/ + +template +void pFlow::boundaryGrainInteraction::allocatePPPairs() +{ + ppPairs_.reset(nullptr); + ppPairs_ = makeUnique(1); +} + +template +void pFlow::boundaryGrainInteraction::allocatePWPairs() +{ + pwPairs_.reset(nullptr); + pwPairs_ = makeUnique(1); +} + + +template +pFlow::boundaryGrainInteraction::boundaryGrainInteraction( + const boundaryBase &boundary, + const grainParticles &grnPrtcls, + const GeometryMotionModel &geomMotion) + : generalBoundary(boundary, grnPrtcls.pStruct(), "", ""), + geometryMotion_(geomMotion), + grnParticles_(grnPrtcls) +{ +} + +template +pFlow::uniquePtr> +pFlow::boundaryGrainInteraction::create( + const boundaryBase &boundary, + const grainParticles &grnPrtcls, + const GeometryMotionModel &geomMotion) +{ + word cfTypeName = ContactForceModel::TYPENAME(); + word gmTypeName = MotionModel::TYPENAME(); + word bType = boundary.type(); + + word boundaryTypeName = angleBracketsNames3( + "boundaryGrainInteraction", + bType, + cfTypeName, + gmTypeName); + + word altBTypeName = angleBracketsNames2( + "boundaryGrainInteraction", + cfTypeName, + gmTypeName); + + if (boundaryBasevCtorSelector_.search(boundaryTypeName)) + { + pOutput.space(4) << "Creating boundry type " << Green_Text(boundaryTypeName) << + " for boundary " << boundary.name() << " . . ." << END_REPORT; + return boundaryBasevCtorSelector_[boundaryTypeName]( + boundary, + grnPrtcls, + geomMotion); + } + else if(boundaryBasevCtorSelector_[altBTypeName]) + { + // if boundary condition is not implemented, the default is used + + pOutput.space(4) << "Creating boundry type " << Green_Text(altBTypeName) << + " for boundary " << boundary.name() << " . . ." << END_REPORT; + return boundaryBasevCtorSelector_[altBTypeName]( + boundary, + grnPrtcls, + geomMotion); + } + else + { + printKeys + ( + fatalError << "Ctor Selector "<< boundaryTypeName<< + " and "<< altBTypeName << " do not exist. \n" + <<"Avaiable ones are: \n\n" + , + boundaryBasevCtorSelector_ + ); + fatalExit; + } + + return nullptr; +} diff --git a/src/Interaction/grainInteraction/boundaries/boundaryGrainInteraction/boundaryGrainInteraction.hpp b/src/Interaction/grainInteraction/boundaries/boundaryGrainInteraction/boundaryGrainInteraction.hpp new file mode 100644 index 00000000..4800194c --- /dev/null +++ b/src/Interaction/grainInteraction/boundaries/boundaryGrainInteraction/boundaryGrainInteraction.hpp @@ -0,0 +1,186 @@ +/*------------------------------- 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 __boundaryGrainInteraction_hpp__ +#define __boundaryGrainInteraction_hpp__ + +#include "virtualConstructor.hpp" +#include "generalBoundary.hpp" +#include "sortedContactList.hpp" +#include "grainParticles.hpp" + +namespace pFlow +{ + +template +class boundaryGrainInteraction +: + public generalBoundary +{ +public: + + using BoundaryGrainInteractionType + = boundaryGrainInteraction; + + using GeometryMotionModel = geometryMotionModel; + + using ContactForceModel = contactForceModel; + + using MotionModel = typename geometryMotionModel::MotionModel; + + using ModelStorage = typename ContactForceModel::contactForceStorage; + + using IdType = uint32; + + using IndexType = uint32; + + using ContactListType = + sortedContactList; + +private: + + const GeometryMotionModel& geometryMotion_; + + /// const reference to sphere particles + const grainParticles& grnParticles_; + + uniquePtr ppPairs_ = nullptr; + + uniquePtr pwPairs_ = nullptr; + +protected: + + void allocatePPPairs(); + + void allocatePWPairs(); + +public: + + TypeInfoTemplate12("boundaryGrainInteraction", ContactForceModel, MotionModel); + + boundaryGrainInteraction( + const boundaryBase& boundary, + const grainParticles& grnPrtcls, + const GeometryMotionModel& geomMotion); + + create_vCtor + ( + BoundaryGrainInteractionType, + boundaryBase, + ( + const boundaryBase& boundary, + const grainParticles& grnPrtcls, + const GeometryMotionModel& geomMotion + ), + (boundary, grnPrtcls, geomMotion) + ); + + add_vCtor + ( + BoundaryGrainInteractionType, + BoundaryGrainInteractionType, + boundaryBase + ); + + ~boundaryGrainInteraction()override=default; + + const auto& grnParticles()const + { + return grnParticles_; + } + + const auto& geometryMotion()const + { + return geometryMotion_; + } + + ContactListType& ppPairs() + { + return ppPairs_(); + } + + const ContactListType& ppPairs()const + { + return ppPairs_(); + } + + ContactListType& pwPairs() + { + return pwPairs_(); + } + + const ContactListType& pwPairs()const + { + return pwPairs_(); + } + + bool ppPairsAllocated()const + { + if( ppPairs_)return true; + return false; + } + + bool pwPairsAllocated()const + { + if( pwPairs_)return true; + return false; + } + + virtual + bool grainGrainInteraction( + real dt, + const ContactForceModel& cfModel, + uint32 step) + { + // for default boundary, no thing to be done + return false; + } + + + + bool hearChanges + ( + real t, + real dt, + uint32 iter, + const message& msg, + const anyList& varList + ) override + { + + pOutput<<"Function (hearChanges in boundarySphereInteractions)is not implmented Message "<< + msg <boundaryName() <<" type "<< this->type()< create( + const boundaryBase& boundary, + const grainParticles& sphPrtcls, + const GeometryMotionModel& geomMotion + ); + +}; + +} + +#include "boundaryGrainInteraction.cpp" + +#endif //__boundaryGrainInteraction_hpp__ diff --git a/src/Interaction/grainInteraction/boundaries/boundaryGrainInteractionList.cpp b/src/Interaction/grainInteraction/boundaries/boundaryGrainInteractionList.cpp new file mode 100644 index 00000000..7875210d --- /dev/null +++ b/src/Interaction/grainInteraction/boundaries/boundaryGrainInteractionList.cpp @@ -0,0 +1,23 @@ + + +template +pFlow::boundaryGrainInteractionList::boundaryGrainInteractionList +( + const grainParticles &grnPrtcls, + const gMModel &geomMotion +) +: + ListPtr>(6), + boundaries_(grnPrtcls.pStruct().boundaries()) +{ + //gSettings::sleepMiliSeconds(1000*pFlowProcessors().localRank()); + for(uint32 i=0; i<6; i++) + { + this->set( + i, + boundaryGrainInteraction::create( + boundaries_[i], + grnPrtcls, + geomMotion)); + } +} \ No newline at end of file diff --git a/src/Interaction/grainInteraction/boundaries/boundaryGrainInteractionList.hpp b/src/Interaction/grainInteraction/boundaries/boundaryGrainInteractionList.hpp new file mode 100644 index 00000000..ed4cabc8 --- /dev/null +++ b/src/Interaction/grainInteraction/boundaries/boundaryGrainInteractionList.hpp @@ -0,0 +1,40 @@ +#ifndef __boundaryGrainInteractionList_hpp__ +#define __boundaryGrainInteractionList_hpp__ + + +#include "boundaryList.hpp" +#include "ListPtr.hpp" +#include "boundaryGrainInteraction.hpp" + + +namespace pFlow +{ + + +template +class boundaryGrainInteractionList +: + public ListPtr> +{ +private: + + const boundaryList& boundaries_; + +public: + + boundaryGrainInteractionList( + const grainParticles& grnPrtcls, + const geometryMotionModel& geomMotion + ); + + ~boundaryGrainInteractionList()=default; + +}; + + + +} + +#include "boundaryGrainInteractionList.cpp" + +#endif //__boundaryGrainInteractionList_hpp__ \ No newline at end of file diff --git a/src/Interaction/grainInteraction/boundaries/createBoundaryGrainInteraction.hpp b/src/Interaction/grainInteraction/boundaries/createBoundaryGrainInteraction.hpp new file mode 100644 index 00000000..12049af0 --- /dev/null +++ b/src/Interaction/grainInteraction/boundaries/createBoundaryGrainInteraction.hpp @@ -0,0 +1,31 @@ +/*------------------------------- 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 "boundaryGrainInteraction.hpp" +#include "periodicBoundaryGrainInteraction.hpp" + +#define createBoundaryGrainInteraction(ForceModel,GeomModel) \ + template class pFlow::boundaryGrainInteraction< \ + ForceModel, \ + GeomModel>; \ + \ + template class pFlow::periodicBoundaryGrainInteraction< \ + ForceModel, \ + GeomModel>; + diff --git a/src/Interaction/grainInteraction/boundaries/periodicBoundaryGrainInteraction/periodicBoundaryGrainInteraction.cpp b/src/Interaction/grainInteraction/boundaries/periodicBoundaryGrainInteraction/periodicBoundaryGrainInteraction.cpp new file mode 100644 index 00000000..0eedf973 --- /dev/null +++ b/src/Interaction/grainInteraction/boundaries/periodicBoundaryGrainInteraction/periodicBoundaryGrainInteraction.cpp @@ -0,0 +1,70 @@ +/*------------------------------- 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 "periodicBoundarySIKernels.hpp" + +template +pFlow::periodicBoundaryGrainInteraction::periodicBoundaryGrainInteraction( + const boundaryBase &boundary, + const grainParticles &grnPrtcls, + const GeometryMotionModel &geomMotion) + : boundaryGrainInteraction(boundary, grnPrtcls, geomMotion), + transferVec_(boundary.mirrorBoundary().displacementVectroToMirror()) +{ + if(boundary.thisBoundaryIndex()%2==1) + { + masterInteraction_ = true; + this->allocatePPPairs(); + this->allocatePWPairs(); + + } + else + { + masterInteraction_ = false; + } +} + +template +bool pFlow::periodicBoundaryGrainInteraction::grainGrainInteraction +( + real dt, + const ContactForceModel &cfModel, + uint32 step +) +{ + if(!masterInteraction_) return false; + + pFlow::periodicBoundarySIKernels::grainGrainInteraction( + dt, + this->ppPairs(), + cfModel, + transferVec_, + this->boundary().thisPoints(), + this->mirrorBoundary().thisPoints(), + this->grnParticles().diameter().deviceViewAll(), + this->grnParticles().coarseGrainFactor().deviceViewAll(), + this->grnParticles().propertyId().deviceViewAll(), + this->grnParticles().velocity().deviceViewAll(), + this->grnParticles().rVelocity().deviceViewAll(), + this->grnParticles().contactForce().deviceViewAll(), + this->grnParticles().contactTorque().deviceViewAll()); + + return false; +} \ No newline at end of file diff --git a/src/Interaction/grainInteraction/boundaries/periodicBoundaryGrainInteraction/periodicBoundaryGrainInteraction.hpp b/src/Interaction/grainInteraction/boundaries/periodicBoundaryGrainInteraction/periodicBoundaryGrainInteraction.hpp new file mode 100644 index 00000000..e9148c9d --- /dev/null +++ b/src/Interaction/grainInteraction/boundaries/periodicBoundaryGrainInteraction/periodicBoundaryGrainInteraction.hpp @@ -0,0 +1,96 @@ +/*------------------------------- 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 __periodicBoundaryGrainInteraction_hpp__ +#define __periodicBoundaryGrainInteraction_hpp__ + +#include "boundaryGrainInteraction.hpp" + +namespace pFlow +{ + +template +class periodicBoundaryGrainInteraction +: + public boundaryGrainInteraction +{ +public: + + using PBSInteractionType = + periodicBoundaryGrainInteraction; + + using BSInteractionType = + boundaryGrainInteraction; + + using GeometryMotionModel = typename BSInteractionType::GeometryMotionModel; + + using ContactForceModel = typename BSInteractionType::ContactForceModel; + + using MotionModel = typename geometryMotionModel::MotionModel; + + using ModelStorage = typename ContactForceModel::contactForceStorage; + + using IdType = typename BSInteractionType::IdType; + + using IndexType = typename BSInteractionType::IndexType; + + using ContactListType = typename BSInteractionType::ContactListType; + +private: + + realx3 transferVec_; + + bool masterInteraction_; +public: + + TypeInfoTemplate22("boundaryGrainInteraction", "periodic",ContactForceModel, MotionModel); + + + periodicBoundaryGrainInteraction( + const boundaryBase& boundary, + const grainParticles& grnPrtcls, + const GeometryMotionModel& geomMotion + ); + + add_vCtor + ( + BSInteractionType, + PBSInteractionType, + boundaryBase + ); + + ~periodicBoundaryGrainInteraction()override = default; + + + + + bool grainGrainInteraction( + real dt, + const ContactForceModel& cfModel, + uint32 step)override; + +}; + +} + +#include "periodicBoundaryGrainInteraction.cpp" + + +#endif //__periodicBoundaryGrainInteraction_hpp__ \ No newline at end of file diff --git a/src/Interaction/grainInteraction/boundaries/periodicBoundaryGrainInteraction/periodicBoundarySIKernels.hpp b/src/Interaction/grainInteraction/boundaries/periodicBoundaryGrainInteraction/periodicBoundarySIKernels.hpp new file mode 100644 index 00000000..6a8a618e --- /dev/null +++ b/src/Interaction/grainInteraction/boundaries/periodicBoundaryGrainInteraction/periodicBoundarySIKernels.hpp @@ -0,0 +1,121 @@ + +namespace pFlow::periodicBoundarySIKernels +{ + +template +inline +void grainGrainInteraction +( + real dt, + const ContactListType& cntctList, + const ContactForceModel& forceModel, + const realx3& transferVec, + const deviceScatteredFieldAccess& thisPoints, + const deviceScatteredFieldAccess& mirrorPoints, + const deviceViewType1D& diam, + const deviceViewType1D& coarseGrainFactor, + const deviceViewType1D& propId, + const deviceViewType1D& vel, + const deviceViewType1D& rVel, + const deviceViewType1D& cForce, + const deviceViewType1D& cTorque +) +{ + + using ValueType = typename ContactListType::ValueType; + uint32 ss = cntctList.size(); + uint32 lastItem = cntctList.loopCount(); + if(lastItem == 0u)return; + + Kokkos::parallel_for( + "pFlow::periodicBoundarySIKernels::grainGrainInteraction", + deviceRPolicyDynamic(0,lastItem), + LAMBDA_HD(uint32 n) + { + + if(!cntctList.isValid(n))return; + + auto [i,j] = cntctList.getPair(n); + uint32 ind_i = thisPoints.index(i); + uint32 ind_j = mirrorPoints.index(j); + + real Ri = 0.5*diam[ind_i]; + real Rj = 0.5*diam[ind_j]; + real cGFi = coarseGrainFactor[ind_i]; + real cGFj = coarseGrainFactor[ind_j]; + realx3 xi = thisPoints.field()[ind_i]; + realx3 xj = mirrorPoints.field()[ind_j]+transferVec; + real dist = length(xj-xi); + real ovrlp = (Ri+Rj) - dist; + + if( ovrlp >0.0 ) + { + auto Nij = (xj-xi)/dist; + auto wi = rVel[ind_i]; + auto wj = rVel[ind_j]; + auto Vr = vel[ind_i] - vel[ind_j] + cross((Ri*wi+Rj*wj), Nij); + + auto history = cntctList.getValue(n); + + int32 propId_i = propId[ind_i]; + int32 propId_j = propId[ind_j]; + + realx3 FCn, FCt, Mri, Mrj, Mij, Mji; + + // calculates contact force + forceModel.contactForce( + dt, i, j, + propId_i, propId_j, + Ri, Rj, cGFi , cGFj , + ovrlp, + Vr, Nij, + history, + FCn, FCt); + + forceModel.rollingFriction( + dt, i, j, + propId_i, propId_j, + Ri, Rj, cGFi , cGFj , + wi, wj, + Nij, + FCn, + Mri, Mrj); + + auto M = cross(Nij,FCt); + Mij = Ri*M+Mri; + Mji = Rj*M+Mrj; + + auto FC = FCn + FCt; + + + Kokkos::atomic_add(&cForce[ind_i].x_,FC.x_); + Kokkos::atomic_add(&cForce[ind_i].y_,FC.y_); + Kokkos::atomic_add(&cForce[ind_i].z_,FC.z_); + + Kokkos::atomic_add(&cForce[ind_j].x_,-FC.x_); + Kokkos::atomic_add(&cForce[ind_j].y_,-FC.y_); + Kokkos::atomic_add(&cForce[ind_j].z_,-FC.z_); + + Kokkos::atomic_add(&cTorque[ind_i].x_, Mij.x_); + Kokkos::atomic_add(&cTorque[ind_i].y_, Mij.y_); + Kokkos::atomic_add(&cTorque[ind_i].z_, Mij.z_); + + Kokkos::atomic_add(&cTorque[ind_j].x_, Mji.x_); + Kokkos::atomic_add(&cTorque[ind_j].y_, Mji.y_); + Kokkos::atomic_add(&cTorque[ind_j].z_, Mji.z_); + + + cntctList.setValue(n,history); + + } + else + { + cntctList.setValue(n, ValueType()); + } + + }); + Kokkos::fence(); +} + + +} //pFlow::periodicBoundarySIKernels \ No newline at end of file diff --git a/src/Interaction/grainInteraction/grainInteraction/grainInteraction.cpp b/src/Interaction/grainInteraction/grainInteraction/grainInteraction.cpp new file mode 100644 index 00000000..65c84a77 --- /dev/null +++ b/src/Interaction/grainInteraction/grainInteraction/grainInteraction.cpp @@ -0,0 +1,359 @@ +/*------------------------------- 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. + +-----------------------------------------------------------------------------*/ + +template class cLT> +bool pFlow::grainInteraction::createGrainInteraction() +{ + + realVector_D rhoD("densities", this->densities()); + + auto modelDict = this->subDict("model"); + + forceModel_ = makeUnique( + this->numMaterials(), + rhoD.deviceView(), + modelDict ); + + + uint32 nPrtcl = grnParticles_.size(); + + contactSearch_ = contactSearch::create( + subDict("contactSearch"), + grnParticles_.extendedDomain().domainBox(), + grnParticles_, + geometryMotion_, + timers()); + + ppContactList_ = makeUnique(nPrtcl+1); + + pwContactList_ = makeUnique(nPrtcl/5+1); + + return true; +} + + +template class cLT> +bool pFlow::grainInteraction::grainGrainInteraction() +{ + auto lastItem = ppContactList_().loopCount(); + + // create the kernel functor + pFlow::grainInteractionKernels::ppInteractionFunctor + ppInteraction( + this->dt(), + this->forceModel_(), + ppContactList_(), // to be read + grnParticles_.diameter().deviceViewAll(), + grnParticles_.coarseGrainFactor().deviceViewAll(), + grnParticles_.propertyId().deviceViewAll(), + grnParticles_.pointPosition().deviceViewAll(), + grnParticles_.velocity().deviceViewAll(), + grnParticles_.rVelocity().deviceViewAll(), + grnParticles_.contactForce().deviceViewAll(), + grnParticles_.contactTorque().deviceViewAll() + ); + + Kokkos::parallel_for( + "ppInteraction", + rpPPInteraction(0,lastItem), + ppInteraction + ); + + Kokkos::fence(); + + return true; +} + + +template class cLT> +bool pFlow::grainInteraction::grainWallInteraction() +{ + + uint32 lastItem = pwContactList_().loopCount(); + uint32 iter = this->currentIter(); + real t = this->currentTime(); + real dt = this->dt(); + + pFlow::grainInteractionKernels::pwInteractionFunctor + pwInteraction( + dt, + this->forceModel_(), + pwContactList_(), + geometryMotion_.getTriangleAccessor(), + geometryMotion_.getModel(iter, t, dt) , + grnParticles_.diameter().deviceViewAll() , + grnParticles_.coarseGrainFactor().deviceViewAll() , + grnParticles_.propertyId().deviceViewAll(), + grnParticles_.pointPosition().deviceViewAll(), + grnParticles_.velocity().deviceViewAll(), + grnParticles_.rVelocity().deviceViewAll() , + grnParticles_.contactForce().deviceViewAll(), + grnParticles_.contactTorque().deviceViewAll() , + geometryMotion_.triMotionIndex().deviceViewAll(), + geometryMotion_.propertyId().deviceViewAll(), + geometryMotion_.contactForceWall().deviceViewAll() + ); + + Kokkos::parallel_for( + "", + rpPWInteraction(0,lastItem), + pwInteraction + ); + + + Kokkos::fence(); + + return true; +} + + +template class cLT> +pFlow::grainInteraction::grainInteraction +( + systemControl& control, + const particles& prtcl, + const geometry& geom +) +: + interaction(control, prtcl, geom), + geometryMotion_(dynamic_cast(geom)), + grnParticles_(dynamic_cast(prtcl)), + boundaryInteraction_(grnParticles_,geometryMotion_), + ppInteractionTimer_("grain-graine interaction (internal)", &this->timers()), + pwInteractionTimer_("grain-wall interaction (internal)", &this->timers()), + boundaryInteractionTimer_("grain-grain interaction (boundary)",&this->timers()), + contactListMangementTimer_("list management (interal)", &this->timers()), + contactListMangementBoundaryTimer_("list management (boundary)", &this->timers()) +{ + + if(!createGrainInteraction()) + { + fatalExit; + } + + for(uint32 i=0; i<6; i++) + { + activeBoundaries_[i] = boundaryInteraction_[i].ppPairsAllocated(); + } +} + +template class cLT> +bool pFlow::grainInteraction::beforeIteration() +{ + return true; +} + +template class cLT> +bool pFlow::grainInteraction::iterate() +{ + + timeInfo ti = this->TimeInfo(); + auto iter = ti.iter(); + auto t = ti.t(); + auto dt = ti.dt(); + + auto& contactSearchRef = contactSearch_(); + + bool broadSearch = contactSearchRef.enterBroadSearch(ti); + bool broadSearchBoundary = contactSearchRef.enterBroadSearchBoundary(ti); + + /// update boundaries of the fields that are being used by inreaction + grnParticles_.diameter().updateBoundaries(DataDirection::SlaveToMaster); + grnParticles_.velocity().updateBoundaries(DataDirection::SlaveToMaster); + grnParticles_.rVelocity().updateBoundaries(DataDirection::SlaveToMaster); + grnParticles_.propertyId().updateBoundaries(DataDirection::SlaveToMaster); + + /// lists + if(broadSearch) + { + contactListMangementTimer_.start(); + ComputationTimer().start(); + ppContactList_().beforeBroadSearch(); + pwContactList_().beforeBroadSearch(); + ComputationTimer().end(); + contactListMangementTimer_.pause(); + } + + if(broadSearchBoundary) + { + contactListMangementBoundaryTimer_.start(); + ComputationTimer().start(); + for(uint32 i=0; i<6u; i++) + { + if(activeBoundaries_[i]) + { + auto& BI = boundaryInteraction_[i]; + BI.ppPairs().beforeBroadSearch(); + BI.pwPairs().beforeBroadSearch(); + } + } + ComputationTimer().end(); + contactListMangementBoundaryTimer_.pause(); + } + + if( grnParticles_.numActive()<=0)return true; + + ComputationTimer().start(); + if( !contactSearchRef.broadSearch( + ti, + ppContactList_(), + pwContactList_()) ) + { + fatalErrorInFunction<< + "unable to perform broadSearch.\n"; + fatalExit; + } + + for(uint32 i=0; i<6u; i++) + { + if(activeBoundaries_[i]) + { + auto& BI = boundaryInteraction_[i]; + if(!contactSearchRef.boundaryBroadSearch( + i, + ti, + BI.ppPairs(), + BI.pwPairs()) + ) + { + fatalErrorInFunction<< + "failed to perform broadSearch for boundary index "<(true); + const auto& cfModel = this->forceModel_(); + uint32 step=1; + boundaryInteractionTimer_.start(); + ComputationTimer().start(); + while(requireStep.anyElement(true) && step <= 10) + { + for(uint32 i=0; i<6u; i++) + { + if(requireStep[i] ) + { + requireStep[i] = boundaryInteraction_[i].grainGrainInteraction( + dt, + this->forceModel_(), + step + ); + } + } + step++; + } + ComputationTimer().end(); + boundaryInteractionTimer_.pause(); + + + ppInteractionTimer_.start(); + ComputationTimer().start(); + grainGrainInteraction(); + ComputationTimer().end(); + ppInteractionTimer_.end(); + + + pwInteractionTimer_.start(); + ComputationTimer().start(); + grainWallInteraction(); + ComputationTimer().start(); + pwInteractionTimer_.end(); + + { + boundaryInteractionTimer_.resume(); + ComputationTimer().start(); + auto requireStep = boundariesMask<6>(true); + + uint32 step = 11; + const auto& cfModel = this->forceModel_(); + while( requireStep.anyElement(true) && step < 20 ) + { + for(uint32 i=0; i<6u; i++) + { + if(requireStep[i]) + { + requireStep[i] = boundaryInteraction_[i].grainGrainInteraction( + dt, + cfModel, + step + ); + } + } + step++; + } + ComputationTimer().end(); + boundaryInteractionTimer_.end(); + } + + return true; +} + +template class cLT> +bool pFlow::grainInteraction::afterIteration() +{ + return true; +} + +template class cLT> +bool pFlow::grainInteraction::hearChanges +( + real t, + real dt, + uint32 iter, + const message& msg, + const anyList& varList +) +{ + if(msg.equivalentTo(message::ITEM_REARRANGE)) + { + notImplementedFunction; + } + return true; +} \ No newline at end of file diff --git a/src/Interaction/grainInteraction/grainInteraction/grainInteraction.hpp b/src/Interaction/grainInteraction/grainInteraction/grainInteraction.hpp new file mode 100644 index 00000000..2d30165b --- /dev/null +++ b/src/Interaction/grainInteraction/grainInteraction/grainInteraction.hpp @@ -0,0 +1,169 @@ +/*------------------------------- 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 __grainInteraction_hpp__ +#define __grainInteraction_hpp__ + +#include "interaction.hpp" +#include "grainParticles.hpp" +#include "boundaryGrainInteractionList.hpp" +#include "grainInteractionKernels.hpp" +#include "boundariesMask.hpp" +#include "MPITimer.hpp" +//#include "unsortedContactList.hpp" + + + +namespace pFlow +{ + +template< + typename contactForceModel, + typename geometryMotionModel, + template class contactListType> +class grainInteraction +: + public interaction +{ +public: + + using GeometryMotionModel = geometryMotionModel; + + using ContactForceModel = contactForceModel; + + using MotionModel = typename geometryMotionModel::MotionModel; + + using ModelStorage = typename ContactForceModel::contactForceStorage; + + using BoundaryListType = boundaryGrainInteractionList; + + using IdType = uint32; + + using IndexType = uint32; + + using ContactListType = + contactListType; + + //using BoundaryContactListType = unsortedContactList; + + + +private: + + /// const reference to geometry + const GeometryMotionModel& geometryMotion_; + + /// const reference to particles + const grainParticles& grnParticles_; + + /// particle-particle and particle-wall interactions at boundaries + BoundaryListType boundaryInteraction_; + + /// a mask for active boundaries (boundaries with intreaction) + boundariesMask<6> activeBoundaries_; + + /// contact search object for pp and pw interactions + uniquePtr contactSearch_ = nullptr; + + /// contact force model + uniquePtr forceModel_ = nullptr; + + /// contact list for particle-particle interactoins (keeps the history) + uniquePtr ppContactList_ = nullptr; + + /// contact list for particle-wall interactions (keeps the history) + uniquePtr pwContactList_ = nullptr; + + + /// timer for particle-particle interaction computations + Timer ppInteractionTimer_; + + /// timer for particle-wall interaction computations + Timer pwInteractionTimer_; + + /// timer for boundary interaction time + Timer boundaryInteractionTimer_; + + /// timer for managing contact lists (only inernal points) + Timer contactListMangementTimer_; + + Timer contactListMangementBoundaryTimer_; + + + + bool createGrainInteraction(); + + bool grainGrainInteraction(); + + bool grainWallInteraction(); + + /// range policy for p-p interaction execution + using rpPPInteraction = + Kokkos::RangePolicy, Kokkos::Schedule>; + + /// range policy for p-w interaction execution + using rpPWInteraction = rpPPInteraction; + +public: + + TypeInfoTemplate13("grainInteraction", ContactForceModel, MotionModel, ContactListType); + + /// Constructor from components + grainInteraction( + systemControl& control, + const particles& prtcl, + const geometry& geom); + + + /// Add virtual constructor + add_vCtor + ( + interaction, + grainInteraction, + systemControl + ); + + /// This is called in time loop, before iterate. (overriden from demComponent) + bool beforeIteration() override; + + /// This is called in time loop. Perform the main calculations + /// when the component should evolve along time. (overriden from demComponent) + bool iterate() override; + + /// This is called in time loop, after iterate. (overriden from demComponent) + bool afterIteration() override; + + /// Check for changes in the point structures. (overriden from observer) + bool hearChanges( + real t, + real dt, + uint32 iter, + const message& msg, + const anyList& varList)override; + + +}; + + +} + +#include "grainInteraction.cpp" + +#endif //__grainInteraction_hpp__ diff --git a/src/Interaction/grainInteraction/grainInteraction/grainInteractionKernels.hpp b/src/Interaction/grainInteraction/grainInteraction/grainInteractionKernels.hpp new file mode 100644 index 00000000..7ee5ef39 --- /dev/null +++ b/src/Interaction/grainInteraction/grainInteraction/grainInteractionKernels.hpp @@ -0,0 +1,337 @@ +/*------------------------------- 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 __grainInteractionKernels_hpp__ +#define __grainInteractionKernels_hpp__ + + +#include "grainTriSurfaceContact.hpp" + +namespace pFlow::grainInteractionKernels +{ + +template< + typename ContactForceModel, + typename ContactListType> +struct ppInteractionFunctor +{ + + using PairType = typename ContactListType::PairType; + using ValueType = typename ContactListType::ValueType; + + real dt_; + + ContactForceModel forceModel_; + ContactListType tobeFilled_; + + deviceViewType1D diam_; + deviceViewType1D coarseGrainFactor_; + deviceViewType1D propId_; + deviceViewType1D pos_; + deviceViewType1D lVel_; + deviceViewType1D rVel_; + deviceViewType1D cForce_; + deviceViewType1D cTorque_; + + + ppInteractionFunctor( + real dt, + ContactForceModel forceModel, + ContactListType tobeFilled, + deviceViewType1D diam, + deviceViewType1D coarseGrainFactor, + deviceViewType1D propId, + deviceViewType1D pos, + deviceViewType1D lVel, + deviceViewType1D rVel, + deviceViewType1D cForce, + deviceViewType1D cTorque ) + : + dt_(dt), + forceModel_(forceModel), + tobeFilled_(tobeFilled), + diam_(diam), + coarseGrainFactor_(coarseGrainFactor), + propId_(propId), + pos_(pos), + lVel_(lVel), + rVel_(rVel), + cForce_(cForce), // this is converted to an atomic vector + cTorque_(cTorque) // this is converted to an atomic vector + {} + + INLINE_FUNCTION_HD + void operator()(const uint32 n)const + { + + if(!tobeFilled_.isValid(n))return; + + auto [i,j] = tobeFilled_.getPair(n); + + real Ri = 0.5*diam_[i]; + real Rj = 0.5*diam_[j]; + + real cGFi = coarseGrainFactor_[j]; + real cGFj = coarseGrainFactor_[j]; + + realx3 xi = pos_[i]; + realx3 xj = pos_[j]; + real dist = length(xj-xi); + real ovrlp = (Ri+Rj) - dist; + + if( ovrlp >0.0 ) + { + + auto Vi = lVel_[i]; + auto Vj = lVel_[j]; + auto wi = rVel_[i]; + auto wj = rVel_[j]; + auto Nij = (xj-xi)/dist; + auto Vr = Vi - Vj + cross((Ri*wi+Rj*wj), Nij); + + auto history = tobeFilled_.getValue(n); + + int32 propId_i = propId_[i]; + int32 propId_j = propId_[j]; + + realx3 FCn, FCt, Mri, Mrj, Mij, Mji; + + // calculates contact force + forceModel_.contactForce( + dt_, i, j, + propId_i, propId_j, + Ri, Rj, cGFi , cGFj , + ovrlp, + Vr, Nij, + history, + FCn, FCt + ); + + forceModel_.rollingFriction( + dt_, i, j, + propId_i, propId_j, + Ri, Rj, cGFi , cGFj , + wi, wj, + Nij, + FCn, + Mri, Mrj + ); + + auto M = cross(Nij,FCt); + Mij = Ri*M+Mri; + Mji = Rj*M+Mrj; + + auto FC = FCn + FCt; + + Kokkos::atomic_add(&cForce_[i].x_,FC.x_); + Kokkos::atomic_add(&cForce_[i].y_,FC.y_); + Kokkos::atomic_add(&cForce_[i].z_,FC.z_); + + Kokkos::atomic_add(&cForce_[j].x_,-FC.x_); + Kokkos::atomic_add(&cForce_[j].y_,-FC.y_); + Kokkos::atomic_add(&cForce_[j].z_,-FC.z_); + + Kokkos::atomic_add(&cTorque_[i].x_, Mij.x_); + Kokkos::atomic_add(&cTorque_[i].y_, Mij.y_); + Kokkos::atomic_add(&cTorque_[i].z_, Mij.z_); + + Kokkos::atomic_add(&cTorque_[j].x_, Mji.x_); + Kokkos::atomic_add(&cTorque_[j].y_, Mji.y_); + Kokkos::atomic_add(&cTorque_[j].z_, Mji.z_); + + + tobeFilled_.setValue(n,history); + + } + else + { + tobeFilled_.setValue(n, ValueType()); + } + + } +}; + + +template< + typename ContactForceModel, + typename ContactListType, + typename TraingleAccessor, + typename MotionModel> +struct pwInteractionFunctor +{ + using PairType = typename ContactListType::PairType; + using ValueType = typename ContactListType::ValueType; + + real dt_; + + ContactForceModel forceModel_; + ContactListType tobeFilled_; + + TraingleAccessor triangles_; + MotionModel motionModel_; + + deviceViewType1D diam_; + deviceViewType1D coarseGrainFactor_; + deviceViewType1D propId_; + deviceViewType1D pos_; + deviceViewType1D lVel_; + deviceViewType1D rVel_; + deviceViewType1D cForce_; + deviceViewType1D cTorque_; + deviceViewType1D wTriMotionIndex_; + deviceViewType1D wPropId_; + deviceViewType1D wCForce_; + + + pwInteractionFunctor( + real dt, + ContactForceModel forceModel, + ContactListType tobeFilled, + TraingleAccessor triangles, + MotionModel motionModel , + deviceViewType1D diam , + deviceViewType1D coarseGrainFactor, + deviceViewType1D propId, + deviceViewType1D pos , + deviceViewType1D lVel, + deviceViewType1D rVel, + deviceViewType1D cForce, + deviceViewType1D cTorque , + deviceViewType1D wTriMotionIndex, + deviceViewType1D wPropId, + deviceViewType1D wCForce) + : + dt_(dt), + forceModel_(forceModel), + tobeFilled_(tobeFilled), + triangles_(triangles) , + motionModel_(motionModel) , + diam_(diam) , + coarseGrainFactor_(coarseGrainFactor), + propId_(propId), + pos_(pos) , + lVel_(lVel), + rVel_(rVel) , + cForce_(cForce), + cTorque_(cTorque) , + wTriMotionIndex_(wTriMotionIndex) , + wPropId_(wPropId), + wCForce_(wCForce) + {} + + INLINE_FUNCTION_HD + void operator()(const int32 n)const + { + + if(!tobeFilled_.isValid(n))return; + + auto [i,tj] = tobeFilled_.getPair(n); + + real Ri = 0.5*diam_[i]; + real Rj = 10000.0; + real cGFi = coarseGrainFactor_[i]; + real cGFj = coarseGrainFactor_[i]; + realx3 xi = pos_[i]; + + realx3x3 tri = triangles_(tj); + real ovrlp; + realx3 Nij, cp; + + if( pFlow::grnTriInteraction::isGrainInContactBothSides( + tri, xi, Ri, ovrlp, Nij, cp) ) + { + auto Vi = lVel_[i]; + auto wi = rVel_[i]; + + int32 mInd = wTriMotionIndex_[tj]; + + auto Vw = motionModel_(mInd, cp); + + //output<< "par-wall index "<< i<<" - "<< tj< 1) + { + Ln = 2; return true; + } + else if (nuW >= 0) + { + if (nu >= 0 && w >= 0) + { + Ln = 0; return true; + } + if (nu > 0 && w < 0) + { + Ln = 1; return true; + } + if (nu < 0 && w > 0) + { + Ln = 3; return true; + } + } + else + { + Ln = 1; return true; + } + + return false; +} + +INLINE_FUNCTION_HD +bool isGrainInContactActiveSide( + const realx3& p1, + const realx3& p2, + const realx3& p3, + const realx3& cntr, + real rad, + real& ovrlp, + realx3& norm, + realx3& cp) +{ + + triWall wall(true, p1,p2,p3); + + real dist = wall.normalDistFromWall(cntr); + + if(dist < 0.0 )return false; + + ovrlp = rad - dist; + + if (ovrlp > 0) + { + realx3 ptOnPlane = wall.nearestPointOnWall(cntr); + + if (pointInPlane(p1, p2, p3, ptOnPlane)) + { + cp = ptOnPlane; + norm = -wall.n_; + return true; + } + + realx3 lnv; + + if (pLine(p1,p2).lineGrainCheck(cntr, rad, lnv, cp, ovrlp)) + { + norm = -lnv; + return true; + } + + if ( pLine(p2,p3).lineGrainCheck(cntr, rad, lnv, cp, ovrlp)) + { + norm = -lnv; + return true; + } + + if ( pLine(p3,p1).lineGrainCheck(cntr, rad, lnv, cp, ovrlp)) + { + norm = -lnv; + return true; + } + } + + return false; +} + +INLINE_FUNCTION_HD +bool isGrainInContactBothSides( + const realx3x3& tri, + const realx3& cntr, + real Rad, + real& ovrlp, + realx3& norm, + realx3& cp) +{ + + triWall wall(true, tri.x_,tri.y_,tri.z_); + + real dist = wall.normalDistFromWall(cntr); + + + ovrlp = Rad - abs(dist); + + if (ovrlp > 0) + { + realx3 ptOnPlane = wall.nearestPointOnWall(cntr); + + if (pointInPlane(tri.x_,tri.y_,tri.z_,ptOnPlane)) + { + cp = ptOnPlane; + + if(dist >= 0.0) + norm = -wall.n_; + else + norm = wall.n_; + return true; + } + + realx3 lnv; + + if (pLine(tri.x_, tri.y_).lineGrainCheck(cntr, Rad, lnv, cp, ovrlp)) + { + norm = -lnv; + return true; + } + + if ( pLine(tri.y_, tri.z_).lineGrainCheck(cntr, Rad, lnv, cp, ovrlp)) + { + norm = -lnv; + return true; + } + + if ( pLine(tri.z_, tri.x_).lineGrainCheck(cntr, Rad, lnv, cp, ovrlp)) + { + norm = -lnv; + return true; + } + } + + return false; +} + + +} // pFlow::grnTriInteraction + + +#endif //__grainTriSurfaceContact_hpp__ \ No newline at end of file diff --git a/src/Interaction/grainInteraction/grainInteraction/pLine.hpp b/src/Interaction/grainInteraction/grainInteraction/pLine.hpp new file mode 100644 index 00000000..848ff66f --- /dev/null +++ b/src/Interaction/grainInteraction/grainInteraction/pLine.hpp @@ -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. + +-----------------------------------------------------------------------------*/ + +#ifndef __pLine_hpp__ +#define __pLine_hpp__ + +#include "types.hpp" + +namespace pFlow::grnTriInteraction +{ + +struct pLine +{ + + realx3 p1_; // point 1 + realx3 p2_; // piont 2 + realx3 v_; // direction vector + real L_; // line lenght + + INLINE_FUNCTION_HD + pLine(){} + + INLINE_FUNCTION_HD + pLine(const realx3 &p1, const realx3 &p2) + : + p1_(p1), + p2_(p2), + v_(p2-p1), + L_(length(v_)) + {} + + // get a point on the line based on input 0<= t <= 1 + INLINE_FUNCTION_HD + realx3 point(real t)const { + return v_ * t + p1_; + } + + // return the projected point of point p on line + INLINE_FUNCTION_HD + realx3 projectPoint(const realx3 &p) const + { + return point(projectNormLength(p)); + } + + // calculates the normalized distance between projected p and p1 + INLINE_FUNCTION_HD + real projectNormLength(realx3 p) const + { + realx3 w = p - p1_; + return dot(w,v_) / (L_*L_); + } + + INLINE_FUNCTION_HD + bool lineGrainCheck( + const realx3 pos, + real Rad, + realx3 &nv, + realx3 &cp, + real &ovrlp)const + { + + + real t = projectNormLength(pos); + + if(t >= 0.0 && t <= 1.0) cp = point(t); + else if(t >= (-Rad / L_) && t < 0.0) cp = point(0.0); + else if(t>1.0 && t >= (1.0 + Rad / L_)) cp = point(1.0); + else return false; + + realx3 vec = pos - cp; // from cp to pos + + real dist = length(vec); + ovrlp = Rad - dist; + + if (ovrlp >= 0.0) + { + if (dist > 0) + nv = vec / dist; + else + nv = v_; + return true; + } + + return false; + } +}; + +} //pFlow::grnTriInteractio + +#endif diff --git a/src/Interaction/grainInteraction/grainInteraction/triWall.hpp b/src/Interaction/grainInteraction/grainInteraction/triWall.hpp new file mode 100644 index 00000000..5a0086a4 --- /dev/null +++ b/src/Interaction/grainInteraction/grainInteraction/triWall.hpp @@ -0,0 +1,108 @@ +/*------------------------------- 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 __triWall_hpp__ +#define __triWall_hpp__ + +#include "types.hpp" + +namespace pFlow::grnTriInteraction +{ + +struct triWall +{ + + realx3 n_; + real offset_; + + INLINE_FUNCTION_H + triWall(const realx3& p1, const realx3& p2, const realx3& p3) + { + if(!makeWall(p1,p2,p3, n_, offset_)) + { + fatalErrorInFunction<< + "bad input for the wall.\n"; + fatalExit; + } + } + + INLINE_FUNCTION_HD + triWall(bool, const realx3& p1, const realx3& p2, const realx3& p3) + { + makeWall(p1,p2,p3,n_,offset_); + } + + INLINE_FUNCTION_HD + triWall(const realx3x3& tri) + { + makeWall(tri.x_, tri.y_, tri.z_, n_, offset_); + } + + INLINE_FUNCTION_HD + triWall(const triWall&) = default; + + INLINE_FUNCTION_HD + triWall& operator=(const triWall&) = default; + + INLINE_FUNCTION_HD + triWall(triWall&&) = default; + + INLINE_FUNCTION_HD + triWall& operator=(triWall&&) = default; + + INLINE_FUNCTION_HD + ~triWall()=default; + + + INLINE_FUNCTION_HD + real normalDistFromWall(const realx3 &p) const + { + return dot(n_, p) + offset_; + } + + INLINE_FUNCTION_HD + realx3 nearestPointOnWall(const realx3 &p) const + { + real t = -(dot(n_, p) + offset_); + return realx3(n_.x_*t + p.x_, n_.y_*t + p.y_, n_.z_*t + p.z_); + } + + INLINE_FUNCTION_HD static + bool makeWall( + const realx3& p1, + const realx3& p2, + const realx3& p3, + realx3& n, real& offset) + { + n = cross(p2 - p1, p3 - p1); + real len = length(n); + + if (len < 0.00000000001) return false; + n /= len; + offset = -dot(n, p1); + return true; + } + + +}; + +} + +#endif diff --git a/src/Interaction/grainInteraction/grainInteractionsLinearModels.cpp b/src/Interaction/grainInteraction/grainInteractionsLinearModels.cpp new file mode 100755 index 00000000..d047df09 --- /dev/null +++ b/src/Interaction/grainInteraction/grainInteractionsLinearModels.cpp @@ -0,0 +1,68 @@ +/*------------------------------- 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 "grainInteraction.hpp" +#include "geometryMotions.hpp" +#include "grainContactForceModels.hpp" +#include "unsortedContactList.hpp" +#include "sortedContactList.hpp" +#include "createBoundaryGrainInteraction.hpp" + + + +#define createInteraction(ForceModel,GeomModel) \ + \ + template class pFlow::grainInteraction< \ + ForceModel, \ + GeomModel, \ + pFlow::unsortedContactList>; \ + \ + template class pFlow::grainInteraction< \ + ForceModel, \ + GeomModel, \ + pFlow::sortedContactList>; \ + createBoundaryGrainInteraction(ForceModel, GeomModel) + + +createInteraction(pFlow::cfModels::grainRolling>, pFlow::rotationAxisMotionGeometry); +createInteraction(pFlow::cfModels::grainRolling>, pFlow::rotationAxisMotionGeometry); + +createInteraction(pFlow::cfModels::grainRolling>, pFlow::rotationAxisMotionGeometry); +createInteraction(pFlow::cfModels::grainRolling>, pFlow::rotationAxisMotionGeometry); + + +createInteraction(pFlow::cfModels::grainRolling>, pFlow::stationaryGeometry); +createInteraction(pFlow::cfModels::grainRolling>, pFlow::stationaryGeometry); + +createInteraction(pFlow::cfModels::grainRolling>, pFlow::stationaryGeometry); +createInteraction(pFlow::cfModels::grainRolling>, pFlow::stationaryGeometry); + + +createInteraction(pFlow::cfModels::grainRolling>, pFlow::vibratingMotionGeometry); +createInteraction(pFlow::cfModels::grainRolling>, pFlow::vibratingMotionGeometry); + +createInteraction(pFlow::cfModels::grainRolling>, pFlow::vibratingMotionGeometry); +createInteraction(pFlow::cfModels::grainRolling>, pFlow::vibratingMotionGeometry); + +createInteraction(pFlow::cfModels::grainRolling>, pFlow::conveyorBeltMotionGeometry); +createInteraction(pFlow::cfModels::grainRolling>, pFlow::conveyorBeltMotionGeometry); + +createInteraction(pFlow::cfModels::grainRolling>, pFlow::conveyorBeltMotionGeometry); +createInteraction(pFlow::cfModels::grainRolling>, pFlow::conveyorBeltMotionGeometry); \ No newline at end of file diff --git a/src/Geometry/geometryMotion/geometryMotionsInstantiate.cpp b/src/Interaction/grainInteraction/grainInteractionsNonLinearModModels.cpp old mode 100644 new mode 100755 similarity index 62% rename from src/Geometry/geometryMotion/geometryMotionsInstantiate.cpp rename to src/Interaction/grainInteraction/grainInteractionsNonLinearModModels.cpp index a8ec4fd9..462b5eb3 --- a/src/Geometry/geometryMotion/geometryMotionsInstantiate.cpp +++ b/src/Interaction/grainInteraction/grainInteractionsNonLinearModModels.cpp @@ -18,15 +18,26 @@ Licence: -----------------------------------------------------------------------------*/ -#include "fixedWall.hpp" -#include "rotatingAxisMotion.hpp" -#include "multiRotatingAxisMotion.hpp" -#include "vibratingMotion.hpp" +#include "grainInteraction.hpp" +#include "geometryMotions.hpp" +#include "grainContactForceModels.hpp" +#include "unsortedContactList.hpp" +#include "sortedContactList.hpp" +#include "createBoundaryGrainInteraction.hpp" -template class pFlow::geometryMotion; -template class pFlow::geometryMotion; -template class pFlow::geometryMotion; +#define createInteraction(ForceModel,GeomModel) \ + \ + template class pFlow::grainInteraction< \ + ForceModel, \ + GeomModel, \ + pFlow::unsortedContactList>; \ + \ + template class pFlow::grainInteraction< \ + ForceModel, \ + GeomModel, \ + pFlow::sortedContactList>; \ + createBoundaryGrainInteraction(ForceModel, GeomModel) + -template class pFlow::geometryMotion; diff --git a/src/Interaction/grainInteraction/grainInteractionsNonLinearModels.cpp b/src/Interaction/grainInteraction/grainInteractionsNonLinearModels.cpp new file mode 100755 index 00000000..462b5eb3 --- /dev/null +++ b/src/Interaction/grainInteraction/grainInteractionsNonLinearModels.cpp @@ -0,0 +1,43 @@ +/*------------------------------- 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 "grainInteraction.hpp" +#include "geometryMotions.hpp" +#include "grainContactForceModels.hpp" +#include "unsortedContactList.hpp" +#include "sortedContactList.hpp" +#include "createBoundaryGrainInteraction.hpp" + + + +#define createInteraction(ForceModel,GeomModel) \ + \ + template class pFlow::grainInteraction< \ + ForceModel, \ + GeomModel, \ + pFlow::unsortedContactList>; \ + \ + template class pFlow::grainInteraction< \ + ForceModel, \ + GeomModel, \ + pFlow::sortedContactList>; \ + createBoundaryGrainInteraction(ForceModel, GeomModel) + + diff --git a/src/Interaction/interaction/interaction.cpp b/src/Interaction/interaction/interaction.cpp index 8d368c29..03abbb4b 100644 --- a/src/Interaction/interaction/interaction.cpp +++ b/src/Interaction/interaction/interaction.cpp @@ -19,7 +19,9 @@ Licence: -----------------------------------------------------------------------------*/ #include "interaction.hpp" - +#include "particles.hpp" +#include "vocabs.hpp" +#include "geometry.hpp" pFlow::interaction::interaction ( @@ -28,26 +30,16 @@ pFlow::interaction::interaction const geometry& geom ) : - demInteraction(control, control.caseSetup().path()+interactionFile__), - interactionBase(prtcl, geom), - fileDict_(control.caseSetup().emplaceObject( - objectFile( - interactionFile__, - "", - objectFile::READ_ALWAYS, - objectFile::WRITE_NEVER), - interactionFile__, - true )) + property(interactionFile__, &control.caseSetup()), + observer + ( + &prtcl.dynPointStruct(), + msg_ + ), + demComponent("interaction", control), + particles_(prtcl), + geometry_(geom) { - this->subscribe(prtcl.pStruct()); - - contactSearch_ = contactSearch::create( - fileDict_.subDict("contactSearch"), - this->control().domain(), - prtcl, - geom, - timers() - ); } @@ -79,14 +71,14 @@ pFlow::uniquePtr pFlow::interaction::create clType); - REPORT(1)<< "Selecting interaction model..."< contactSearch_ = nullptr; + static inline + const message msg_ = message::ITEM_REARRANGE; public: @@ -65,11 +65,10 @@ public: const particles& prtcl, const geometry& geom ); + ~interaction() override = default; - - virtual ~interaction() = default; - - create_vCtor( + create_vCtor + ( interaction, systemControl, ( @@ -78,21 +77,18 @@ public: const geometry& geom ), (control, prtcl, geom) - ); + ); - auto& contactSearchPtr() + inline + const auto& Particles()const { - return contactSearch_; + return particles_; } - auto& contactSearchRef() + inline + const auto& Geometry()const { - return contactSearch_(); - } - - const auto& fileDict()const - { - return fileDict_; + return geometry_; } static diff --git a/src/Interaction/sphereInteraction/boundaries/boundarySphereInteraction/boundarySphereInteraction.cpp b/src/Interaction/sphereInteraction/boundaries/boundarySphereInteraction/boundarySphereInteraction.cpp new file mode 100644 index 00000000..74a50bd3 --- /dev/null +++ b/src/Interaction/sphereInteraction/boundaries/boundarySphereInteraction/boundarySphereInteraction.cpp @@ -0,0 +1,104 @@ +#include "boundarySphereInteraction.hpp" +/*------------------------------- 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. + +-----------------------------------------------------------------------------*/ + +template +void pFlow::boundarySphereInteraction::allocatePPPairs() +{ + ppPairs_.reset(nullptr); + ppPairs_ = makeUnique(1); +} + +template +void pFlow::boundarySphereInteraction::allocatePWPairs() +{ + pwPairs_.reset(nullptr); + pwPairs_ = makeUnique(1); +} + + +template +pFlow::boundarySphereInteraction::boundarySphereInteraction( + const boundaryBase &boundary, + const sphereParticles &sphPrtcls, + const GeometryMotionModel &geomMotion) + : generalBoundary(boundary, sphPrtcls.pStruct(), "", ""), + geometryMotion_(geomMotion), + sphParticles_(sphPrtcls) +{ +} + +template +pFlow::uniquePtr> +pFlow::boundarySphereInteraction::create( + const boundaryBase &boundary, + const sphereParticles &sphPrtcls, + const GeometryMotionModel &geomMotion) +{ + word cfTypeName = ContactForceModel::TYPENAME(); + word gmTypeName = MotionModel::TYPENAME(); + word bType = boundary.type(); + + word boundaryTypeName = angleBracketsNames3( + "boundarySphereInteraction", + bType, + cfTypeName, + gmTypeName); + + word altBTypeName = angleBracketsNames2( + "boundarySphereInteraction", + cfTypeName, + gmTypeName); + + if (boundaryBasevCtorSelector_.search(boundaryTypeName)) + { + pOutput.space(4) << "Creating boundry type " << Green_Text(boundaryTypeName) << + " for boundary " << boundary.name() << " . . ." << END_REPORT; + return boundaryBasevCtorSelector_[boundaryTypeName]( + boundary, + sphPrtcls, + geomMotion); + } + else if(boundaryBasevCtorSelector_[altBTypeName]) + { + // if boundary condition is not implemented, the default is used + + pOutput.space(4) << "Creating boundry type " << Green_Text(altBTypeName) << + " for boundary " << boundary.name() << " . . ." << END_REPORT; + return boundaryBasevCtorSelector_[altBTypeName]( + boundary, + sphPrtcls, + geomMotion); + } + else + { + printKeys + ( + fatalError << "Ctor Selector "<< boundaryTypeName<< + " and "<< altBTypeName << " do not exist. \n" + <<"Avaiable ones are: \n\n" + , + boundaryBasevCtorSelector_ + ); + fatalExit; + } + + return nullptr; +} diff --git a/src/Interaction/sphereInteraction/boundaries/boundarySphereInteraction/boundarySphereInteraction.hpp b/src/Interaction/sphereInteraction/boundaries/boundarySphereInteraction/boundarySphereInteraction.hpp new file mode 100644 index 00000000..b36188c5 --- /dev/null +++ b/src/Interaction/sphereInteraction/boundaries/boundarySphereInteraction/boundarySphereInteraction.hpp @@ -0,0 +1,186 @@ +/*------------------------------- 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 __boundarySphereInteraction_hpp__ +#define __boundarySphereInteraction_hpp__ + +#include "virtualConstructor.hpp" +#include "generalBoundary.hpp" +#include "sortedContactList.hpp" +#include "sphereParticles.hpp" + +namespace pFlow +{ + +template +class boundarySphereInteraction +: + public generalBoundary +{ +public: + + using BoundarySphereInteractionType + = boundarySphereInteraction; + + using GeometryMotionModel = geometryMotionModel; + + using ContactForceModel = contactForceModel; + + using MotionModel = typename geometryMotionModel::MotionModel; + + using ModelStorage = typename ContactForceModel::contactForceStorage; + + using IdType = uint32; + + using IndexType = uint32; + + using ContactListType = + sortedContactList; + +private: + + const GeometryMotionModel& geometryMotion_; + + /// const reference to sphere particles + const sphereParticles& sphParticles_; + + uniquePtr ppPairs_ = nullptr; + + uniquePtr pwPairs_ = nullptr; + +protected: + + void allocatePPPairs(); + + void allocatePWPairs(); + +public: + + TypeInfoTemplate12("boundarySphereInteraction", ContactForceModel, MotionModel); + + boundarySphereInteraction( + const boundaryBase& boundary, + const sphereParticles& sphPrtcls, + const GeometryMotionModel& geomMotion); + + create_vCtor + ( + BoundarySphereInteractionType, + boundaryBase, + ( + const boundaryBase& boundary, + const sphereParticles& sphPrtcls, + const GeometryMotionModel& geomMotion + ), + (boundary, sphPrtcls, geomMotion) + ); + + add_vCtor + ( + BoundarySphereInteractionType, + BoundarySphereInteractionType, + boundaryBase + ); + + ~boundarySphereInteraction()override=default; + + const auto& sphParticles()const + { + return sphParticles_; + } + + const auto& geometryMotion()const + { + return geometryMotion_; + } + + ContactListType& ppPairs() + { + return ppPairs_(); + } + + const ContactListType& ppPairs()const + { + return ppPairs_(); + } + + ContactListType& pwPairs() + { + return pwPairs_(); + } + + const ContactListType& pwPairs()const + { + return pwPairs_(); + } + + bool ppPairsAllocated()const + { + if( ppPairs_)return true; + return false; + } + + bool pwPairsAllocated()const + { + if( pwPairs_)return true; + return false; + } + + virtual + bool sphereSphereInteraction( + real dt, + const ContactForceModel& cfModel, + uint32 step) + { + // for default boundary, no thing to be done + return false; + } + + + + bool hearChanges + ( + real t, + real dt, + uint32 iter, + const message& msg, + const anyList& varList + ) override + { + + pOutput<<"Function (hearChanges in boundarySphereInteractions)is not implmented Message "<< + msg <boundaryName() <<" type "<< this->type()< create( + const boundaryBase& boundary, + const sphereParticles& sphPrtcls, + const GeometryMotionModel& geomMotion + ); + +}; + +} + +#include "boundarySphereInteraction.cpp" + +#endif //__boundarySphereInteraction_hpp__ diff --git a/src/Interaction/sphereInteraction/boundaries/boundarySphereInteractionList.cpp b/src/Interaction/sphereInteraction/boundaries/boundarySphereInteractionList.cpp new file mode 100644 index 00000000..00b86bc4 --- /dev/null +++ b/src/Interaction/sphereInteraction/boundaries/boundarySphereInteractionList.cpp @@ -0,0 +1,23 @@ + + +template +pFlow::boundarySphereInteractionList::boundarySphereInteractionList +( + const sphereParticles &sphPrtcls, + const gMModel &geomMotion +) +: + ListPtr>(6), + boundaries_(sphPrtcls.pStruct().boundaries()) +{ + //gSettings::sleepMiliSeconds(1000*pFlowProcessors().localRank()); + for(uint32 i=0; i<6; i++) + { + this->set( + i, + boundarySphereInteraction::create( + boundaries_[i], + sphPrtcls, + geomMotion)); + } +} \ No newline at end of file diff --git a/src/Interaction/sphereInteraction/boundaries/boundarySphereInteractionList.hpp b/src/Interaction/sphereInteraction/boundaries/boundarySphereInteractionList.hpp new file mode 100644 index 00000000..1a5086fa --- /dev/null +++ b/src/Interaction/sphereInteraction/boundaries/boundarySphereInteractionList.hpp @@ -0,0 +1,40 @@ +#ifndef __boundarySphereInteractionList_hpp__ +#define __boundarySphereInteractionList_hpp__ + + +#include "boundaryList.hpp" +#include "ListPtr.hpp" +#include "boundarySphereInteraction.hpp" + + +namespace pFlow +{ + + +template +class boundarySphereInteractionList +: + public ListPtr> +{ +private: + + const boundaryList& boundaries_; + +public: + + boundarySphereInteractionList( + const sphereParticles& sphPrtcls, + const geometryMotionModel& geomMotion + ); + + ~boundarySphereInteractionList()=default; + +}; + + + +} + +#include "boundarySphereInteractionList.cpp" + +#endif //__boundarySphereInteractionList_hpp__ \ No newline at end of file diff --git a/src/Interaction/sphereInteraction/boundaries/createBoundarySphereInteraction.hpp b/src/Interaction/sphereInteraction/boundaries/createBoundarySphereInteraction.hpp new file mode 100644 index 00000000..27494be2 --- /dev/null +++ b/src/Interaction/sphereInteraction/boundaries/createBoundarySphereInteraction.hpp @@ -0,0 +1,31 @@ +/*------------------------------- 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 "boundarySphereInteraction.hpp" +#include "periodicBoundarySphereInteraction.hpp" + +#define createBoundarySphereInteraction(ForceModel,GeomModel) \ + template class pFlow::boundarySphereInteraction< \ + ForceModel, \ + GeomModel>; \ + \ + template class pFlow::periodicBoundarySphereInteraction< \ + ForceModel, \ + GeomModel>; + diff --git a/src/Interaction/sphereInteraction/boundaries/periodicBoundarySphereInteraction/periodicBoundarySIKernels.hpp b/src/Interaction/sphereInteraction/boundaries/periodicBoundarySphereInteraction/periodicBoundarySIKernels.hpp new file mode 100644 index 00000000..2320b1c5 --- /dev/null +++ b/src/Interaction/sphereInteraction/boundaries/periodicBoundarySphereInteraction/periodicBoundarySIKernels.hpp @@ -0,0 +1,118 @@ + +namespace pFlow::periodicBoundarySIKernels +{ + +template +inline +void sphereSphereInteraction +( + real dt, + const ContactListType& cntctList, + const ContactForceModel& forceModel, + const realx3& transferVec, + const deviceScatteredFieldAccess& thisPoints, + const deviceScatteredFieldAccess& mirrorPoints, + const deviceViewType1D& diam, + const deviceViewType1D& propId, + const deviceViewType1D& vel, + const deviceViewType1D& rVel, + const deviceViewType1D& cForce, + const deviceViewType1D& cTorque +) +{ + + using ValueType = typename ContactListType::ValueType; + uint32 ss = cntctList.size(); + uint32 lastItem = cntctList.loopCount(); + if(lastItem == 0u)return; + + Kokkos::parallel_for( + "pFlow::periodicBoundarySIKernels::sphereSphereInteraction", + deviceRPolicyDynamic(0,lastItem), + LAMBDA_HD(uint32 n) + { + + if(!cntctList.isValid(n))return; + + auto [i,j] = cntctList.getPair(n); + uint32 ind_i = thisPoints.index(i); + uint32 ind_j = mirrorPoints.index(j); + + real Ri = 0.5*diam[ind_i]; + real Rj = 0.5*diam[ind_j]; + realx3 xi = thisPoints.field()[ind_i]; + realx3 xj = mirrorPoints.field()[ind_j]+transferVec; + real dist = length(xj-xi); + real ovrlp = (Ri+Rj) - dist; + + if( ovrlp >0.0 ) + { + auto Nij = (xj-xi)/dist; + auto wi = rVel[ind_i]; + auto wj = rVel[ind_j]; + auto Vr = vel[ind_i] - vel[ind_j] + cross((Ri*wi+Rj*wj), Nij); + + auto history = cntctList.getValue(n); + + int32 propId_i = propId[ind_i]; + int32 propId_j = propId[ind_j]; + + realx3 FCn, FCt, Mri, Mrj, Mij, Mji; + + // calculates contact force + forceModel.contactForce( + dt, i, j, + propId_i, propId_j, + Ri, Rj, + ovrlp, + Vr, Nij, + history, + FCn, FCt); + + forceModel.rollingFriction( + dt, i, j, + propId_i, propId_j, + Ri, Rj, + wi, wj, + Nij, + FCn, + Mri, Mrj); + + auto M = cross(Nij,FCt); + Mij = Ri*M+Mri; + Mji = Rj*M+Mrj; + + auto FC = FCn + FCt; + + + Kokkos::atomic_add(&cForce[ind_i].x_,FC.x_); + Kokkos::atomic_add(&cForce[ind_i].y_,FC.y_); + Kokkos::atomic_add(&cForce[ind_i].z_,FC.z_); + + Kokkos::atomic_add(&cForce[ind_j].x_,-FC.x_); + Kokkos::atomic_add(&cForce[ind_j].y_,-FC.y_); + Kokkos::atomic_add(&cForce[ind_j].z_,-FC.z_); + + Kokkos::atomic_add(&cTorque[ind_i].x_, Mij.x_); + Kokkos::atomic_add(&cTorque[ind_i].y_, Mij.y_); + Kokkos::atomic_add(&cTorque[ind_i].z_, Mij.z_); + + Kokkos::atomic_add(&cTorque[ind_j].x_, Mji.x_); + Kokkos::atomic_add(&cTorque[ind_j].y_, Mji.y_); + Kokkos::atomic_add(&cTorque[ind_j].z_, Mji.z_); + + + cntctList.setValue(n,history); + + } + else + { + cntctList.setValue(n, ValueType()); + } + + }); + Kokkos::fence(); +} + + +} //pFlow::periodicBoundarySIKernels \ No newline at end of file diff --git a/src/Interaction/sphereInteraction/boundaries/periodicBoundarySphereInteraction/periodicBoundarySphereInteraction.cpp b/src/Interaction/sphereInteraction/boundaries/periodicBoundarySphereInteraction/periodicBoundarySphereInteraction.cpp new file mode 100644 index 00000000..3200c4e7 --- /dev/null +++ b/src/Interaction/sphereInteraction/boundaries/periodicBoundarySphereInteraction/periodicBoundarySphereInteraction.cpp @@ -0,0 +1,69 @@ +/*------------------------------- 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 "periodicBoundarySIKernels.hpp" + +template +pFlow::periodicBoundarySphereInteraction::periodicBoundarySphereInteraction( + const boundaryBase &boundary, + const sphereParticles &sphPrtcls, + const GeometryMotionModel &geomMotion) + : boundarySphereInteraction(boundary, sphPrtcls, geomMotion), + transferVec_(boundary.mirrorBoundary().displacementVectroToMirror()) +{ + if(boundary.thisBoundaryIndex()%2==1) + { + masterInteraction_ = true; + this->allocatePPPairs(); + this->allocatePWPairs(); + + } + else + { + masterInteraction_ = false; + } +} + +template +bool pFlow::periodicBoundarySphereInteraction::sphereSphereInteraction +( + real dt, + const ContactForceModel &cfModel, + uint32 step +) +{ + if(!masterInteraction_) return false; + + pFlow::periodicBoundarySIKernels::sphereSphereInteraction( + dt, + this->ppPairs(), + cfModel, + transferVec_, + this->boundary().thisPoints(), + this->mirrorBoundary().thisPoints(), + this->sphParticles().diameter().deviceViewAll(), + this->sphParticles().propertyId().deviceViewAll(), + this->sphParticles().velocity().deviceViewAll(), + this->sphParticles().rVelocity().deviceViewAll(), + this->sphParticles().contactForce().deviceViewAll(), + this->sphParticles().contactTorque().deviceViewAll()); + + return false; +} \ No newline at end of file diff --git a/src/Interaction/sphereInteraction/boundaries/periodicBoundarySphereInteraction/periodicBoundarySphereInteraction.hpp b/src/Interaction/sphereInteraction/boundaries/periodicBoundarySphereInteraction/periodicBoundarySphereInteraction.hpp new file mode 100644 index 00000000..5f1e7a45 --- /dev/null +++ b/src/Interaction/sphereInteraction/boundaries/periodicBoundarySphereInteraction/periodicBoundarySphereInteraction.hpp @@ -0,0 +1,96 @@ +/*------------------------------- 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 __periodicBoundarySphereInteraction_hpp__ +#define __periodicBoundarySphereInteraction_hpp__ + +#include "boundarySphereInteraction.hpp" + +namespace pFlow +{ + +template +class periodicBoundarySphereInteraction +: + public boundarySphereInteraction +{ +public: + + using PBSInteractionType = + periodicBoundarySphereInteraction; + + using BSInteractionType = + boundarySphereInteraction; + + using GeometryMotionModel = typename BSInteractionType::GeometryMotionModel; + + using ContactForceModel = typename BSInteractionType::ContactForceModel; + + using MotionModel = typename geometryMotionModel::MotionModel; + + using ModelStorage = typename ContactForceModel::contactForceStorage; + + using IdType = typename BSInteractionType::IdType; + + using IndexType = typename BSInteractionType::IndexType; + + using ContactListType = typename BSInteractionType::ContactListType; + +private: + + realx3 transferVec_; + + bool masterInteraction_; +public: + + TypeInfoTemplate22("boundarySphereInteraction", "periodic",ContactForceModel, MotionModel); + + + periodicBoundarySphereInteraction( + const boundaryBase& boundary, + const sphereParticles& sphPrtcls, + const GeometryMotionModel& geomMotion + ); + + add_vCtor + ( + BSInteractionType, + PBSInteractionType, + boundaryBase + ); + + ~periodicBoundarySphereInteraction()override = default; + + + + + bool sphereSphereInteraction( + real dt, + const ContactForceModel& cfModel, + uint32 step)override; + +}; + +} + +#include "periodicBoundarySphereInteraction.cpp" + + +#endif //__periodicBoundarySphereInteraction_hpp__ \ No newline at end of file diff --git a/src/Interaction/sphereInteraction/sphereInteraction.cpp b/src/Interaction/sphereInteraction/sphereInteraction.cpp deleted file mode 100644 index 0dacee74..00000000 --- a/src/Interaction/sphereInteraction/sphereInteraction.cpp +++ /dev/null @@ -1,130 +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. - ------------------------------------------------------------------------------*/ - -template< - typename contactForceModel, - typename geometryMotionModel, - template class contactListType > -bool pFlow::sphereInteraction:: - createSphereInteraction() -{ - - realVector_D rhoD(this->densities()); - - auto modelDict = this->fileDict().subDict("model"); - - REPORT(1)<<"Createing contact force model . . ."<( - this->numMaterials(), - rhoD.deviceVector(), - modelDict ); - - - uint32 nPrtcl = sphParticles_.size(); - - ppContactList_ = makeUnique(nPrtcl+1); - - pwContactList_ = makeUnique(nPrtcl/4+1); - - return true; -} - - - -template< - typename contactForceModel, - typename geometryMotionModel, - template class contactListType > -bool pFlow::sphereInteraction:: - sphereSphereInteraction() -{ - - - - auto lastItem = ppContactList_().loopCount(); - - // create the kernel functor - pFlow::sphereInteractionKernels::ppInteractionFunctor - ppInteraction( - this->dt(), - this->forceModel_(), - ppContactList_(), // to be read - sphParticles_.diameter().deviceVectorAll(), - sphParticles_.propertyId().deviceVectorAll(), - sphParticles_.pointPosition().deviceVectorAll(), - sphParticles_.velocity().deviceVectorAll(), - sphParticles_.rVelocity().deviceVectorAll(), - sphParticles_.contactForce().deviceVectorAll(), - sphParticles_.contactTorque().deviceVectorAll() - ); - - Kokkos::parallel_for( - "", - rpPPInteraction(0,lastItem), - ppInteraction - ); - - Kokkos::fence(); - - return true; -} - - -template< - typename contactForceModel, - typename geometryMotionModel, - template class contactListType > -bool pFlow::sphereInteraction:: - sphereWallInteraction() -{ - - int32 lastItem = pwContactList_().loopCount(); - real t = this->currentTime(); - - pFlow::sphereInteractionKernels::pwInteractionFunctor - pwInteraction( - this->dt(), - this->forceModel_(), - pwContactList_(), - geometryMotion_.getTriangleAccessor(), - geometryMotion_.getModel(t) , - sphParticles_.diameter().deviceVectorAll() , - sphParticles_.propertyId().deviceVectorAll(), - sphParticles_.pointPosition().deviceVectorAll(), - sphParticles_.velocity().deviceVectorAll(), - sphParticles_.rVelocity().deviceVectorAll() , - sphParticles_.contactForce().deviceVectorAll(), - sphParticles_.contactTorque().deviceVectorAll() , - geometryMotion_.triMotionIndex().deviceVectorAll(), - geometryMotion_.propertyId().deviceVectorAll(), - geometryMotion_.contactForceWall().deviceVectorAll() - ); - - Kokkos::parallel_for( - "", - rpPWInteraction(0,lastItem), - pwInteraction - ); - - - Kokkos::fence(); - - return true; -} \ No newline at end of file diff --git a/src/Interaction/sphereInteraction/sphereInteraction.hpp b/src/Interaction/sphereInteraction/sphereInteraction.hpp deleted file mode 100644 index b256c452..00000000 --- a/src/Interaction/sphereInteraction/sphereInteraction.hpp +++ /dev/null @@ -1,226 +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 __sphereInteraction_hpp__ -#define __sphereInteraction_hpp__ - -#include "interaction.hpp" -#include "sphereParticles.hpp" - -#include "sphereInteractionKernels.hpp" - -namespace pFlow -{ - -template< - typename contactForceModel, - typename geometryMotionModel, - template class contactListType> -class sphereInteraction -: - public interaction -{ -public: - - using GeometryMotionModel = geometryMotionModel; - - using ContactForceModel = contactForceModel; - - using MotionModel = typename geometryMotionModel::MotionModel; - - using ModelStorage = typename ContactForceModel::contactForceStorage; - - using IdType = typename interaction::IdType; - - using IndexType = typename interaction::IndexType; - - using ExecutionSpace = typename interaction::ExecutionSpace; - - using ContactListType = - contactListType; - - using PairsContainerType= typename contactSearch::PairContainerType; - -protected: - - /// const reference to geometry - const GeometryMotionModel& geometryMotion_; - - /// const reference to particles - const sphereParticles& sphParticles_; - - - /// contact force model - uniquePtr forceModel_ = nullptr; - - /// contact list for particle-particle interactoins (keeps the history) - uniquePtr ppContactList_ = nullptr; - - /// contact list for particle-wall interactions (keeps the history) - uniquePtr pwContactList_ = nullptr; - - /// timer for particle-particle interaction computations - Timer ppInteractionTimer_; - - /// timer for particle-wall interaction computations - Timer pwInteractionTimer_; - - bool createSphereInteraction(); - - bool managePPContactLists(); - - bool managePWContactLists(); - - /// range policy for p-p interaction execution - using rpPPInteraction = - Kokkos::RangePolicy, Kokkos::Schedule>; - - /// range policy for p-w interaction execution - using rpPWInteraction = rpPPInteraction; - -public: - - TypeInfoTemplate3("sphereInteraction", ContactForceModel, MotionModel, ContactListType); - - // constructor - - sphereInteraction( - systemControl& control, - const particles& prtcl, - const geometry& geom) - : - interaction(control, prtcl, geom), - geometryMotion_(dynamic_cast(geom)), - sphParticles_(dynamic_cast(prtcl)), - ppInteractionTimer_("sphere-sphere interaction", &this->timers()), - pwInteractionTimer_("sphere-wall interaction", &this->timers()) - { - if(!createSphereInteraction()) - { - fatalExit; - } - } - - add_vCtor - ( - interaction, - sphereInteraction, - systemControl - ); - - - bool beforeIteration() override - { - return true; - } - - - bool iterate() override - { - -//Info<<"before contact search"<contactSearch_) - { - - if( this->contactSearch_().ppEnterBroadSearch()) - { - //Info<<" before ppEnterBroadSearch"<contactSearch_().pwEnterBroadSearch()) - { - //Info<<" before pwEnterBroadSearch"<contactSearch_().ppPerformedBroadSearch()) - { - //Info<<" before afterBroadSearch"<contactSearch_().pwPerformedBroadSearch()) - { - //Info<<" before pwContactList_().afterBroadSearch()"< class cLT> +bool pFlow::sphereInteraction::createSphereInteraction() +{ + + realVector_D rhoD("densities", this->densities()); + + auto modelDict = this->subDict("model"); + + forceModel_ = makeUnique( + this->numMaterials(), + rhoD.deviceView(), + modelDict ); + + + uint32 nPrtcl = sphParticles_.size(); + + contactSearch_ = contactSearch::create( + subDict("contactSearch"), + sphParticles_.extendedDomain().domainBox(), + sphParticles_, + geometryMotion_, + timers()); + + ppContactList_ = makeUnique(nPrtcl+1); + + pwContactList_ = makeUnique(nPrtcl/5+1); + + return true; +} + + +template class cLT> +bool pFlow::sphereInteraction::sphereSphereInteraction() +{ + auto lastItem = ppContactList_().loopCount(); + + // create the kernel functor + pFlow::sphereInteractionKernels::ppInteractionFunctor + ppInteraction( + this->dt(), + this->forceModel_(), + ppContactList_(), // to be read + sphParticles_.diameter().deviceViewAll(), + sphParticles_.propertyId().deviceViewAll(), + sphParticles_.pointPosition().deviceViewAll(), + sphParticles_.velocity().deviceViewAll(), + sphParticles_.rVelocity().deviceViewAll(), + sphParticles_.contactForce().deviceViewAll(), + sphParticles_.contactTorque().deviceViewAll() + ); + + Kokkos::parallel_for( + "ppInteraction", + rpPPInteraction(0,lastItem), + ppInteraction + ); + + Kokkos::fence(); + + return true; +} + + +template class cLT> +bool pFlow::sphereInteraction::sphereWallInteraction() +{ + + uint32 lastItem = pwContactList_().loopCount(); + uint32 iter = this->currentIter(); + real t = this->currentTime(); + real dt = this->dt(); + + pFlow::sphereInteractionKernels::pwInteractionFunctor + pwInteraction( + dt, + this->forceModel_(), + pwContactList_(), + geometryMotion_.getTriangleAccessor(), + geometryMotion_.getModel(iter, t, dt) , + sphParticles_.diameter().deviceViewAll() , + sphParticles_.propertyId().deviceViewAll(), + sphParticles_.pointPosition().deviceViewAll(), + sphParticles_.velocity().deviceViewAll(), + sphParticles_.rVelocity().deviceViewAll() , + sphParticles_.contactForce().deviceViewAll(), + sphParticles_.contactTorque().deviceViewAll() , + geometryMotion_.triMotionIndex().deviceViewAll(), + geometryMotion_.propertyId().deviceViewAll(), + geometryMotion_.contactForceWall().deviceViewAll() + ); + + Kokkos::parallel_for( + "", + rpPWInteraction(0,lastItem), + pwInteraction + ); + + + Kokkos::fence(); + + return true; +} + + +template class cLT> +pFlow::sphereInteraction::sphereInteraction +( + systemControl& control, + const particles& prtcl, + const geometry& geom +) +: + interaction(control, prtcl, geom), + geometryMotion_(dynamic_cast(geom)), + sphParticles_(dynamic_cast(prtcl)), + boundaryInteraction_(sphParticles_,geometryMotion_), + ppInteractionTimer_("sphere-sphere interaction (internal)", &this->timers()), + pwInteractionTimer_("sphere-wall interaction (internal)", &this->timers()), + boundaryInteractionTimer_("sphere-sphere interaction (boundary)",&this->timers()), + contactListMangementTimer_("list management (interal)", &this->timers()), + contactListMangementBoundaryTimer_("list management (boundary)", &this->timers()) +{ + + if(!createSphereInteraction()) + { + fatalExit; + } + + for(uint32 i=0; i<6; i++) + { + activeBoundaries_[i] = boundaryInteraction_[i].ppPairsAllocated(); + } +} + +template class cLT> +bool pFlow::sphereInteraction::beforeIteration() +{ + return true; +} + +template class cLT> +bool pFlow::sphereInteraction::iterate() +{ + + timeInfo ti = this->TimeInfo(); + auto iter = ti.iter(); + auto t = ti.t(); + auto dt = ti.dt(); + + auto& contactSearchRef = contactSearch_(); + + bool broadSearch = contactSearchRef.enterBroadSearch(ti); + bool broadSearchBoundary = contactSearchRef.enterBroadSearchBoundary(ti); + + /// update boundaries of the fields that are being used by inreaction + sphParticles_.diameter().updateBoundaries(DataDirection::SlaveToMaster); + sphParticles_.velocity().updateBoundaries(DataDirection::SlaveToMaster); + sphParticles_.rVelocity().updateBoundaries(DataDirection::SlaveToMaster); + sphParticles_.propertyId().updateBoundaries(DataDirection::SlaveToMaster); + + /// lists + if(broadSearch) + { + contactListMangementTimer_.start(); + ComputationTimer().start(); + ppContactList_().beforeBroadSearch(); + pwContactList_().beforeBroadSearch(); + ComputationTimer().end(); + contactListMangementTimer_.pause(); + } + + if(broadSearchBoundary) + { + contactListMangementBoundaryTimer_.start(); + ComputationTimer().start(); + for(uint32 i=0; i<6u; i++) + { + if(activeBoundaries_[i]) + { + auto& BI = boundaryInteraction_[i]; + BI.ppPairs().beforeBroadSearch(); + BI.pwPairs().beforeBroadSearch(); + } + } + ComputationTimer().end(); + contactListMangementBoundaryTimer_.pause(); + } + + if( sphParticles_.numActive()<=0)return true; + + ComputationTimer().start(); + if( !contactSearchRef.broadSearch( + ti, + ppContactList_(), + pwContactList_()) ) + { + fatalErrorInFunction<< + "unable to perform broadSearch.\n"; + fatalExit; + } + + for(uint32 i=0; i<6u; i++) + { + if(activeBoundaries_[i]) + { + auto& BI = boundaryInteraction_[i]; + if(!contactSearchRef.boundaryBroadSearch( + i, + ti, + BI.ppPairs(), + BI.pwPairs()) + ) + { + fatalErrorInFunction<< + "failed to perform broadSearch for boundary index "<(true); + const auto& cfModel = this->forceModel_(); + uint32 step=1; + boundaryInteractionTimer_.start(); + ComputationTimer().start(); + while(requireStep.anyElement(true) && step <= 10) + { + for(uint32 i=0; i<6u; i++) + { + if(requireStep[i] ) + { + requireStep[i] = boundaryInteraction_[i].sphereSphereInteraction( + dt, + this->forceModel_(), + step + ); + } + } + step++; + } + ComputationTimer().end(); + boundaryInteractionTimer_.pause(); + + + ppInteractionTimer_.start(); + ComputationTimer().start(); + sphereSphereInteraction(); + ComputationTimer().end(); + ppInteractionTimer_.end(); + + + pwInteractionTimer_.start(); + ComputationTimer().start(); + sphereWallInteraction(); + ComputationTimer().start(); + pwInteractionTimer_.end(); + + { + boundaryInteractionTimer_.resume(); + ComputationTimer().start(); + auto requireStep = boundariesMask<6>(true); + + uint32 step = 11; + const auto& cfModel = this->forceModel_(); + while( requireStep.anyElement(true) && step < 20 ) + { + for(uint32 i=0; i<6u; i++) + { + if(requireStep[i]) + { + requireStep[i] = boundaryInteraction_[i].sphereSphereInteraction( + dt, + cfModel, + step + ); + } + } + step++; + } + ComputationTimer().end(); + boundaryInteractionTimer_.end(); + } + + return true; +} + +template class cLT> +bool pFlow::sphereInteraction::afterIteration() +{ + return true; +} + +template class cLT> +bool pFlow::sphereInteraction::hearChanges +( + real t, + real dt, + uint32 iter, + const message& msg, + const anyList& varList +) +{ + if(msg.equivalentTo(message::ITEM_REARRANGE)) + { + notImplementedFunction; + } + return true; +} \ No newline at end of file diff --git a/src/Interaction/sphereInteraction/sphereInteraction/sphereInteraction.hpp b/src/Interaction/sphereInteraction/sphereInteraction/sphereInteraction.hpp new file mode 100644 index 00000000..472ba519 --- /dev/null +++ b/src/Interaction/sphereInteraction/sphereInteraction/sphereInteraction.hpp @@ -0,0 +1,169 @@ +/*------------------------------- 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 __sphereInteraction_hpp__ +#define __sphereInteraction_hpp__ + +#include "interaction.hpp" +#include "sphereParticles.hpp" +#include "boundarySphereInteractionList.hpp" +#include "sphereInteractionKernels.hpp" +#include "boundariesMask.hpp" +#include "MPITimer.hpp" +//#include "unsortedContactList.hpp" + + + +namespace pFlow +{ + +template< + typename contactForceModel, + typename geometryMotionModel, + template class contactListType> +class sphereInteraction +: + public interaction +{ +public: + + using GeometryMotionModel = geometryMotionModel; + + using ContactForceModel = contactForceModel; + + using MotionModel = typename geometryMotionModel::MotionModel; + + using ModelStorage = typename ContactForceModel::contactForceStorage; + + using BoundaryListType = boundarySphereInteractionList; + + using IdType = uint32; + + using IndexType = uint32; + + using ContactListType = + contactListType; + + //using BoundaryContactListType = unsortedContactList; + + + +private: + + /// const reference to geometry + const GeometryMotionModel& geometryMotion_; + + /// const reference to particles + const sphereParticles& sphParticles_; + + /// particle-particle and particle-wall interactions at boundaries + BoundaryListType boundaryInteraction_; + + /// a mask for active boundaries (boundaries with intreaction) + boundariesMask<6> activeBoundaries_; + + /// contact search object for pp and pw interactions + uniquePtr contactSearch_ = nullptr; + + /// contact force model + uniquePtr forceModel_ = nullptr; + + /// contact list for particle-particle interactoins (keeps the history) + uniquePtr ppContactList_ = nullptr; + + /// contact list for particle-wall interactions (keeps the history) + uniquePtr pwContactList_ = nullptr; + + + /// timer for particle-particle interaction computations + Timer ppInteractionTimer_; + + /// timer for particle-wall interaction computations + Timer pwInteractionTimer_; + + /// timer for boundary interaction time + Timer boundaryInteractionTimer_; + + /// timer for managing contact lists (only inernal points) + Timer contactListMangementTimer_; + + Timer contactListMangementBoundaryTimer_; + + + + bool createSphereInteraction(); + + bool sphereSphereInteraction(); + + bool sphereWallInteraction(); + + /// range policy for p-p interaction execution + using rpPPInteraction = + Kokkos::RangePolicy, Kokkos::Schedule>; + + /// range policy for p-w interaction execution + using rpPWInteraction = rpPPInteraction; + +public: + + TypeInfoTemplate13("sphereInteraction", ContactForceModel, MotionModel, ContactListType); + + /// Constructor from components + sphereInteraction( + systemControl& control, + const particles& prtcl, + const geometry& geom); + + + /// Add virtual constructor + add_vCtor + ( + interaction, + sphereInteraction, + systemControl + ); + + /// This is called in time loop, before iterate. (overriden from demComponent) + bool beforeIteration() override; + + /// This is called in time loop. Perform the main calculations + /// when the component should evolve along time. (overriden from demComponent) + bool iterate() override; + + /// This is called in time loop, after iterate. (overriden from demComponent) + bool afterIteration() override; + + /// Check for changes in the point structures. (overriden from observer) + bool hearChanges( + real t, + real dt, + uint32 iter, + const message& msg, + const anyList& varList)override; + + +}; + + +} + +#include "sphereInteraction.cpp" + +#endif //__sphereInteraction_hpp__ diff --git a/src/Interaction/sphereInteraction/sphereInteractionKernels.hpp b/src/Interaction/sphereInteraction/sphereInteraction/sphereInteractionKernels.hpp similarity index 94% rename from src/Interaction/sphereInteraction/sphereInteractionKernels.hpp rename to src/Interaction/sphereInteraction/sphereInteraction/sphereInteractionKernels.hpp index cef5fa72..751c0fec 100644 --- a/src/Interaction/sphereInteraction/sphereInteractionKernels.hpp +++ b/src/Interaction/sphereInteraction/sphereInteraction/sphereInteractionKernels.hpp @@ -42,7 +42,7 @@ struct ppInteractionFunctor ContactListType tobeFilled_; deviceViewType1D diam_; - deviceViewType1D propId_; + deviceViewType1D propId_; deviceViewType1D pos_; deviceViewType1D lVel_; deviceViewType1D rVel_; @@ -55,7 +55,7 @@ struct ppInteractionFunctor ContactForceModel forceModel, ContactListType tobeFilled, deviceViewType1D diam, - deviceViewType1D propId, + deviceViewType1D propId, deviceViewType1D pos, deviceViewType1D lVel, deviceViewType1D rVel, @@ -75,7 +75,7 @@ struct ppInteractionFunctor {} INLINE_FUNCTION_HD - void operator()(const int32 n)const + void operator()(const uint32 n)const { if(!tobeFilled_.isValid(n))return; @@ -181,14 +181,14 @@ struct pwInteractionFunctor MotionModel motionModel_; deviceViewType1D diam_; - deviceViewType1D propId_; + deviceViewType1D propId_; deviceViewType1D pos_; deviceViewType1D lVel_; deviceViewType1D rVel_; deviceViewType1D cForce_; deviceViewType1D cTorque_; - deviceViewType1D wTriMotionIndex_; - deviceViewType1D wPropId_; + deviceViewType1D wTriMotionIndex_; + deviceViewType1D wPropId_; deviceViewType1D wCForce_; @@ -199,14 +199,14 @@ struct pwInteractionFunctor TraingleAccessor triangles, MotionModel motionModel , deviceViewType1D diam , - deviceViewType1D propId, + deviceViewType1D propId, deviceViewType1D pos , deviceViewType1D lVel, deviceViewType1D rVel, deviceViewType1D cForce, deviceViewType1D cTorque , - deviceViewType1D wTriMotionIndex, - deviceViewType1D wPropId, + deviceViewType1D wTriMotionIndex, + deviceViewType1D wPropId, deviceViewType1D wCForce) : dt_(dt), @@ -261,7 +261,7 @@ struct pwInteractionFunctor int32 propId_i = propId_[i]; int32 wPropId_j = wPropId_[tj]; - realx3 FCn, FCt, Mri, Mrj, Mij, Mji; + realx3 FCn, FCt, Mri, Mrj, Mij; //output<< "before "<; - -template class pFlow::sphereInteraction< - pFlow::cfModels::limitedLinearNormalRolling, - pFlow::fixedGeometry, - pFlow::sortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::nonLimitedLinearNormalRolling, - pFlow::fixedGeometry, - pFlow::unsortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::nonLimitedLinearNormalRolling, - pFlow::fixedGeometry, - pFlow::sortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::limitedLinearNormalRolling, - pFlow::rotationAxisMotionGeometry, - pFlow::unsortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::limitedLinearNormalRolling, - pFlow::rotationAxisMotionGeometry, - pFlow::sortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::nonLimitedLinearNormalRolling, - pFlow::rotationAxisMotionGeometry, - pFlow::unsortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::nonLimitedLinearNormalRolling, - pFlow::rotationAxisMotionGeometry, - pFlow::sortedContactList>; - - -template class pFlow::sphereInteraction< - pFlow::cfModels::limitedLinearNormalRolling, - pFlow::vibratingMotionGeometry, - pFlow::unsortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::limitedLinearNormalRolling, - pFlow::vibratingMotionGeometry, - pFlow::sortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::nonLimitedLinearNormalRolling, - pFlow::vibratingMotionGeometry, - pFlow::unsortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::nonLimitedLinearNormalRolling, - pFlow::vibratingMotionGeometry, - pFlow::sortedContactList>; - - -template class pFlow::sphereInteraction< - pFlow::cfModels::limitedLinearNormalRolling, - pFlow::multiRotationAxisMotionGeometry, - pFlow::unsortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::limitedLinearNormalRolling, - pFlow::multiRotationAxisMotionGeometry, - pFlow::sortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::nonLimitedLinearNormalRolling, - pFlow::multiRotationAxisMotionGeometry, - pFlow::unsortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::nonLimitedLinearNormalRolling, - pFlow::multiRotationAxisMotionGeometry, - pFlow::sortedContactList>; - -/// non-linear models - -template class pFlow::sphereInteraction< - pFlow::cfModels::limitedNonLinearNormalRolling, - pFlow::fixedGeometry, - pFlow::unsortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::limitedNonLinearNormalRolling, - pFlow::fixedGeometry, - pFlow::sortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::nonLimitedNonLinearNormalRolling, - pFlow::fixedGeometry, - pFlow::unsortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::nonLimitedNonLinearNormalRolling, - pFlow::fixedGeometry, - pFlow::sortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::limitedNonLinearNormalRolling, - pFlow::rotationAxisMotionGeometry, - pFlow::unsortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::limitedNonLinearNormalRolling, - pFlow::rotationAxisMotionGeometry, - pFlow::sortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::nonLimitedNonLinearNormalRolling, - pFlow::rotationAxisMotionGeometry, - pFlow::unsortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::nonLimitedNonLinearNormalRolling, - pFlow::rotationAxisMotionGeometry, - pFlow::sortedContactList>; - - -template class pFlow::sphereInteraction< - pFlow::cfModels::limitedNonLinearNormalRolling, - pFlow::vibratingMotionGeometry, - pFlow::unsortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::limitedNonLinearNormalRolling, - pFlow::vibratingMotionGeometry, - pFlow::sortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::nonLimitedNonLinearNormalRolling, - pFlow::vibratingMotionGeometry, - pFlow::unsortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::nonLimitedNonLinearNormalRolling, - pFlow::vibratingMotionGeometry, - pFlow::sortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::limitedNonLinearNormalRolling, - pFlow::multiRotationAxisMotionGeometry, - pFlow::unsortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::limitedNonLinearNormalRolling, - pFlow::multiRotationAxisMotionGeometry, - pFlow::sortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::nonLimitedNonLinearNormalRolling, - pFlow::multiRotationAxisMotionGeometry, - pFlow::unsortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::nonLimitedNonLinearNormalRolling, - pFlow::multiRotationAxisMotionGeometry, - pFlow::sortedContactList>; - - -// - nonLinearMod models -template class pFlow::sphereInteraction< - pFlow::cfModels::limitedNonLinearModNormalRolling, - pFlow::fixedGeometry, - pFlow::unsortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::limitedNonLinearModNormalRolling, - pFlow::fixedGeometry, - pFlow::sortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::nonLimitedNonLinearModNormalRolling, - pFlow::fixedGeometry, - pFlow::unsortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::nonLimitedNonLinearModNormalRolling, - pFlow::fixedGeometry, - pFlow::sortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::limitedNonLinearModNormalRolling, - pFlow::rotationAxisMotionGeometry, - pFlow::unsortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::limitedNonLinearModNormalRolling, - pFlow::rotationAxisMotionGeometry, - pFlow::sortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::nonLimitedNonLinearModNormalRolling, - pFlow::rotationAxisMotionGeometry, - pFlow::unsortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::nonLimitedNonLinearModNormalRolling, - pFlow::rotationAxisMotionGeometry, - pFlow::sortedContactList>; - - -template class pFlow::sphereInteraction< - pFlow::cfModels::limitedNonLinearModNormalRolling, - pFlow::vibratingMotionGeometry, - pFlow::unsortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::limitedNonLinearModNormalRolling, - pFlow::vibratingMotionGeometry, - pFlow::sortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::nonLimitedNonLinearModNormalRolling, - pFlow::vibratingMotionGeometry, - pFlow::unsortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::nonLimitedNonLinearModNormalRolling, - pFlow::vibratingMotionGeometry, - pFlow::sortedContactList>; - - -template class pFlow::sphereInteraction< - pFlow::cfModels::limitedNonLinearModNormalRolling, - pFlow::multiRotationAxisMotionGeometry, - pFlow::unsortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::limitedNonLinearModNormalRolling, - pFlow::multiRotationAxisMotionGeometry, - pFlow::sortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::nonLimitedNonLinearModNormalRolling, - pFlow::multiRotationAxisMotionGeometry, - pFlow::unsortedContactList>; - -template class pFlow::sphereInteraction< - pFlow::cfModels::nonLimitedNonLinearModNormalRolling, - pFlow::multiRotationAxisMotionGeometry, - pFlow::sortedContactList>; diff --git a/src/Interaction/sphereInteraction/sphereInteractionsLinearModels.cpp b/src/Interaction/sphereInteraction/sphereInteractionsLinearModels.cpp new file mode 100644 index 00000000..1c45936b --- /dev/null +++ b/src/Interaction/sphereInteraction/sphereInteractionsLinearModels.cpp @@ -0,0 +1,63 @@ +/*------------------------------- 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 "sphereInteraction.hpp" +#include "geometryMotions.hpp" +#include "contactForceModels.hpp" +#include "unsortedContactList.hpp" +#include "sortedContactList.hpp" +#include "createBoundarySphereInteraction.hpp" + + + +#define createInteraction(ForceModel,GeomModel) \ + \ + template class pFlow::sphereInteraction< \ + ForceModel, \ + GeomModel, \ + pFlow::unsortedContactList>; \ + \ + template class pFlow::sphereInteraction< \ + ForceModel, \ + GeomModel, \ + pFlow::sortedContactList>; \ + createBoundarySphereInteraction(ForceModel, GeomModel) + + +// stationaryGeometry +createInteraction(pFlow::cfModels::limitedLinearNormalRolling, pFlow::stationaryGeometry); +createInteraction(pFlow::cfModels::nonLimitedLinearNormalRolling,pFlow::stationaryGeometry); + +// rotationAxisMotionGeometry +createInteraction(pFlow::cfModels::limitedLinearNormalRolling, pFlow::rotationAxisMotionGeometry); +createInteraction(pFlow::cfModels::nonLimitedLinearNormalRolling,pFlow::rotationAxisMotionGeometry); + +// vibratingMotionGeometry +createInteraction(pFlow::cfModels::limitedLinearNormalRolling, pFlow::vibratingMotionGeometry); +createInteraction(pFlow::cfModels::nonLimitedLinearNormalRolling,pFlow::vibratingMotionGeometry); + +// conveyorBeltGeometry +createInteraction(pFlow::cfModels::limitedLinearNormalRolling, pFlow::conveyorBeltMotionGeometry); +createInteraction(pFlow::cfModels::nonLimitedLinearNormalRolling,pFlow::conveyorBeltMotionGeometry); + +// multiRotationAxisMotionGeometry +//createInteraction(pFlow::cfModels::limitedLinearNormalRolling, pFlow::multiRotationAxisMotionGeometry); +//createInteraction(pFlow::cfModels::nonLimitedLinearNormalRolling,pFlow::multiRotationAxisMotionGeometry); + diff --git a/src/Interaction/sphereInteraction/sphereInteractionsNonLinearModModels.cpp b/src/Interaction/sphereInteraction/sphereInteractionsNonLinearModModels.cpp new file mode 100644 index 00000000..d7f79ff7 --- /dev/null +++ b/src/Interaction/sphereInteraction/sphereInteractionsNonLinearModModels.cpp @@ -0,0 +1,62 @@ +/*------------------------------- 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 "sphereInteraction.hpp" +#include "geometryMotions.hpp" +#include "contactForceModels.hpp" +#include "unsortedContactList.hpp" +#include "sortedContactList.hpp" +#include "createBoundarySphereInteraction.hpp" + + + +#define createInteraction(ForceModel,GeomModel) \ + \ + template class pFlow::sphereInteraction< \ + ForceModel, \ + GeomModel, \ + pFlow::unsortedContactList>; \ + \ + template class pFlow::sphereInteraction< \ + ForceModel, \ + GeomModel, \ + pFlow::sortedContactList>; \ + createBoundarySphereInteraction(ForceModel, GeomModel) + + +// stationaryGeometry +createInteraction(pFlow::cfModels::limitedNonLinearModNormalRolling, pFlow::stationaryGeometry); +createInteraction(pFlow::cfModels::nonLimitedNonLinearModNormalRolling,pFlow::stationaryGeometry); + +// rotationAxisMotionGeometry +createInteraction(pFlow::cfModels::limitedNonLinearModNormalRolling, pFlow::rotationAxisMotionGeometry); +createInteraction(pFlow::cfModels::nonLimitedNonLinearModNormalRolling,pFlow::rotationAxisMotionGeometry); + +// vibratingMotionGeometry +createInteraction(pFlow::cfModels::limitedNonLinearModNormalRolling, pFlow::vibratingMotionGeometry); +createInteraction(pFlow::cfModels::nonLimitedNonLinearModNormalRolling,pFlow::vibratingMotionGeometry); + +// conveyorBeltMotionGeometry +createInteraction(pFlow::cfModels::limitedNonLinearModNormalRolling, pFlow::conveyorBeltMotionGeometry); +createInteraction(pFlow::cfModels::nonLimitedNonLinearModNormalRolling,pFlow::conveyorBeltMotionGeometry); + +// multiRotationAxisMotionGeometry +//createInteraction(pFlow::cfModels::limitedNonLinearModNormalRolling, pFlow::multiRotationAxisMotionGeometry); +//createInteraction(pFlow::cfModels::nonLimitedNonLinearModNormalRolling,pFlow::multiRotationAxisMotionGeometry); diff --git a/src/Interaction/sphereInteraction/sphereInteractionsNonLinearModels.cpp b/src/Interaction/sphereInteraction/sphereInteractionsNonLinearModels.cpp new file mode 100644 index 00000000..c13ec77e --- /dev/null +++ b/src/Interaction/sphereInteraction/sphereInteractionsNonLinearModels.cpp @@ -0,0 +1,62 @@ +/*------------------------------- 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 "sphereInteraction.hpp" +#include "geometryMotions.hpp" +#include "contactForceModels.hpp" +#include "unsortedContactList.hpp" +#include "sortedContactList.hpp" +#include "createBoundarySphereInteraction.hpp" + + + +#define createInteraction(ForceModel,GeomModel) \ + \ + template class pFlow::sphereInteraction< \ + ForceModel, \ + GeomModel, \ + pFlow::unsortedContactList>; \ + \ + template class pFlow::sphereInteraction< \ + ForceModel, \ + GeomModel, \ + pFlow::sortedContactList>; \ + createBoundarySphereInteraction(ForceModel, GeomModel) + + +// stationaryGeometry +createInteraction(pFlow::cfModels::limitedNonLinearNormalRolling, pFlow::stationaryGeometry); +createInteraction(pFlow::cfModels::nonLimitedNonLinearNormalRolling,pFlow::stationaryGeometry); + +// rotationAxisMotionGeometry +createInteraction(pFlow::cfModels::limitedNonLinearNormalRolling, pFlow::rotationAxisMotionGeometry); +createInteraction(pFlow::cfModels::nonLimitedNonLinearNormalRolling,pFlow::rotationAxisMotionGeometry); + +// vibratingMotionGeometry +createInteraction(pFlow::cfModels::limitedNonLinearNormalRolling, pFlow::vibratingMotionGeometry); +createInteraction(pFlow::cfModels::nonLimitedNonLinearNormalRolling,pFlow::vibratingMotionGeometry); + +// conveyorBeltMotionGeometry +createInteraction(pFlow::cfModels::limitedNonLinearNormalRolling, pFlow::conveyorBeltMotionGeometry); +createInteraction(pFlow::cfModels::nonLimitedNonLinearNormalRolling,pFlow::conveyorBeltMotionGeometry); + +// multiRotationAxisMotionGeometry +//createInteraction(pFlow::cfModels::limitedNonLinearNormalRolling, pFlow::multiRotationAxisMotionGeometry); +//createInteraction(pFlow::cfModels::nonLimitedNonLinearNormalRolling,pFlow::multiRotationAxisMotionGeometry); diff --git a/src/MotionModel/CMakeLists.txt b/src/MotionModel/CMakeLists.txt index 9438c2ab..1e92a989 100644 --- a/src/MotionModel/CMakeLists.txt +++ b/src/MotionModel/CMakeLists.txt @@ -1,13 +1,22 @@ list(APPEND SourceFiles -entities/rotatingAxis/rotatingAxis.cpp -entities/multiRotatingAxis/multiRotatingAxis.cpp entities/timeInterval/timeInterval.cpp -entities/vibrating/vibrating.cpp -fixedWall/fixedWall.cpp + +entities/rotatingAxis/rotatingAxis.cpp rotatingAxisMotion/rotatingAxisMotion.cpp -multiRotatingAxisMotion/multiRotatingAxisMotion.cpp + +entities/vibrating/vibrating.cpp vibratingMotion/vibratingMotion.cpp + +stationaryWall/stationaryWall.cpp +entities/stationary/stationary.cpp + +conveyorBeltMotion/conveyorBeltMotion.cpp +entities/conveyorBelt/conveyorBelt.cpp + +#entities/multiRotatingAxis/multiRotatingAxis.cpp +#multiRotatingAxisMotion/multiRotatingAxisMotion.cpp + ) set(link_libs Kokkos::kokkos phasicFlow) diff --git a/src/MotionModel/MotionModel/MotionModel.cpp b/src/MotionModel/MotionModel/MotionModel.cpp new file mode 100644 index 00000000..6a530eaa --- /dev/null +++ b/src/MotionModel/MotionModel/MotionModel.cpp @@ -0,0 +1,147 @@ +/*------------------------------- 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. + +-----------------------------------------------------------------------------*/ + + +template +inline +bool pFlow::MotionModel::impl_nameToIndex(const word& name, uint32& indx)const +{ + if( auto i = componentNames_.findi(name); i == -1) + { + return false; + } + else + { + indx = static_cast(i); + return true; + } + +} + +template +inline +bool pFlow::MotionModel::impl_indexToName(uint32 i, word& name)const +{ + if(i < numComponents_ ) + { + name = componentNames_[i]; + return true; + } + else + { + return false; + } +} + +template +inline +bool pFlow::MotionModel::impl_readDictionary +( + const dictionary& dict +) +{ + + auto modelName = dict.getVal("motionModel"); + + if(modelName != getTypeName()) + { + fatalErrorInFunction<< + " motionModel should be "<< Yellow_Text(getTypeName())<< + ", but found "<< Yellow_Text(modelName)< components( + "Read::modelComponent", + compNames.size()+1, + 0, + RESERVE()); + + componentNames_.clear(); + + + for(auto& cName: compNames) + { + auto& compDict = motionInfo.subDict(cName); + + if(auto compPtr = makeUnique(compDict); compPtr) + { + components.push_back(compPtr()); + componentNames_.push_back(cName); + } + } + + if( !componentNames_.search("none") ) + { + components.push_back + ( + impl_noneComponent() + ); + componentNames_.push_back("none"); + } + + motionComponents_.assign(components); + numComponents_ = motionComponents_.size(); + + return true; +} + + +template +inline +bool pFlow::MotionModel::impl_writeDictionary +( + dictionary& dict +)const +{ + word modelName = getTypeName(); + + dict.add("motionModel", modelName ); + + auto modelDictName = modelName+"Info"; + + auto& motionInfo = dict.subDictOrCreate(modelDictName); + auto hostComponents = motionComponents_.hostView(); + + ForAll(i, motionComponents_) + { + + auto& axDict = motionInfo.subDictOrCreate(componentNames_[i]); + if( !hostComponents[i].write(axDict)) + { + fatalErrorInFunction<< + " error in writing axis "<< componentNames_[i] << " to dicrionary " + << motionInfo.globalName()< +pFlow::MotionModel::MotionModel() +: + motionComponents_("motionComponents") +{} \ No newline at end of file diff --git a/src/MotionModel/MotionModel/MotionModel.hpp b/src/MotionModel/MotionModel/MotionModel.hpp new file mode 100644 index 00000000..6dae3175 --- /dev/null +++ b/src/MotionModel/MotionModel/MotionModel.hpp @@ -0,0 +1,246 @@ +/*------------------------------- 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 __MotionModel_hpp__ +#define __MotionModel_hpp__ + + + +#include "VectorSingles.hpp" +#include "Vector.hpp" +#include "List.hpp" +#include "dictionary.hpp" + + +namespace pFlow +{ + +/** + * @brief Motion model abstract class (CRTP) for all the motion models +*/ +template +class MotionModel +{ +public: + + using ModelType = Model; + + using ModelComponent = Component; + + using ComponentVector_D = VectorSingle; + + /** Motion model class to be passed to computational units/kernels for + * transfing points and returning velocities at various positions + */ + class ModelInterface + { + private: + + deviceViewType1D components_; + + uint32 numComponents_=0; + + public: + + INLINE_FUNCTION_HD + ModelInterface + ( + deviceViewType1D Comps, + uint32 numComp + ): + components_(Comps), + numComponents_(numComp) + {} + + INLINE_FUNCTION_HD + ModelInterface(const ModelInterface&) = default; + + INLINE_FUNCTION_HD + ModelInterface& operator=(const ModelInterface&) = default; + + INLINE_FUNCTION_HD + ModelInterface(ModelInterface&&) noexcept = default; + + INLINE_FUNCTION_HD + ModelInterface& operator=(ModelInterface&&) noexcept= default; + + INLINE_FUNCTION_HD + ~ModelInterface()=default; + + INLINE_FUNCTION_HD + realx3 pointVelocity(uint32 n, const realx3& p)const + { + return components_[n].linVelocityPoint(p); + } + + INLINE_FUNCTION_HD + realx3 operator()(uint32 n, const realx3& p)const + { + return pointVelocity(n,p); + } + + INLINE_FUNCTION_HD + realx3 transferPoint(uint32 n, const realx3 p, real dt)const + { + return components_[n].transferPoint(p, dt); + } + + INLINE_FUNCTION_HD + uint32 size()const + { + return numComponents_; + } + }; + +private: + + // friends + friend ModelType; + + /// Number of axes components + uint32 numComponents_= 0; + + /// Vector to store motion components + ComponentVector_D motionComponents_; + + /// Names of compoenents + wordList componentNames_; + +protected: + + /// @brief obtain a reference to the actual motion model + inline + auto& getModel() + { + return static_cast(*this); + } + + /// @brief Obtain a const reference to the actual motion model + inline + const auto& getModel()const + { + return static_cast(*this); + } + + /// Return a none object for the motion model + inline + auto impl_noneComponent()const + { + return ModelType::noneComponent(); + } + + /// Name of the compoenent to index of the component + bool impl_nameToIndex(const word& name, uint32& idx)const; + + /// Component index to motion component name + bool impl_indexToName(uint32 i, word& name)const; + + /// const reference to the list of component names + inline + const wordList& impl_componentNames()const + { + return componentNames_; + } + + /// Return model interface + auto impl_getModelInterface(uint32 iter, real t, real dt)const + { + getModel().impl_setTime(iter, t, dt); + + return ModelInterface( + motionComponents_.deviceViewAll(), + numComponents_); + } + + /// Read from dictionary + bool impl_readDictionary(const dictionary& dict); + + /// Write to dictionary + bool impl_writeDictionary(dictionary& dict)const; + +public: + + // - Constructors + + /// Empty + MotionModel(); + + /// Copy constructor + MotionModel(const MotionModel&) = default; + + /// Move constructor + MotionModel(MotionModel&&) = default; + + /// Copy assignment + MotionModel& operator=(const MotionModel&) = default; + + /// No move assignment + MotionModel& operator=(MotionModel&&) = default; + + /// Destructor + ~MotionModel() = default; + + // - Methods + + /// name of the compoenent to index of the component + bool nameToIndex(const word& name, uint32& idx)const + { + return getModel().impl_nameToIndex(name, idx); + } + + /// Component index to motion component name + bool indexToName(uint32 idx, word& name)const + { + return getModel().impl_indexToName(idx, name); + } + + /// @brief Return a const reference to the list of compoenent names + /// @return + const wordList& componentNames()const + { + return getModel().impl_componentNames(); + } + + /// Is the wall assocciated to this motion component moving? + bool isMoving()const + { + return getModel().impl_isMoving(); + } + + /// Move the component itself + bool move(uint32 iter, real t, real dt) + { + return getModel().impl_move(iter, t, dt); + } + + /// Obtain an object to model interface + auto getModelInterface(uint32 iter, real t, real dt)const + { + return getModel().impl_getModelInterface(iter, t, dt); + } + +}; + +} // pFlow + +#include "MotionModel.cpp" + + +#endif //__MotionModel_hpp__ diff --git a/src/MotionModel/conveyorBeltMotion/conveyorBeltMotion.cpp b/src/MotionModel/conveyorBeltMotion/conveyorBeltMotion.cpp new file mode 100644 index 00000000..2315e43e --- /dev/null +++ b/src/MotionModel/conveyorBeltMotion/conveyorBeltMotion.cpp @@ -0,0 +1,75 @@ +/*------------------------------- 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 "conveyorBeltMotion.hpp" + + +pFlow::conveyorBeltMotion::conveyorBeltMotion +( + const objectFile &objf, + repository *owner +) +: + fileDictionary(objf, owner) +{ + + if(!impl_readDictionary(*this) ) + { + fatalErrorInFunction; + fatalExit; + } +} + +pFlow::conveyorBeltMotion::conveyorBeltMotion +( + const objectFile &objf, + const dictionary &dict, + repository *owner +) +: + fileDictionary(objf, dict, owner) +{ + if(!impl_readDictionary(*this) ) + { + fatalErrorInFunction; + fatalExit; + } +} + +bool pFlow::conveyorBeltMotion::write +( + iOstream &os, + const IOPattern &iop +) const +{ + // a global dictionary + dictionary newDict(fileDictionary::dictionary::name(), true); + if( iop.thisProcWriteData() ) + { + if( !this->impl_writeDictionary(newDict) || + !newDict.write(os)) + { + fatalErrorInFunction<< + " error in writing to dictionary "<< newDict.globalName()< +{ +protected: + + friend MotionModel; + + bool impl_isMoving()const + { + return false; + } + + bool impl_move(uint32, real, real)const + { + return true; + } + + void impl_setTime(uint32 ,real ,real )const + {} + +public: + + TypeInfo("conveyorBeltMotion"); + + conveyorBeltMotion(const objectFile& objf, repository* owner); + + conveyorBeltMotion( + const objectFile& objf, + const dictionary& dict, + repository* owner); + + + using fileDictionary::write; + + bool write(iOstream& os, const IOPattern& iop)const override; + + static + auto noneComponent() + { + return conveyorBelt(); + } +}; + +} // pFlow + + +#endif // __conveyorBeltMotion_hpp__ \ No newline at end of file diff --git a/src/phasicFlow/structuredData/pointStructure/selectors/selectRange/selectRange.cpp b/src/MotionModel/entities/conveyorBelt/conveyorBelt.cpp similarity index 54% rename from src/phasicFlow/structuredData/pointStructure/selectors/selectRange/selectRange.cpp rename to src/MotionModel/entities/conveyorBelt/conveyorBelt.cpp index 09315952..2e63a5a1 100644 --- a/src/phasicFlow/structuredData/pointStructure/selectors/selectRange/selectRange.cpp +++ b/src/MotionModel/entities/conveyorBelt/conveyorBelt.cpp @@ -18,51 +18,53 @@ Licence: -----------------------------------------------------------------------------*/ - -#include "selectRange.hpp" +#include "conveyorBelt.hpp" #include "dictionary.hpp" -void pFlow::selectRange::selectAllPointsInRange() -{ - // to reduct allocations - int32 maxNum = (end_ - begin_)/stride_+2; - - selectedPoints_.reserve (maxNum); - selectedPoints_.clear(); - - for(int32 i = begin_; i("begin") - ), - end_ - ( - dict.subDict("selectRangeInfo").getValOrSet("end", pStruct.size()) - ), - stride_ - ( - dict.subDict("selectRangeInfo").getValOrSet("stride", 1) - ) -{ - begin_ = max(begin_,1); - end_ = min(end_, static_cast(pStruct.size())); - stride_ = max(stride_,1); +FUNCTION_H +bool pFlow::conveyorBelt::read(const dictionary& dict) +{ - selectAllPointsInRange(); + tangentVelocity_ = dict.getVal("tangentVelocity"); + + return true; } + +FUNCTION_H +bool pFlow::conveyorBelt::write(dictionary& dict) const +{ + if( !dict.add("tangentVelocity", tangentVelocity_) ) + { + fatalErrorInFunction<< + " error in writing tangentVelocity to dictionary "<< dict.globalName()<endTime_) return 0; - - return static_cast( (currentTime - startTime_ + interval_)*rate_ - numInserted_ ); - } - - size_t addToNumInserted(size_t newInserted) - { - return numInserted_ += newInserted; - } + realx3 tangentVelocity_{0, 0, 0}; public: + TypeInfoNV("conveyorBelt"); - timeFlowControl(const dictionary& dict); + FUNCTION_HD + conveyorBelt()=default; + FUNCTION_H + explicit conveyorBelt(const dictionary& dict); + - bool insertionTime( real currentTime, real dt) + FUNCTION_HD + conveyorBelt(const conveyorBelt&) = default; + + conveyorBelt& operator=(const conveyorBelt&) = default; + + INLINE_FUNCTION_HD + void setTime(real t) + {} + + INLINE_FUNCTION_HD + realx3 linVelocityPoint(const realx3 &)const { - if(currentTime < startTime_) return false; - - if(currentTime > endTime_) return false; - if( mod(abs(currentTime-startTime_),interval_)/dt < 1 ) return true; - - return false; + return tangentVelocity_; } - size_t totalInserted()const + INLINE_FUNCTION_HD + realx3 transferPoint(const realx3& p, real)const { - return numInserted_; + return p; } - bool read(const dictionary& dict) - { - return readTimeFlowControl(dict); - } + // - IO operation + FUNCTION_H + bool read(const dictionary& dict); - bool write(dictionary& dict)const - { - return writeTimeFlowControl(dict); - } + FUNCTION_H + bool write(dictionary& dict) const; + + FUNCTION_H + bool read(iIstream& is); + + FUNCTION_H + bool write(iOstream& os)const; }; +inline iOstream& operator <<(iOstream& os, const conveyorBelt& obj) +{ + + return os; } -#endif //__timeFlowControl_hpp__ +inline iIstream& operator >>(iIstream& is, conveyorBelt& obj) +{ + + return is; +} + +} + + +#endif diff --git a/src/MotionModel/entities/multiRotatingAxis/multiRotatingAxis.hpp b/src/MotionModel/entities/multiRotatingAxis/multiRotatingAxis.hpp index 2f2d81de..c79e87c8 100644 --- a/src/MotionModel/entities/multiRotatingAxis/multiRotatingAxis.hpp +++ b/src/MotionModel/entities/multiRotatingAxis/multiRotatingAxis.hpp @@ -78,7 +78,7 @@ class multiRotatingAxis { protected: - /// This is either host/device pointer to all axes + /// This is device pointer to all axes multiRotatingAxis* axisList_; /// Index of parent axis @@ -170,7 +170,7 @@ public: /// Set the pointer to the list of all axes. /// This pointer is device pointer INLINE_FUNCTION_H - void setAxisList(multiRotatingAxis* axisList) + void setAxisListPtr(multiRotatingAxis* axisList) { axisList_ = axisList; } diff --git a/src/MotionModel/entities/rotatingAxis/rotatingAxis.cpp b/src/MotionModel/entities/rotatingAxis/rotatingAxis.cpp index dbb9206e..d5aa3ca2 100644 --- a/src/MotionModel/entities/rotatingAxis/rotatingAxis.cpp +++ b/src/MotionModel/entities/rotatingAxis/rotatingAxis.cpp @@ -28,7 +28,6 @@ pFlow::rotatingAxis::rotatingAxis const dictionary& dict ) { - if(!read(dict)) { fatalErrorInFunction<< @@ -73,7 +72,7 @@ bool pFlow::rotatingAxis::read if(!timeInterval::read(dict))return false; if(!line::read(dict)) return false; - real omega = dict.getValOrSet("omega", static_cast(0.0)); + real omega = dict.getValOrSet("omega", 0.0); setOmega(omega); return true; diff --git a/src/MotionModel/entities/rotatingAxis/rotatingAxis.hpp b/src/MotionModel/entities/rotatingAxis/rotatingAxis.hpp index ee37eba9..7d40f06e 100644 --- a/src/MotionModel/entities/rotatingAxis/rotatingAxis.hpp +++ b/src/MotionModel/entities/rotatingAxis/rotatingAxis.hpp @@ -24,13 +24,12 @@ Licence: #include "timeInterval.hpp" #include "line.hpp" +#include "rotatingAxisFwd.hpp" + namespace pFlow { class dictionary; -class rotatingAxis; - -#include "rotatingAxisFwd.hpp" /** * An axis which rotates around itself at specified speed @@ -64,7 +63,7 @@ class rotatingAxis public timeInterval, public line { -protected: +private: /// rotation speed real omega_ = 0; @@ -76,13 +75,15 @@ public: // - Constructor + TypeInfoNV("rotatingAxis"); + /// Empty constructor FUNCTION_HD - rotatingAxis(){} + rotatingAxis()=default; /// Construct from dictionary FUNCTION_H - rotatingAxis(const dictionary& dict); + explicit rotatingAxis(const dictionary& dict); /// Construct from components FUNCTION_HD @@ -92,9 +93,19 @@ public: FUNCTION_HD rotatingAxis(const rotatingAxis&) = default; + FUNCTION_HD + rotatingAxis(rotatingAxis&&) = default; + /// Copy asssignment rotatingAxis& operator=(const rotatingAxis&) = default; + /// Copy asssignment + rotatingAxis& operator=(rotatingAxis&&) = default; + + /// destructor + ~rotatingAxis()=default; + + /// Set omega FUNCTION_HD real setOmega(real omega); @@ -115,7 +126,10 @@ public: /// Linear tangential velocity at point p INLINE_FUNCTION_HD - realx3 linTangentialVelocityPoint(const realx3 &p)const; + realx3 linVelocityPoint(const realx3 &p)const; + + INLINE_FUNCTION_HD + realx3 transferPoint(const realx3 p, real dt)const; // - IO operation diff --git a/src/MotionModel/entities/rotatingAxis/rotatingAxisFwd.hpp b/src/MotionModel/entities/rotatingAxis/rotatingAxisFwd.hpp index 8cbfe593..140411c5 100755 --- a/src/MotionModel/entities/rotatingAxis/rotatingAxisFwd.hpp +++ b/src/MotionModel/entities/rotatingAxis/rotatingAxisFwd.hpp @@ -18,6 +18,11 @@ Licence: -----------------------------------------------------------------------------*/ +namespace pFlow +{ + +class rotatingAxis; + INLINE_FUNCTION_HD realx3 rotate(const realx3 &p, const line& ln, real theta); @@ -25,10 +30,10 @@ INLINE_FUNCTION_HD realx3 rotate(const realx3& p, const rotatingAxis& ax, real dt); INLINE_FUNCTION_HD -void rotate(realx3* p, size_t n, const line& ln, real theta); +void rotate(realx3* p, uint32 n, const line& ln, real theta); INLINE_FUNCTION_HD -void rotate(realx3* p, size_t n, const rotatingAxis& ax, real dt); - +void rotate(realx3* p, uint32 n, const rotatingAxis& ax, real dt); +} diff --git a/src/MotionModel/entities/rotatingAxis/rotatingAxisI.hpp b/src/MotionModel/entities/rotatingAxis/rotatingAxisI.hpp index c7563020..10a730cc 100755 --- a/src/MotionModel/entities/rotatingAxis/rotatingAxisI.hpp +++ b/src/MotionModel/entities/rotatingAxis/rotatingAxisI.hpp @@ -1,3 +1,4 @@ +#include "rotatingAxis.hpp" /*------------------------------- phasicFlow --------------------------------- O C enter of O O E ngineering and @@ -19,7 +20,7 @@ Licence: -----------------------------------------------------------------------------*/ INLINE_FUNCTION_HD -pFlow::realx3 pFlow::rotatingAxis::linTangentialVelocityPoint(const realx3 &p)const +pFlow::realx3 pFlow::rotatingAxis::linVelocityPoint(const realx3 &p)const { if(!inTimeRange()) return {0,0,0}; @@ -28,6 +29,12 @@ pFlow::realx3 pFlow::rotatingAxis::linTangentialVelocityPoint(const realx3 &p)co return cross(omega_*unitVector(),L); } +INLINE_FUNCTION_HD +pFlow::realx3 pFlow::rotatingAxis::transferPoint(const realx3 p, real dt)const +{ + return rotate(p, *this, dt); +} + INLINE_FUNCTION_HD pFlow::realx3 pFlow::rotate(const realx3& p, const rotatingAxis& ax, real dt) { @@ -97,7 +104,7 @@ pFlow::realx3 pFlow::rotate(const realx3 &p, const line& ln, real theta) } INLINE_FUNCTION_HD -void pFlow::rotate(realx3* p, size_t n, const line& ln, real theta) +void pFlow::rotate(realx3* p, uint32 n, const line& ln, real theta) { realx3 nv = ln.unitVector(); real cos_tet = cos(theta); @@ -110,7 +117,7 @@ void pFlow::rotate(realx3* p, size_t n, const line& ln, real theta) // (a(v2+w2) - u( bv + cw - ux - vy - wz)) (1-cos_tet) + x cos_tet + (- cv + bw - wy + vz) sin_tet realx3 res; - for(label i=0; i>(iIstream& is, stationary& obj) +{ + + return is; +} + +} + + +#endif diff --git a/src/MotionModel/entities/vibrating/vibrating.hpp b/src/MotionModel/entities/vibrating/vibrating.hpp index 4ece54a2..62241dfa 100644 --- a/src/MotionModel/entities/vibrating/vibrating.hpp +++ b/src/MotionModel/entities/vibrating/vibrating.hpp @@ -67,7 +67,7 @@ class vibrating public timeInterval { -protected: +private: // rotation speed realx3 angularFreq_{0,0,0}; @@ -94,11 +94,13 @@ protected: public: + TypeInfoNV("vibrating"); + FUNCTION_HD - vibrating(){} + vibrating()=default; FUNCTION_H - vibrating(const dictionary& dict); + explicit vibrating(const dictionary& dict); FUNCTION_HD @@ -115,16 +117,16 @@ public: } INLINE_FUNCTION_HD - realx3 linTangentialVelocityPoint(const realx3 &p)const + realx3 linVelocityPoint(const realx3 &)const { return velocity_; } INLINE_FUNCTION_HD - realx3 transferPoint(const realx3& p, real dt) + realx3 transferPoint(const realx3& p, real dt)const { if(!inTimeRange()) return p; - return p + static_cast(0.5)*dt*(velocity0_+velocity_); + return p + static_cast(0.5*dt)*(velocity0_+velocity_); } // - IO operation diff --git a/src/MotionModel/fixedWall/fixedWall.cpp b/src/MotionModel/fixedWall/fixedWall.cpp deleted file mode 100644 index 6c3dba2e..00000000 --- a/src/MotionModel/fixedWall/fixedWall.cpp +++ /dev/null @@ -1,110 +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. - ------------------------------------------------------------------------------*/ - -#include "fixedWall.hpp" -#include "dictionary.hpp" -#include "vocabs.hpp" - -bool pFlow::fixedWall::readDictionary -( - const dictionary& dict -) -{ - - auto motionModel = dict.getVal("motionModel"); - - if(motionModel != "fixedWall") - { - fatalErrorInFunction<< - " motionModel should be fixedWall, but found " << motionModel <("motionModel"); - - if(motionModel != "rotatingAxisMotion") - { - fatalErrorInFunction<< - " motionModel should be rotatingAxisMotion, but found " - << motionModel <(axDict); axPtr) - { - axis_.push_back(axPtr()); - axisName_.push_back(aName); - } - else - { - fatalErrorInFunction<< - "could not read rotating axis from "<< axDict.globalName()<impl_writeDictionary(newDict) || + !newDict.write(os)) + { + fatalErrorInFunction<< + " error in writing to dictionary "<< newDict.globalName()< { -public: - - /** Motion model class to be passed to computational units/kernels for - * transfing points and returning velocities at various positions - */ - class Model - { - protected: - - deviceViewType1D axis_; - int32 numAxis_=0; - - public: - - INLINE_FUNCTION_HD - Model(deviceViewType1D axis, int32 numAxis): - axis_(axis), - numAxis_(numAxis) - {} - - INLINE_FUNCTION_HD - Model(const Model&) = default; - - - INLINE_FUNCTION_HD - Model& operator=(const Model&) = default; - - - INLINE_FUNCTION_HD - realx3 pointVelocity(int32 n, const realx3& p)const - { - return axis_[n].linTangentialVelocityPoint(p); - } - - INLINE_FUNCTION_HD - realx3 operator()(int32 n, const realx3& p)const - { - return pointVelocity(n,p); - } - - INLINE_FUNCTION_HD - realx3 transferPoint(int32 n, const realx3 p, real dt)const - { - return rotate(p, axis_[n], dt); - } - - INLINE_FUNCTION_HD int32 numComponents()const - { - return numAxis_; - } - }; - protected: - using axisVector_HD = VectorDual; + friend MotionModel; - /// Vector to store axes - axisVector_HD axis_; + /// is the geometry attached to this component moving + bool impl_isMoving()const + { + return true; + } + + /// move the component itself + bool impl_move(uint32, real, real)const + { + return true; + } - /// Names of axes - wordList axisName_; - - /// Number of axes components - label numAxis_= 0; - - /// Read from dictionary - bool readDictionary(const dictionary& dict); - - /// Write to dictionary - bool writeDictionary(dictionary& dict)const; - public: - - /// Type info - TypeInfoNV("rotatingAxisMotion"); - // - Constructors - - /// Empty - FUNCTION_H - rotatingAxisMotion(); + TypeInfo("rotatingAxisMotion"); - /// Construct with dictionary - FUNCTION_H - rotatingAxisMotion(const dictionary& dict); + rotatingAxisMotion(const objectFile& objf, repository* owner); - /// Copy constructor - FUNCTION_H - rotatingAxisMotion(const rotatingAxisMotion&) = default; + rotatingAxisMotion( + const objectFile& objf, + const dictionary& dict, + repository* owner); - /// No move constructor - rotatingAxisMotion(rotatingAxisMotion&&) = delete; + using fileDictionary::write; - /// Copy assignment - FUNCTION_H - rotatingAxisMotion& operator=(const rotatingAxisMotion&) = default; + bool write(iOstream& os, const IOPattern& iop)const override; - /// No move assignment - rotatingAxisMotion& operator=(rotatingAxisMotion&&) = delete; - - /// Destructor - FUNCTION_H - ~rotatingAxisMotion() = default; - - // - Methods - /// Return the motion model at time t - Model getModel(real t) - { - for(int32 i= 0; iimpl_writeDictionary(newDict) || + !newDict.write(os)) + { + fatalErrorInFunction<< + " error in writing to dictionary "<< newDict.globalName()< +{ +protected: + + friend MotionModel; + + bool impl_isMoving()const + { + return false; + } + + bool impl_move(uint32, real, real)const + { + return true; + } + + void impl_setTime(uint32 ,real ,real )const + {} + +public: + + TypeInfo("stationaryWall"); + + stationaryWall(const objectFile& objf, repository* owner); + + stationaryWall( + const objectFile& objf, + const dictionary& dict, + repository* owner); + + + using fileDictionary::write; + + bool write(iOstream& os, const IOPattern& iop)const override; + + static + auto noneComponent() + { + return stationary(); + } +}; + +} // pFlow + + +#endif // __stationaryWall_hpp__ \ No newline at end of file diff --git a/src/MotionModel/vibratingMotion/vibratingMotion.cpp b/src/MotionModel/vibratingMotion/vibratingMotion.cpp index 1cc472a8..896a35e0 100644 --- a/src/MotionModel/vibratingMotion/vibratingMotion.cpp +++ b/src/MotionModel/vibratingMotion/vibratingMotion.cpp @@ -1,167 +1,66 @@ -/*------------------------------- 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 "vibratingMotion.hpp" -#include "dictionary.hpp" -#include "vocabs.hpp" - -bool pFlow::vibratingMotion::readDictionary +void pFlow::vibratingMotion::impl_setTime ( - const dictionary& dict -) -{ - - auto motionModel = dict.getVal("motionModel"); - - if(motionModel != "vibratingMotion") - { - fatalErrorInFunction<< - " motionModel should be vibratingMotion, but found " - << motionModel <(compDict); compPtr) - { - components_.push_back(compPtr()); - componentName_.push_back(cName); - } - else - { - fatalErrorInFunction<< - "could not read vibrating motion from "<< compDict.globalName()< { -public: - - /** Motion model class to be passed to computational units/kernels for - * transfing points and returning velocities at various positions - */ - class Model - { - protected: - - deviceViewType1D components_; - int32 numComponents_=0; - - public: - - INLINE_FUNCTION_HD - Model(deviceViewType1D comps, int32 numComps): - components_(comps), - numComponents_(numComps) - {} - - INLINE_FUNCTION_HD - Model(const Model&) = default; - - - INLINE_FUNCTION_HD - Model& operator=(const Model&) = default; - - - INLINE_FUNCTION_HD - realx3 pointVelocity(int32 n, const realx3& p)const - { - return components_[n].linTangentialVelocityPoint(p); - } - - INLINE_FUNCTION_HD - realx3 operator()(int32 n, const realx3& p)const - { - return pointVelocity(n,p); - } - - INLINE_FUNCTION_HD - realx3 transferPoint(int32 n, const realx3 p, real dt)const - { - return components_[n].transferPoint(p, dt); - } - - INLINE_FUNCTION_HD int32 numComponents()const - { - return numComponents_; - } - }; protected: - - using axisVector_HD = VectorDual; - - /// Vibrating motion components - axisVector_HD components_; - /// Names of components - wordList componentName_; + friend MotionModel; - /// Number of components - label numComponents_= 0; + bool impl_isMoving()const + { + return true; + } - /// Read from a dictionary - bool readDictionary(const dictionary& dict); + /// move the component itself + bool impl_move(uint32, real, real)const + { + return true; + } - /// Write to a dictionary - bool writeDictionary(dictionary& dict)const; public: /// Type info - TypeInfoNV("vibratingMotion"); + TypeInfo("vibratingMotion"); + + vibratingMotion(const objectFile& objf, repository* owner); - /// Empty - FUNCTION_H - vibratingMotion(); - - /// Construct with dictionary - FUNCTION_H - vibratingMotion(const dictionary& dict); - - /// Copy constructor - FUNCTION_H - vibratingMotion(const vibratingMotion&) = default; - - /// No move - vibratingMotion(vibratingMotion&&) = delete; - - /// Copy assignment - FUNCTION_H - vibratingMotion& operator=(const vibratingMotion&) = default; - - /// No Move assignment - vibratingMotion& operator=(vibratingMotion&&) = delete; + vibratingMotion( + const objectFile& objf, + const dictionary& dict, + repository* owner); /// Destructor - FUNCTION_H - ~vibratingMotion() = default; + ~vibratingMotion()override = default; - /// Return motion model at time t - Model getModel(real t) - { - for(int32 i= 0; i pFlow::boundaryGrainParticles::create( + const boundaryBase &boundary, + grainParticles &prtcls +) +{ + + word bType = angleBracketsNames2( + "boundaryGrainParticles", + pFlowProcessors().localRunTypeName(), + boundary.type()); + + word altBType{"boundaryGrainParticles"}; + + if( boundaryBasevCtorSelector_.search(bType) ) + { + pOutput.space(4)<<"Creating boundary "<< Green_Text(bType)<< + " for "<"); + + boundaryGrainParticles( + const boundaryBase &boundary, + grainParticles& prtcls + ); + + create_vCtor( + boundaryGrainParticles, + boundaryBase, + ( + const boundaryBase &boundary, + grainParticles& prtcls + ), + (boundary, prtcls) + ); + + add_vCtor( + boundaryGrainParticles, + boundaryGrainParticles, + boundaryBase + ); + + grainParticles& Particles(); + + const grainParticles& Particles()const; + + bool hearChanges( + real t, + real dt, + uint32 iter, + const message &msg, + const anyList &varList) override + { + return true; + } + + virtual + bool acceleration(const timeInfo& ti, const realx3& g) + { + return true; + } + + static + uniquePtr create( + const boundaryBase &boundary, + grainParticles& prtcls); + +}; + + +} + + + +#endif diff --git a/src/Particles/GrainParticles/boundaryGrainParticlesList.cpp b/src/Particles/GrainParticles/boundaryGrainParticlesList.cpp new file mode 100644 index 00000000..4cd941bd --- /dev/null +++ b/src/Particles/GrainParticles/boundaryGrainParticlesList.cpp @@ -0,0 +1,19 @@ +#include "boundaryGrainParticlesList.hpp" + +pFlow::boundaryGrainParticlesList::boundaryGrainParticlesList( + const boundaryList &bndrs, + grainParticles &prtcls +) +: + ListPtr(bndrs.size()), + boundaries_(bndrs) +{ + for(auto i=0; iset + ( + i, + boundaryGrainParticles::create(boundaries_[i], prtcls) + ); + } +} \ No newline at end of file diff --git a/src/Particles/GrainParticles/boundaryGrainParticlesList.hpp b/src/Particles/GrainParticles/boundaryGrainParticlesList.hpp new file mode 100644 index 00000000..4fe22ad8 --- /dev/null +++ b/src/Particles/GrainParticles/boundaryGrainParticlesList.hpp @@ -0,0 +1,36 @@ + + +#ifndef __boundaryGrainParticlesList_hpp__ +#define __boundaryGrainParticlesList_hpp__ + +#include "ListPtr.hpp" +#include "boundaryList.hpp" +#include "boundaryGrainParticles.hpp" + +namespace pFlow +{ + +class boundaryGrainParticlesList +: + public ListPtr +{ +private: + + const boundaryList& boundaries_; + +public: + + boundaryGrainParticlesList( + const boundaryList& bndrs, + grainParticles& prtcls + ); + + ~boundaryGrainParticlesList()=default; + +}; + +} + + + +#endif \ No newline at end of file diff --git a/src/Particles/GrainParticles/grainParticles/grainParticles.cpp b/src/Particles/GrainParticles/grainParticles/grainParticles.cpp new file mode 100644 index 00000000..8293a510 --- /dev/null +++ b/src/Particles/GrainParticles/grainParticles/grainParticles.cpp @@ -0,0 +1,422 @@ +/*------------------------------- 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 "grainParticles.hpp" +#include "systemControl.hpp" +#include "vocabs.hpp" +#include "grainParticlesKernels.hpp" + +bool pFlow::grainParticles::initializeParticles() +{ + + using exeSpace = typename realPointField_D::execution_space; + using policy = Kokkos::RangePolicy< + exeSpace, + Kokkos::IndexType>; + + auto [minIndex, maxIndex] = minMax(shapeIndex().internal()); + + if( !grains_.indexValid(maxIndex) ) + { + fatalErrorInFunction<< + "the maximum value of shapeIndex is "<< maxIndex << + " which is not valid."<(shapeNames.size()); + + propIds.clear(); + propIds.reserve(numNew); + + diams.clear(); + diams.reserve(numNew); + + coarseGrainFactors.clear(); + coarseGrainFactors.reserve(numNew); + + m.clear(); + m.reserve(numNew); + + Is.clear(); + Is.reserve(numNew); + + shIndex.clear(); + shIndex.reserve(numNew); + + + for(const auto& name:shapeNames) + { + uint32 indx; + if(grains_.shapeNameToIndex(name,indx)) + { + shIndex.push_back(indx); + Is.push_back( grains_.Inertia(indx)); + m.push_back(grains_.mass(indx)); + diams.push_back(grains_.boundingDiameter(indx)); + coarseGrainFactors.push_back(grains_.coarseGrainFactor(indx)); + propIds.push_back( grains_.propertyId(indx)); + } + else + { + fatalErrorInFunction<<"Shape name "<< name << + "does not exist. The list is "<(0.0000000001) + ), + rVelocity_ + ( + objectFile + ( + "rVelocity", + "", + objectFile::READ_IF_PRESENT, + objectFile::WRITE_ALWAYS + ), + dynPointStruct(), + zero3 + ), + rAcceleration_ + ( + objectFile( + "rAcceleration", + "", + objectFile::READ_IF_PRESENT, + objectFile::WRITE_ALWAYS + ), + dynPointStruct(), + zero3 + ), + boundaryGrainParticles_ + ( + dynPointStruct().boundaries(), + *this + ), + accelerationTimer_( + "Acceleration", &this->timers() ), + intPredictTimer_( + "Integration-predict", &this->timers() ), + intCorrectTimer_( + "Integration-correct", &this->timers() ), + fieldUpdateTimer_( + "fieldUpdate", &this->timers() ) +{ + + auto intMethod = control.settingsDict().getVal("integrationMethod"); + REPORT(1)<<"Creating integration method "<dt(); + dynPointStruct().predict(dt, accelertion()); + rVelIntegration_().predict(dt,rVelocity_, rAcceleration_); + intPredictTimer_.end(); + + fieldUpdateTimer_.start(); + propertyId_.updateBoundariesSlaveToMasterIfRequested(); + grainDiameter_.updateBoundariesSlaveToMasterIfRequested(); + coarseGrainFactor_.updateBoundariesSlaveToMasterIfRequested(); + mass_.updateBoundariesSlaveToMasterIfRequested(); + I_.updateBoundariesSlaveToMasterIfRequested(); + rVelocity_.updateBoundariesSlaveToMasterIfRequested(); + rAcceleration_.updateBoundariesSlaveToMasterIfRequested(); + rVelIntegration_().updateBoundariesSlaveToMasterIfRequested(); + fieldUpdateTimer_.end(); + + return true; +} + +bool pFlow::grainParticles::iterate() +{ + + timeInfo ti = TimeInfo(); + realx3 g = control().g(); + + particles::iterate(); + accelerationTimer_.start(); + pFlow::grainParticlesKernels::acceleration( + g, + mass().deviceViewAll(), + contactForce().deviceViewAll(), + I().deviceViewAll(), + contactTorque().deviceViewAll(), + dynPointStruct().activePointsMaskDevice(), + accelertion().deviceViewAll(), + rAcceleration().deviceViewAll() + ); + for(auto& bndry:boundaryGrainParticles_) + { + bndry->acceleration(ti, g); + } + accelerationTimer_.end(); + + intCorrectTimer_.start(); + + if(!dynPointStruct().correct(dt(), accelertion())) + { + return false; + } + if(!rVelIntegration_().correct( + dt(), + rVelocity_, + rAcceleration_)) + { + return false; + } + + intCorrectTimer_.end(); + + return true; +} + +bool pFlow::grainParticles::insertParticles +( + const realx3Vector &position, + const wordVector &shapesNames, + const anyList &setVarList +) +{ + anyList newVarList(setVarList); + + realVector mass("mass"); + realVector I("I"); + realVector diameter("diameter"); + realVector coarseGrainFactor("coarseGrainFactor"); + uint32Vector propId("propId"); + uint32Vector shapeIdx("shapeIdx"); + + if(!getParticlesInfoFromShape( + shapesNames, + propId, + diameter, + coarseGrainFactor, + mass, + I, + shapeIdx)) + { + return false; + } + + newVarList.emplaceBack( + mass_.name()+"Vector", + std::move(mass)); + + newVarList.emplaceBack( + I_.name()+"Vector", + std::move(I)); + + newVarList.emplaceBack( + grainDiameter_.name()+"Vector", + std::move(diameter)); + + newVarList.emplaceBack( + coarseGrainFactor_.name()+"Vector", + std::move(coarseGrainFactor)); + + newVarList.emplaceBack( + propertyId_.name()+"Vector", + std::move(propId)); + + newVarList.emplaceBack( + shapeIndex().name()+"Vector", + std::move(shapeIdx)); + + if(!dynPointStruct().insertPoints(position, newVarList)) + { + return false; + } + + return true; +} + +pFlow::word pFlow::grainParticles::shapeTypeName()const +{ + return "grain"; +} + +const pFlow::shape &pFlow::grainParticles::getShapes() const +{ + return grains_; +} + +void pFlow::grainParticles::boundingSphereMinMax +( + real & minDiam, + real& maxDiam +)const +{ + minDiam = grains_.minBoundingSphere(); + maxDiam = grains_.maxBoundingSphere(); +} diff --git a/src/Particles/GrainParticles/grainParticles/grainParticles.hpp b/src/Particles/GrainParticles/grainParticles/grainParticles.hpp new file mode 100644 index 00000000..b6c7a802 --- /dev/null +++ b/src/Particles/GrainParticles/grainParticles/grainParticles.hpp @@ -0,0 +1,249 @@ +/*------------------------------- 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::sphereParticles + * + * @brief Class for managing spherical particles + * + * This is a top-level class that contains the essential components for + * defining spherical prticles in a DEM simulation. + */ + +#ifndef __grainParticles_hpp__ +#define __grainParticles_hpp__ + +#include "indexContainer.hpp" +#include "particles.hpp" +#include "property.hpp" +#include "grainShape.hpp" +#include "boundaryGrainParticlesList.hpp" +#include "systemControl.hpp" + +namespace pFlow +{ + +class grainParticles : public particles +{ +public: + + using ShapeType = grainShape; + +private: + + /// reference to shapes + ShapeType grains_; + + /// property id on device + uint32PointField_D propertyId_; + + /// diameter / boundig sphere size of particles on device + realPointField_D grainDiameter_; + + realPointField_D coarseGrainFactor_; + + + /// mass of particles field + realPointField_D mass_; + + /// pointField of inertial of particles + realPointField_D I_; + + /// pointField of rotational Velocity of particles on device + realx3PointField_D rVelocity_; + + /// pointField of rotational acceleration of particles on device + realx3PointField_D rAcceleration_; + + /// boundaries + boundaryGrainParticlesList boundaryGrainParticles_; + + /// rotational velocity integrator + uniquePtr rVelIntegration_ = nullptr; + + /// timer for acceleration computations + Timer accelerationTimer_; + + /// timer for integration computations (prediction step) + Timer intPredictTimer_; + + /// timer for integration computations (correction step) + Timer intCorrectTimer_; + + Timer fieldUpdateTimer_; + +private: + + + bool getParticlesInfoFromShape( + const wordVector& shapeNames, + uint32Vector& propIds, + realVector& diams, + realVector& coarseGrainFactors, + realVector& m, + realVector& Is, + uint32Vector& shIndex + ); + +protected: + + Timer& accelerationTimer() + { + return accelerationTimer_; + } + + Timer& intCorrectTimer() + { + return intCorrectTimer_; + } + + integration& rVelIntegration() + { + return rVelIntegration_(); + } + +public: + + /// construct from systemControl and property + grainParticles(systemControl& control, const property& prop); + + ~grainParticles() override = default; + + /** + * Insert new particles in position with specified shapes + * + * This function is involked by inserted object to insert new set of + * particles into the simulation. \param position position of new particles + * \param shape shape of new particles + * \param setField initial value of the selected fields for new particles + */ + /*bool insertParticles + ( + const realx3Vector& position, + const wordVector& shapes, + const setFieldList& setField + ) override ;*/ + + // TODO: make this method private later + bool initializeParticles(); + + /// const reference to shapes object + const auto& grains() const + { + return grains_; + } + + /// const reference to inertia pointField + const auto& I() const + { + return I_; + } + + /// reference to inertia pointField + auto& I() + { + return I_; + } + + const auto& rVelocity() const + { + return rVelocity_; + } + + auto& rVelocity() + { + return rVelocity_; + } + + bool hearChanges( + real t, + real dt, + uint32 iter, + const message& msg, + const anyList& varList + ) override + { + notImplementedFunction; + return false; + } + + const uint32PointField_D& propertyId() const override + { + return propertyId_; + } + + const realPointField_D& diameter() const override + { + return grainDiameter_; + } + + const realPointField_D& grainDiameter()const + { + return grainDiameter_; + } + + const realPointField_D& coarseGrainFactor() const + { + return coarseGrainFactor_; + } + + + const realPointField_D& mass() const override + { + return mass_; + } + + /// before iteration step + bool beforeIteration() override; + + /// iterate particles + bool iterate() override; + + bool insertParticles( + const realx3Vector& position, + const wordVector& shapesNames, + const anyList& setVarList + ) override; + + realx3PointField_D& rAcceleration() override + { + return rAcceleration_; + } + + const realx3PointField_D& rAcceleration() const override + { + return rAcceleration_; + } + + const realPointField_D& boundingSphere() const override + { + return diameter(); + } + + word shapeTypeName() const override; + + const shape& getShapes() const override; + + void boundingSphereMinMax(real& minDiam, real& maxDiam) const override; + +};// grainParticles + +} // pFlow + +#endif //__sphereParticles_hpp__ diff --git a/src/Particles/GrainParticles/grainParticles/grainParticlesKernels.cpp b/src/Particles/GrainParticles/grainParticles/grainParticlesKernels.cpp new file mode 100644 index 00000000..51891205 --- /dev/null +++ b/src/Particles/GrainParticles/grainParticles/grainParticlesKernels.cpp @@ -0,0 +1,101 @@ +/*------------------------------- 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 "grainParticlesKernels.hpp" + +using policy = Kokkos::RangePolicy< + pFlow::DefaultExecutionSpace, + Kokkos::Schedule, + Kokkos::IndexType>; + +void pFlow::grainParticlesKernels::addMassDiamInertiaProp +( + deviceViewType1D shapeIndex, + deviceViewType1D mass, + deviceViewType1D diameter, + deviceViewType1D coarseGrainFactor, + deviceViewType1D I, + deviceViewType1D propertyId, + pFlagTypeDevice incld, + deviceViewType1D src_mass, + deviceViewType1D src_diameter, + deviceViewType1D src_I, + deviceViewType1D src_propertyId +) +{ + auto aRange = incld.activeRange(); + + Kokkos::parallel_for( + "particles::initInertia", + policy(aRange.start(), aRange.end()), + LAMBDA_HD(uint32 i) + { + if(incld(i)) + { + uint32 index = shapeIndex[i]; + I[i] = src_I[index]; + diameter[i] = src_diameter[index]; + mass[i] = src_mass[index]; + propertyId[i] = src_propertyId[index]; + } + }); + +} + +void pFlow::grainParticlesKernels::acceleration +( + const realx3& g, + const deviceViewType1D& mass, + const deviceViewType1D& force, + const deviceViewType1D& I, + const deviceViewType1D& torque, + const pFlagTypeDevice& incld, + deviceViewType1D lAcc, + deviceViewType1D rAcc +) +{ + + auto activeRange = incld.activeRange(); + if(incld.isAllActive()) + { + Kokkos::parallel_for( + "pFlow::grainParticlesKernels::acceleration", + policy(activeRange.start(), activeRange.end()), + LAMBDA_HD(uint32 i){ + lAcc[i] = force[i]/mass[i] + g; + rAcc[i] = torque[i]/I[i]; + }); + } + else + { + Kokkos::parallel_for( + "pFlow::grainParticlesKernels::acceleration", + policy(activeRange.start(), activeRange.end()), + LAMBDA_HD(uint32 i){ + if(incld(i)) + { + lAcc[i] = force[i]/mass[i] + g; + rAcc[i] = torque[i]/I[i]; + } + }); + + } + + Kokkos::fence(); +} diff --git a/src/Particles/GrainParticles/grainParticles/grainParticlesKernels.hpp b/src/Particles/GrainParticles/grainParticles/grainParticlesKernels.hpp new file mode 100644 index 00000000..daed7808 --- /dev/null +++ b/src/Particles/GrainParticles/grainParticles/grainParticlesKernels.hpp @@ -0,0 +1,59 @@ +/*------------------------------- 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 __grainParticlesKernels_hpp__ +#define __grainParticlesKernels_hpp__ + +#include "types.hpp" +#include "pointFlag.hpp" + +namespace pFlow::grainParticlesKernels +{ + +void addMassDiamInertiaProp( + deviceViewType1D shapeIndex, + deviceViewType1D mass, + deviceViewType1D diameter, + deviceViewType1D coarseGrainFactor, + + deviceViewType1D I, + deviceViewType1D propertyId, + pFlagTypeDevice incld, + deviceViewType1D src_mass, + deviceViewType1D src_grainDiameter, + deviceViewType1D src_I, + deviceViewType1D src_propertyId +); + +void acceleration( + const realx3& g, + const deviceViewType1D& mass, + const deviceViewType1D& force, + const deviceViewType1D& I, + const deviceViewType1D& torque, + const pFlagTypeDevice& incld, + deviceViewType1D lAcc, + deviceViewType1D rAcc +); + + +} + +#endif diff --git a/src/Particles/GrainParticles/grainShape/grainShape.cpp b/src/Particles/GrainParticles/grainShape/grainShape.cpp new file mode 100644 index 00000000..4558940b --- /dev/null +++ b/src/Particles/GrainParticles/grainShape/grainShape.cpp @@ -0,0 +1,242 @@ +/*------------------------------- 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 "grainShape.hpp" + + +bool pFlow::grainShape::readFromDictionary3() +{ + + grainDiameters_ = getVal("grainDiameters"); + + sphereDiameters_ = getVal("sphereDiameters"); + + coarseGrainFactor_ = grainDiameters_ / sphereDiameters_ ; + + + if(grainDiameters_.size() != numShapes() ) + { + fatalErrorInFunction<< + " number of elements in grain diameters in "<< globalName()<<" is not consistent"<"); + + grainShape( + const word& fileName, + repository* owner, + const property& prop); + + + ~grainShape() override = default; + + //// - Methods + + real maxBoundingSphere()const override; + + real minBoundingSphere()const override; + + bool boundingDiameter(uint32 index, real& bDiam)const override; + + real boundingDiameter(uint32 index)const override; + + realVector boundingDiameter()const override; + + real coarseGrainFactor(uint32 index)const ; + + realVector coarseGrainFactor()const ; + + real orginalDiameter(uint32 index)const ; + + realVector orginalDiameter()const ; + + bool mass(uint32 index, real& m)const override; + + real mass(uint32 index) const override; + + realVector mass()const override; + + realVector density() const override; + + bool Inertia(uint32 index, real& I)const override; + + real Inertia(uint32 index)const override; + + realVector Inertia()const override; + + bool Inertia_xx(uint32 index, real& Ixx)const override; + + real Inertial_xx(uint32 index)const override; + + bool Inertia_yy(uint32 index, real& Iyy)const override; + + real Inertial_yy(uint32 index)const override; + + bool Inertia_zz(uint32 index, real& Izz)const override; + + real Inertial_zz(uint32 index)const override; + +}; + +} // pFlow + +#endif //__grainShape_hpp__ diff --git a/src/Particles/Insertion/Insertion/Insertion.cpp b/src/Particles/Insertion/Insertion/Insertion.cpp index acc70b28..a0e2cc77 100644 --- a/src/Particles/Insertion/Insertion/Insertion.cpp +++ b/src/Particles/Insertion/Insertion/Insertion.cpp @@ -18,31 +18,7 @@ Licence: -----------------------------------------------------------------------------*/ -template -bool pFlow::Insertion::readInsertionDict -( - const dictionary& dict -) -{ - if(!insertion::readInsertionDict(dict)) return false; - - regions_.clear(); - - if( !this->isActive() ) - { - return true; - } - wordList regionDicNames = dict.dictionaryKeywords(); - - for(auto& name:regionDicNames) - { - REPORT(2)<<"reading insertion region "<< greenText(name)< bool pFlow::Insertion::writeInsertionDict @@ -50,7 +26,8 @@ bool pFlow::Insertion::writeInsertionDict dictionary& dict )const { - if( !insertion::writeInsertionDict(dict) ) return false; + + if(!insertion::writeInsertionDict(dict))return false; if( !this->isActive() ) return true; @@ -60,6 +37,8 @@ bool pFlow::Insertion::writeInsertionDict if( !regions_[i].write(rgnDict) ) { + fatalErrorInFunction<< + "Error in writing to dictionary "<::writeInsertionDict return true; } +template +bool +pFlow::Insertion::readInsertionDict() +{ + regions_.clear(); + + if( !this->isActive() ) + { + return true; + } + + wordList regionDicNames = this->dictionaryKeywords(); + + for(const auto& name:regionDicNames) + { + REPORT(2)<<"reading insertion region "<< Green_Text(name)<>( + name, + *this, + shapes_)); + } + + return true; + +} + template pFlow::Insertion::Insertion( particles& prtcl, @@ -75,11 +81,14 @@ pFlow::Insertion::Insertion( insertion(prtcl), shapes_(shapes) { - - + if(!readInsertionDict()) + { + fatalErrorInFunction; + fatalExit; + } } -template +/*template pFlow::Insertion::Insertion( fileSystem file, particles& prtcl, @@ -95,13 +104,14 @@ pFlow::Insertion::Insertion( file< bool pFlow::Insertion::insertParticles ( - real currentTime, + uint32 iter, + real t, real dt ) { @@ -112,21 +122,21 @@ bool pFlow::Insertion::insertParticles { bool insertionOccured = false; auto& rgn = regions_[i]; - if( rgn.insertionTime(currentTime, dt) ) + if( rgn.insertionTime(iter, t, dt) ) { realx3Vector pos; wordVector shapes; - if( rgn.insertParticles(currentTime, dt, shapes, pos, insertionOccured) ) + if( rgn.insertParticles(iter, t, dt, shapes, pos, insertionOccured) ) { if(insertionOccured) { - REPORT(0)<<"\nParticle insertion from "<< greenText(rgn.name())<::insertParticles return false; } REPORT(1)<<"Total number of particles inserted from this region is "<< - cyanText(rgn.totalInserted())<<'\n'<::insertParticles { if(insertionOccured) { - yWARNING<< "\n fewer number of particles are inserted from region "<< rgn.name() << - " than expected. You may stop the simulation to change settings."<::insertParticles } -template +/*template bool pFlow::Insertion::read ( iIstream& is @@ -217,4 +233,4 @@ bool pFlow::Insertion::write } return true; -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/src/Particles/Insertion/Insertion/Insertion.hpp b/src/Particles/Insertion/Insertion/Insertion.hpp index cd9aff68..ddeb9c56 100644 --- a/src/Particles/Insertion/Insertion/Insertion.hpp +++ b/src/Particles/Insertion/Insertion/Insertion.hpp @@ -2,67 +2,85 @@ O C enter of O O E ngineering and O O M ultiscale modeling of - OOOOOOO F luid flow + 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 + 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 + 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 __Insertion_hpp__ #define __Insertion_hpp__ - -#include "insertion.hpp" -#include "ListPtr.hpp" #include "InsertionRegion.hpp" +#include "ListPtr.hpp" +#include "insertion.hpp" #include "particles.hpp" namespace pFlow { -template -class Insertion -: - public insertion +/** + * This class manages all the insertion regions for particles insertion + * in the simulation. + * + * Any number of insertion regions can be defined in a simulation. The + * data for particle insertion is provided in particleInsertion file, which + * looks like this. A list of insertion regions (class insertionRegion) can be +defined in this file. + * For more information see file insertionRegion.hpp. + * \verbatim +active yes; + +region1 { + // the data for insertionRegion +} + +region2 +{ + // Data for insertionRegion +} + \endverbatim + */ +template +class Insertion : public insertion +{ +private: + + const ShapeType& shapes_; + + // - insertion regions + ListPtr> regions_; + + bool readInsertionDict(); + protected: - const ShapeType& shapes_; - - // - insertion regions - ListPtr> regions_; - - - bool readInsertionDict(const dictionary& dict); - - bool writeInsertionDict(dictionary& dict)const; + bool writeInsertionDict(dictionary& dict)const override; public: - TypeInfoTemplateNV("Insertion",ShapeType); + TypeInfoTemplateNV11("Insertion", ShapeType); Insertion(particles& prtcl, const ShapeType& shapes); - Insertion(fileSystem file, particles& prtcl, const ShapeType& shapes); + // Insertion(fileSystem file, particles& prtcl, const ShapeType& shapes); + bool insertParticles(uint32 iter, real t, real dt); - bool insertParticles(real currentTime, real dt); - - virtual bool read(iIstream& is) override; - - virtual bool write(iOstream& os)const override; + /*virtual bool read(iIstream& is) override; + virtual bool write(iOstream& os)const override;*/ }; } diff --git a/src/Particles/Insertion/Insertion/Insertions.cpp b/src/Particles/Insertion/Insertion/Insertions.cpp index 2bc3bd92..5405b3f6 100644 --- a/src/Particles/Insertion/Insertion/Insertions.cpp +++ b/src/Particles/Insertion/Insertion/Insertions.cpp @@ -21,4 +21,5 @@ Licence: #include "Insertions.hpp" -template class pFlow::Insertion; \ No newline at end of file +template class pFlow::Insertion; +template class pFlow::Insertion; \ No newline at end of file diff --git a/src/Particles/Insertion/Insertion/Insertions.hpp b/src/Particles/Insertion/Insertion/Insertions.hpp index deaafba2..b513295d 100644 --- a/src/Particles/Insertion/Insertion/Insertions.hpp +++ b/src/Particles/Insertion/Insertion/Insertions.hpp @@ -24,11 +24,15 @@ Licence: #include "Insertion.hpp" #include "sphereShape.hpp" +#include "grainShape.hpp" + namespace pFlow { using sphereInsertion = Insertion ; +using grainInsertion = Insertion ; + } diff --git a/src/Particles/Insertion/InsertionRegion/InsertionRegion.cpp b/src/Particles/Insertion/InsertionRegion/InsertionRegion.cpp index 57404bf7..4434f64b 100644 --- a/src/Particles/Insertion/InsertionRegion/InsertionRegion.cpp +++ b/src/Particles/Insertion/InsertionRegion/InsertionRegion.cpp @@ -39,77 +39,211 @@ bool pFlow::InsertionRegion::checkForContact template pFlow::InsertionRegion::InsertionRegion ( - const dictionary& dict, + const word& name, + const insertion& instn, const ShapeType& shapes ) : - insertionRegion(dict), + insertionRegion(name, instn), shapes_(shapes) -{ - -} +{} template bool pFlow::InsertionRegion::insertParticles ( - real currentTime, + uint32 iter, + real t, real dt, - wordVector& names, - realx3Vector& pos, + wordVector& names, + realx3Vector& positions, bool& insertionOccured ) { insertionOccured = false; - if(!insertionTime( currentTime, dt)) return true; + if(!insertionTime(iter, t, dt)) return true; - size_t newNum = numberToBeInserted(currentTime); - + uint32 newNum = numberToBeInserted(iter, t, dt); if(newNum == 0) return true; - names.reserve(max(newNum,names.capacity())); - pos.reserve(max(newNum,pos.capacity())); - names.clear(); - pos.clear(); - - realVector diams(newNum, RESERVE()); - - mixture_->getNextShapeNameN(newNum, names); - - if(!shapes_.shapeToDiameter(names,diams)) + // get the internal box + auto internalBox = pStruct().internalDomainBox(); + if( !(internalBox.minPoint() < internalBox.maxPoint())) { - fatalErrorInFunction<< - " error occured in insertion region "<< name() << - " while converting shapes to diameter. \n"; + WARNING<<"Minimum point of internal point is not lower than "<< + "the maximum point \n"<< + "minimum point: "<< internalBox.minPoint()<< + "\nmaximum point:"< + ( + selector(), + Insertion().diameterName() + ); } + + auto collCheck = collisionCheck( + {minP, maxP}, + maxDiam, + allPositions, + allDiameters); - fatalErrorInFunction<< - " Cannot insert "<< newNum << " new particles from region "<< name()<<". \n" - " pFlow could position only "<< n<< " particles in this region. \n"; - addToNumInserted(n); - insertionOccured = false; - return false; + uint32 numInserted = 0; -} \ No newline at end of file + uint32 idx; + word name = mix.getNextShapeName(); + shapes_.shapeNameToIndex(name, idx); + real d = shapes_.boundingDiameter(idx); + + for(uint32 i=0; i< 100*newNum ; ++i) + { + realx3 p = pReg.peek(); + // check if point is inside internal box + if(!internalBox.isInside(p))continue; + + if( collCheck.checkPoint( p, d) ) + { + names.push_back(name); + positions.push_back(p); + numInserted++; + if( numInserted == newNum ) break; + + // add this new particle to collision check set + allDiameters.push_back(d); + allPositions.push_back(p); + collCheck.mapLastAddedParticle(); + + // obtain next shape name and diameter + name = mix.getNextShapeName(); + shapes_.shapeNameToIndex(name, idx); + d = shapes_.boundingDiameter(idx); + } + + } + + insertionOccured = true; + addToNumInserted(numInserted); + return numInserted == newNum; +} + + + +/*if(!checkForCollision) + { + realVector diams("diams", newNum, 0, RESERVE()); + + uint32 idx; + word name = mix.getNextShapeName(); + shapes_.shapeNameToIndex(name, idx); + real d = shapes_.boundingDiameter(idx); + + for(uint32 i=0; i< 100*newNum ; ++i) + { + realx3 p = pReg.peek(); + // check if point is inside internal box + if(!internalBox.isInside(p))continue; + + if( !checkForContact(positions, diams, p, d) ) + { + names.push_back(name); + positions.push_back(p); + diams.push_back(d); + numInserted++; + + if( numInserted == newNum ) break; + + name = mix.getNextShapeName(); + shapes_.shapeNameToIndex(name, idx); + d = shapes_.boundingDiameter(idx); + } + } + } + else + { + real maxDiam = shapes_.maxBoundingSphere(); + auto minP = pReg.minPoint() - maxDiam; + auto maxP = pReg.maxPoint() + maxDiam; + auto bDict = dictionary("boxInfo"); + bDict.add("min", minP); + bDict.add("max", maxP); + auto selector = pStructSelector::create( + "box", + pStruct(), + bDict); + + auto allPositions = selector().selectedPointPositions(); + auto allDiameters = selectedFieldVals(selector(), "diameter"); + auto collCheck = collisionCheck( + {minP, maxP}, + maxDiam, + allPositions, + allDiameters); + + uint32 idx; + word name = mix.getNextShapeName(); + shapes_.shapeNameToIndex(name, idx); + real d = shapes_.boundingDiameter(idx); + + for(uint32 i=0; i< 100*newNum ; ++i) + { + realx3 p = pReg.peek(); + // check if point is inside internal box + if(!internalBox.isInside(p))continue; + + if( collCheck.checkPoint( p, d) ) + { + names.push_back(name); + positions.push_back(p); + numInserted++; + if( numInserted == newNum ) break; + + // add this new particle to collision check set + allDiameters.push_back(d); + allPositions.push_back(p); + collCheck.mapLastAddedParticle(); + + // obtain next shape name and diameter + name = mix.getNextShapeName(); + shapes_.shapeNameToIndex(name, idx); + d = shapes_.boundingDiameter(idx); + } + + } + }*/ \ No newline at end of file diff --git a/src/Particles/Insertion/InsertionRegion/InsertionRegion.hpp b/src/Particles/Insertion/InsertionRegion/InsertionRegion.hpp index d7bdbf0a..526dde6b 100644 --- a/src/Particles/Insertion/InsertionRegion/InsertionRegion.hpp +++ b/src/Particles/Insertion/InsertionRegion/InsertionRegion.hpp @@ -2,17 +2,17 @@ O C enter of O O E ngineering and O O M ultiscale modeling of - OOOOOOO F luid flow + 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 + 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 + 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. @@ -21,75 +21,77 @@ Licence: #ifndef __InsertionRegion_hpp__ #define __InsertionRegion_hpp__ - #include "insertionRegion.hpp" #include "dictionary.hpp" +#include "pointStructure.hpp" +#include "insertion.hpp" +#include "collisionCheck.hpp" +#include "pStructSelector.hpp" +#include "fieldSelector.hpp" + + namespace pFlow { +/** + * This manages insertion of particles from a region based on the ShapeType + * + */ template -class InsertionRegion -: - public insertionRegion +class InsertionRegion + : public insertionRegion { -protected: - // - type of particle shapes - const ShapeType& shapes_; +private: - static bool checkForContact( - const realx3Vector& pos, - const realVector& diams, - const realx3& p, - const real& d); + /// Ref to Shapes + const ShapeType& shapes_; + + static bool checkForContact( + const realx3Vector& pos, + const realVector& diams, + const realx3& p, + const real& d + ); public: - // - type info - TypeInfoTemplateNV("insertionRegion", ShapeType); + /// Type info + TypeInfoTemplateNV11("insertionRegion", ShapeType); - InsertionRegion(const dictionary& dict, const ShapeType& shapes); + // - Constructors - InsertionRegion(const InsertionRegion& ) = default; - - InsertionRegion(InsertionRegion&&) = default; - - InsertionRegion& operator=(const InsertionRegion& ) = default; - - InsertionRegion& operator=(InsertionRegion&&) = default; - - - auto clone()const - { - return makeUnique>(*this); - } - - auto clonePtr()const - { - return new InsertionRegion(*this); - } - - - bool insertParticles - ( - real currentTime, - real dt, - wordVector& names, - realx3Vector& pos, - bool& insertionOccured + /// Construct from dictionary + InsertionRegion( + const word& name, + const insertion& instn, + const ShapeType& shapes ); - //bool read(const dictionary& dict); + ~InsertionRegion() = default; - //bool write(dictionary& dict)const; + // - Methods + /// Insert particles at current time t + /// Check if currentTime is the right moment for + /// particle insertion. Fill the vectors name, pos and signal + /// if particle insertion occured or not. + bool insertParticles( + uint32 iter, + real t, + real dt, + wordVector& names, + realx3Vector& pos, + bool& insertionOccured + ); + + // bool read(const dictionary& dict); + + // bool write(dictionary& dict)const; }; - - } // pFlow - #include "InsertionRegion.cpp" #endif diff --git a/src/Particles/Insertion/collisionCheck/collisionCheck.cpp b/src/Particles/Insertion/collisionCheck/collisionCheck.cpp new file mode 100644 index 00000000..ba8d4c9d --- /dev/null +++ b/src/Particles/Insertion/collisionCheck/collisionCheck.cpp @@ -0,0 +1,104 @@ +#include "collisionCheck.hpp" + +bool +pFlow::collisionCheck::build() +{ + fill(head_, static_cast(-1)); + fill(next_, static_cast(-1)); + + for (auto i = 0uL; i < position_.size(); i++) + { + if(!searchBox_.isInside(position_[i])) + { + fatalErrorInFunction<< + "Point "<< position_[i]<< "is not in search box"<(i); + } + + return true; +} + +pFlow::collisionCheck::collisionCheck( + box sBox, + real dx, + const realx3Vector& pos, + const realVector& diam +) + : searchBox_(sBox), + dx_(dx), + nCells_((sBox.maxPoint() - sBox.minPoint()) / dx + realx3(1.0)), + position_(pos), + diameters_(diam), + next_("next", pos.size()), + head_("head", nCells_.x(), nCells_.y(), nCells_.z()) +{ + if(!build()) + { + fatalExit; + } +} + +bool +pFlow::collisionCheck::checkPoint(const realx3& p, const real d) const +{ + + if(!searchBox_.isInside(p)) return false; + + const auto ind = pointIndex(p); + const auto startInd = max(ind - 1 ,int32x3(0)); + const auto endInd = min( ind+1 ,nCells_-1); + + for(int32 i=startInd.x(); i<=endInd.x(); i++) + { + for(int32 j=startInd.y(); j<=endInd.y(); j++) + { + for(int32 k=startInd.z(); k<=endInd.z(); k++) + { + uint32 n = head_(i, j, k); + + while( n != static_cast(-1)) + { + if( ((position_[n]-p).length() - 0.5*(diameters_[n]+d )) <= 0.0 ) + { + return false; + } + n = next_[n]; + } + } + } + } + + return true; +} + +bool +pFlow::collisionCheck::mapLastAddedParticle() +{ + size_t n = position_.size()-1; + if( next_.size() != n ) + { + fatalErrorInFunction<< + "size mismatch of next and position"<(-1)); + const auto& p = position_[n]; + + if(!searchBox_.isInside(p)) + { + fatalErrorInFunction<< + "Point "<< p <<" is not inside the search box"<(n); + + return true; +} diff --git a/src/Particles/Insertion/collisionCheck/collisionCheck.hpp b/src/Particles/Insertion/collisionCheck/collisionCheck.hpp new file mode 100644 index 00000000..f0a6b267 --- /dev/null +++ b/src/Particles/Insertion/collisionCheck/collisionCheck.hpp @@ -0,0 +1,54 @@ + +#ifndef __collisionCheck_hpp__ +#define __collisionCheck_hpp__ + +#include "Vectors.hpp" +#include "VectorSingles.hpp" +#include "box.hpp" + + +namespace pFlow +{ + +class collisionCheck +{ +private: + + box searchBox_; + + real dx_; + + int32x3 nCells_; + + const realx3Vector& position_; + + const realVector& diameters_; + + uint32Vector next_; + + ViewType3D head_; + + int32x3 pointIndex(const realx3& p)const + { + return int32x3( (p - searchBox_.minPoint())/dx_ ); + } + + bool build(); + +public: + + collisionCheck( + box sBox, + real dx, + const realx3Vector& pos, + const realVector& diam + ); + + bool checkPoint(const realx3& p, const real d)const; + + bool mapLastAddedParticle(); +}; + +} + +#endif //__collisionCheck_hpp__ \ No newline at end of file diff --git a/src/Particles/Insertion/insertion/insertion.cpp b/src/Particles/Insertion/insertion/insertion.cpp index 18b53d2c..bb551a47 100644 --- a/src/Particles/Insertion/insertion/insertion.cpp +++ b/src/Particles/Insertion/insertion/insertion.cpp @@ -2,73 +2,149 @@ O C enter of O O E ngineering and O O M ultiscale modeling of - OOOOOOO F luid flow + 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 + 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 + 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 "particles.hpp" -#include "dictionary.hpp" #include "insertion.hpp" +#include "particles.hpp" #include "streams.hpp" +#include "systemControl.hpp" +#include "vocabs.hpp" -bool pFlow::insertion::readInsertionDict -( - const dictionary& dict -) +pFlow::insertion::insertion(particles& prtcl) + : fileDictionary( + objectFile( + insertionFile__, + "", + objectFile::READ_IF_PRESENT, + objectFile::WRITE_ALWAYS + ), + &prtcl.time() + ), + particles_(prtcl) { - - active_ = dict.getVal("active"); - - if(active_) - REPORT(1)<< "Particle insertion mechanism is "<< - yellowText("active")<<" in the simulation."<("active"); + + if (active_) { - fatalErrorInFunction<< - " error in writing active to dictionary "<("checkForCollision"); + + REPORT(1) << "Particle insertion mechanism is " << Yellow_Text("active") + << " in the simulation." << END_REPORT; + } + else + { + REPORT(1) << "Particle insertion mechanism is " + << Yellow_Text("not active") << " in the simulation." + << END_REPORT; + } + return true; +} + +bool +pFlow::insertion::writeInsertionDict(dictionary& dict) const +{ + if (!dict.add("active", active_)) + { + fatalErrorInFunction <<"Error in writing active to dictionary " + < +bool +setOneEntry(const twoPartEntry& tpEntry, anyList& varList) +{ + if (getTypeName() != tpEntry.firstPart()) + return false; - name_ = dict.name(); - type_ = dict.getVal("type"); - - pRegion_ = peakableRegion::create(type_, dict.subDict(type_+"Info")); - - mixture_ = makeUnique(dict.subDict("mixture")); + T val = tpEntry.secondPartVal(); + varList.emplaceBack(tpEntry.keyword(), val); - addToNumInserted(mixture_().totalInserted()); + return true; +} - if( !dict.containsDictionay("setFields")) +bool +readOneEtrty(const dataEntry& entry, anyList& varList) +{ + twoPartEntry stField(entry); + + if (!(setOneEntry(stField, varList) || + setOneEntry(stField, varList) || + setOneEntry(stField, varList) || + setOneEntry(stField, varList) || + setOneEntry(stField, varList) || + setOneEntry(stField, varList) || + setOneEntry(stField, varList) || + setOneEntry(stField, varList) || + setOneEntry(stField, varList))) { - output<<"\n insertion region "<< name_ << " does not contain setFields dictionary." - " An empty dictoiinary is created for it. \n"; - setFields_ = makeUnique( dictionary("setFields") ); + fatalErrorInFunction << "un-supported data type " << stField.firstPart() + << endl; + return false; } - else + return true; +} +} + +bool +pFlow::insertionRegion::readInsertionRegion(const dictionary& dict) +{ + type_ = dict.getVal("regionType"); + + rate_ = dict.getVal("rate"); + + pRegion_ = peakableRegion::create(type_, dict.subDict(type_ + "Info")); + + mixture_ = makeUnique( + dict.subDict("mixture"), + insertion_.Particles().getShapes().shapeNameList() + ); + + numInserted_ = mixture_().totalInserted(); + + if (dict.containsDictionay("setFields")) { - setFields_ = makeUnique( dict.subDict("setFields") ); + setFieldDict_ = + makeUnique("setFields", dict, dict.subDict("setFields")); } - for(auto& sfEntry:setFields_()) + if (setFieldDict_) { - if(!sfEntry.checkForTypeAndValueAll()) + if (!readSetFieldDict()) { - fatalErrorInFunction<< - " error in setFields dictionary "<< dict.globalName()<clone(): nullptr), - mixture_( src.mixture_? src.mixture_->clone(): nullptr), - setFields_( src.setFields_? src.setFields_->clone(): nullptr) -{} - -pFlow::insertionRegion& pFlow::insertionRegion::operator= -( - const insertionRegion& src -) +const pFlow::pointStructure& +pFlow::insertionRegion::pStruct() const { - - if(&src == this)return *this; - timeFlowControl::operator=(src); - - name_ = src.name_; - type_ = src.type_; - pRegion_ = (src.pRegion_? src.pRegion_->clone(): nullptr); - mixture_ = (src.mixture_? src.mixture_->clone(): nullptr); - setFields_ = (src.setFields_? src.setFields_->clone(): nullptr); - - return *this; + return Insertion().pStruct(); } +pFlow::uint32 +pFlow::insertionRegion::numberToBeInserted(uint32 iter, real t, real dt) +{ + if (!tControl_.isInRange(iter, t, dt)) + return 0u; + if (tControl_.isTimeStep()) + { + return static_cast( + (iter - tControl_.startIter() + tControl_.iInterval()) * dt * rate_ - + numInserted_ + ); + } + else + { + return static_cast( + (t - tControl_.startTime() + tControl_.rInterval()) * rate_ - + numInserted_ + ); + } +} diff --git a/src/Particles/Insertion/insertionRegion/insertionRegion.hpp b/src/Particles/Insertion/insertionRegion/insertionRegion.hpp index 04a1bf7e..9b4a73db 100644 --- a/src/Particles/Insertion/insertionRegion/insertionRegion.hpp +++ b/src/Particles/Insertion/insertionRegion/insertionRegion.hpp @@ -2,17 +2,17 @@ O C enter of O O E ngineering and O O M ultiscale modeling of - OOOOOOO F luid flow + 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 + 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 + 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. @@ -21,94 +21,205 @@ Licence: #ifndef __insertionRegion_hpp__ #define __insertionRegion_hpp__ -#include "timeFlowControl.hpp" +#include "anyList.hpp" +#include "baseTimeControl.hpp" +#include "peakableRegion.hpp" #include "shapeMixture.hpp" -#include "peakableRegions.hpp" -#include "setFieldList.hpp" namespace pFlow { class dictionary; +class insertion; +class pointStructure; -class insertionRegion -: - public timeFlowControl +/** + * This class defines all the necessary enteties for defining an insertion + * region. + * + * Insertion region information are supplied through a dictionary in a file. + * For example: +\verbatim { -protected: + type cylinderRegion; // type of insertion region + rate 15000; // insertion rate (particles/s) + startTime 0; // (s) + endTime 0.5; // (s) + interval 0.025; // (s) - // - name of the region - word name_; + cylinderRegionInfo + { + radius 0.09; // radius of cylinder (m) + p1 (0.0 0.0 0.10); // (m,m,m) + p2 (0.0 0.0 0.11); // (m,m,m) + } - // - type of insertion region - word type_; + setFields + { + velocity realx3 (0.0 0.0 -0.6); // initial velocity of inserted +particles + } - // peakable region of points - uniquePtr pRegion_ = nullptr; + mixture + { + lightSphere 1; // mixture composition of inserted particles + } +} \endverbatim + * + * More information on the above dictionary entries can be found in + * the table below. + * + * + * | Parameter | Type | Description | Optional [default value] | + * |----| :---: | ---- | ---- | + * | type | word | type of the insertion region with name ### | No | + * | rate | real | rate of insertion (particle/s) | No | + * | startTime | real | start of insertion (s) | No | + * | endTime | real | end of insertion (s) | No | + * | interval | real | time interval between successive insertions (s) | No | + * | ###Info | dictionary | data for insertion region | No | + * | setFields | dictionary | set field for inserted particles (s) | Yes [empty +dictionray] | + * | mixture | dictionary | mixture of particles to be inserted (s) | No | + * + */ +class insertionRegion +{ +private: - // mixture of shapes - uniquePtr mixture_ = nullptr; + /// name of this region + const word name_; - // setFields for insertion region - uniquePtr setFields_ = nullptr; + /// insertion region dictionary + const dictionary& dict_; + /// ref to insertion + const insertion& insertion_; + /// @brief time control for insertion events + baseTimeControl tControl_; + + /// rate of insertion + real rate_; + + /// number of inserted particles + uint32 numInserted_ = 0; + + /// type of insertion region + word type_; + + /// peakable region of points + uniquePtr pRegion_ = nullptr; + + /// mixture of shapes + uniquePtr mixture_ = nullptr; + + /// @brief dictionary for set field + uniquePtr setFieldDict_ = nullptr; + + /// list of (filedName type value) for the fields + anyList setFieldList_; + +private: + + // - private methods + + /// read from dictionary bool readInsertionRegion(const dictionary& dict); + /// write to dictionary bool writeInsertionRegion(dictionary& dict) const; + bool readSetFieldDict(); public: + /// Type info TypeInfoNV("insertionRegion"); - //// - Constructors + // - Constructors - insertionRegion(const dictionary& dict); + /// Construct from a dictionary + insertionRegion(const word& name, const insertion& instn); - insertionRegion(const insertionRegion& src); + /// Destructor + ~insertionRegion() = default; - insertionRegion(insertionRegion&&) = default; + // - Methods - insertionRegion& operator=(const insertionRegion&); + /// Const ref to name of the region + const auto& name() const + { + return name_; + } - insertionRegion& operator=(insertionRegion&&) = default; + /// return type of insertion region + const auto& type() const + { + return type_; + } + const auto& dict()const + { + return dict_; + } - ~insertionRegion() = default; + const auto& Insertion() const + { + return insertion_; + } + const pointStructure& pStruct()const; - //// - Methods - const auto& setFields()const - { - return setFields_(); - } + inline bool insertionTime(uint32 iter, real t, real dt) const + { + return tControl_.timeEvent(iter, t, dt); + } - const auto& name()const - { - return name_; - } + uint32 numberToBeInserted(uint32 iter, real t, real dt); + inline uint32 addToNumInserted(uint32 newInserted) + { + return numInserted_ += newInserted; + } - //// - IO operation + inline uint32 totalInserted() const + { + return numInserted_; + } - bool read(const dictionary& dict) - { - if(!timeFlowControl::read(dict))return false; + auto& mixture() + { + return mixture_(); + } - return readInsertionRegion(dict); - } + auto& pRegion() + { + return pRegion_(); + } - bool write(dictionary& dict)const - { - if(!timeFlowControl::write(dict)) return false; + const auto& setFieldList() const + { + return setFieldList_; + } + // - IO operation - return writeInsertionRegion(dict); - } + /// read from dictionary + /*bool read(const dictionary& dict) + { + if (!timeFlowControl::read(dict)) + return false; + return readInsertionRegion(dict); + }*/ + /// write to dictionary + bool write(dictionary& dict) const + { + return writeInsertionRegion(dict); + } }; -} //pFlow +} // pFlow #endif //__insertionRegion_hpp__ diff --git a/src/Particles/Insertion/shapeMixture/shapeMixture.cpp b/src/Particles/Insertion/shapeMixture/shapeMixture.cpp index 041f71dc..1038af15 100755 --- a/src/Particles/Insertion/shapeMixture/shapeMixture.cpp +++ b/src/Particles/Insertion/shapeMixture/shapeMixture.cpp @@ -2,150 +2,167 @@ O C enter of O O E ngineering and O O M ultiscale modeling of - OOOOOOO F luid flow + 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 + 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 + 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 "shapeMixture.hpp" #include "dictionary.hpp" - -pFlow::shapeMixture::shapeMixture -( - const dictionary & dict +pFlow::shapeMixture::shapeMixture( + const dictionary& dict, + const wordList& validNames ) { - if( !read(dict)) + if (!read(dict)) { fatalExit; } + + for (const auto& rN : names_) + { + bool found = false; + for (const auto& vN : validNames) + { + if (rN == vN) + { + found = true; + break; + } + } + + if (!found) + { + fatalErrorInFunction + << "Shape name " << rN << " provided in mixture dictionary " + << dict.globalName() << " is invalid. \n Valid names are " + << validNames << endl; + } + } } -pFlow::word pFlow::shapeMixture::getNextShapeName() +pFlow::word +pFlow::shapeMixture::getNextShapeName() { - ForAll(i, names_) { - if(current_[i]< number_[i]) + if (current_[i] < number_[i]) { current_[i]++; numberInserted_[i]++; return names_[i]; } } - + fill(current_, static_cast(0)); return getNextShapeName(); } -void pFlow::shapeMixture::getNextShapeNameN -( - size_t n, - wordVector& names -) +void +pFlow::shapeMixture::getNextShapeNameN(size_t n, wordVector& names) { names.clear(); - - for(label i=0; i(nm); - if( num <= 0 ) - { - fatalErrorInFunction<< - " number inserte in front of "<< nm << " is invalid: "<< num<(nm); + if (num <= 0) + { + fatalErrorInFunction << " number inserte in front of " << nm + << " is invalid: " << num << endl + << " in dictionary " << dict.globalName() + << endl; + return false; + } + number_.push_back(num); + } - if(containNumberIneserted) - { - numberInserted_ = dict.getVal("numberInserted"); - } - else - { - numberInserted_ = uint32Vector(size(), static_cast(0)); - } + if (containNumberIneserted) + { + numberInserted_ = dict.getVal("numberInserted"); + } + else + { + numberInserted_ = + uint32Vector(numberInserted_.name(), size(), static_cast(0)); + } - if(numberInserted_.size() != names_.size() ) - { - fatalErrorInFunction<< - " number of elements in numberInserted ("< clone()const { return makeUnique(*this); } - shapeMixture* clonePtr()const - { - return new shapeMixture(*this); - } - - - // + /// Destructor ~shapeMixture() = default; - //// - Methods + // - Methods + + /// The name of the next shape that should be inserted word getNextShapeName(); - + /// The name of the n next shapes that should be inserted void getNextShapeNameN(size_t n, wordVector& names); - + /// Size of mixture (names) auto size()const { return names_.size(); } + /// Total number inserted particles auto totalInserted()const { return sum(numberInserted_); } - //// - IO operatoins + // - IO operatoins + bool read(const dictionary& dict); bool write(dictionary& dict) const; diff --git a/src/Particles/SphereParticles/boundarySphereParticles.cpp b/src/Particles/SphereParticles/boundarySphereParticles.cpp new file mode 100644 index 00000000..8eb5eaa0 --- /dev/null +++ b/src/Particles/SphereParticles/boundarySphereParticles.cpp @@ -0,0 +1,64 @@ +#include "boundarySphereParticles.hpp" +#include "boundaryBase.hpp" +#include "sphereParticles.hpp" + + +pFlow::boundarySphereParticles::boundarySphereParticles( + const boundaryBase &boundary, + sphereParticles &prtcls +) +: + generalBoundary(boundary, prtcls.pStruct(), "", ""), + particles_(prtcls) +{ + +} + +pFlow::sphereParticles &pFlow::boundarySphereParticles::Particles() +{ + return particles_; +} + +const pFlow::sphereParticles &pFlow::boundarySphereParticles::Particles() const +{ + return particles_; +} + +pFlow::uniquePtr pFlow::boundarySphereParticles::create( + const boundaryBase &boundary, + sphereParticles &prtcls +) +{ + + word bType = angleBracketsNames2( + "boundarySphereParticles", + pFlowProcessors().localRunTypeName(), + boundary.type()); + + word altBType{"boundarySphereParticles"}; + + if( boundaryBasevCtorSelector_.search(bType) ) + { + pOutput.space(4)<<"Creating boundary "<< Green_Text(bType)<< + " for "<"); + + boundarySphereParticles( + const boundaryBase &boundary, + sphereParticles& prtcls + ); + + create_vCtor( + boundarySphereParticles, + boundaryBase, + ( + const boundaryBase &boundary, + sphereParticles& prtcls + ), + (boundary, prtcls) + ); + + add_vCtor( + boundarySphereParticles, + boundarySphereParticles, + boundaryBase + ); + + sphereParticles& Particles(); + + const sphereParticles& Particles()const; + + bool hearChanges( + real t, + real dt, + uint32 iter, + const message &msg, + const anyList &varList) override + { + return true; + } + + virtual + bool acceleration(const timeInfo& ti, const realx3& g) + { + return true; + } + + static + uniquePtr create( + const boundaryBase &boundary, + sphereParticles& prtcls); + +}; + + +} + + + +#endif diff --git a/src/Particles/SphereParticles/boundarySphereParticlesList.cpp b/src/Particles/SphereParticles/boundarySphereParticlesList.cpp new file mode 100644 index 00000000..5cbebc32 --- /dev/null +++ b/src/Particles/SphereParticles/boundarySphereParticlesList.cpp @@ -0,0 +1,19 @@ +#include "boundarySphereParticlesList.hpp" + +pFlow::boundarySphereParticlesList::boundarySphereParticlesList( + const boundaryList &bndrs, + sphereParticles &prtcls +) +: + ListPtr(bndrs.size()), + boundaries_(bndrs) +{ + for(auto i=0; iset + ( + i, + boundarySphereParticles::create(boundaries_[i], prtcls) + ); + } +} \ No newline at end of file diff --git a/src/Particles/SphereParticles/boundarySphereParticlesList.hpp b/src/Particles/SphereParticles/boundarySphereParticlesList.hpp new file mode 100644 index 00000000..cd6770df --- /dev/null +++ b/src/Particles/SphereParticles/boundarySphereParticlesList.hpp @@ -0,0 +1,36 @@ + + +#ifndef __boundarySphereParticlesList_hpp__ +#define __boundarySphereParticlesList_hpp__ + +#include "ListPtr.hpp" +#include "boundaryList.hpp" +#include "boundarySphereParticles.hpp" + +namespace pFlow +{ + +class boundarySphereParticlesList +: + public ListPtr +{ +private: + + const boundaryList& boundaries_; + +public: + + boundarySphereParticlesList( + const boundaryList& bndrs, + sphereParticles& prtcls + ); + + ~boundarySphereParticlesList()=default; + +}; + +} + + + +#endif \ No newline at end of file diff --git a/src/Particles/SphereParticles/sphereParticles/sphereParticles.cpp b/src/Particles/SphereParticles/sphereParticles/sphereParticles.cpp index cfa0ea80..9274f48c 100644 --- a/src/Particles/SphereParticles/sphereParticles/sphereParticles.cpp +++ b/src/Particles/SphereParticles/sphereParticles/sphereParticles.cpp @@ -19,10 +19,13 @@ Licence: -----------------------------------------------------------------------------*/ #include "sphereParticles.hpp" -#include "setFieldList.hpp" +#include "systemControl.hpp" +#include "vocabs.hpp" #include "sphereParticlesKernels.hpp" -pFlow::uniquePtr> + +//#include "setFieldList.hpp" +/*pFlow::uniquePtr> pFlow::sphereParticles::getFieldObjectList()const { auto objListPtr = particles::getFieldObjectList(); @@ -78,10 +81,10 @@ bool pFlow::sphereParticles::initializeParticles() static_cast(shapeName_.size())); return insertSphereParticles(shapeName_, indices, false); -} +}*/ -bool pFlow::sphereParticles::beforeIteration() +/*bool pFlow::sphereParticles::beforeIteration() { particles::beforeIteration(); @@ -98,45 +101,19 @@ bool pFlow::sphereParticles::beforeIteration() intPredictTimer_.end(); return true; -} +}*/ -bool pFlow::sphereParticles::iterate() -{ - - accelerationTimer_.start(); - //INFO<<"before accelerationTimer_ "<dt(), accelertion_); - - rVelIntegration_().correct(this->dt(), rVelocity_, rAcceleration_); - - intCorrectTimer_.end(); - - return true; -} -bool pFlow::sphereParticles::afterIteration() + +/*bool pFlow::sphereParticles::afterIteration() { return true; -} +}*/ -bool pFlow::sphereParticles::insertSphereParticles( +/*bool pFlow::sphereParticles::insertSphereParticles( const wordVector& names, const int32IndexContainer& indices, bool setId @@ -219,86 +196,220 @@ bool pFlow::sphereParticles::insertSphereParticles( return true; +}*/ + +bool pFlow::sphereParticles::initializeParticles() +{ + + using exeSpace = typename realPointField_D::execution_space; + using policy = Kokkos::RangePolicy< + exeSpace, + Kokkos::IndexType>; + + auto [minIndex, maxIndex] = minMax(shapeIndex().internal()); + + if( !spheres_.indexValid(maxIndex) ) + { + fatalErrorInFunction<< + "the maximum value of shapeIndex is "<< maxIndex << + " which is not valid."<(shapeNames.size()); + + propIds.clear(); + propIds.reserve(numNew); + + diams.clear(); + diams.reserve(numNew); + + m.clear(); + m.reserve(numNew); + + Is.clear(); + Is.reserve(numNew); + + shIndex.clear(); + shIndex.reserve(numNew); + + + for(const auto& name:shapeNames) + { + uint32 indx; + if(spheres_.shapeNameToIndex(name,indx)) + { + shIndex.push_back(indx); + Is.push_back( spheres_.Inertia(indx)); + m.push_back(spheres_.mass(indx)); + diams.push_back(spheres_.boundingDiameter(indx)); + propIds.push_back( spheres_.propertyId(indx)); + } + else + { + fatalErrorInFunction<<"Shape name "<< name << + "does not exist. The list is "<( - objectFile( - sphereShapeFile__, - "", - objectFile::READ_ALWAYS, - objectFile::WRITE_NEVER - ) - ) + dynPointStruct(), + 0u + ), + diameter_ + ( + objectFile( + "diameter", + "", + objectFile::READ_NEVER, + objectFile::WRITE_NEVER), + dynPointStruct(), + 0.00000000001 + ), + mass_ + ( + objectFile( + "mass", + "", + objectFile::READ_NEVER, + objectFile::WRITE_NEVER), + dynPointStruct(), + 0.0000000001 + ), + I_ + ( + objectFile + ( + "I", + "", + objectFile::READ_NEVER, + objectFile::WRITE_NEVER ), - I_( - this->time().emplaceObject( - objectFile( - "I", - "", - objectFile::READ_NEVER, - objectFile::WRITE_ALWAYS - ), - pStruct(), - static_cast(0.0000000001) - ) - ), - rVelocity_( - this->time().emplaceObject( - objectFile( - "rVelocity", - "", - objectFile::READ_IF_PRESENT, - objectFile::WRITE_ALWAYS - ), - pStruct(), - zero3 - ) - ), - rAcceleration_( - this->time().emplaceObject( - objectFile( - "rAcceleration", - "", - objectFile::READ_IF_PRESENT, - objectFile::WRITE_ALWAYS - ), - pStruct(), - zero3 - ) + dynPointStruct(), + static_cast(0.0000000001) + ), + rVelocity_ + ( + objectFile + ( + "rVelocity", + "", + objectFile::READ_IF_PRESENT, + objectFile::WRITE_ALWAYS ), + dynPointStruct(), + zero3 + ), + rAcceleration_ + ( + objectFile( + "rAcceleration", + "", + objectFile::READ_IF_PRESENT, + objectFile::WRITE_ALWAYS + ), + dynPointStruct(), + zero3 + ), + boundarySphereParticles_ + ( + dynPointStruct().boundaries(), + *this + ), accelerationTimer_( "Acceleration", &this->timers() ), intPredictTimer_( "Integration-predict", &this->timers() ), intCorrectTimer_( - "Integration-correct", &this->timers() ) - + "Integration-correct", &this->timers() ), + fieldUpdateTimer_( + "fieldUpdate", &this->timers() ) { - - REPORT(1)<<"Creating integration method "<integrationMethod()) - << " for rotational velocity."<("integrationMethod"); + REPORT(1)<<"Creating integration method "<time().integration(), - this->pStruct(), - this->integrationMethod()); + dynPointStruct(), + intMethod, + rVelocity_.field() + ); if( !rVelIntegration_ ) { @@ -307,37 +418,17 @@ pFlow::sphereParticles::sphereParticles( fatalExit; } - if(rVelIntegration_->needSetInitialVals()) - { - - auto [minInd, maxInd] = pStruct().activeRange(); - int32IndexContainer indexHD(minInd, maxInd); - - auto n = indexHD.size(); - auto index = indexHD.indicesHost(); - - realx3Vector rvel(n,RESERVE()); - const auto hrVel = rVelocity_.hostVector(); - - for(auto i=0; isetInitialVals(indexHD, rvel); - - } - + WARNING<<"setFields for rVelIntegration_"<needSetInitialVals()) @@ -350,7 +441,7 @@ bool pFlow::sphereParticles::update(const eventMessage& msg) auto index = indexHD.indicesHost(); realx3Vector rvel(n,RESERVE()); - const auto hrVel = rVelocity_.hostVector(); + const auto hrVel = rVelocity_.hostView(); for(auto i=0; idt(); + dynPointStruct().predict(dt, accelertion()); + rVelIntegration_().predict(dt,rVelocity_, rAcceleration_); + intPredictTimer_.end(); + + fieldUpdateTimer_.start(); + propertyId_.updateBoundariesSlaveToMasterIfRequested(); + diameter_.updateBoundariesSlaveToMasterIfRequested(); + mass_.updateBoundariesSlaveToMasterIfRequested(); + I_.updateBoundariesSlaveToMasterIfRequested(); + rVelocity_.updateBoundariesSlaveToMasterIfRequested(); + rAcceleration_.updateBoundariesSlaveToMasterIfRequested(); + rVelIntegration_().updateBoundariesSlaveToMasterIfRequested(); + fieldUpdateTimer_.end(); + + return true; +} + +bool pFlow::sphereParticles::iterate() +{ + + timeInfo ti = TimeInfo(); + realx3 g = control().g(); + + particles::iterate(); + accelerationTimer_.start(); + pFlow::sphereParticlesKernels::acceleration( + g, + mass().deviceViewAll(), + contactForce().deviceViewAll(), + I().deviceViewAll(), + contactTorque().deviceViewAll(), + dynPointStruct().activePointsMaskDevice(), + accelertion().deviceViewAll(), + rAcceleration().deviceViewAll() + ); + for(auto& bndry:boundarySphereParticles_) + { + bndry->acceleration(ti, g); + } + accelerationTimer_.end(); + + intCorrectTimer_.start(); + + if(!dynPointStruct().correct(dt(), accelertion())) + { + return false; + } + if(!rVelIntegration_().correct( + dt(), + rVelocity_, + rAcceleration_)) + { + return false; + } + + intCorrectTimer_.end(); + + return true; +} + +bool pFlow::sphereParticles::insertParticles +( + const realx3Vector &position, + const wordVector &shapesNames, + const anyList &setVarList +) +{ + anyList newVarList(setVarList); + + realVector mass("mass"); + realVector I("I"); + realVector diameter("diameter"); + uint32Vector propId("propId"); + uint32Vector shapeIdx("shapeIdx"); + + if(!getParticlesInfoFromShape( + shapesNames, + propId, + diameter, + mass, + I, + shapeIdx)) + { + return false; + } + + newVarList.emplaceBack( + mass_.name()+"Vector", + std::move(mass)); + + newVarList.emplaceBack( + I_.name()+"Vector", + std::move(I)); + + newVarList.emplaceBack( + diameter_.name()+"Vector", + std::move(diameter)); + + newVarList.emplaceBack( + propertyId_.name()+"Vector", + std::move(propId)); + + newVarList.emplaceBack( + shapeIndex().name()+"Vector", + std::move(shapeIdx)); + + if(!dynPointStruct().insertPoints(position, newVarList)) + { + return false; + } + + return true; +} + +pFlow::word pFlow::sphereParticles::shapeTypeName()const +{ + return "sphere"; +} + +const pFlow::shape &pFlow::sphereParticles::getShapes() const +{ + return spheres_; +} + +void pFlow::sphereParticles::boundingSphereMinMax +( + real & minDiam, + real& maxDiam +)const +{ + minDiam = spheres_.minBoundingSphere(); + maxDiam = spheres_.maxBoundingSphere(); +} diff --git a/src/Particles/SphereParticles/sphereParticles/sphereParticles.hpp b/src/Particles/SphereParticles/sphereParticles/sphereParticles.hpp index 38d57e0c..7033d800 100644 --- a/src/Particles/SphereParticles/sphereParticles/sphereParticles.hpp +++ b/src/Particles/SphereParticles/sphereParticles/sphereParticles.hpp @@ -2,189 +2,239 @@ O C enter of O O E ngineering and O O M ultiscale modeling of - OOOOOOO F luid flow + 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 + 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 + 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::sphereParticles - - @brief Class for managing spherical particles - - This is a top-level class that contains the essential components for - defining spherical prticles in a DEM simulation. +/** + * @class pFlow::sphereParticles + * + * @brief Class for managing spherical particles + * + * This is a top-level class that contains the essential components for + * defining spherical prticles in a DEM simulation. */ #ifndef __sphereParticles_hpp__ -#define __sphereParticles_hpp__ +#define __sphereParticles_hpp__ -#include "systemControl.hpp" -#include "particles.hpp" -#include "sphereShape.hpp" -#include "property.hpp" #include "indexContainer.hpp" - - +#include "particles.hpp" +#include "property.hpp" +#include "sphereShape.hpp" +#include "boundarySphereParticlesList.hpp" +#include "systemControl.hpp" namespace pFlow { -class sphereParticles -: - public particles +class sphereParticles : public particles { -protected: - - /// reference to material properties - const property& property_; - - /// reference to shapes - sphereShape& shapes_; - - /// pointField of inertial of particles - realPointField_D& I_; - - /// pointField of rotational Velocity of particles on device - realx3PointField_D& rVelocity_; - - /// pointField of rotational acceleration of particles on device - realx3PointField_D& rAcceleration_; - - /// rotational velocity integrator - uniquePtr rVelIntegration_ = nullptr; - - /// timer for acceleration computations - Timer accelerationTimer_; - - /// timer for integration computations (prediction step) - Timer intPredictTimer_; - - /// timer for integration computations (correction step) - Timer intCorrectTimer_; - - bool diameterMassInertiaPropId(const word& shName, real& diam, real& mass, real& I, int8& propIdx); - - bool initializeParticles(); - - bool insertSphereParticles( - const wordVector& names, - const int32IndexContainer& indices, - bool setId = true); - - virtual uniquePtr> getFieldObjectList()const override; - public: - /// construct from systemControl and property - sphereParticles(systemControl &control, const property& prop); + using ShapeType = sphereShape; - /// no copy constructor - sphereParticles(const sphereParticles&) = delete; +private: - /// move constructor - sphereParticles(sphereParticles&&) = default; + /// reference to shapes + ShapeType spheres_; - /// no copy-assignement - sphereParticles& operator=(const sphereParticles&) = delete; + /// property id on device + uint32PointField_D propertyId_; - /// move-assignement - sphereParticles& operator=(sphereParticles&&) = default; + /// diameter / boundig sphere size of particles on device + realPointField_D diameter_; - virtual ~sphereParticles()=default; + /// mass of particles field + realPointField_D mass_; + + /// pointField of inertial of particles + realPointField_D I_; + + /// pointField of rotational Velocity of particles on device + realx3PointField_D rVelocity_; + + /// pointField of rotational acceleration of particles on device + realx3PointField_D rAcceleration_; + + /// boundaries + boundarySphereParticlesList boundarySphereParticles_; + + /// rotational velocity integrator + uniquePtr rVelIntegration_ = nullptr; + + /// timer for acceleration computations + Timer accelerationTimer_; + + /// timer for integration computations (prediction step) + Timer intPredictTimer_; + + /// timer for integration computations (correction step) + Timer intCorrectTimer_; + + Timer fieldUpdateTimer_; + +private: + + + bool getParticlesInfoFromShape( + const wordVector& shapeNames, + uint32Vector& propIds, + realVector& diams, + realVector& m, + realVector& Is, + uint32Vector& shIndex + ); + /*bool initializeParticles(); + + bool insertSphereParticles( + const wordVector& names, + const int32IndexContainer& indices, + bool setId = true); + + virtual uniquePtr> getFieldObjectList()const override; + */ +protected: + Timer& accelerationTimer() + { + return accelerationTimer_; + } + + Timer& intCorrectTimer() + { + return intCorrectTimer_; + } + + integration& rVelIntegration() + { + return rVelIntegration_(); + } + +public: + + /// construct from systemControl and property + sphereParticles(systemControl& control, const property& prop); + + ~sphereParticles() override = default; /** * Insert new particles in position with specified shapes - * - * This function is involked by inserted object to insert new set of particles - * into the simulation. - * \param position position of new particles + * + * This function is involked by inserted object to insert new set of + * particles into the simulation. \param position position of new particles * \param shape shape of new particles * \param setField initial value of the selected fields for new particles */ - bool insertParticles + /*bool insertParticles ( - const realx3Vector& position, - const wordVector& shapes, - const setFieldList& setField - ) override ; + const realx3Vector& position, + const wordVector& shapes, + const setFieldList& setField + ) override ;*/ - /// const reference to shapes object - const auto& shapes()const + // TODO: make this method private later + bool initializeParticles(); + + /// const reference to shapes object + const auto& spheres() const { - return shapes_; + return spheres_; } /// const reference to inertia pointField - const auto& I()const + const auto& I() const { return I_; } - /// reference to inertia pointField + /// reference to inertia pointField auto& I() { return I_; } - - const realx3Vector_D rVelocity()const - { + + const auto& rVelocity() const + { return rVelocity_; } - const realVector_D& boundingSphere()const override + auto& rVelocity() { - return this->diameter(); + return rVelocity_; } - word shapeTypeName() const override + bool hearChanges( + real t, + real dt, + uint32 iter, + const message& msg, + const anyList& varList + ) override { - return "sphere"; + notImplementedFunction; + return false; } - void boundingSphereMinMax( - real& minDiam, - real& maxDiam )const override + const uint32PointField_D& propertyId() const override { - shapes_.diameterMinMax(minDiam, maxDiam); + return propertyId_; } - bool update(const eventMessage& msg) override; - - + const realPointField_D& diameter() const override + { + return diameter_; + } + + const realPointField_D& mass() const override + { + return mass_; + } + + /// before iteration step + bool beforeIteration() override; + + /// iterate particles + bool iterate() override; + + bool insertParticles( + const realx3Vector& position, + const wordVector& shapesNames, + const anyList& setVarList + ) override; + realx3PointField_D& rAcceleration() override { return rAcceleration_; } - + const realx3PointField_D& rAcceleration() const override { return rAcceleration_; } - /// before iteration step - bool beforeIteration() override; + const realPointField_D& boundingSphere() const override + { + return diameter(); + } - /// iterate particles - bool iterate() override; + word shapeTypeName() const override; - /// after iteration step - bool afterIteration() override; - + const shape& getShapes() const override; - -}; //sphereParticles + void boundingSphereMinMax(real& minDiam, real& maxDiam) const override; + +}; // sphereParticles } // pFlow diff --git a/src/Particles/SphereParticles/sphereParticles/sphereParticlesKernels.cpp b/src/Particles/SphereParticles/sphereParticles/sphereParticlesKernels.cpp new file mode 100644 index 00000000..5e2def60 --- /dev/null +++ b/src/Particles/SphereParticles/sphereParticles/sphereParticlesKernels.cpp @@ -0,0 +1,100 @@ +/*------------------------------- 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 "sphereParticlesKernels.hpp" + +using policy = Kokkos::RangePolicy< + pFlow::DefaultExecutionSpace, + Kokkos::Schedule, + Kokkos::IndexType>; + +void pFlow::sphereParticlesKernels::addMassDiamInertiaProp +( + deviceViewType1D shapeIndex, + deviceViewType1D mass, + deviceViewType1D diameter, + deviceViewType1D I, + deviceViewType1D propertyId, + pFlagTypeDevice incld, + deviceViewType1D src_mass, + deviceViewType1D src_diameter, + deviceViewType1D src_I, + deviceViewType1D src_propertyId +) +{ + auto aRange = incld.activeRange(); + + Kokkos::parallel_for( + "particles::initInertia", + policy(aRange.start(), aRange.end()), + LAMBDA_HD(uint32 i) + { + if(incld(i)) + { + uint32 index = shapeIndex[i]; + I[i] = src_I[index]; + diameter[i] = src_diameter[index]; + mass[i] = src_mass[index]; + propertyId[i] = src_propertyId[index]; + } + }); + +} + +void pFlow::sphereParticlesKernels::acceleration +( + const realx3& g, + const deviceViewType1D& mass, + const deviceViewType1D& force, + const deviceViewType1D& I, + const deviceViewType1D& torque, + const pFlagTypeDevice& incld, + deviceViewType1D lAcc, + deviceViewType1D rAcc +) +{ + + auto activeRange = incld.activeRange(); + if(incld.isAllActive()) + { + Kokkos::parallel_for( + "pFlow::sphereParticlesKernels::acceleration", + policy(activeRange.start(), activeRange.end()), + LAMBDA_HD(uint32 i){ + lAcc[i] = force[i]/mass[i] + g; + rAcc[i] = torque[i]/I[i]; + }); + } + else + { + Kokkos::parallel_for( + "pFlow::sphereParticlesKernels::acceleration", + policy(activeRange.start(), activeRange.end()), + LAMBDA_HD(uint32 i){ + if(incld(i)) + { + lAcc[i] = force[i]/mass[i] + g; + rAcc[i] = torque[i]/I[i]; + } + }); + + } + + Kokkos::fence(); +} diff --git a/src/Particles/SphereParticles/sphereParticles/sphereParticlesKernels.hpp b/src/Particles/SphereParticles/sphereParticles/sphereParticlesKernels.hpp index 2edeff2b..628b1c49 100644 --- a/src/Particles/SphereParticles/sphereParticles/sphereParticlesKernels.hpp +++ b/src/Particles/SphereParticles/sphereParticles/sphereParticlesKernels.hpp @@ -21,56 +21,36 @@ Licence: #ifndef __sphereParticlesKernels_hpp__ #define __sphereParticlesKernels_hpp__ +#include "types.hpp" +#include "pointFlag.hpp" + namespace pFlow::sphereParticlesKernels { -using rpAcceleration = Kokkos::RangePolicy< - DefaultExecutionSpace, - Kokkos::Schedule, - Kokkos::IndexType - >; - -template -void acceleration( - realx3 g, - deviceViewType1D mass, - deviceViewType1D force, +void addMassDiamInertiaProp( + deviceViewType1D shapeIndex, + deviceViewType1D mass, + deviceViewType1D diameter, deviceViewType1D I, - deviceViewType1D torque, - IncludeFunctionType incld, - deviceViewType1D lAcc, - deviceViewType1D rAcc - ) -{ + deviceViewType1D propertyId, + pFlagTypeDevice incld, + deviceViewType1D src_mass, + deviceViewType1D src_diameter, + deviceViewType1D src_I, + deviceViewType1D src_propertyId +); - auto activeRange = incld.activeRange(); - if(incld.allActive()) - { - Kokkos::parallel_for( - "pFlow::sphereParticlesKernels::acceleration", - rpAcceleration(activeRange.first, activeRange.second), - LAMBDA_HD(int32 i){ - lAcc[i] = force[i]/mass[i] + g; - rAcc[i] = torque[i]/I[i]; - }); - } - else - { - Kokkos::parallel_for( - "pFlow::sphereParticlesKernels::acceleration", - rpAcceleration(activeRange.first, activeRange.second), - LAMBDA_HD(int32 i){ - if(incld(i)) - { - lAcc[i] = force[i]/mass[i] + g; - rAcc[i] = torque[i]/I[i]; - } - }); +void acceleration( + const realx3& g, + const deviceViewType1D& mass, + const deviceViewType1D& force, + const deviceViewType1D& I, + const deviceViewType1D& torque, + const pFlagTypeDevice& incld, + deviceViewType1D lAcc, + deviceViewType1D rAcc +); - } - - Kokkos::fence(); -} } diff --git a/src/Particles/SphereParticles/sphereShape/sphereShape.cpp b/src/Particles/SphereParticles/sphereShape/sphereShape.cpp index 7723f039..fac52d3c 100644 --- a/src/Particles/SphereParticles/sphereShape/sphereShape.cpp +++ b/src/Particles/SphereParticles/sphereShape/sphereShape.cpp @@ -19,186 +19,182 @@ Licence: -----------------------------------------------------------------------------*/ #include "sphereShape.hpp" -#include "dictionary.hpp" -#include "vocabs.hpp" -#include "streams.hpp" -bool pFlow::sphereShape::insertNames -( - const wordVector& names -) +bool pFlow::sphereShape::readFromDictionary3() { - names_.clear(); - uint32 i=0; - for(const auto& nm:names) - { - if(!names_.insertIf(nm, i)) - { - fatalErrorInFunction<< - " repeated name in the list of sphere names: " << names; - return false; - } - i++; - } - names_.rehash(0); - - numShapes_ = names_.size(); - - return true; -} + diameters_ = getVal("diameters"); -bool pFlow::sphereShape::readDictionary -( - const dictionary& dict -) -{ - diameters_ = dict.getVal("diameters"); - materials_ = dict.getVal("materials"); - auto names = dict.getVal("names"); - - if(diameters_.size() != materials_.size() ) + if(diameters_.size() != numShapes() ) { - fatalErrorInFunction<< - " number of elements in diameters and properties are not the same in "<< dict.globalName()< names_; +protected: - size_t numShapes_; - - - bool insertNames(const wordVector& names); - - bool readDictionary(const dictionary& dict); - - bool writeDictionary(dictionary& dict)const; + bool writeToDict(dictionary& dict)const override; public: // - type info - TypeInfoNV("sphereShape"); + TypeInfo("shape"); + sphereShape( + const word& fileName, + repository* owner, + const property& prop); - sphereShape(){} - - sphereShape( - const realVector& diameter, - const wordVector& property, - const wordVector& name - ); - - sphereShape(const sphereShape&) = default; - - sphereShape(sphereShape&&) = default; - - sphereShape& operator=(const sphereShape&) = default; - - sphereShape& operator=(sphereShape&&) = default; - - auto clone()const - { - return makeUnique(*this); - } - - sphereShape* clonePtr()const - { - return new sphereShape(*this); - } - - ~sphereShape() = default; + + ~sphereShape() override = default; //// - Methods - const auto& names()const{ - return names_; - } - const auto& diameters()const{ - return diameters_; - } + real maxBoundingSphere()const override; - const auto& materials()const{ - return materials_; - } + real minBoundingSphere()const override; - const auto diameter(label i)const{ - return diameters_[i]; - } + bool boundingDiameter(uint32 index, real& bDiam)const override; - const auto material(label i)const{ - return materials_[i]; - } + real boundingDiameter(uint32 index)const override; + realVector boundingDiameter()const override; - // name to index - bool nameToIndex(const word& name, uint32& index)const - { - if(auto[iter, found] = names_.findIf(name); found ) - { - index = iter->second; - return true; - } - else - { - index = 0; - return false; - } - } + bool mass(uint32 index, real& m)const override; - uint32 nameToIndex(const word& name)const - { - return names_.at(name); - } + real mass(uint32 index) const override; - bool indexToName(uint32 i, word& name)const - { - for(auto& nm: names_) - { - if(nm.second == i) - { - name = nm.first; - return true; - } - } - name = ""; - return false; - } + realVector mass()const override; - bool shapeToDiameter(wordVector& names, realVector& diams)const; + realVector density() const override; - void diameterMinMax(real& minD, real& maxD)const - { - minD = min(diameters_); - maxD = max(diameters_); - } + bool Inertia(uint32 index, real& I)const override; - //// - IO operatoin + real Inertia(uint32 index)const override; - // - read from stream/file - bool read(iIstream& is); + realVector Inertia()const override; + + bool Inertia_xx(uint32 index, real& Ixx)const override; - // - write to stream/file - bool write(iOstream& os)const; + real Inertial_xx(uint32 index)const override; + + bool Inertia_yy(uint32 index, real& Iyy)const override; - // - read from dictionary - bool read(const dictionary& dict) - { - return readDictionary(dict); - } + real Inertial_yy(uint32 index)const override; - // - write to dictionary - bool write(dictionary& dict)const - { - return writeDictionary(dict); - } + bool Inertia_zz(uint32 index, real& Izz)const override; + real Inertial_zz(uint32 index)const override; }; diff --git a/src/Particles/dynamicPointStructure/dynamicPointStructure.cpp b/src/Particles/dynamicPointStructure/dynamicPointStructure.cpp index 16e5b849..f0875341 100644 --- a/src/Particles/dynamicPointStructure/dynamicPointStructure.cpp +++ b/src/Particles/dynamicPointStructure/dynamicPointStructure.cpp @@ -19,57 +19,41 @@ Licence: -----------------------------------------------------------------------------*/ #include "dynamicPointStructure.hpp" - +#include "systemControl.hpp" pFlow::dynamicPointStructure::dynamicPointStructure ( - Time& time, - const word& integrationMethod + systemControl& control ) : - time_(time), - integrationMethod_(integrationMethod), - pStruct_( - time_.emplaceObject( - objectFile( - pointStructureFile__, - "", - objectFile::READ_ALWAYS, - objectFile::WRITE_ALWAYS - ) - ) - ), - velocity_( - time_.emplaceObject( - objectFile( - "velocity", - "", - objectFile::READ_ALWAYS, - objectFile::WRITE_ALWAYS - ), - pStruct(), - zero3 - ) - ) - + pointStructure(control), + velocity_ + ( + objectFile( + "velocity", + "", + objectFile::READ_ALWAYS, + objectFile::WRITE_ALWAYS + ), + *this, + zero3 + ), + velocityUpdateTimer_("velocity boundary update", &timers()), + integrationMethod_ + ( + control.settingsDict().getVal("integrationMethod") + ) { - - this->subscribe(pStruct()); - REPORT(1)<< "Creating integration method "<< - greenText(integrationMethod_)<<" for dynamicPointStructure."<needSetInitialVals()) return; - - - - auto [minInd, maxInd] = pStruct().activeRange(); - int32IndexContainer indexHD(minInd, maxInd); - - auto n = indexHD.size(); - auto index = indexHD.indicesHost(); - - realx3Vector pos(n,RESERVE()); - realx3Vector vel(n,RESERVE()); - const auto hVel = velocity().hostVector(); - const auto hPos = pStruct().pointPosition().hostVector(); - - for(auto i=0; isetInitialVals(indexHD, pos); - - REPORT(2)<< "Initializing the required vectors for velocity integratoin\n "<setInitialVals(indexHD, vel); } -bool pFlow::dynamicPointStructure::predict -( - real dt, - realx3PointField_D& acceleration -) -{ - auto& pos = pStruct().pointPosition(); - if(!integrationPos_().predict(dt, pos.VectorField(), velocity_.VectorField() ))return false; - if(!integrationVel_().predict(dt, velocity_.VectorField(), acceleration.VectorField()))return false; +bool pFlow::dynamicPointStructure::beforeIteration() +{ + if(!pointStructure::beforeIteration())return false; + velocityUpdateTimer_.start(); + velocity_.updateBoundariesSlaveToMasterIfRequested(); + integrationPos_->updateBoundariesSlaveToMasterIfRequested(); + integrationVel_->updateBoundariesSlaveToMasterIfRequested(); + velocityUpdateTimer_.end(); + return true; +} + +bool pFlow::dynamicPointStructure::iterate() +{ + return pointStructure::iterate(); + + /*real dt = this->dt(); + + auto& acc = time().lookupObject("acceleration"); + return correct(dt, acc);*/ +} + +bool pFlow::dynamicPointStructure::predict( + real dt, + realx3PointField_D &acceleration) +{ + + if(!integrationPos_().predict(dt, pointPosition(), velocity_ ))return false; + if(!integrationVel_().predict(dt, velocity_, acceleration))return false; return true; } @@ -137,82 +118,11 @@ bool pFlow::dynamicPointStructure::correct realx3PointField_D& acceleration ) { - auto& pos = pStruct().pointPosition(); + //auto& pos = pStruct().pointPosition(); - if(!integrationPos_().correct(dt, pos.VectorField(), velocity_.VectorField() ))return false; + if(!integrationPos_().correctPStruct(dt, *this, velocity_) )return false; - if(!integrationVel_().correct(dt, velocity_.VectorField(), acceleration.VectorField()))return false; + if(!integrationVel_().correct(dt, velocity_, acceleration))return false; return true; } - -/*FUNCTION_H -pFlow::uniquePtr pFlow::dynamicPointStructure::insertPoints -( - const realx3Vector& pos, - const List& exclusionList -) -{ - auto newIndicesPtr = pointStructure::insertPoints(pos, exclusionList); - - // no new point is inserted - if( !newIndicesPtr ) return newIndicesPtr; - - if(!integrationPos_().needSetInitialVals()) return newIndicesPtr; - - auto hVel = velocity_.hostVector(); - auto n = newIndicesPtr().size(); - auto index = newIndicesPtr().indicesHost(); - - realx3Vector velVec(n, RESERVE()); - for(auto i=0; isetInitialVals(newIndicesPtr(), pos ); - integrationVel_->setInitialVals(newIndicesPtr(), velVec ); - - return newIndicesPtr; - -}*/ - - -bool pFlow::dynamicPointStructure::update( - const eventMessage& msg) -{ - if( msg.isInsert()) - { - - if(!integrationPos_->needSetInitialVals())return true; - - const auto indexHD = pStruct().insertedPointIndex(); - - - auto n = indexHD.size(); - - if(n==0) return true; - - auto index = indexHD.indicesHost(); - - realx3Vector pos(n,RESERVE()); - realx3Vector vel(n,RESERVE()); - const auto hVel = velocity().hostVector(); - const auto hPos = pStruct().pointPosition().hostVector(); - - for(auto i=0; isetInitialVals(indexHD, pos); - - integrationVel_->setInitialVals(indexHD, vel); - - } - - return true; -} \ No newline at end of file diff --git a/src/Particles/dynamicPointStructure/dynamicPointStructure.hpp b/src/Particles/dynamicPointStructure/dynamicPointStructure.hpp index 843a3c46..f82f1dca 100644 --- a/src/Particles/dynamicPointStructure/dynamicPointStructure.hpp +++ b/src/Particles/dynamicPointStructure/dynamicPointStructure.hpp @@ -30,98 +30,71 @@ Licence: namespace pFlow { +class systemControl; + class dynamicPointStructure : - //public pointStructure -public eventObserver + public pointStructure { -protected: +private: - Time& time_; + realx3PointField_D velocity_; - word integrationMethod_; + uniquePtr integrationPos_ = nullptr; - pointStructure& pStruct_; + uniquePtr integrationVel_ = nullptr; - realx3PointField_D& velocity_; + Timer velocityUpdateTimer_; - uniquePtr integrationPos_; - - uniquePtr integrationVel_; + /// @brief integration method for velocity and position + word integrationMethod_; public: TypeInfo("dynamicPointStructure"); - dynamicPointStructure(Time& time, const word& integrationMethod); - - dynamicPointStructure(const dynamicPointStructure& ps) = default; + explicit dynamicPointStructure(systemControl& control); + dynamicPointStructure(const dynamicPointStructure& ps) = delete; - // - no move construct + // - no move construct dynamicPointStructure(dynamicPointStructure&&) = delete; - // - copy assignment - // - // should be changed, may causs undefined behavior - ////////////////////////////////////////////////////////////// - dynamicPointStructure& operator=(const dynamicPointStructure&) = default; + /// + dynamicPointStructure& operator=(const dynamicPointStructure&) = delete; // - no move assignment dynamicPointStructure& operator=(dynamicPointStructure&&) = delete; // - destructor - virtual ~dynamicPointStructure() = default; + ~dynamicPointStructure() override = default; - inline pointStructure& pStruct() - { - return pStruct_; - } - - inline const pointStructure& pStruct() const - { - return pStruct_; - } - - inline const realx3PointField_D& velocity()const + inline + const realx3PointField_D& velocity()const { return velocity_; } - inline auto velocityHostAll() + inline + realx3PointField_D& velocity() { - return velocity_.hostVectorAll(); + return velocity_; } - inline auto pointPositionHostAll() - { - return pStruct_.pointPositionHostAll(); - } - - auto markDeleteOutOfBox(const box& domain) - { - return pStruct_.markDeleteOutOfBox(domain); - } + /// In the time loop before iterate + bool beforeIteration() override; + /// @brief This is called in time loop. Perform the main calculations + /// when the component should evolve along time. + bool iterate() override; + + /// prediction step (if any), is called in beforeIteration bool predict(real dt, realx3PointField_D& acceleration); + /// correction step, is called in iterate bool correct(real dt, realx3PointField_D& acceleration); - - // - update data structure by inserting/setting new points - // Notifies all the fields in the registered list of data structure - // and exclude the fields that re in the exclusionList - // retrun nullptr if it fails - /*FUNCTION_H - virtual uniquePtr insertPoints( - const realx3Vector& pos, - const List& exclusionList={nullptr} - )override;*/ - - bool update(const eventMessage& msg) override; - - }; } diff --git a/src/Particles/particles/particleIdHandler/particleIdHandler.cpp b/src/Particles/particles/particleIdHandler/particleIdHandler.cpp new file mode 100644 index 00000000..5288e156 --- /dev/null +++ b/src/Particles/particles/particleIdHandler/particleIdHandler.cpp @@ -0,0 +1,99 @@ +/*------------------------------- 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 "particleIdHandler.hpp" + +pFlow::particleIdHandler::particleIdHandler(pointStructure& pStruct) +: + uint32PointField_D + ( + objectFile + ( + "id", + "", + objectFile::READ_IF_PRESENT, + objectFile::WRITE_ALWAYS + ), + pStruct, + static_cast(-1), + static_cast(-1) + ) +{ + +} + +bool +pFlow::particleIdHandler::hearChanges( + real t, + real dt, + uint32 iter, + const message& msg, + const anyList& varList +) +{ + if(msg.equivalentTo(message::ITEM_INSERT)) + { + const word eventName = message::eventName(message::ITEM_INSERT); + + const auto& indices = varList.getObject( + eventName); + + uint32 numNew = indices.size(); + if(numNew == 0u)return true; + + auto idRange = getIdRange(numNew); + uint32Vector newId("newId",numNew,numNew,RESERVE()); + fillSequence(newId, idRange.first); + + return this->field().insertSetElement(indices, newId); + } + else + { + return uint32PointField_D::hearChanges(t,dt,iter, msg,varList); + } +} + +pFlow::uniquePtr +pFlow::particleIdHandler::create(pointStructure& pStruct) +{ + word idHType = angleBracketsNames( + "particleIdHandler", + pFlowProcessors().localRunTypeName()); + + + if( pointStructurevCtorSelector_.search(idHType) ) + { + REPORT(1)<<"Creating particle id handler "<< + Green_Text(idHType)< getIdRange(uint32 nNewParticles)=0; + + virtual + uint32 maxId()const = 0; + + + + // heat change for possible insertion of particles + // overrdie from internalField + bool hearChanges + ( + real t, + real dt, + uint32 iter, + const message& msg, + const anyList& varList + ) override; + + static + uniquePtr create( + pointStructure& pStruct); + +}; + +} + +#endif diff --git a/src/Particles/particles/particles.cpp b/src/Particles/particles/particles.cpp index d5c3bb45..a8fc970a 100644 --- a/src/Particles/particles/particles.cpp +++ b/src/Particles/particles/particles.cpp @@ -2,201 +2,121 @@ O C enter of O O E ngineering and O O M ultiscale modeling of - OOOOOOO F luid flow + 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 + 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 + 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 "particles.hpp" - -pFlow::particles::particles -( - systemControl& control, - const word& integrationMethod -) -: - demParticles(control), - time_(control.time()), - integrationMethod_(integrationMethod), - /*dynPointStruct_( - time_.emplaceObject( - objectFile( - pointStructureFile__, - "", - objectFile::READ_ALWAYS, - objectFile::WRITE_ALWAYS - ), - control.time(), - integrationMethod - ) - ),*/ - dynPointStruct_( - control.time(), - integrationMethod), - shapeName_( - control.time().emplaceObject( - objectFile( - "shapeName", - "", - objectFile::READ_ALWAYS, - objectFile::WRITE_ALWAYS, - false - ), - pStruct(), - word("NO_NAME_SHAPE") - ) - ), - id_( - control.time().emplaceObject( - objectFile( - "id", - "", - objectFile::READ_IF_PRESENT, - objectFile::WRITE_ALWAYS - ), - pStruct(), - static_cast(-1) - ) - ), - propertyId_( - control.time().emplaceObject( - objectFile( - "propertyId", - "", - objectFile::READ_NEVER, - objectFile::WRITE_NEVER - ), - pStruct(), - static_cast(0) - ) - ), - diameter_( - control.time().emplaceObject( - objectFile( - "diameter", - "", - objectFile::READ_NEVER, - objectFile::WRITE_ALWAYS - ), - pStruct(), - static_cast(0.00000000001) - ) - ), - mass_( - control.time().emplaceObject( - objectFile( - "mass", - "", - objectFile::READ_NEVER, - objectFile::WRITE_ALWAYS - ), - pStruct(), - static_cast(0.0000000001) - ) - ), - accelertion_( - control.time().emplaceObject( - objectFile( - "accelertion", - "", - objectFile::READ_IF_PRESENT, - objectFile::WRITE_ALWAYS - ), - pStruct(), - zero3 - ) - ), - contactForce_( - control.time().emplaceObject( - objectFile( - "contactForce", - "", - objectFile::READ_IF_PRESENT, - objectFile::WRITE_ALWAYS - ), - pStruct(), - zero3 - ) - ), - contactTorque_( - control.time().emplaceObject( - objectFile( - "contactTorque", - "", - objectFile::READ_IF_PRESENT, - objectFile::WRITE_ALWAYS - ), - pStruct(), - zero3 - ) - ), - idHandler_(id_) +pFlow::particles::particles(systemControl& control) + : observer(defaultMessage_), + demComponent("particles", control), + dynPointStruct_(control), + /*id_( + objectFile( + "id", + "", + objectFile::READ_IF_PRESENT, + objectFile::WRITE_ALWAYS + ), + dynPointStruct_, + static_cast(-1), + static_cast(-1) + ),*/ + shapeIndex_( + objectFile( + "shapeIndex", + "", + objectFile::READ_ALWAYS, + objectFile::WRITE_ALWAYS + ), + dynPointStruct_, + 0 + ), + accelertion_( + objectFile( + "accelertion", + "", + objectFile::READ_IF_PRESENT, + objectFile::WRITE_ALWAYS + ), + dynPointStruct_, + zero3 + ), + contactForce_( + objectFile( + "contactForce", + "", + objectFile::READ_IF_PRESENT, + objectFile::WRITE_ALWAYS + ), + dynPointStruct_, + zero3 + ), + contactTorque_( + objectFile( + "contactTorque", + "", + objectFile::READ_IF_PRESENT, + objectFile::WRITE_ALWAYS + ), + dynPointStruct_, + zero3 + ), + idHandler_(particleIdHandler::create(dynPointStruct_)), + baseFieldBoundaryUpdateTimer_("baseFieldBoundaryUpdate",&timers()) { - - this->subscribe(pStruct()); + this->addToSubscriber(dynPointStruct_); + //idHandler_().initialIdCheck(); } -bool pFlow::particles::beforeIteration() +bool +pFlow::particles::beforeIteration() { - auto domain = this->control().domain(); + if( !dynPointStruct_.beforeIteration()) + { + return false; + } - auto numMarked = dynPointStruct_.markDeleteOutOfBox(domain); - - if(time_.sortTime()) - { - real min_dx, max_dx; - boundingSphereMinMax(min_dx, max_dx); - Timer t; - t.start(); - REPORT(0)<<"Performing morton sorting on particles ...."<zeroForce(); - this->zeroTorque(); - - return true; + zeroForce(); + zeroTorque(); + baseFieldBoundaryUpdateTimer_.start(); + shapeIndex_.updateBoundariesSlaveToMasterIfRequested(); + accelertion_.updateBoundariesSlaveToMasterIfRequested(); + idHandler_().updateBoundariesSlaveToMasterIfRequested(); + baseFieldBoundaryUpdateTimer_.end(); + return true; } -pFlow::uniquePtr> -pFlow::particles::getFieldObjectList()const +bool +pFlow::particles::iterate() { - auto objListPtr = makeUnique>(); - objListPtr().push_back( - static_cast(&id_) ); - - objListPtr().push_back( - static_cast(&propertyId_) ); - - objListPtr().push_back( - static_cast(&diameter_) ); - - objListPtr().push_back( - static_cast(&mass_) ); - - objListPtr().push_back( - static_cast(&shapeName_) ); - - return objListPtr; + return dynPointStruct_.iterate(); +} + +bool +pFlow::particles::afterIteration() +{ + return dynPointStruct_.afterIteration(); +} + +void +pFlow::particles::boundingSphereMinMax(real& minDiam, real& maxDiam) const +{ + auto& shp = getShapes(); + + minDiam = shp.minBoundingSphere(); + maxDiam = shp.maxBoundingSphere(); } diff --git a/src/Particles/particles/particles.hpp b/src/Particles/particles/particles.hpp index 7b207c50..12e3da8c 100644 --- a/src/Particles/particles/particles.hpp +++ b/src/Particles/particles/particles.hpp @@ -1,79 +1,65 @@ -/*------------------------------- phasicFlow --------------------------------- - O C enter of - O O E ngineering and - O O M ultiscale modeling of - OOOOOOO F luid flow +/*------------------------------- 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. + 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 __particles_hpp__ #define __particles_hpp__ +#include "demComponent.hpp" #include "dynamicPointStructure.hpp" #include "particleIdHandler.hpp" -#include "demParticles.hpp" +#include "shape.hpp" + namespace pFlow { -class setFieldList; - class particles -: - public eventObserver, - public demParticles + : public observer + , public demComponent { +private: + + /// dynamic point structure for particles center mass + dynamicPointStructure dynPointStruct_; + + /// shape index of each particle + uint32PointField_D shapeIndex_; + + /// acceleration on device + realx3PointField_D accelertion_; + + /// contact force field + realx3PointField_D contactForce_; + + /// contact torque field + realx3PointField_D contactTorque_; + + /// handling new ids for new particles + uniquePtr idHandler_ = nullptr; + + Timer baseFieldBoundaryUpdateTimer_; + + /// messages for this objects + static inline const message defaultMessage_{ message::DEFAULT }; + protected: - - // owner repository - Time& time_; - - const word integrationMethod_; - - // dynamic point structure for particles - dynamicPointStructure dynPointStruct_; - - // - name of shapes - this is managed by particles - wordPointField& shapeName_; - - // id of particles on host - int32PointField_HD& id_; - - // property id on device - int8PointField_D& propertyId_; - - // diameter / boundig sphere size of particles on device - realPointField_D& diameter_; - - // mass on device - realPointField_D& mass_; - - // - acceleration on device - realx3PointField_D& accelertion_; - - - realx3PointField_D& contactForce_; - - - realx3PointField_D& contactTorque_; - - - // - object handling particle id - particleIdHandler idHandler_; - - virtual uniquePtr> getFieldObjectList()const; void zeroForce() { @@ -85,193 +71,156 @@ protected: contactTorque_.fill(zero3); } -public: - - // type info - TypeInfo("particles"); - - particles(systemControl& control, const word& integrationMethod); - - inline const auto& time()const { - return time_; - } - - inline auto& time() { - return time_; - } - - inline auto integrationMethod()const - { - return integrationMethod_; - } - - inline const auto& dynPointStruct()const - { - return dynPointStruct_; - } - inline auto& dynPointStruct() { return dynPointStruct_; } - inline const auto& pStruct()const{ - return dynPointStruct_.pStruct(); - } - - inline auto& pStruct(){ - return dynPointStruct_.pStruct(); - } - - inline auto size()const{ - return pStruct().size(); - } - - inline auto capacity() const{ - return pStruct().capacity(); - } - - inline auto activePointsMaskD()const{ - return pStruct().activePointsMaskD(); - } - - inline auto numActive()const + inline auto& pointPosition() { - return pStruct().numActive(); + return dynPointStruct_.pointPosition(); + } + + inline auto& idHandler() + { + return idHandler_(); } - inline bool allActive()const{ - return pStruct().allActive(); - } - - inline auto activeRange()const{ - return pStruct().activeRange(); - } - - inline auto activePointsMaskH()const{ - return pStruct().activePointsMaskH(); - } - - inline const auto& pointPosition()const{ - return pStruct().pointPosition(); - } - - inline const auto& position()const + inline auto& shapeIndex() { - return pStruct().pointPosition(); + return shapeIndex_; } - inline const auto& pointVelocity()const{ - return dynPointStruct().velocity(); +public: + + // type info + TypeInfo("particles"); + + explicit particles(systemControl& control); + + inline const auto& dynPointStruct() const + { + return dynPointStruct_; } - inline const auto& velocity()const{ - return dynPointStruct().velocity(); + inline const pointStructure& pStruct() const + { + return dynPointStruct_; } - inline const auto& id()const{ - return id_; + inline const auto& simDomain() const + { + return dynPointStruct_.simDomain(); } - inline auto& id(){ - return id_; + inline const auto& thisDomain() const + { + return dynPointStruct_.thisDomain(); } - inline const auto& diameter()const{ - return diameter_; + inline const auto& extendedDomain() const + { + return dynPointStruct_.extendedDomain(); } - inline auto& diameter(){ - return diameter_; + inline auto size() const + { + return dynPointStruct_.size(); } - inline const auto& mass()const{ - return mass_; + inline auto capacity() const + { + return dynPointStruct_.capacity(); } - inline auto& mass() { - return mass_; + inline auto numActive() const + { + return dynPointStruct_.numActive(); } - inline const auto& accelertion()const{ + inline bool isAllActive() const + { + return dynPointStruct_.isAllActive(); + } + + inline const auto& pointPosition() const + { + return dynPointStruct_.pointPosition(); + } + + inline const auto& velocity() const + { + return dynPointStruct_.velocity(); + } + + inline const auto& accelertion() const + { return accelertion_; } - inline auto& accelertion(){ + inline auto& accelertion() + { return accelertion_; } + inline auto& contactForce() + { + return contactForce_; + } + + inline const auto& contactForce() const + { + return contactForce_; + } + + inline auto& contactTorque() + { + return contactTorque_; + } + + inline const auto& contactTorque() const + { + return contactTorque_; + } + inline - realx3PointField_D& contactForce() + uint maxId()const { - return contactForce_; + return idHandler_().maxId(); } - inline - const realx3PointField_D& contactForce() const - { - return contactForce_; - } + bool beforeIteration() override; - inline - realx3PointField_D& contactTorque() - { - return contactTorque_; - } + bool iterate() override; - inline - const realx3PointField_D& contactTorque() const - { - return contactTorque_; - } + bool afterIteration() override; - inline const auto& propertyId()const{ - return propertyId_; - } + virtual bool insertParticles( + const realx3Vector& position, + const wordVector& shapesNames, + const anyList& setVarList + ) = 0; - inline auto& propertyId(){ - return propertyId_; - } + virtual const uint32PointField_D& propertyId() const = 0; - inline const auto& shapeName()const{ - return shapeName_; - } + virtual const realPointField_D& diameter() const = 0; - inline auto& shapName(){ - return shapeName_; - } + virtual const realPointField_D& mass() const = 0; - bool beforeIteration() override; + virtual realx3PointField_D& rAcceleration() = 0; - virtual - bool insertParticles - ( - const realx3Vector& position, - const wordVector& shapes, - const setFieldList& setField - ) = 0; + virtual const realx3PointField_D& rAcceleration() const = 0; - + virtual const realPointField_D& boundingSphere() const = 0; - virtual - realx3PointField_D& rAcceleration() = 0; + virtual word shapeTypeName() const = 0; - virtual - const realx3PointField_D& rAcceleration() const = 0; + virtual const shape& getShapes() const = 0; - virtual - const realVector_D& boundingSphere()const = 0; - - virtual - word shapeTypeName()const = 0; - - virtual - void boundingSphereMinMax(real & minDiam, real& maxDiam)const = 0; - - + virtual void boundingSphereMinMax(real& minDiam, real& maxDiam) const = 0; }; // particles -} // pFlow +} // namespace pFlow #endif //__particles_hpp__ diff --git a/src/Particles/particles/regularParticleIdHandler/regularParticleIdHandler.cpp b/src/Particles/particles/regularParticleIdHandler/regularParticleIdHandler.cpp new file mode 100644 index 00000000..b8a55aba --- /dev/null +++ b/src/Particles/particles/regularParticleIdHandler/regularParticleIdHandler.cpp @@ -0,0 +1,54 @@ +#include "regularParticleIdHandler.hpp" + + + +pFlow::regularParticleIdHandler::regularParticleIdHandler +( + pointStructure& pStruct +) +: + particleIdHandler(pStruct) +{ + initialIdCheck(); +} + +pFlow::Pair + pFlow::regularParticleIdHandler::getIdRange(uint32 nNewParticles) +{ + + if(nNewParticles==0) return {0,0}; + + uint32 startId; + if(maxId_== static_cast(-1)) + { + startId = 0; + } + else + { + startId = maxId_+1; + } + uint32 endId = startId+nNewParticles-1; + maxId_ = endId; + return {startId, endId}; +} + +bool pFlow::regularParticleIdHandler::initialIdCheck() +{ + /// empty point structure / no particles in simulation + if( pStruct().empty() ) return true; + + uint32 maxId = max( *this ); + + /// particles should get ids from 0 to size-1 + if(maxId == static_cast(-1)) + { + fillSequence(*this,0u); + maxId_ = size()-1; + } + else + { + maxId_ = maxId; + } + + return true; +} diff --git a/src/Particles/particles/regularParticleIdHandler/regularParticleIdHandler.hpp b/src/Particles/particles/regularParticleIdHandler/regularParticleIdHandler.hpp new file mode 100644 index 00000000..3e4f8b41 --- /dev/null +++ b/src/Particles/particles/regularParticleIdHandler/regularParticleIdHandler.hpp @@ -0,0 +1,64 @@ +/*------------------------------- 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 __regularParticleIdHandler_hpp__ +#define __regularParticleIdHandler_hpp__ + +#include "particleIdHandler.hpp" + +namespace pFlow +{ + +class regularParticleIdHandler +: + public particleIdHandler +{ +private: + + uint32 maxId_ = static_cast(-1); + + bool initialIdCheck()override; +public: + + ClassInfo("particleIdHandler"); + + explicit regularParticleIdHandler(pointStructure& pStruct); + + ~regularParticleIdHandler()override = default; + + add_vCtor + ( + particleIdHandler, + regularParticleIdHandler, + pointStructure + ); + + Pair getIdRange(uint32 nNewParticles)override; + + uint32 maxId()const override + { + return maxId_; + } + +}; + +} + + +#endif //__regularParticleIdHandler_hpp__ \ No newline at end of file diff --git a/src/Particles/particles/shape/baseShapeNames.cpp b/src/Particles/particles/shape/baseShapeNames.cpp new file mode 100644 index 00000000..eaef39cb --- /dev/null +++ b/src/Particles/particles/shape/baseShapeNames.cpp @@ -0,0 +1,122 @@ +/*------------------------------- 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 "baseShapeNames.hpp" + +bool pFlow::baseShapeNames::createHashNames() +{ + hashNames_.clear(); + hashes_.clear(); + + std::hash hasher; + + uint32 i=0; + for(const auto& nm:shapeNames_) + { + if(!hashNames_.insertIf(nm, i)) + { + fatalErrorInFunction<< + " repeated name in the list of shape names: " << shapeNames_; + return false; + } + hashes_.push_back(hasher(nm)); + i++; + } + hashNames_.rehash(0); + + return true; +} + + +bool pFlow::baseShapeNames::readFromDictionary1() +{ + + shapeNames_ = getVal("names"); + numShapes_ = shapeNames_.size(); + + return true; +} + + +pFlow::baseShapeNames::baseShapeNames +( + const word &fileName, + repository *owner +) +: + fileDictionary + ( + objectFile + ( + fileName, + "", + objectFile::READ_ALWAYS, + objectFile::WRITE_ALWAYS + ), + owner + ) +{ + + if( !readFromDictionary1() ) + { + fatalErrorInFunction; + fatalExit; + } + + if( !createHashNames()) + { + fatalErrorInFunction; + fatalExit; + } + +} + + +bool pFlow::baseShapeNames::writeToDict(dictionary &dict)const +{ + + if( !dict.add("names", shapeNames_) ) + { + fatalErrorInFunction<< + " Error in writing names to dictionary "<< dict.globalName()< hashNames_; + + /// list of shape names + wordVector shapeNames_{"shapeNames"}; + + /// hash for names + Vector hashes_{"hashes"}; + + bool createHashNames(); + + bool readFromDictionary1(); + + using hasher = typename wordHashMap::hasher; + +protected: + + virtual + bool writeToDict(dictionary& dict)const; + +public: + + TypeInfo("baseShapeNames"); + + baseShapeNames( + const word& fileName, + repository* owner); + + ~baseShapeNames() override=default; + + + inline + const wordVector& shapeNames()const + { + return shapeNames_; + } + + inline + wordList shapeNameList()const + { + wordList wl; + wl.insert(wl.begin(), shapeNames_.begin(), shapeNames_.end()); + return wl; + } + + inline + const auto& hashes()const + { + return hashes_; + } + + inline + size_t numShapes()const + { + return numShapes_; + } + + // name to index + inline + bool shapeNameToIndex(const word& name, uint32& index)const + { + if(auto[iter, found] = hashNames_.findIf(name); found ) + { + index = iter->second; + return true; + } + else + { + index = 0; + return false; + } + } + + inline + bool indexToShapeName(uint32 i, word& name)const + { + if( i < numShapes_) + { + name = shapeNames_[i]; + return true; + } + return false; + } + + inline bool hashToIndex(const size_t& hs, uint32& idx) + { + for(auto i=0; i(-1); + return false; + } + + inline + bool indexValid(uint32 index)const + { + return index < numShapes_; + } + + // - IO + + using fileDictionary::write; + + bool write(iOstream& os)const override; + +}; + +} + +#endif //__shapeNames_hpp__ \ No newline at end of file diff --git a/src/Particles/particles/shape/shape.cpp b/src/Particles/particles/shape/shape.cpp new file mode 100644 index 00000000..bcf66e74 --- /dev/null +++ b/src/Particles/particles/shape/shape.cpp @@ -0,0 +1,77 @@ +#include "shape.hpp" + + +bool pFlow::shape::findPropertyIds() +{ + shapePropertyIds_.resize(numShapes()); + + ForAll( i, materialNames_) + { + if(uint32 propId; property_.nameToIndex(materialNames_[i], propId) ) + { + shapePropertyIds_[i] = propId; + } + else + { + fatalErrorInFunction<<"Material name "<< materialNames_[i]<< + " is not valid in dictionary "<("materials"); + + if(materialNames_.size() != numShapes() ) + { + fatalErrorInFunction<< + " number of elements in materials and names are not the same in "<< globalName()<(propId) < property_.numMaterials(); + } + + + inline + bool indexToDensity(uint32 index, real& rho)const + { + if(indexValid(index)) + return property_.density(shapePropertyIds_[index], rho); + return false; + } + + inline + real indexToDensity(uint32 index)const + { + if(indexValid(index)) + { + return property_.density(shapePropertyIds_[index]); + } + + fatalExit; + return 0.0; + } + + inline + uint32 propertyId(uint32 index)const + { + if(indexValid(index)) + { + return shapePropertyIds_[index]; + } + fatalExit; + return 0.0; + } + + virtual + real maxBoundingSphere()const = 0; + + virtual + real minBoundingSphere()const = 0; + + virtual + bool boundingDiameter(uint32 index, real& bDiam)const =0; + + virtual + real boundingDiameter(uint32 index)const = 0; + + virtual + realVector boundingDiameter()const = 0; + + virtual + bool mass(uint32 index, real& m)const = 0; + + virtual + real mass(uint32 index) const =0; + + virtual + realVector mass()const =0; + + virtual + realVector density()const =0; + + virtual + bool Inertia(uint32 index, real& I)const = 0; + + virtual + real Inertia(uint32 index)const = 0; + + virtual + realVector Inertia()const=0; + + virtual + bool Inertia_xx(uint32 index, real& Ixx)const = 0; + + virtual + real Inertial_xx(uint32 index)const =0; + + virtual + bool Inertia_yy(uint32 index, real& Iyy)const = 0; + + virtual + real Inertial_yy(uint32 index)const = 0; + + virtual + bool Inertia_zz(uint32 index, real& Izz)const = 0; + + virtual + real Inertial_zz(uint32 index)const = 0; + +}; + +} + +#endif //__shape_hpp__ \ No newline at end of file diff --git a/src/Property/property.cpp b/src/Property/property.cpp index b2745e10..d6af1f47 100644 --- a/src/Property/property.cpp +++ b/src/Property/property.cpp @@ -18,55 +18,42 @@ Licence: -----------------------------------------------------------------------------*/ - #include "property.hpp" #include "dictionary.hpp" -bool pFlow::property::readDictionary -( - const dictionary& dict -) +bool pFlow::property::readDictionary() { - materials_ = dict.getVal("materials"); + materials_ = getVal("materials"); - densities_ = dict.getVal("densities"); + densities_ = getVal("densities"); if(materials_.size() != densities_.size() ) { fatalErrorInFunction<< " number of elements in material ("<(materials_.size()); return true; } pFlow::property::property ( + const word& fileName, const wordVector& materials, - const realVector& densities + const realVector& densities, + repository* owner ) : + fileDictionary + ( + objectFile + ( + fileName, + "", + objectFile::READ_NEVER, + objectFile::WRITE_NEVER + ), + owner + ), materials_(materials), densities_(densities) { + + if(!writeDictionary()) + { + fatalExit; + } + if(!makeNameIndex()) { fatalErrorInFunction<< - " error in the input parameters of constructor. \n"; + "error in the input parameters of constructor. \n"; fatalExit; } } pFlow::property::property ( -const fileSystem& file + const word& fileName, + repository* owner ) : - dict_ + fileDictionary ( - makeUnique - ("property", true) - ) -{ - iFstream dictStream(file); - - if(!dict_().read(dictStream)) - { - ioErrorInFile(dictStream.name(), dictStream.lineNumber()); - fatalExit; - } - - if(!readDictionary(dict_())) - { - fatalExit; - } - -} - -pFlow::property::property -( - const dictionary& dict -) -: - dict_ - ( - makeUnique(dict) + objectFile + ( + fileName, + "", + objectFile::READ_ALWAYS, + objectFile::WRITE_NEVER + ), + owner ) { - if(!readDictionary(dict_())) + if(!readDictionary()) { fatalExit; } + + if(!makeNameIndex()) + { + fatalErrorInFunction<< + "error in dictionary "<< globalName()< dict_ = nullptr; - /// list of name of materials wordVector materials_; @@ -55,6 +51,7 @@ protected: /// rapid mapping from name to index wordHashMap nameIndex_; + /// number of materials uint32 numMaterials_ = 0; @@ -62,10 +59,10 @@ protected: // - protected member functions /// read from dict - bool readDictionary(const dictionary& dict); + bool readDictionary(); /// write to dict - bool writeDictionary(dictionary& dict)const; + bool writeDictionary(); /// creates a mapp bool makeNameIndex(); @@ -73,22 +70,24 @@ protected: public: /// Type info - TypeInfoNV("property"); + TypeInfo("property"); - // - Constructors - /// Emptry constructor, used for reading from a file - property(){} + explicit + property( + const word& fileName, + repository* owner=nullptr); - /// Constructe from materials and densities - property(const wordVector& materials, const realVector& densities); - - /// Construct from file - property(const fileSystem& file); - - /// Construct from dictionary dict - property(const dictionary& dict); + property( + const word& fileName, + const fileSystem& dir + ); + + property(const word& fileName, + const wordVector& materials, + const realVector& densities, + repository* owner=nullptr); /// Default copy property(const property& ) = default; @@ -103,17 +102,11 @@ public: property& operator= (property&&) = default; /// Default destructor - ~property() = default; + ~property() override = default; // - Methods - /// Return dictionary - inline const auto& dict()const - { - return dict_(); - } - /// Return number of materials inline auto numMaterials()const { @@ -189,21 +182,9 @@ public: return false; } } + + - //// - IO operatoins - - /// Read from dictionary - bool read(const dictionary& dict) - { - return readDictionary(dict); - } - - /// Write to dictionary - bool write(dictionary& dict)const - { - return writeDictionary(dict); - } - }; } diff --git a/src/phasicFlow/CMakeLists-old.txt b/src/phasicFlow/CMakeLists-old.txt new file mode 100644 index 00000000..b6b68815 --- /dev/null +++ b/src/phasicFlow/CMakeLists-old.txt @@ -0,0 +1,87 @@ + +list(APPEND SourceFiles +types/basicTypes/bTypesFunctions.cpp +types/basicTypes/Logical.cpp +types/types.cpp + +globals/error.cpp + +streams/token/tokenIO.cpp +streams/token/token.cpp +streams/iStream/IOstream.cpp +streams/iStream/iIstream.cpp +streams/iStream/iOstream.cpp +streams/Stream/Istream.cpp +streams/Stream/Ostream.cpp +streams/Fstream/iFstream.cpp +streams/Fstream/oFstream.cpp +streams/Fstream/fileStream.cpp +streams/TStream/iTstream.cpp +streams/TStream/oTstream.cpp +streams/streams.cpp + +dictionary/dictionary.cpp +dictionary/entry/iEntry.cpp +dictionary/entry/dataEntry.cpp +dictionary/twoPartEntry/twoPartEntry.cpp + +fileSystem/fileSystem.cpp + +commandLine/commandLine.cpp + +random/randomReal/randomReal.cpp +random/randomReal/randomReals.cpp + +Timer/Timer.cpp +Timer/Timers.cpp + +repository/Time/Time.cpp +repository/Time/timeControl.cpp +repository/systemControl/systemControl.cpp +repository/systemControl/dynamicLinkLibs.cpp +repository/repository/repository.cpp +repository/IOobject/objectFile.cpp +repository/IOobject/IOobject.cpp +repository/IOobject/IOfileHeader.cpp + +structuredData/box/box.cpp +structuredData/cells/cells.cpp +structuredData/cylinder/cylinder.cpp +structuredData/sphere/sphere.cpp +structuredData/iBox/iBoxs.cpp +structuredData/line/line.cpp +structuredData/zAxis/zAxis.cpp +structuredData/pointStructure/pointStructure.cpp +structuredData/pointStructure/mortonIndexing.cpp +structuredData/pointStructure/selectors/pStructSelector/pStructSelector.cpp +structuredData/pointStructure/selectors/selectBox/selectBox.cpp +structuredData/pointStructure/selectors/selectRange/selectRange.cpp +structuredData/pointStructure/selectors/selectRandom/selectRandom.cpp +structuredData/trisurfaceStructure/triSurface.cpp +structuredData/trisurfaceStructure/multiTriSurface.cpp +structuredData/trisurfaceStructure/stlFile.cpp +structuredData/peakableRegion/sphereRegion/sphereRegion.cpp +structuredData/peakableRegion/cylinderRegion/cylinderRegion.cpp +structuredData/peakableRegion/boxRegion/boxRegion.cpp +structuredData/peakableRegion/peakableRegion/peakableRegion.cpp +structuredData/peakableRegion/peakableRegions.cpp + +containers/Vector/Vectors.cpp +containers/Field/Fields.cpp +containers/symArrayHD/symArrays.cpp +containers/triSurfaceField/triSurfaceFields.cpp +containers/bitsetHD/bitsetHDs.cpp +containers/indexContainer/indexContainer.cpp + +setFieldList/setFieldList.cpp +setFieldList/setFieldEntry.cpp + +eventSubscriber/eventSubscriber.cpp +eventSubscriber/eventObserver.cpp) + +set(link_libs Kokkos::kokkos tbb) + +pFlow_add_library_install(phasicFlow SourceFiles link_libs) + +target_include_directories(phasicFlow PUBLIC ./Kokkos ./algorithms ./globals) + diff --git a/src/phasicFlow/CMakeLists.txt b/src/phasicFlow/CMakeLists.txt index b6b68815..eb50c1a7 100644 --- a/src/phasicFlow/CMakeLists.txt +++ b/src/phasicFlow/CMakeLists.txt @@ -5,83 +5,156 @@ types/basicTypes/Logical.cpp types/types.cpp globals/error.cpp +globals/globalSettings.cpp + +processors/processors.cpp +processors/localProcessors.cpp +processors/pFlowProcessors.cpp +processors/MPITimer.cpp + streams/token/tokenIO.cpp streams/token/token.cpp streams/iStream/IOstream.cpp -streams/iStream/iIstream.cpp streams/iStream/iOstream.cpp -streams/Stream/Istream.cpp +streams/iStream/iIstream.cpp streams/Stream/Ostream.cpp -streams/Fstream/iFstream.cpp -streams/Fstream/oFstream.cpp -streams/Fstream/fileStream.cpp +streams/Stream/Istream.cpp +streams/processorOstream/processorOstream.cpp +streams/masterOstream/masterOstream.cpp streams/TStream/iTstream.cpp streams/TStream/oTstream.cpp +streams/Fstream/iFstream.cpp +streams/Fstream/oFstream.cpp +streams/Fstream/fileStream.cpp +streams/dataIO/dataIORegulars.cpp streams/streams.cpp +fileSystem/fileSystem.cpp + dictionary/dictionary.cpp +dictionary/fileDictionary.cpp dictionary/entry/iEntry.cpp dictionary/entry/dataEntry.cpp dictionary/twoPartEntry/twoPartEntry.cpp -fileSystem/fileSystem.cpp +repository/IOobject/objectFile.cpp +repository/IOobject/IOfileHeader.cpp +repository/IOobject/IOobject.cpp +repository/IOobject/IOPattern.cpp +repository/repository/repository.cpp +repository/Time/Time.cpp +repository/Time/timeControl.cpp +repository/Time/baseTimeControl.cpp +repository/systemControl/systemControl.cpp +repository/systemControl/dynamicLinkLibs.cpp commandLine/commandLine.cpp -random/randomReal/randomReal.cpp -random/randomReal/randomReals.cpp +eventManagement/subscriber.cpp +eventManagement/observer.cpp + +demComponent/demComponent.cpp Timer/Timer.cpp Timer/Timers.cpp -repository/Time/Time.cpp -repository/Time/timeControl.cpp -repository/systemControl/systemControl.cpp -repository/systemControl/dynamicLinkLibs.cpp -repository/repository/repository.cpp -repository/IOobject/objectFile.cpp -repository/IOobject/IOobject.cpp -repository/IOobject/IOfileHeader.cpp - -structuredData/box/box.cpp -structuredData/cells/cells.cpp -structuredData/cylinder/cylinder.cpp -structuredData/sphere/sphere.cpp -structuredData/iBox/iBoxs.cpp -structuredData/line/line.cpp -structuredData/zAxis/zAxis.cpp -structuredData/pointStructure/pointStructure.cpp -structuredData/pointStructure/mortonIndexing.cpp -structuredData/pointStructure/selectors/pStructSelector/pStructSelector.cpp -structuredData/pointStructure/selectors/selectBox/selectBox.cpp -structuredData/pointStructure/selectors/selectRange/selectRange.cpp -structuredData/pointStructure/selectors/selectRandom/selectRandom.cpp -structuredData/trisurfaceStructure/triSurface.cpp -structuredData/trisurfaceStructure/multiTriSurface.cpp -structuredData/trisurfaceStructure/stlFile.cpp -structuredData/peakableRegion/sphereRegion/sphereRegion.cpp -structuredData/peakableRegion/cylinderRegion/cylinderRegion.cpp -structuredData/peakableRegion/boxRegion/boxRegion.cpp -structuredData/peakableRegion/peakableRegion/peakableRegion.cpp -structuredData/peakableRegion/peakableRegions.cpp containers/Vector/Vectors.cpp +containers/VectorHD/wordVectorHost.cpp +containers/VectorHD/VectorSingles.cpp containers/Field/Fields.cpp containers/symArrayHD/symArrays.cpp +containers/List/anyList/anyList.cpp + +structuredData/zAxis/zAxis.cpp +structuredData/box/box.cpp +structuredData/sphere/sphere.cpp +structuredData/cylinder/cylinder.cpp +structuredData/peakableRegion/geometricRegion/geometricRegions.cpp +structuredData/peakableRegion/PeakableRegion/PeakableRegions.cpp +structuredData/peakableRegion/peakableRegion/peakableRegion.cpp + +structuredData/pointStructure/internalPoints/internalPointsKernels.cpp +structuredData/pointStructure/internalPoints/internalPoints.cpp + +structuredData/line/line.cpp +structuredData/infinitePlane/infinitePlane.cpp +structuredData/plane/plane.cpp +structuredData/domain/domain.cpp +structuredData/domain/simulationDomain.cpp +structuredData/domain/regularSimulationDomain.cpp +structuredData/boundaries/boundaryBase/boundaryBase.cpp +structuredData/boundaries/boundaryBase/boundaryBaseKernels.cpp +structuredData/boundaries/boundaryExit/boundaryExit.cpp +structuredData/boundaries/boundaryNone/boundaryNone.cpp +structuredData/boundaries/boundaryPeriodic/boundaryPeriodic.cpp +structuredData/boundaries/boundaryReflective/boundaryReflective.cpp +structuredData/boundaries/boundaryList.cpp +structuredData/pointStructure/pointStructure/pointStructure.cpp +structuredData/pointStructure/selectors/pStructSelector/pStructSelector.cpp +structuredData/pointStructure/selectors/selectorStridedRange/selectorStridedRange.cpp +structuredData/pointStructure/selectors/selectorRandomPoints/selectorRandomPoints.cpp +structuredData/pointStructure/selectors/selectBox/selectBox.cpp +structuredData/pointStructure/selectors/selectorGeometric/selectorGeometrics.cpp +structuredData/pointStructure/pointStructure/pointSorting/mortonIndexing.cpp +structuredData/pointStructure/pointStructure/pointSorting/pointSorting.cpp + +triSurface/subSurface.cpp +triSurface/triSurface.cpp +triSurface/multiTriSurface.cpp + +containers/pointField/boundaryField/generalBoundary/generalBoundary.cpp +containers/pointField/pointField/pointFields.cpp containers/triSurfaceField/triSurfaceFields.cpp -containers/bitsetHD/bitsetHDs.cpp -containers/indexContainer/indexContainer.cpp setFieldList/setFieldList.cpp setFieldList/setFieldEntry.cpp -eventSubscriber/eventSubscriber.cpp -eventSubscriber/eventObserver.cpp) +) +set(link_libs) set(link_libs Kokkos::kokkos tbb) + -pFlow_add_library_install(phasicFlow SourceFiles link_libs) -target_include_directories(phasicFlow PUBLIC ./Kokkos ./algorithms ./globals) +if(pFlow_Build_MPI) + + set(Zoltan_Install_DIR) + if(DEFINED ENV{Zoltan_DIR}) + set(Zoltan_Install_DIR $ENV{Zoltan_DIR}) + else() + set(Zoltan_Install_DIR $ENV{HOME}/PhasicFlow/Zoltan) + endif() + message(STATUS "Zoltan install directory is ${Zoltan_Install_DIR}") + + set(ZOLTAN_PREFIX "${Zoltan_Install_DIR}" CACHE STRING "Zoltan install directory") + + find_path(ZOLTAN_INCLUDE_DIR zoltan.h PATHS "${ZOLTAN_PREFIX}/include") + + message(STATUS "Zoltan include path: ${ZOLTAN_INCLUDE_DIR}") + + find_library(ZOLTAN_LIBRARY zoltan PATHS "${ZOLTAN_PREFIX}/lib") + message(STATUS "Zoltan lib path: ${ZOLTAN_LIBRARY}") + + list(APPEND SourceFiles + MPIParallelization/domain/partitioning/partitioning.cpp + MPIParallelization/domain/partitioning/rcb1DPartitioning.cpp + MPIParallelization/domain/MPISimulationDomain.cpp + MPIParallelization/dataIOMPI/dataIOMPIs.cpp + MPIParallelization/MPI/procCommunication.cpp + MPIParallelization/MPI/scatteredMasterDistributeChar.cpp + MPIParallelization/pointStructure/boundaries/boundaryProcessor.cpp + MPIParallelization/pointField/processorBoundaryFields.cpp + ) + + list(APPEND link_libs MPI::MPI_CXX ${ZOLTAN_LIBRARY} -lm ) + pFlow_add_library_install(phasicFlow SourceFiles link_libs) + target_include_directories(phasicFlow PUBLIC ./globals ${ZOLTAN_INCLUDE_DIR}) + +else() + pFlow_add_library_install(phasicFlow SourceFiles link_libs) + target_include_directories(phasicFlow PUBLIC ./globals) +endif() + diff --git a/src/phasicFlow/Kokkos/KokkosTypes.hpp b/src/phasicFlow/Kokkos/KokkosTypes.hpp index 4f59872f..c902abef 100644 --- a/src/phasicFlow/Kokkos/KokkosTypes.hpp +++ b/src/phasicFlow/Kokkos/KokkosTypes.hpp @@ -2,149 +2,161 @@ O C enter of O O E ngineering and O O M ultiscale modeling of - OOOOOOO F luid flow + 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 + 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 + 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 __KokkosTypes_hpp__ #define __KokkosTypes_hpp__ +/** + * \file KokkosType.hpp + * + * \brief name aliases and typedesf for Kokkos entities that are + * frequently used in PhasicFlow. + * + */ #include #include #include -#include "iOstream.hpp" - +#include "builtinTypes.hpp" namespace pFlow { -class DeviceSide{}; -class HostSide{}; +/// Host memory space +using HostSpace = Kokkos::HostSpace; -template -struct selectSide{}; - -using HostSpace = Kokkos::HostSpace; -using Serial = Kokkos::Serial; +/// Serial execution space +using Serial = Kokkos::Serial; #ifdef _OPENMP -using OpenMP = Kokkos::OpenMP; +/// OpenMp execution space +using OpenMP = Kokkos::OpenMP; #endif -using DefaultHostExecutionSpace = Kokkos::DefaultHostExecutionSpace; -using DefaultExecutionSpace = Kokkos::DefaultExecutionSpace; - - - -template - using kPair = Kokkos::pair; - -template - using kRange = kPair; - -using range = kRange; - -using range64 = kRange; - -template - using ViewTypeScalar = Kokkos::View; - -template - using ViewType1D = Kokkos::View; - -template - using DualViewType1D = Kokkos::DualView; - -template - using ViewType3D = Kokkos::View; - -template - using unorderedMap = Kokkos::UnorderedMap; - -template - using unorderedSet = Kokkos::UnorderedMap; - -template - using deviceHashMap= Kokkos::UnorderedMap; - -template - using hostHashMap= Kokkos::UnorderedMap; - -template - using deviceHashSet= Kokkos::UnorderedMap; - -template - using hostHashSet = Kokkos::UnorderedMap; - -// a 1D array (vector) with default device (memory space and execution space) -template - using deviceViewTypeScalar = Kokkos::View; - -template - using deviceViewType1D = Kokkos::View; - -template - using deviceViewType2D = Kokkos::View; - - -// a 1D array (vector with host memeory space) -template - using hostViewTypeScalar = Kokkos::View; - -template - using hostViewType1D = Kokkos::View; - -template - using hostViewType2D = Kokkos::View; - - #ifdef __CUDACC__ -using Cuda = Kokkos::Cuda; -template - using cudaViewTypeScalar = Kokkos::View; - -template - using cudaViewType1D = Kokkos::View; - -template - using cudaViewType2D = Kokkos::View; +/// Cuda execution space +using Cuda = Kokkos::Cuda; #endif +/// Default Host execution space, on top of all host execution spaces +using DefaultHostExecutionSpace = Kokkos::DefaultHostExecutionSpace; + +/// Default execution space, it can be device exe. space, if a device space is +/// activated. +using DefaultExecutionSpace = Kokkos::DefaultExecutionSpace; + +using deviceRPolicyStatic = Kokkos::RangePolicy< + Kokkos::DefaultExecutionSpace, + Kokkos::Schedule, + Kokkos::IndexType>; + +using hostRPolicyStatic = Kokkos::RangePolicy< + Kokkos::DefaultExecutionSpace, + Kokkos::Schedule, + Kokkos::IndexType>; + +using deviceRPolicyDynamic = Kokkos::RangePolicy< + Kokkos::DefaultExecutionSpace, + Kokkos::Schedule, + Kokkos::IndexType>; + +using hostRPolicyDynamic = Kokkos::RangePolicy< + Kokkos::DefaultExecutionSpace, + Kokkos::Schedule, + Kokkos::IndexType>; + +/// Pair of two variables +template +using Pair = Kokkos::pair; + +/// View for a scalar +template +using ViewTypeScalar = Kokkos::View; + +/// 1D veiw as a vector +template +using ViewType1D = Kokkos::View; + +/// 2D view as an array +template +using ViewType2D = Kokkos::View; + +/// 3D view as an array +template +using ViewType3D = Kokkos::View; + +/// 1D dual view as a vector +template +using DualViewType1D = Kokkos::DualView; + +/// unordered map +template +using unorderedMap = Kokkos::UnorderedMap; + +/// unordered set +template +using unorderedSet = Kokkos::UnorderedMap; + +/// Scalar on device +template +using deviceViewTypeScalar = Kokkos::View; + +/// 1D array (vector) with default device (memory space and execution space) +template +using deviceViewType1D = Kokkos::View; + +/// 2D view on device as an array on device +template +using deviceViewType2D = Kokkos::View; + +/// 3D view on device as an array on device +template +using deviceViewType3D = Kokkos::View; template -using deviceAtomicViewType1D = - Kokkos::View< - T*, - Kokkos::MemoryTraits::value?0:Kokkos::Atomic>>; +using hostViewTypeScalar = Kokkos::View; +/// 1D array (vector with host memeory space) template -using deviceAtomicViewType3D = - Kokkos::View< - T***, - Kokkos::MemoryTraits::value?0:Kokkos::Atomic>>; +using hostViewType1D = Kokkos::View; +/// 2D array on host +template +using hostViewType2D = Kokkos::View; + +/// 3D array on host +template +using hostViewType3D = Kokkos::View; + +/// 1D vector on device with atomic capabilities template -iOstream& operator <<(iOstream& os, const kRange& rng) -{ - os<<"["< ? 0 : Kokkos::Atomic>>; +/// 3D array on device with atomic capabilities +template +using deviceAtomicViewType3D = Kokkos::View< + T***, + Kokkos::MemoryTraits< + std::is_same_v ? 0 : Kokkos::Atomic>>; } // pFlow -#endif //__KokkosTypes_hpp__ +#endif //__KokkosTypes_hpp__ diff --git a/src/phasicFlow/Kokkos/KokkosUtilities.hpp b/src/phasicFlow/Kokkos/KokkosUtilities.hpp index 34e6aa2f..7669ba1f 100644 --- a/src/phasicFlow/Kokkos/KokkosUtilities.hpp +++ b/src/phasicFlow/Kokkos/KokkosUtilities.hpp @@ -2,17 +2,17 @@ O C enter of O O E ngineering and O O M ultiscale modeling of - OOOOOOO F luid flow + 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 + 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 + 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. @@ -21,110 +21,205 @@ Licence: #ifndef __KokkosUtilities_hpp__ #define __KokkosUtilities_hpp__ - #include "KokkosTypes.hpp" +#include "dataIO.hpp" +#include "iOstream.hpp" #include "pFlowMacros.hpp" +#include "span.hpp" #include "types.hpp" - namespace pFlow { template -INLINE_FUNCTION_H -bool constexpr isHostAccessible() +INLINE_FUNCTION_H bool constexpr isHostAccessible() { - return Kokkos::SpaceAccessibility::accessible; + return Kokkos::SpaceAccessibility::accessible; } +template +INLINE_FUNCTION_H bool constexpr isDeviceAccessible() +{ + return Kokkos::SpaceAccessibility< + ExecutionSpace, + DefaultExecutionSpace::memory_space>::accessible; +} + +/// Is MemoerySpace accessible from ExecutionSpace template -INLINE_FUNCTION_H -bool constexpr areAccessible() +INLINE_FUNCTION_H bool constexpr areAccessible() { - return Kokkos::SpaceAccessibility::accessible; + return Kokkos::SpaceAccessibility::accessible; } -template < - typename Type, - typename... Properties> -INLINE_FUNCTION_H -void realloc( ViewType1D& view, int32 len) +template +INLINE_FUNCTION_H void +reallocInit(ViewType1D& view, uint32 len) { - Kokkos::realloc(view, len); + Kokkos::realloc(Kokkos::WithoutInitializing, view, len); } -template < - typename Type, - typename... Properties> -INLINE_FUNCTION_H -void reallocNoInit(ViewType1D& view, int32 len) +template +INLINE_FUNCTION_H void +reallocNoInit(ViewType1D& view, uint32 len) { - using ViewType = ViewType1D; - word vl = view.label(); - view = ViewType(); // Deallocate first - view = ViewType( - Kokkos::view_alloc( - Kokkos::WithoutInitializing, - vl), - len); + Kokkos::realloc(Kokkos::WithoutInitializing, view, len); } -template < - typename Type, - typename... Properties> -INLINE_FUNCTION_H -void reallocFill( ViewType1D& view, int32 len, Type val) +template +INLINE_FUNCTION_H void +reallocFill(ViewType1D& view, uint32 len, Type val) { reallocNoInit(view, len); Kokkos::deep_copy(view, val); } +template +INLINE_FUNCTION_H void +reallocInit(ViewType2D& view, uint32 len1, uint32 len2) +{ + Kokkos::realloc(view, len1, len2); +} -template < - typename Type, - typename... Properties> -INLINE_FUNCTION_H -void realloc( ViewType3D& view, int32 len1, int32 len2, int32 len3) +template +INLINE_FUNCTION_H void +reallocNoInit(ViewType2D& view, uint32 len1, uint32 len2) +{ + Kokkos::realloc(Kokkos::WithoutInitializing, view, len1, len2); +} + +template +INLINE_FUNCTION_H void +reallocFill( + ViewType2D& view, + uint32 len1, + uint32 len2, + Type val +) +{ + reallocNoInit(view, len1, len2); + Kokkos::deep_copy(view, val); +} + +template +INLINE_FUNCTION_H void +reallocInit( + ViewType3D& view, + uint32 len1, + uint32 len2, + uint32 len3 +) { Kokkos::realloc(view, len1, len2, len3); } -template < - typename Type, - typename... Properties> -INLINE_FUNCTION_H -void reallocNoInit(ViewType3D& view, int32 len1, int32 len2, int32 len3) +template +INLINE_FUNCTION_H void +reallocNoInit( + ViewType3D& view, + uint32 len1, + uint32 len2, + uint32 len3 +) { - using ViewType = ViewType3D; - word vl = view.label(); - view = ViewType(); // Deallocate first - view = ViewType( - Kokkos::view_alloc( - Kokkos::WithoutInitializing, - vl), - len1, len2, len3); + Kokkos::realloc(Kokkos::WithoutInitializing, view, len1, len2, len3); } -template < - typename Type, - typename... Properties> -INLINE_FUNCTION_H -void reallocFill( ViewType3D& view, int32 len1, int32 len2, int32 len3, Type val) +template +INLINE_FUNCTION_H void +reallocFill( + ViewType3D& view, + uint32 len1, + uint32 len2, + uint32 len3, + Type val +) { reallocNoInit(view, len1, len2, len3); Kokkos::deep_copy(view, val); } +template +INLINE_FUNCTION_H void +resizeInit(ViewType1D& view, uint32 newLen) +{ + Kokkos::resize(view, newLen); +} + +template +INLINE_FUNCTION_H void +resizeNoInit(ViewType1D& view, uint32 newLen) +{ + Kokkos::resize(Kokkos::WithoutInitializing, view, newLen); +} template -INLINE_FUNCTION_H -void swapViews(ViewType& v1, ViewType &v2) +INLINE_FUNCTION_H void +swapViews(ViewType& v1, ViewType& v2) { - auto tmp = v1; - v1 = v2; - v2 = tmp; + static_assert( + std::is_move_assignable_v && + std::is_move_constructible_v, + "swapViews arguments must be move assignable and move constructible" + ); + + ViewType tmp = std::move(v1); + v1 = std::move(v2); + v2 = std::move(tmp); +} + +template +INLINE_FUNCTION_H iOstream& +operator<<(iOstream& os, const Pair& p) +{ + os << '(' << p.first << " " << p.second << ')'; + return os; +} + +template +INLINE_FUNCTION_H span + makeSpan(ViewType1D& v) +{ + return span(v.data(), v.size()); +} + +template +INLINE_FUNCTION_H span + makeSpan(ViewType1D& v, uint32 size) +{ + return span(v.data(), size); +} + +template +INLINE_FUNCTION_H span + makeSpan(const ViewType1D& v) +{ + return span(const_cast(v.data()), v.size()); +} + +template +INLINE_FUNCTION_H span + makeSpan(const ViewType1D& v, uint32 size) +{ + return span(const_cast(v.data()), size); +} + +template +INLINE_FUNCTION_H iOstream& +operator<<(iOstream& os, const ViewType1D& v) +{ + using ExSpace = typename ViewType1D::execution_space; + + static_assert( + isHostAccessible(), "View memory is not accessible from Host" + ); + + span spn(v.data(), v.size()); + os << spn; + + return os; } } // pFlow -#endif //__KokkosUtilities_hpp__ +#endif //__KokkosUtilities_hpp__ diff --git a/src/phasicFlow/Kokkos/Range.hpp b/src/phasicFlow/Kokkos/Range.hpp new file mode 100644 index 00000000..cbdd385d --- /dev/null +++ b/src/phasicFlow/Kokkos/Range.hpp @@ -0,0 +1,149 @@ +/*------------------------------- 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 __Range_hpp__ +#define __Range_hpp__ + +#include + +#include "builtinTypes.hpp" +#include "iOstream.hpp" +#include "pFlowMacros.hpp" +#include "typeInfo.hpp" + +namespace pFlow +{ + +/** + * Range for elements in an vector [start,end) + * + */ +template +struct Range : public Kokkos::pair +{ + using Pair = Kokkos::pair; + + TypeInfoTemplateNV11("Range", T) + + //// - Constructors + + /// Default + INLINE_FUNCTION_HD Range() = default; + + /// From end, set start to 0 + INLINE_FUNCTION_HD + explicit Range(const T& e) + : Range(0, e) + { + } + + /// From componeents + INLINE_FUNCTION_HD + Range(const T& s, const T& e) + : Range::Pair(s, e) + { + } + + /// From pair + INLINE_FUNCTION_HD + Range(const Range::Pair& src) + : Range::Pair(src) + { + } + + /// Copy + INLINE_FUNCTION_HD + Range(const Range&) = default; + + /// Move + INLINE_FUNCTION_HD + Range(Range&&) = default; + + /// Copy assignment + INLINE_FUNCTION_HD + Range& operator=(const Range&) = default; + + /// Move assignment + INLINE_FUNCTION_HD + Range& operator=(Range&&) = default; + + /// Destructor + INLINE_FUNCTION_HD + ~Range() = default; + + //// - Methods + + /// Start + INLINE_FUNCTION_HD + T& start() + { + return this->first; + } + + /// End + INLINE_FUNCTION_HD + T& end() + { + return this->second; + } + + INLINE_FUNCTION_HD + const T& start() const + { + return this->first; + } + + INLINE_FUNCTION_HD + const T& end() const + { + return this->second; + } + + INLINE_FUNCTION_HD + T numElements() + { + return end() - start(); + } + + INLINE_FUNCTION_HD + auto getPair() const + { + return Pair(this->first, this->second); + } +}; + +template +INLINE_FUNCTION_H iOstream& +operator<<(iOstream& os, const Range& rng) +{ + os << "[" << rng.start() << " " << rng.end() << ")"; + return os; +} + +using range32 = Range; + +using range64 = Range; + +using rangeU32 = Range; + +using rangeU64 = Range; + +} // pFlow + +#endif //__KokkosTypes_hpp__ diff --git a/src/phasicFlow/Kokkos/ViewAlgorithms.hpp b/src/phasicFlow/Kokkos/ViewAlgorithms.hpp index 2e94cc3c..28e32abd 100644 --- a/src/phasicFlow/Kokkos/ViewAlgorithms.hpp +++ b/src/phasicFlow/Kokkos/ViewAlgorithms.hpp @@ -2,17 +2,17 @@ O C enter of O O E ngineering and O O M ultiscale modeling of - OOOOOOO F luid flow + 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 + 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 + 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. @@ -21,364 +21,279 @@ Licence: #ifndef __ViewAlgorithms_hpp__ #define __ViewAlgorithms_hpp__ - -#include "numericConstants.hpp" #include "KokkosUtilities.hpp" +#include "Range.hpp" +#include "numericConstants.hpp" + +#include "cudaAlgorithms.hpp" #include "kokkosAlgorithms.hpp" #include "stdAlgorithms.hpp" -#include "cudaAlgorithms.hpp" - namespace pFlow -{ - -inline const size_t maxSizeToSerial__ = 64; - -template -INLINE_FUNCTION_H -int32 count( - const ViewType1D& view, - int32 start, - int32 end, - const T& val) { - using ExecutionSpace = typename ViewType1D::execution_space; - - int32 numElems = end-start; - - if constexpr( isHostAccessible()) - { - if(numElems( - view.data()+start, - numElems, - val); - } - } - - return pFlow::algorithms::KOKKOS::count( - view.data()+start, - numElems, - val); -} - template -INLINE_FUNCTION_H -void fill -( - ViewType1D& view, - range span, - T val +INLINE_FUNCTION_H uint32 +count( + const ViewType1D& view, + uint32 start, + uint32 end, + const T& val ) { - using ExecutionSpace = typename ViewType1D::execution_space; + using ExecutionSpace = + typename ViewType1D::execution_space; + uint32 numElems = end - start; - if constexpr( isHostAccessible()) + return pFlow::algorithms::KOKKOS::count( + view.data() + start, numElems, val + ); +} + +template +INLINE_FUNCTION_H void +fill(ViewType1D& view, rangeU32 span, T val) +{ + using exe_space = typename ViewType1D::execution_space; + auto subV = Kokkos::subview(view, span.getPair()); + if constexpr (std::is_trivially_copyable_v) { - int32 numElems = span.second-span.first; - if( numElems()) + { + for (auto i = span.start(); i < span.end(); i++) { - pFlow::algorithms::STD::fill( - view.data()+span.first, - numElems, - val); - return; + view[i] = val; } } + else + { + static_assert("fill is not valid for non-trivially-copyable data type"); + } +} - auto subV = Kokkos::subview(view, span); +template +void +fill(ViewType1D& view, uint32 start, uint32 end, T val) +{ + fill(view, rangeU32(start, end), val); +} + +template +void +fill( + ViewType3D& view, + rangeU32 range1, + rangeU32 range2, + rangeU32 range3, + const T& val +) +{ + static_assert(std::is_trivially_copyable_v, "Not valid type for fill"); + auto subV = Kokkos::subview(view, range1, range2, range3); Kokkos::deep_copy(subV, val); } template -void fill -( - ViewType1D& view, - int32 start, - int32 end, - T val +void +fill(ViewType3D& view, const T& val) +{ + static_assert(std::is_trivially_copyable_v, "Not valid type for fill"); + Kokkos::deep_copy(view, val); +} + +template +void +fillSequence( + ViewType1D& view, + uint32 start, + uint32 end, + const Type startVal ) { - fill(view, range(start,end),val); -} - -template< - typename Type, - typename... properties> -void fillSequence( - ViewType1D& view, - int32 start, - int32 end, - const Type startVal - ) -{ - - using ExecutionSpace = typename ViewType1D::execution_space; - int32 numElems = end-start; - - if constexpr( isHostAccessible()) - { - if(numElems( - view.data()+start, - numElems, - startVal); - return ; - } - } + static_assert( + std::is_trivially_copyable_v, "Not valid type for fill" + ); + using ExecutionSpace = + typename ViewType1D::execution_space; + uint32 numElems = end - start; pFlow::algorithms::KOKKOS::fillSequence( - view.data()+start, - numElems, - startVal); + view.data() + start, numElems, startVal + ); - return ; + return; } - template< - typename Type, - typename... properties, - typename indexType, - typename... indexProperties> -bool fillSelected( - ViewType1D view, - const ViewType1D indices, - const int32 numElems, - const Type val, - typename std::enable_if_t< - areAccessible< - typename ViewType1D::execution_space, - typename ViewType1D::memory_space>(), - bool> = true ) + typename Type, + typename... properties, + typename indexType, + typename... indexProperties> +bool +fillSelected( + ViewType1D view, + ViewType1D indices, + uint32 numElems, + Type val +) { + static_assert( + std::is_trivially_copyable_v, "Not valid type for fillSelected" + ); + static_assert( + areAccessible< + typename ViewType1D::execution_space, + typename ViewType1D::memory_space>(), + "In fillSelected, arguments view and indices must have similar spaces" + ); - using ExecutionSpace = typename ViewType1D::execution_space; - - if constexpr( isHostAccessible()) - { - if(numElems( - view.data(), - indices.data(), - numElems, - val); - return true; - } - } + using ExSpace = typename ViewType1D::execution_space; + using policy = Kokkos::RangePolicy>; - pFlow::algorithms::KOKKOS::fillSelected( - view.data(), - indices.data(), - numElems, - val); + Kokkos::parallel_for( + "ViewAlgorithms::fillSelected", + policy(0, numElems), + LAMBDA_HD(uint32 i){ + // view[indices[i]]= val; + } + ); + Kokkos::fence(); return true; } template< - typename Type, - typename... properties, - typename indexType, - typename... indexProperties> - //typename valType> //, - //typename... valProperties> -bool fillSelected( - ViewType1D view, - const ViewType1D indices, - const ViewType1D vals, - const int32 numElems , - typename std::enable_if_t< - areAccessible< - typename ViewType1D::execution_space, - typename ViewType1D::memory_space>(), - bool> = true ) + typename Type, + typename... properties, + typename indexType, + typename... indexProperties> +bool +fillSelected( + ViewType1D view, + const ViewType1D indices, + const ViewType1D vals, + const uint32 numElems +) { + static_assert( + std::is_trivially_copyable_v, "Not valid type for fillSelected" + ); + static_assert( + areAccessible< + typename ViewType1D::execution_space, + typename ViewType1D::memory_space>(), + "In fillSelected arguments view and indices must have similar spaces" + ); - using ExecutionSpace = typename ViewType1D::execution_space; - - - - if constexpr( isHostAccessible()) - { - if(numElems( - view.data(), - indices.data(), - vals.data(), - numElems - ); - return true; - } - } - + using ExecutionSpace = + typename ViewType1D::execution_space; pFlow::algorithms::KOKKOS::fillSelected( - view.data(), - indices.data(), - vals.data(), - numElems - ); + view.data(), indices.data(), vals.data(), numElems + ); return true; } - template -INLINE_FUNCTION_H -T min( - const ViewType1D& view, - int32 start, - int32 end) +INLINE_FUNCTION_H T +min(const ViewType1D& view, uint32 start, uint32 end) { + using ExecutionSpace = + typename ViewType1D::execution_space; - using ExecutionSpace = typename ViewType1D::execution_space; - - int32 numElems = end-start; + uint32 numElems = end - start; - if constexpr( isHostAccessible()) - { - if(numElems( - view.data()+start, - numElems); - } - } - - return - pFlow::algorithms::KOKKOS::min( - view.data()+start, - numElems); + return pFlow::algorithms::KOKKOS::min( + view.data() + start, numElems + ); } template -INLINE_FUNCTION_H -T max( - const ViewType1D& view, - int32 start, - int32 end) +INLINE_FUNCTION_H T +max(const ViewType1D& view, uint32 start, uint32 end) { + using ExecutionSpace = + typename ViewType1D::execution_space; - using ExecutionSpace = typename ViewType1D::execution_space; - - int32 numElems = end-start; + uint32 numElems = end - start; - if constexpr( isHostAccessible()) - { - if(numElems( - view.data()+start, - numElems); - } - } - - return - pFlow::algorithms::KOKKOS::max( - view.data()+start, - numElems); -} - -template < - typename dType, - typename... dProperties, - typename sType, - typename... sProperties> -INLINE_FUNCTION_H -void copy( - const ViewType1D& dst, - const ViewType1D& src - ) -{ - Kokkos::deep_copy(dst,src); + return pFlow::algorithms::KOKKOS::max( + view.data() + start, numElems + ); } -template < - typename dType, - typename... dProperties, - typename sType, - typename... sProperties> -INLINE_FUNCTION_H -void copy( - const ViewType1D& dst, - int32 dStart, - const ViewType1D& src, - int32 sStart, - int32 sEnd - ) +template< + typename dType, + typename... dProperties, + typename sType, + typename... sProperties> +INLINE_FUNCTION_H void +copy( + const ViewType1D& dst, + const ViewType1D& src +) { - - range sSpan(sStart,sEnd); - range dSpan(dStart,dStart+(sEnd-sStart)); - - auto srcSub = Kokkos::subview(src, sSpan); - auto dstSub = Kokkos::subview(dst, dSpan); - - Kokkos::deep_copy(dstSub,srcSub); + Kokkos::deep_copy(dst, src); } -template < - typename dType, - typename sType, - typename... sProperties> -INLINE_FUNCTION_H -void getNth( - dType& dst, - const ViewType1D& src, - const int32 n - ) +template< + typename dType, + typename... dProperties, + typename sType, + typename... sProperties> +INLINE_FUNCTION_H void +copy( + const ViewType1D& dst, + uint32 dStart, + const ViewType1D& src, + uint32 sStart, + uint32 sEnd +) { - range span(n,n+1); - auto subV = Kokkos::subview(src, span); - hostViewType1D dstView("getNth",1); - Kokkos::deep_copy(dstView,subV); + + auto srcSub = Kokkos::subview( + src, + Kokkos::make_pair(sStart, sEnd)); + + auto dstSub = Kokkos::subview( + dst, + Kokkos::make_pair(dStart, dStart + (sEnd - sStart))); + + Kokkos::deep_copy(dstSub, srcSub); +} + +template +INLINE_FUNCTION_H void +getNth(Type& dst, const ViewType1D& src, const uint32 n) +{ + auto subV = Kokkos::subview(src, Kokkos::make_pair(n, n + 1)); + hostViewType1D dstView("getNth", 1); + // hostViewTypeScalar + Kokkos::deep_copy(dstView, subV); dst = *dstView.data(); } - template -INLINE_FUNCTION_H -void sort( - ViewType1D& view, - int32 start, - int32 end) +INLINE_FUNCTION_H void +sort(ViewType1D& view, uint32 start, uint32 end) { + using ExecutionSpace = + typename ViewType1D::execution_space; - using ExecutionSpace = typename ViewType1D::execution_space; - - int32 numElems = end-start; + uint32 numElems = end - start; - if constexpr( isHostAccessible()) + if constexpr (isHostAccessible()) { - if(numElems( - view.data()+start, - numElems); - return; - } - else - { - pFlow::algorithms::STD::sort( - view.data()+start, - numElems); - return; - } + pFlow::algorithms::STD::sort(view.data() + start, numElems); + return; } #ifdef __CUDACC__ - - pFlow::algorithms::CUDA::sort( - view.data()+start, - numElems); + + pFlow::algorithms::CUDA::sort(view.data() + start, numElems); #else static_assert("sort on device is not defined!"); @@ -388,44 +303,32 @@ void sort( } template -INLINE_FUNCTION_H -void sort( - ViewType1D& view, - int32 start, - int32 end, - CompareFunc compare) +INLINE_FUNCTION_H void +sort( + ViewType1D& view, + uint32 start, + uint32 end, + CompareFunc compare +) { + using ExecutionSpace = + typename ViewType1D::execution_space; - using ExecutionSpace = typename ViewType1D::execution_space; - - int32 numElems = end-start; + uint32 numElems = end - start; - if constexpr( isHostAccessible()) + if constexpr (isHostAccessible()) { - if(numElems( - view.data()+start, - numElems, - compare); - return; - } - else - { - pFlow::algorithms::STD::sort( - view.data()+start, - numElems, - compare); - return; - } + pFlow::algorithms::STD::sort( + view.data() + start, numElems, compare + ); + return; } #ifdef __CUDACC__ - + pFlow::algorithms::CUDA::sort( - view.data()+start, - numElems, - compare); + view.data() + start, numElems, compare + ); #else static_assert("sort on device is not defined!"); @@ -435,159 +338,157 @@ void sort( } template< - typename Type, - typename... properties, - typename permType, - typename... permProperties> -void permuteSort( - const ViewType1D& view, - int32 start, - int32 end, - ViewType1D& permuteView, - int32 permStart, - typename std::enable_if_t< - areAccessible< - typename ViewType1D::execution_space, - typename ViewType1D::memory_space>(), - bool> = true ) + typename Type, + typename... properties, + typename permType, + typename... permProperties> +void +permuteSort( + const ViewType1D& view, + uint32 start, + uint32 end, + ViewType1D& permuteView, + uint32 permStart +) { - using ExecutionSpace = typename ViewType1D::execution_space; - - int32 numElems = end-start; + static_assert( + areAccessible< + typename ViewType1D::execution_space, + typename ViewType1D::memory_space>(), + "In permuteSort, view and permuteView should have the same space" + ); - if constexpr( isHostAccessible()) - { - if(numElems( - view.data()+start, - permuteView.data()+permStart, - numElems ); - return; - } - else - { - pFlow::algorithms::STD::permuteSort( - view.data()+start, - permuteView.data()+permStart, - numElems); - return; - } - } + using ExecutionSpace = + typename ViewType1D::execution_space; + + uint32 numElems = end - start; + + pFlow::algorithms::STD::permuteSort( + view.data() + start, permuteView.data() + permStart, numElems + ); + return; #ifdef __CUDACC__ - + pFlow::algorithms::CUDA::permuteSort( - view.data()+start, - permuteView.data()+permStart, - numElems); + view.data() + start, permuteView.data() + permStart, numElems + ); #else static_assert("sort on device is not defined!"); #endif - } -template< - typename Type, - typename... properties> -INLINE_FUNCTION_HD -int32 binarySearch( - const ViewType1D& view, - int32 start, - int32 end, - const Type& val) +template +INLINE_FUNCTION_HD int32 +binarySearch_(const T* array, int32 length, const T& val) { - - if(end<=start)return -1; + if (length <= 0) + return -1; - if(auto res = - pFlow::algorithms::binarySearch(view.data()+start,end-start,val); res>=0) { - return res+start; + int low = 0; + int high = length - 1; + + while (low <= high) + { + int mid = low + (high - low) / 2; + + if (array[mid] > val) + { + high = mid - 1; + } + else if (array[mid] < val) + { + low = mid + 1; + } + else + { + return mid; + } } - else{ + + return -1; // val not found in array[0, length) +} + +/// On DEVICE and HOST calls +template +INLINE_FUNCTION_HD uint32 +binarySearch( + const ViewType1D& view, + uint32 start, + uint32 end, + const Type& val +) +{ + if (end <= start) + return static_cast(-1); + + if (auto res = binarySearch_(view.data() + start, end - start, val); + res != static_cast(-1)) + { + return res + start; + } + else + { return res; } } -template< - typename Type, - typename... properties, - typename dType, - typename... dProperties> -void exclusiveScan( - const ViewType1D& view, - int32 start, - int32 end, - ViewType1D& dView, - int32 dStart, - typename std::enable_if_t< - areAccessible< - typename ViewType1D::execution_space, - typename ViewType1D::memory_space>(), - bool> = true ) +template +void +exclusiveScan( + const ViewType1D& view, + uint32 start, + uint32 end, + ViewType1D& dView, + uint32 dStart +) { - using ExecutionSpace = typename ViewType1D::execution_space; - - int32 numElems = end-start; - if constexpr( isHostAccessible()) - { - if(numElems( - view.data()+start, - dView.data()+dStart, - numElems); - return; - } - } + static_assert( + areAccessible< + typename ViewType1D::execution_space, + typename ViewType1D::memory_space>(), + "In exclusiveScan, view and dView should have the same space" - pFlow::algorithms::KOKKOS::exclusiveScan( - view.data()+start, - dView.data()+dStart, - numElems); + ); + + using ExecutionSpace = + typename ViewType1D::execution_space; + + uint32 numElems = end - start; + + pFlow::algorithms::KOKKOS::exclusiveScan( + view.data() + start, dView.data() + dStart, numElems + ); } - -template< - typename Type, - typename... properties, - typename dType, - typename... dProperties> -void inclusiveScan( - const ViewType1D& view, - int32 start, - int32 end, - ViewType1D& dView, - int32 dStart, - typename std::enable_if_t< - areAccessible< - typename ViewType1D::execution_space, - typename ViewType1D::memory_space>(), - bool> = true ) +template +void +inclusiveScan( + const ViewType1D& view, + uint32 start, + uint32 end, + ViewType1D& dView, + uint32 dStart +) { - using ExecutionSpace = typename ViewType1D::execution_space; - - int32 numElems = end-start; - if constexpr( isHostAccessible()) - { - if(numElems( - view.data()+start, - dView.data()+dStart, - numElems); - return; - } - } + using ExecutionSpace = + typename ViewType1D::execution_space; - pFlow::algorithms::KOKKOS::inclusiveScan( - view.data()+start, - dView.data()+dStart, - numElems); + static_assert( + areAccessible< + typename ViewType1D::execution_space, + typename ViewType1D::memory_space>(), + "In exclusiveScan, view and dView should have the same space" + ); + + uint32 numElems = end - start; + + pFlow::algorithms::KOKKOS::inclusiveScan( + view.data() + start, dView.data() + dStart, numElems + ); } } // pFlow - -#endif // Viewalgorithms +#endif // __ViewAlgorithms_hpp__ diff --git a/src/phasicFlow/Kokkos/baseAlgorithms.hpp b/src/phasicFlow/Kokkos/baseAlgorithms.hpp deleted file mode 100644 index 70f1f76f..00000000 --- a/src/phasicFlow/Kokkos/baseAlgorithms.hpp +++ /dev/null @@ -1,246 +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 __baseAlgorithms_hpp__ -#define __baseAlgorithms_hpp__ - - -#include "numericConstants.hpp" -#include "KokkosUtilities.hpp" - -inline const size_t sizeToSerial__ = 64; - -namespace pFlow -{ - -// counts the number of elements that matches val -// the execution space is selected based on the View::execution_spcae -/*template -INLINE_FUNCTION_H -size_t count( - const ViewType1D& view, - size_t start, - size_t end, - const T& val - ) -{ - - auto RP = Kokkos::RangePolicy< - Kokkos::IndexType, - typename ViewType1D::execution_space >(start, end); - - size_t totalNum=0; - Kokkos::parallel_reduce( - "baseAlgorithms-count", - RP, - LAMBDA_HD(label i, size_t & valueToUpdate){ - if( equal(view[i], val) ) valueToUpdate += 1; - }, totalNum ); - - return totalNum; -}*/ - - -template -INLINE_FUNCTION_H -T min( const ViewType1D& view, size_t start, size_t end ) -{ - - T minValue = largestPositive(); - - auto RP = Kokkos::RangePolicy< - Kokkos::IndexType, - typename ViewType1D::execution_space >(start, end); - - Kokkos::parallel_reduce("baseAlgorithms-min", - RP, - LAMBDA_HD(label i, T& valueToUpdate){ - valueToUpdate = min(view[i],valueToUpdate); - }, - Kokkos :: Min < T >( minValue ) - ); - return minValue; -} - -template -INLINE_FUNCTION_H -T max( const ViewType1D& view, size_t start, size_t end ) -{ - - T maxValue = largestNegative(); - - auto RP = Kokkos::RangePolicy< - Kokkos::IndexType, - typename ViewType1D::execution_space >(start, end); - - Kokkos::parallel_reduce("baseAlgorithms-max", - RP, - LAMBDA_HD(label i, T& valueToUpdate){ - valueToUpdate = max(view[i],valueToUpdate); - }, - Kokkos::Max( maxValue ) - ); - return maxValue; -} - -template -INLINE_FUNCTION_H -T min_serial(const ViewType1D& view, size_t start, size_t end) -{ - T minValue = largestPositive(); - for(label i=start; i -INLINE_FUNCTION_H -T max_serial(const ViewType1D& view, size_t start, size_t end) -{ - T maxValue = largestNegative(); - for(label i=start; i -void apply_to_each(const ViewType1D& view, size_t start, size_t end, UnaryFunction func) -{ - auto RP = Kokkos::RangePolicy< - Kokkos::IndexType, - typename ViewType1D::execution_space >(start, end); - - Kokkos::parallel_for("baseAlgorithms-for_each", - RP, - LAMBDA_HD(label i){ - view[i] = func(i); - } - ); -} - - -template -void insertSetElementH -( - ViewType1D& view, - hostViewType1D