diff --git a/.github/scripts/sync-wiki.py b/.github/scripts/sync-wiki.py new file mode 100755 index 00000000..9129e267 --- /dev/null +++ b/.github/scripts/sync-wiki.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python3 + +import os +import re +import yaml +import sys + +# Constants +REPO_URL = "https://github.com/PhasicFlow/phasicFlow" +REPO_PATH = os.path.join(os.environ.get("GITHUB_WORKSPACE", ""), "repo") +WIKI_PATH = os.path.join(os.environ.get("GITHUB_WORKSPACE", ""), "wiki") +MAPPING_FILE = os.path.join(REPO_PATH, "doc/mdDocs/markdownList.yml") + +def load_mapping(): + """Load the markdown to wiki page mapping file.""" + try: + with open(MAPPING_FILE, 'r') as f: + data = yaml.safe_load(f) + return data.get('mappings', []) + except Exception as e: + print(f"Error loading mapping file: {e}") + return [] + +def convert_relative_links(content, source_path): + """Convert relative links in markdown content to absolute URLs.""" + # Find markdown links with regex pattern [text](url) + md_pattern = r'\[([^\]]+)\]\(([^)]+)\)' + + # Find HTML img tags + img_pattern = r' {target_path}") + + try: + # Check if source exists + if not os.path.exists(source_path): + print(f"Source file not found: {source_path}") + return False + + # Read source content + with open(source_path, 'r') as f: + content = f.read() + + # Convert relative links + content = convert_relative_links(content, source_file) + + # Write to wiki page + with open(target_path, 'w') as f: + f.write(content) + + return True + + except Exception as e: + print(f"Error processing {source_file}: {e}") + return False + +def main(): + # Check if wiki directory exists + if not os.path.exists(WIKI_PATH): + print(f"Wiki path not found: {WIKI_PATH}") + sys.exit(1) + + # Load mapping + mappings = load_mapping() + if not mappings: + print("No mappings found in the mapping file") + sys.exit(1) + + print(f"Found {len(mappings)} mappings to process") + + # Process each mapping + success_count = 0 + for mapping in mappings: + source = mapping.get('source') + target = mapping.get('target') + + if not source or not target: + print(f"Invalid mapping: {mapping}") + continue + + if process_file(source, target): + success_count += 1 + + print(f"Successfully processed {success_count} of {len(mappings)} files") + + # Exit with error if any file failed + if success_count < len(mappings): + sys.exit(1) + +if __name__ == "__main__": + main() diff --git a/.github/workflows/sync-wiki.yml b/.github/workflows/sync-wiki.yml new file mode 100644 index 00000000..180a4d6b --- /dev/null +++ b/.github/workflows/sync-wiki.yml @@ -0,0 +1,60 @@ +name: Sync-Wiki + +on: + push: + branches: + - main + paths: + - "**/*.md" + - ".github/workflows/sync-wiki.yml" + - "doc/mdDocs/markdownList.yml" + - ".github/scripts/sync-wiki.py" + workflow_dispatch: + +jobs: + sync-wiki: + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v3 + with: + path: repo + - name: Checkout Wiki + uses: actions/checkout@v3 + with: + repository: ${{ github.repository }}.wiki + path: wiki + continue-on-error: true + - name: Create Wiki Directory if Not Exists + run: | + if [ ! -d "wiki" ]; then + mkdir -p wiki + cd wiki + git init + git config user.name "${{ github.actor }}" + git config user.email "${{ github.actor }}@users.noreply.github.com" + git remote add origin "https://github.com/${{ github.repository }}.wiki.git" + fi + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.10' + - name: Install dependencies + run: pip install pyyaml + - name: Sync markdown files to Wiki + run: | + python $GITHUB_WORKSPACE/repo/.github/scripts/sync-wiki.py + env: + GITHUB_REPOSITORY: ${{ github.repository }} + - name: Push changes to wiki + run: | + cd wiki + git config user.name "${{ github.actor }}" + git config user.email "${{ github.actor }}@users.noreply.github.com" + git add . + if git status --porcelain | grep .; then + git commit -m "Auto sync wiki from main repository" + git push --set-upstream https://${{ github.actor }}:${{ github.token }}@github.com/${{ github.repository }}.wiki.git master -f + else + echo "No changes to commit" + fi diff --git a/CMakeLists.txt b/CMakeLists.txt index fa88bc95..546725a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,30 +3,17 @@ cmake_minimum_required(VERSION 3.16 FATAL_ERROR) # set the project name and version project(phasicFlow VERSION 1.0 ) -set(CMAKE_CXX_STANDARD 17 CACHE STRING "" FORCE) +set(CMAKE_CXX_STANDARD 20 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 Debug CACHE STRING "build type" FORCE) +set(CMAKE_BUILD_TYPE Release CACHE STRING "build type") set(BUILD_SHARED_LIBS ON CACHE BOOL "Build using shared libraries" FORCE) mark_as_advanced(FORCE var BUILD_SHARED_LIBS) -message(STATUS ${CMAKE_INSTALL_PREFIX}) +message(STATUS "Install prefix is:" ${CMAKE_INSTALL_PREFIX}) include(cmake/globals.cmake) -#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} ${phasicFlow_BINARY_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) @@ -34,6 +21,8 @@ option(pFlow_Build_Cuda "Build phasicFlow and backends for Cuda execution" OFF 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) +#for installing the required packages +include(cmake/preReq.cmake) if(pFlow_Build_Serial) set(Kokkos_ENABLE_SERIAL ON CACHE BOOL "Serial execution" FORCE) @@ -46,7 +35,8 @@ elseif(pFlow_Build_OpenMP ) 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_DEFAULT_HOST_PARALLEL_EXECUTION_SPACE Serial CACHE STRING "" FORCE) + set(Kokkos_DEFAULT_DEVICE_PARALLEL_EXECUTION_SPACE OpenMP 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) @@ -65,18 +55,17 @@ 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}") - add_subdirectory(src) add_subdirectory(solvers) add_subdirectory(utilities) -#add_subdirectory(DEMSystems) -add_subdirectory(testIO) +add_subdirectory(DEMSystems) install(FILES "${PROJECT_BINARY_DIR}/phasicFlowConfig.H" DESTINATION include) 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..424af8ae 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,11 +178,9 @@ public: int argc, char* argv[]); - - }; } // pFlow -#endif // __DEMSystem_hpp__ \ No newline at end of file +#endif // __DEMSystem_hpp__ 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..1f04ece8 --- /dev/null +++ b/DEMSystems/grainDEMSystem/grainDEMSystem.cpp @@ -0,0 +1,273 @@ +/*------------------------------- 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 . . . "<( + pFlow::shapeFile__, + &Control().caseSetup(), + Property() ); + + REPORT(0)<<"\nReading grain particles . . ."<(Control(), grains_()); + + + 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..af849941 --- /dev/null +++ b/DEMSystems/grainDEMSystem/grainDEMSystem.hpp @@ -0,0 +1,165 @@ +/*------------------------------- 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 grains_ = 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..b70cbc05 --- /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 grainShape& grains) + : grainParticles(control, grains), + 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() +{ + const auto ti = this->TimeInfo(); + accelerationTimer().start(); + pFlow::grainFluidParticlesKernels::acceleration( + control().g(), + mass().deviceViewAll(), + contactForce().deviceViewAll(), + fluidForce_.deviceViewAll(), + I().deviceViewAll(), + contactTorque().deviceViewAll(), + fluidTorque_.deviceViewAll(), + pStruct().activePointsMaskDevice(), + acceleration().deviceViewAll(), + rAcceleration().deviceViewAll() + ); + accelerationTimer().end(); + + intCorrectTimer().start(); + + dynPointStruct().correct(ti.dt()); + + rVelIntegration().correct(ti.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..04d4642d --- /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 grainShape& grains); + + ~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..9a87d8db 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,37 @@ 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 . . . "<( + pFlow::shapeFile__, + &Control().caseSetup(), + Property()); - REPORT(0)<<"\nReading sphere particles . . ."<(Control(), Property()); + REPORT(0)<<"\nReading sphere particles . . ."<(Control(), spheres_()); - 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 +165,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 +232,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..1b6ab072 100644 --- a/DEMSystems/sphereDEMSystem/sphereDEMSystem.hpp +++ b/DEMSystems/sphereDEMSystem/sphereDEMSystem.hpp @@ -42,24 +42,31 @@ protected: // protected members - uniquePtr property_ = nullptr; + uniquePtr property_ = nullptr; - uniquePtr geometry_ = nullptr; + uniquePtr geometry_ = nullptr; - uniquePtr particles_ = nullptr; + uniquePtr spheres_ = nullptr; - uniquePtr insertion_ = nullptr; + uniquePtr particles_ = nullptr; - uniquePtr interaction_ = nullptr; + uniquePtr insertion_ = nullptr; - uniquePtr particleDistribution_=nullptr; + uniquePtr interaction_ = 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 +99,8 @@ public: word demSystemName, const std::vector& domains, int argc, - char* argv[]); + char* argv[], + bool requireRVel=false); virtual ~sphereDEMSystem(); @@ -110,15 +118,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..8f13fb70 100644 --- a/DEMSystems/sphereDEMSystem/sphereFluidParticles.cpp +++ b/DEMSystems/sphereDEMSystem/sphereFluidParticles.cpp @@ -21,85 +21,85 @@ 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 sphereShape& shpShape) + : sphereParticles(control, shpShape), + 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; } bool pFlow::sphereFluidParticles::iterate() { - - accelerationTimer_.start(); + const auto ti = this->TimeInfo(); + 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(), + acceleration().deviceViewAll(), + rAcceleration().deviceViewAll() ); - accelerationTimer_.end(); + accelerationTimer().end(); - intCorrectTimer_.start(); + intCorrectTimer().start(); - dynPointStruct_.correct(this->dt(), accelertion_); + dynPointStruct().correct(ti.dt()); - rVelIntegration_().correct(this->dt(), rVelocity_, rAcceleration_); + rVelIntegration().correct(ti.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..6a6cd445 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,12 +61,12 @@ protected: void zeroFluidTorque_H() { fluidTorque_.fillHost(zero3); - } + }*/ public: /// construct from systemControl and property - sphereFluidParticles(systemControl &control, const property& prop); + sphereFluidParticles(systemControl &control, const sphereShape& shpShape); /// before iteration step bool beforeIteration() override; @@ -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 e1281936..ff041c6b 100644 --- a/README.md +++ b/README.md @@ -1,48 +1,76 @@ -
- +
+ PhasicFlow Logo
+## **PhasicFlow: High-Performance Discrete Element Method Simulations** -**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. +PhasicFlow is a robust, open-source C++ framework designed for the efficient simulation of granular materials using the Discrete Element Method (DEM). Leveraging parallel computing paradigms, PhasicFlow is capable of executing simulations on shared-memory multi-core architectures, including CPUs and NVIDIA GPUs (CUDA-enabled). The core parallelization strategy focuses on loop-level parallelism, enabling significant performance gains on modern hardware. Users can seamlessly transition between serial execution on standard PCs, parallel execution on multi-core CPUs (OpenMP), and accelerated simulations on GPUs. Currently, PhasicFlow supports simulations involving up to 80 million particles on a single desktop workstation. Detailed performance benchmarks are available on the [PhasicFlow Wiki](https://github.com/PhasicFlow/phasicFlow/wiki/Performance-of-phasicFlow). -**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. 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). +**Scalable Parallelism: MPI Integration** -## 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/) +Ongoing development includes the integration of MPI-based parallelization with dynamic load balancing. This enhancement will extend PhasicFlow's capabilities to distributed memory environments, such as multi-GPU workstations and high-performance computing clusters. Upon completion, PhasicFlow will offer six distinct execution modes: -## How to use PhasicFlow? -You can navigate into [tutorials folder](./tutorials) in the phasicFlow folder to see some simulation case setups. If you need more detailed discription, visit our [wiki page tutorials](https://github.com/PhasicFlow/phasicFlow/wiki/Tutorials). +1. **Serial Execution:** Single-core CPU. +2. **Shared-Memory Parallelism:** Multi-core CPU (OpenMP). +3. **GPU Acceleration:** NVIDIA GPU (CUDA). +4. **Distributed-Memory Parallelism:** MPI. +5. **Hybrid Parallelism:** MPI + OpenMP. +6. **Multi-GPU Parallelism:** MPI + CUDA. -## [PhasicFlowPlus](https://github.com/PhasicFlow/PhasicFlowPlus) -PhasicFlowPlus is and extension to PhasicFlow for simulating particle-fluid systems using resolved and unresolved CFD-DEM. [See the repository of this package.](https://github.com/PhasicFlow/PhasicFlowPlus) +## **Build and Installation** +PhasicFlow can be compiled for both CPU and GPU execution. -## Supporting packages -* [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. +* **Current Development (v-1.0):** Comprehensive build instructions are available [here](https://github.com/PhasicFlow/phasicFlow/wiki/How-to-build-PhasicFlow%E2%80%90v%E2%80%901.0). +* **Latest Release (v-0.1):** Detailed build instructions are available [here](https://github.com/PhasicFlow/phasicFlow/wiki/How-to-Build-PhasicFlow). + +## **Comprehensive Documentation** + +In-depth documentation, including code structure, features, and usage guidelines, is accessible via the [online documentation portal](https://phasicflow.github.io/phasicFlow/). + +### **Tutorials and Examples** + +Practical examples and simulation setups are provided in the [tutorials directory](./tutorials). For detailed explanations and step-by-step guides, please refer to the [tutorial section on the PhasicFlow Wiki](https://github.com/PhasicFlow/phasicFlow/wiki/Tutorials). + +## Contributing to PhasicFlow +We welcome contributions to PhasicFlow! Whether you're a developer or a new user, there are many ways to get involved. Here's how you can help: +1. Bug Reports +2. Suggestions for better user experience +3. Feature request and algorithm improvements +4. Tutorials, Simulation Case Setups and documentation +5. Direct Code Contributions + +For more details on how you can contribute to PhasicFlow see [this page](https://github.com/PhasicFlow/phasicFlow/wiki/How-to-contribute-to-PhasicFlow). + +## **PhasicFlowPlus: Coupled CFD-DEM Simulations** + +PhasicFlowPlus is an extension of PhasicFlow that facilitates the simulation of particle-fluid systems using resolved and unresolved CFD-DEM methods. The repository for PhasicFlowPlus can be found [here](https://github.com/PhasicFlow/PhasicFlowPlus). + +## How to cite PhasicFlow? -## 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} +@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} } ``` + + +## **Dependencies** + +PhasicFlow relies on the following external libraries: + +* **Kokkos:** A community-led performance portability ecosystem within the Linux Foundation's High-Performance Software Foundation (HPSF). ([https://github.com/kokkos/kokkos](https://github.com/kokkos/kokkos)) +* **CLI11 1.8:** A command-line interface parser developed by the University of Cincinnati. ([https://github.com/CLIUtils/CLI11](https://github.com/CLIUtils/CLI11)) diff --git a/benchmarks/helicalMixer_4MParticles/caseSetup/interaction b/benchmarks/helicalMixer/caseSetup/interaction similarity index 100% rename from benchmarks/helicalMixer_4MParticles/caseSetup/interaction rename to benchmarks/helicalMixer/caseSetup/interaction diff --git a/benchmarks/helicalMixer_4MParticles/caseSetup/particleInsertion b/benchmarks/helicalMixer/caseSetup/particleInsertion similarity index 100% rename from benchmarks/helicalMixer_4MParticles/caseSetup/particleInsertion rename to benchmarks/helicalMixer/caseSetup/particleInsertion diff --git a/benchmarks/helicalMixer_4MParticles/caseSetup/sphereShape b/benchmarks/helicalMixer/caseSetup/sphereShape similarity index 100% rename from benchmarks/helicalMixer_4MParticles/caseSetup/sphereShape rename to benchmarks/helicalMixer/caseSetup/sphereShape diff --git a/benchmarks/helicalMixer_4MParticles/cleanThisCase b/benchmarks/helicalMixer/cleanThisCase similarity index 100% rename from benchmarks/helicalMixer_4MParticles/cleanThisCase rename to benchmarks/helicalMixer/cleanThisCase diff --git a/benchmarks/helicalMixer/readme.md b/benchmarks/helicalMixer/readme.md new file mode 100644 index 00000000..57bec363 --- /dev/null +++ b/benchmarks/helicalMixer/readme.md @@ -0,0 +1 @@ +# Helical Mixer Benchmark (phasicFlow v-1.0) diff --git a/benchmarks/helicalMixer_4MParticles/runThisCase b/benchmarks/helicalMixer/runThisCase similarity index 100% rename from benchmarks/helicalMixer_4MParticles/runThisCase rename to benchmarks/helicalMixer/runThisCase diff --git a/benchmarks/helicalMixer_4MParticles/settings/geometryDict b/benchmarks/helicalMixer/settings/geometryDict similarity index 100% rename from benchmarks/helicalMixer_4MParticles/settings/geometryDict rename to benchmarks/helicalMixer/settings/geometryDict diff --git a/benchmarks/helicalMixer_4MParticles/settings/particlesDict b/benchmarks/helicalMixer/settings/particlesDict similarity index 100% rename from benchmarks/helicalMixer_4MParticles/settings/particlesDict rename to benchmarks/helicalMixer/settings/particlesDict diff --git a/benchmarks/helicalMixer_4MParticles/settings/settingsDict b/benchmarks/helicalMixer/settings/settingsDict similarity index 100% rename from benchmarks/helicalMixer_4MParticles/settings/settingsDict rename to benchmarks/helicalMixer/settings/settingsDict diff --git a/benchmarks/readme.md b/benchmarks/readme.md new file mode 100644 index 00000000..888bab60 --- /dev/null +++ b/benchmarks/readme.md @@ -0,0 +1,7 @@ + +# Benchmarks + +Benchmakrs has been done on two different simulations: a simulation with simple geometry (rotating drum) and a simulation with complex geometry (helical mixer). + +- [rotating drum](./rotatingDrum/readme.md) +- [helical mixer](./helicalMixer/readme.md) \ No newline at end of file diff --git a/benchmarks/rotatingDrum/images/commericalDEMsnapshot.png b/benchmarks/rotatingDrum/images/commericalDEMsnapshot.png new file mode 100644 index 00000000..3dd8e08f Binary files /dev/null and b/benchmarks/rotatingDrum/images/commericalDEMsnapshot.png differ diff --git a/benchmarks/rotatingDrum/images/performance1.png b/benchmarks/rotatingDrum/images/performance1.png new file mode 100644 index 00000000..ce9828ff Binary files /dev/null and b/benchmarks/rotatingDrum/images/performance1.png differ diff --git a/benchmarks/rotatingDrum/images/phasicFlow_snapshot.png b/benchmarks/rotatingDrum/images/phasicFlow_snapshot.png new file mode 100644 index 00000000..33b2999d Binary files /dev/null and b/benchmarks/rotatingDrum/images/phasicFlow_snapshot.png differ diff --git a/benchmarks/rotatingDrum/readme.md b/benchmarks/rotatingDrum/readme.md new file mode 100644 index 00000000..ad3d8121 --- /dev/null +++ b/benchmarks/rotatingDrum/readme.md @@ -0,0 +1,96 @@ +# Rotating Drum Benchmark (phasicFlow v-1.0) + +## Overview + +This benchmark compares the performance of phasicFlow with a well-stablished commercial DEM software for simulating a rotating drum with varying particle counts (250k to 8M particles). The benchmark measures both computational efficiency and memory usage across different hardware configurations. + +## Simulation Setup + +
+ +
+

Figure 1. Commercial DEM simulation snapshot

+
+
+ +
+ +
+

Figure 2. phasicFlow simulation snapshot and visualized using Paraview

+
+
+ +### Hardware Specifications + +
+ Table 1. Hardware specifications used for benchmarking. +
+ +| System | CPU | GPU | Operating System | +| :---------: | :----------------------: | :--------------------------: | :--------------: | +| Laptop | Intel i9-13900HX 2.2 GHz | NVIDIA GeForce RTX 4050Ti 6G | Windows 11 24H2 | +| Workstation | Intel Xeon 4210 2.2 GHz | NVIDIA RTX A4000 16G | Ubuntu 22.04 | + +### Simulation Parameters + +
+ Table 2. Parameters for rotating drum simulations. +
+ +| Case | Particle Diameter | Particle Count | Drum Length | Drum Radius | +| :-------: | :---------------: | :--------------: | :------------------: | :------------------: | +| 250k | 6 mm | 250,000 | 0.8 m | 0.2 m | +| 500k | 5 mm | 500,000 | 0.8 m | 0.2 m | +| 1M | 4 mm | 1,000,000 | 0.8 m | 0.2 m | +| 2M | 3 mm | 2,000,000 | 1.2 m | 0.2 m | +| 4M | 3 mm | 4,000,000 | 1.6 m | 0.2 m | +| 8M | 2 mm | 8,000,000 | 1.6 m | 0.2 m | + +The time step for all simulations was set to 1.0e-5 seconds and the simulation ran for 4 seconds. + +## Performance Comparison + +### Execution Time + +
+ Table 3. Total calculation time (minutes) for different configurations. +
+ +| Software | 250k | 500k | 1M | 2M | 4M | 8M | +| :---------------: | :----: | :-----: | :-----: | :-----: | :-----: | :------: | +| phasicFlow-4050Ti | 54 min | 111 min | 216 min | 432 min | - | - | +| Commercial DEM-4050Ti | 68 min | 136 min | 275 min | 570 min | - | - | +| phasicFlow-A4000 | 38 min | 73 min | 146 min | 293 min | 589 min | 1188 min | + +The execution time scales linearly with particle count. phasicFlow demonstrates approximately: + +- 20% faster calculation than the well-established commercial DEM software on the same hardware +- 30% performance improvement when using the NVIDIA RTX A4000 compared to the RTX 4050Ti + +
+ +

Figure 3. Calculation time comparison between phasicFlow and the well-established commercial DEM software.

+
+ +### Memory Usage + +
+ Table 4. Memory consumption for different configurations. +
+ +| Software | 250k | 500k | 1M | 2M | 4M | 8M | +| :---------------: | :-----: | :-----: | :-----: | :-----: | :-----: | :-----: | +| phasicFlow-4050Ti | 252 MB | 412 MB | 710 MB | 1292 MB | - | - | +| Commercial DEM-4050Ti | 485 MB | 897 MB | 1525 MB | 2724 MB | - | - | +| phasicFlow-A4000 | 344 MB | 480 MB | 802 MB | 1386 MB | 2590 MB | 4966 MB | + +Memory efficiency comparison: + +- phasicFlow uses approximately 0.7 GB of memory per million particles +- Commercial DEM software uses approximately 1.2 GB of memory per million particles +- phasicFlow shows ~42% lower memory consumption compared to the commercial alternative +- The memory usage scales linearly with particle count in both software packages. But due to memory limitations on GPUs, it is possible to run larger simulation on GPUs with phasicFlow. + +## Run Your Own Benchmarks + +The simulation case setup files are available in this folder for users interested in performing similar benchmarks on their own hardware. These files can be used to reproduce the tests and compare performance across different systems. diff --git a/benchmarks/rotatingDrum/rotatingDrum_1mParticles/caseSetup/interaction b/benchmarks/rotatingDrum/rotatingDrum_1mParticles/caseSetup/interaction new file mode 100644 index 00000000..4ef2c32f --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_1mParticles/caseSetup/interaction @@ -0,0 +1,60 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ + +objectName interaction; +objectType dictionary; +fileFormat ASCII; + +/*---------------------------------------------------------------------------*/ + +materials (glassMat wallMat); // a list of materials names + +densities (2500.0 2500); // density of materials [kg/m3] + +contactListType sortedContactList; + +contactSearch +{ + method NBS; + + updateInterval 20; + + sizeRatio 1.1; + + cellExtent 0.55; + + adjustableBox Yes; +} + +model +{ + contactForceModel nonLinearLimited; + + rollingFrictionModel normal; + + /* + Property (glassMat-glassMat glassMat-wallMat + wallMat-wallMat); + */ + + Yeff (1.0e6 1.0e6 + 1.0e6); // Young modulus [Pa] + + Geff (0.8e6 0.8e6 + 0.8e6); // Shear modulus [Pa] + + nu (0.25 0.25 + 0.25); // Poisson's ratio [-] + + en (0.97 0.85 + 1.00); // coefficient of normal restitution + + mu (0.65 0.65 + 0.65); // dynamic friction + + mur (0.1 0.1 + 0.1); // rolling friction +} + diff --git a/benchmarks/rotatingDrum/rotatingDrum_1mParticles/caseSetup/shapes b/benchmarks/rotatingDrum/rotatingDrum_1mParticles/caseSetup/shapes new file mode 100644 index 00000000..c2302c64 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_1mParticles/caseSetup/shapes @@ -0,0 +1,15 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ + +objectName shapes; +objectType dictionary; +fileFormat ASCII; +/*---------------------------------------------------------------------------*/ + +names (glassBead); // names of shapes + +diameters (0.004); // diameter of shapes + +materials (glassMat); // material names for shapes diff --git a/benchmarks/rotatingDrum_4MParticles/cleanThisCase b/benchmarks/rotatingDrum/rotatingDrum_1mParticles/cleanThisCase similarity index 100% rename from benchmarks/rotatingDrum_4MParticles/cleanThisCase rename to benchmarks/rotatingDrum/rotatingDrum_1mParticles/cleanThisCase diff --git a/benchmarks/rotatingDrum_4MParticles/runThisCase b/benchmarks/rotatingDrum/rotatingDrum_1mParticles/runThisCase similarity index 100% rename from benchmarks/rotatingDrum_4MParticles/runThisCase rename to benchmarks/rotatingDrum/rotatingDrum_1mParticles/runThisCase diff --git a/benchmarks/rotatingDrum/rotatingDrum_1mParticles/settings/domainDict b/benchmarks/rotatingDrum/rotatingDrum_1mParticles/settings/domainDict new file mode 100644 index 00000000..ec704467 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_1mParticles/settings/domainDict @@ -0,0 +1,50 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ +objectName domainDict; +objectType dictionary; +fileFormat ASCII; +/*---------------------------------------------------------------------------*/ +globalBox // Simulation domain: every particles that goes outside this domain will be deleted +{ + min (-0.2 -0.2 0.0); + max ( 0.2 0.2 0.8); +} + +boundaries +{ + neighborListUpdateInterval 200; + + updateInterval 20; + + left + { + type exit; // other options: periodic, reflective + } + + right + { + type exit; // other options: periodic, reflective + } + + bottom + { + type exit; // other options: periodic, reflective + } + + top + { + type exit; // other options: periodic, reflective + } + + rear + { + type exit; // other options: periodic, reflective + } + + front + { + type exit; // other options: periodic, reflective + } +} diff --git a/benchmarks/rotatingDrum/rotatingDrum_1mParticles/settings/geometryDict b/benchmarks/rotatingDrum/rotatingDrum_1mParticles/settings/geometryDict new file mode 100644 index 00000000..e2a0c797 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_1mParticles/settings/geometryDict @@ -0,0 +1,86 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ + +objectName geometryDict; +objectType dictionary; +fileFormat ASCII; + +motionModel rotatingAxis; // motion model: rotating object around an axis + +rotatingAxisInfo // information for rotatingAxisMotion motion model +{ + rotAxis + { + p1 (0.0 0.0 0.0); // first point for the axis of rotation + + p2 (0.0 0.0 1.0); // second point for the axis of rotation + + omega 1.256; // rotation speed (rad/s) => 12 rpm + } +} + +surfaces +{ + cylinder + { + type cylinderWall; // type of the wall + + p1 (0.0 0.0 0.0); // begin point of cylinder axis + + p2 (0.0 0.0 0.8); // end point of cylinder axis + + radius1 0.2; // radius at p1 + + radius2 0.2; // radius at p2 + + resolution 60; // number of divisions + + material wallMat; // material name of this wall + + motion rotAxis; // motion component name + } + + /* + This is a plane wall at the rear end of cylinder + */ + + wall1 + { + type planeWall; // type of the wall + + p1 (-0.2 -0.2 0.0); // first point of the wall + + p2 ( 0.2 -0.2 0.0); // second point + + p3 ( 0.2 0.2 0.0); // third point + + p4 (-0.2 0.2 0.0); // fourth point + + material wallMat; // material name of the wall + + motion rotAxis; // motion component name + } + + /* + This is a plane wall at the front end of cylinder + */ + + wall2 + { + type planeWall; // type of the wall + + p1 (-0.2 -0.2 0.8); // first point of the wall + + p2 ( 0.2 -0.2 0.8); // second point + + p3 ( 0.2 0.2 0.8); // third point + + p4 (-0.2 0.2 0.8); // fourth point + + material wallMat; // material name of the wall + + motion rotAxis; // motion component name + } +} diff --git a/benchmarks/rotatingDrum/rotatingDrum_1mParticles/settings/particlesDict b/benchmarks/rotatingDrum/rotatingDrum_1mParticles/settings/particlesDict new file mode 100644 index 00000000..f395b571 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_1mParticles/settings/particlesDict @@ -0,0 +1,47 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ + +objectName particlesDict; +objectType dictionary; +fileFormat ASCII; + +setFields +{ + defaultValue + { + velocity realx3 (0 0 0); // linear velocity (m/s) + acceleration realx3 (0 0 0); // linear acceleration (m/s2) + rotVelocity realx3 (0 0 0); // rotational velocity (rad/s) + shapeName word glassBead; // name of the particle shape + } + + selectors + {} +} + +positionParticles +{ + method ordered; + + orderedInfo + { + distance 0.004; // minimum space between centers of particles + + numPoints 1000000; // number of particles in the simulation + + axisOrder (z x y); // axis order for filling the space with particles + } + + regionType cylinder; // other options: box and sphere + + cylinderInfo // cylinder for positioning particles + { + p1 (0.0 0.0 0.01); // lower corner point of the box + + p2 (0.0 0.0 0.79); // upper corner point of the box + + radius 0.195; // radius of cylinder + } +} diff --git a/benchmarks/rotatingDrum/rotatingDrum_1mParticles/settings/settingsDict b/benchmarks/rotatingDrum/rotatingDrum_1mParticles/settings/settingsDict new file mode 100644 index 00000000..e98fa06a --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_1mParticles/settings/settingsDict @@ -0,0 +1,34 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ +objectName settingsDict; +objectType dictionary; +fileFormat ASCII; +/*---------------------------------------------------------------------------*/ +run rotatingDrum_1mParticles; + +dt 0.00001; // time step for integration (s) + +startTime 0; // start time for simulation + +endTime 4; // end time for simulation + +saveInterval 0.2; // time interval for saving the simulation + +timePrecision 5; // maximum number of digits for time folder + +g (0 -9.8 0); // gravity vector (m/s2) + +includeObjects (diameter); // save necessary (i.e., required) data on disk + +// exclude unnecessary data from saving on disk +excludeObjects (rVelocity.dy1 pStructPosition.dy1 pStructVelocity.dy1); + +integrationMethod AdamsBashforth2; // integration method + +writeFormat binary; // data writting format (ascii or binary) + +timersReport Yes; + +timersReportInterval 0.01; diff --git a/benchmarks/rotatingDrum/rotatingDrum_250kParticles/caseSetup/interaction b/benchmarks/rotatingDrum/rotatingDrum_250kParticles/caseSetup/interaction new file mode 100644 index 00000000..4ef2c32f --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_250kParticles/caseSetup/interaction @@ -0,0 +1,60 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ + +objectName interaction; +objectType dictionary; +fileFormat ASCII; + +/*---------------------------------------------------------------------------*/ + +materials (glassMat wallMat); // a list of materials names + +densities (2500.0 2500); // density of materials [kg/m3] + +contactListType sortedContactList; + +contactSearch +{ + method NBS; + + updateInterval 20; + + sizeRatio 1.1; + + cellExtent 0.55; + + adjustableBox Yes; +} + +model +{ + contactForceModel nonLinearLimited; + + rollingFrictionModel normal; + + /* + Property (glassMat-glassMat glassMat-wallMat + wallMat-wallMat); + */ + + Yeff (1.0e6 1.0e6 + 1.0e6); // Young modulus [Pa] + + Geff (0.8e6 0.8e6 + 0.8e6); // Shear modulus [Pa] + + nu (0.25 0.25 + 0.25); // Poisson's ratio [-] + + en (0.97 0.85 + 1.00); // coefficient of normal restitution + + mu (0.65 0.65 + 0.65); // dynamic friction + + mur (0.1 0.1 + 0.1); // rolling friction +} + diff --git a/benchmarks/rotatingDrum/rotatingDrum_250kParticles/caseSetup/shapes b/benchmarks/rotatingDrum/rotatingDrum_250kParticles/caseSetup/shapes new file mode 100644 index 00000000..b8aadc13 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_250kParticles/caseSetup/shapes @@ -0,0 +1,15 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ + +objectName shapes; +objectType dictionary; +fileFormat ASCII; +/*---------------------------------------------------------------------------*/ + +names (glassBead); // names of shapes + +diameters (0.006); // diameter of shapes + +materials (glassMat); // material names for shapes diff --git a/tutorials/sphereGranFlow/toteblender/cleanThisCase b/benchmarks/rotatingDrum/rotatingDrum_250kParticles/cleanThisCase old mode 100644 new mode 100755 similarity index 100% rename from tutorials/sphereGranFlow/toteblender/cleanThisCase rename to benchmarks/rotatingDrum/rotatingDrum_250kParticles/cleanThisCase diff --git a/tutorials/sphereGranFlow/toteblender/runThisCase b/benchmarks/rotatingDrum/rotatingDrum_250kParticles/runThisCase old mode 100644 new mode 100755 similarity index 100% rename from tutorials/sphereGranFlow/toteblender/runThisCase rename to benchmarks/rotatingDrum/rotatingDrum_250kParticles/runThisCase diff --git a/benchmarks/rotatingDrum/rotatingDrum_250kParticles/settings/domainDict b/benchmarks/rotatingDrum/rotatingDrum_250kParticles/settings/domainDict new file mode 100644 index 00000000..ec704467 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_250kParticles/settings/domainDict @@ -0,0 +1,50 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ +objectName domainDict; +objectType dictionary; +fileFormat ASCII; +/*---------------------------------------------------------------------------*/ +globalBox // Simulation domain: every particles that goes outside this domain will be deleted +{ + min (-0.2 -0.2 0.0); + max ( 0.2 0.2 0.8); +} + +boundaries +{ + neighborListUpdateInterval 200; + + updateInterval 20; + + left + { + type exit; // other options: periodic, reflective + } + + right + { + type exit; // other options: periodic, reflective + } + + bottom + { + type exit; // other options: periodic, reflective + } + + top + { + type exit; // other options: periodic, reflective + } + + rear + { + type exit; // other options: periodic, reflective + } + + front + { + type exit; // other options: periodic, reflective + } +} diff --git a/benchmarks/rotatingDrum/rotatingDrum_250kParticles/settings/geometryDict b/benchmarks/rotatingDrum/rotatingDrum_250kParticles/settings/geometryDict new file mode 100644 index 00000000..e2a0c797 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_250kParticles/settings/geometryDict @@ -0,0 +1,86 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ + +objectName geometryDict; +objectType dictionary; +fileFormat ASCII; + +motionModel rotatingAxis; // motion model: rotating object around an axis + +rotatingAxisInfo // information for rotatingAxisMotion motion model +{ + rotAxis + { + p1 (0.0 0.0 0.0); // first point for the axis of rotation + + p2 (0.0 0.0 1.0); // second point for the axis of rotation + + omega 1.256; // rotation speed (rad/s) => 12 rpm + } +} + +surfaces +{ + cylinder + { + type cylinderWall; // type of the wall + + p1 (0.0 0.0 0.0); // begin point of cylinder axis + + p2 (0.0 0.0 0.8); // end point of cylinder axis + + radius1 0.2; // radius at p1 + + radius2 0.2; // radius at p2 + + resolution 60; // number of divisions + + material wallMat; // material name of this wall + + motion rotAxis; // motion component name + } + + /* + This is a plane wall at the rear end of cylinder + */ + + wall1 + { + type planeWall; // type of the wall + + p1 (-0.2 -0.2 0.0); // first point of the wall + + p2 ( 0.2 -0.2 0.0); // second point + + p3 ( 0.2 0.2 0.0); // third point + + p4 (-0.2 0.2 0.0); // fourth point + + material wallMat; // material name of the wall + + motion rotAxis; // motion component name + } + + /* + This is a plane wall at the front end of cylinder + */ + + wall2 + { + type planeWall; // type of the wall + + p1 (-0.2 -0.2 0.8); // first point of the wall + + p2 ( 0.2 -0.2 0.8); // second point + + p3 ( 0.2 0.2 0.8); // third point + + p4 (-0.2 0.2 0.8); // fourth point + + material wallMat; // material name of the wall + + motion rotAxis; // motion component name + } +} diff --git a/benchmarks/rotatingDrum/rotatingDrum_250kParticles/settings/particlesDict b/benchmarks/rotatingDrum/rotatingDrum_250kParticles/settings/particlesDict new file mode 100644 index 00000000..b096c0cc --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_250kParticles/settings/particlesDict @@ -0,0 +1,47 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ + +objectName particlesDict; +objectType dictionary; +fileFormat ASCII; + +setFields +{ + defaultValue + { + velocity realx3 (0 0 0); // linear velocity (m/s) + acceleration realx3 (0 0 0); // linear acceleration (m/s2) + rotVelocity realx3 (0 0 0); // rotational velocity (rad/s) + shapeName word glassBead; // name of the particle shape + } + + selectors + {} +} + +positionParticles +{ + method ordered; + + orderedInfo + { + distance 0.006; // minimum space between centers of particles + + numPoints 250000; // number of particles in the simulation + + axisOrder (z x y); // axis order for filling the space with particles + } + + regionType cylinder; // other options: box and sphere + + cylinderInfo // cylinder for positioning particles + { + p1 (0.0 0.0 0.01); // lower corner point of the box + + p2 (0.0 0.0 0.79); // upper corner point of the box + + radius 0.195; // radius of cylinder + } +} diff --git a/benchmarks/rotatingDrum/rotatingDrum_250kParticles/settings/settingsDict b/benchmarks/rotatingDrum/rotatingDrum_250kParticles/settings/settingsDict new file mode 100644 index 00000000..6f971c6f --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_250kParticles/settings/settingsDict @@ -0,0 +1,34 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ +objectName settingsDict; +objectType dictionary; +fileFormat ASCII; +/*---------------------------------------------------------------------------*/ +run rotatingDrum_250KParticles; + +dt 0.00001; // time step for integration (s) + +startTime 0; // start time for simulation + +endTime 4; // end time for simulation + +saveInterval 0.2; // time interval for saving the simulation + +timePrecision 5; // maximum number of digits for time folder + +g (0 -9.8 0); // gravity vector (m/s2) + +includeObjects (diameter); // save necessary (i.e., required) data on disk + +// exclude unnecessary data from saving on disk +excludeObjects (rVelocity.dy1 pStructPosition.dy1 pStructVelocity.dy1); + +integrationMethod AdamsBashforth2; // integration method + +writeFormat binary; // data writting format (ascii or binary) + +timersReport Yes; + +timersReportInterval 0.01; diff --git a/benchmarks/rotatingDrum/rotatingDrum_2mParticles/caseSetup/interaction b/benchmarks/rotatingDrum/rotatingDrum_2mParticles/caseSetup/interaction new file mode 100644 index 00000000..4ef2c32f --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_2mParticles/caseSetup/interaction @@ -0,0 +1,60 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ + +objectName interaction; +objectType dictionary; +fileFormat ASCII; + +/*---------------------------------------------------------------------------*/ + +materials (glassMat wallMat); // a list of materials names + +densities (2500.0 2500); // density of materials [kg/m3] + +contactListType sortedContactList; + +contactSearch +{ + method NBS; + + updateInterval 20; + + sizeRatio 1.1; + + cellExtent 0.55; + + adjustableBox Yes; +} + +model +{ + contactForceModel nonLinearLimited; + + rollingFrictionModel normal; + + /* + Property (glassMat-glassMat glassMat-wallMat + wallMat-wallMat); + */ + + Yeff (1.0e6 1.0e6 + 1.0e6); // Young modulus [Pa] + + Geff (0.8e6 0.8e6 + 0.8e6); // Shear modulus [Pa] + + nu (0.25 0.25 + 0.25); // Poisson's ratio [-] + + en (0.97 0.85 + 1.00); // coefficient of normal restitution + + mu (0.65 0.65 + 0.65); // dynamic friction + + mur (0.1 0.1 + 0.1); // rolling friction +} + diff --git a/benchmarks/rotatingDrum/rotatingDrum_2mParticles/caseSetup/shapes b/benchmarks/rotatingDrum/rotatingDrum_2mParticles/caseSetup/shapes new file mode 100644 index 00000000..d08fdf86 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_2mParticles/caseSetup/shapes @@ -0,0 +1,15 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ + +objectName shapes; +objectType dictionary; +fileFormat ASCII; +/*---------------------------------------------------------------------------*/ + +names (glassBead); // names of shapes + +diameters (0.003); // diameter of shapes + +materials (glassMat); // material names for shapes diff --git a/benchmarks/rotatingDrum/rotatingDrum_2mParticles/cleanThisCase b/benchmarks/rotatingDrum/rotatingDrum_2mParticles/cleanThisCase new file mode 100755 index 00000000..8a0ab919 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_2mParticles/cleanThisCase @@ -0,0 +1,7 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory + +ls | grep -P "^(([0-9]+\.?[0-9]*)|(\.[0-9]+))$" | xargs -d"\n" rm -rf +rm -rf VTK + +#------------------------------------------------------------------------------ diff --git a/benchmarks/rotatingDrum/rotatingDrum_2mParticles/runThisCase b/benchmarks/rotatingDrum/rotatingDrum_2mParticles/runThisCase new file mode 100755 index 00000000..c48d71fe --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_2mParticles/runThisCase @@ -0,0 +1,21 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory +echo "\n<--------------------------------------------------------------------->" +echo "1) Creating particles" +echo "<--------------------------------------------------------------------->\n" +particlesPhasicFlow + +echo "\n<--------------------------------------------------------------------->" +echo "2) Creating geometry" +echo "<--------------------------------------------------------------------->\n" +geometryPhasicFlow + +echo "\n<--------------------------------------------------------------------->" +echo "3) Running the case" +echo "<--------------------------------------------------------------------->\n" +sphereGranFlow + + + + +#------------------------------------------------------------------------------ diff --git a/benchmarks/rotatingDrum/rotatingDrum_2mParticles/settings/domainDict b/benchmarks/rotatingDrum/rotatingDrum_2mParticles/settings/domainDict new file mode 100644 index 00000000..1b4718fd --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_2mParticles/settings/domainDict @@ -0,0 +1,50 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ +objectName domainDict; +objectType dictionary; +fileFormat ASCII; +/*---------------------------------------------------------------------------*/ +globalBox // Simulation domain: every particles that goes outside this domain will be deleted +{ + min (-0.2 -0.2 0.0); + max ( 0.2 0.2 1.2); +} + +boundaries +{ + neighborListUpdateInterval 200; + + updateInterval 20; + + left + { + type exit; // other options: periodic, reflective + } + + right + { + type exit; // other options: periodic, reflective + } + + bottom + { + type exit; // other options: periodic, reflective + } + + top + { + type exit; // other options: periodic, reflective + } + + rear + { + type exit; // other options: periodic, reflective + } + + front + { + type exit; // other options: periodic, reflective + } +} diff --git a/benchmarks/rotatingDrum/rotatingDrum_2mParticles/settings/geometryDict b/benchmarks/rotatingDrum/rotatingDrum_2mParticles/settings/geometryDict new file mode 100644 index 00000000..2b92233c --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_2mParticles/settings/geometryDict @@ -0,0 +1,86 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ + +objectName geometryDict; +objectType dictionary; +fileFormat ASCII; + +motionModel rotatingAxis; // motion model: rotating object around an axis + +rotatingAxisInfo // information for rotatingAxisMotion motion model +{ + rotAxis + { + p1 (0.0 0.0 0.0); // first point for the axis of rotation + + p2 (0.0 0.0 1.0); // second point for the axis of rotation + + omega 1.256; // rotation speed (rad/s) => 12 rpm + } +} + +surfaces +{ + cylinder + { + type cylinderWall; // type of the wall + + p1 (0.0 0.0 0.0); // begin point of cylinder axis + + p2 (0.0 0.0 1.2); // end point of cylinder axis + + radius1 0.2; // radius at p1 + + radius2 0.2; // radius at p2 + + resolution 60; // number of divisions + + material wallMat; // material name of this wall + + motion rotAxis; // motion component name + } + + /* + This is a plane wall at the rear end of cylinder + */ + + wall1 + { + type planeWall; // type of the wall + + p1 (-0.2 -0.2 0.0); // first point of the wall + + p2 ( 0.2 -0.2 0.0); // second point + + p3 ( 0.2 0.2 0.0); // third point + + p4 (-0.2 0.2 0.0); // fourth point + + material wallMat; // material name of the wall + + motion rotAxis; // motion component name + } + + /* + This is a plane wall at the front end of cylinder + */ + + wall2 + { + type planeWall; // type of the wall + + p1 (-0.2 -0.2 1.2); // first point of the wall + + p2 ( 0.2 -0.2 1.2); // second point + + p3 ( 0.2 0.2 1.2); // third point + + p4 (-0.2 0.2 1.2); // fourth point + + material wallMat; // material name of the wall + + motion rotAxis; // motion component name + } +} diff --git a/benchmarks/rotatingDrum/rotatingDrum_2mParticles/settings/particlesDict b/benchmarks/rotatingDrum/rotatingDrum_2mParticles/settings/particlesDict new file mode 100644 index 00000000..ca61762a --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_2mParticles/settings/particlesDict @@ -0,0 +1,47 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ + +objectName particlesDict; +objectType dictionary; +fileFormat ASCII; + +setFields +{ + defaultValue + { + velocity realx3 (0 0 0); // linear velocity (m/s) + acceleration realx3 (0 0 0); // linear acceleration (m/s2) + rotVelocity realx3 (0 0 0); // rotational velocity (rad/s) + shapeName word glassBead; // name of the particle shape + } + + selectors + {} +} + +positionParticles +{ + method ordered; + + orderedInfo + { + distance 0.003; // minimum space between centers of particles + + numPoints 2000000; // number of particles in the simulation + + axisOrder (z x y); // axis order for filling the space with particles + } + + regionType cylinder; // other options: box and sphere + + cylinderInfo // cylinder for positioning particles + { + p1 (0.0 0.0 0.01); // lower corner point of the box + + p2 (0.0 0.0 1.19); // upper corner point of the box + + radius 0.195; // radius of cylinder + } +} diff --git a/benchmarks/rotatingDrum/rotatingDrum_2mParticles/settings/settingsDict b/benchmarks/rotatingDrum/rotatingDrum_2mParticles/settings/settingsDict new file mode 100644 index 00000000..b53afca8 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_2mParticles/settings/settingsDict @@ -0,0 +1,34 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ +objectName settingsDict; +objectType dictionary; +fileFormat ASCII; +/*---------------------------------------------------------------------------*/ +run rotatingDrum_2mParticles; + +dt 0.00001; // time step for integration (s) + +startTime 0; // start time for simulation + +endTime 4; // end time for simulation + +saveInterval 0.2; // time interval for saving the simulation + +timePrecision 5; // maximum number of digits for time folder + +g (0 -9.8 0); // gravity vector (m/s2) + +includeObjects (diameter); // save necessary (i.e., required) data on disk + +// exclude unnecessary data from saving on disk +excludeObjects (rVelocity.dy1 pStructPosition.dy1 pStructVelocity.dy1); + +integrationMethod AdamsBashforth2; // integration method + +writeFormat binary; // data writting format (ascii or binary) + +timersReport Yes; + +timersReportInterval 0.01; diff --git a/benchmarks/rotatingDrum/rotatingDrum_4mParticles/caseSetup/interaction b/benchmarks/rotatingDrum/rotatingDrum_4mParticles/caseSetup/interaction new file mode 100644 index 00000000..4ef2c32f --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_4mParticles/caseSetup/interaction @@ -0,0 +1,60 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ + +objectName interaction; +objectType dictionary; +fileFormat ASCII; + +/*---------------------------------------------------------------------------*/ + +materials (glassMat wallMat); // a list of materials names + +densities (2500.0 2500); // density of materials [kg/m3] + +contactListType sortedContactList; + +contactSearch +{ + method NBS; + + updateInterval 20; + + sizeRatio 1.1; + + cellExtent 0.55; + + adjustableBox Yes; +} + +model +{ + contactForceModel nonLinearLimited; + + rollingFrictionModel normal; + + /* + Property (glassMat-glassMat glassMat-wallMat + wallMat-wallMat); + */ + + Yeff (1.0e6 1.0e6 + 1.0e6); // Young modulus [Pa] + + Geff (0.8e6 0.8e6 + 0.8e6); // Shear modulus [Pa] + + nu (0.25 0.25 + 0.25); // Poisson's ratio [-] + + en (0.97 0.85 + 1.00); // coefficient of normal restitution + + mu (0.65 0.65 + 0.65); // dynamic friction + + mur (0.1 0.1 + 0.1); // rolling friction +} + diff --git a/benchmarks/rotatingDrum/rotatingDrum_4mParticles/caseSetup/shapes b/benchmarks/rotatingDrum/rotatingDrum_4mParticles/caseSetup/shapes new file mode 100644 index 00000000..d08fdf86 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_4mParticles/caseSetup/shapes @@ -0,0 +1,15 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ + +objectName shapes; +objectType dictionary; +fileFormat ASCII; +/*---------------------------------------------------------------------------*/ + +names (glassBead); // names of shapes + +diameters (0.003); // diameter of shapes + +materials (glassMat); // material names for shapes diff --git a/benchmarks/rotatingDrum/rotatingDrum_4mParticles/cleanThisCase b/benchmarks/rotatingDrum/rotatingDrum_4mParticles/cleanThisCase new file mode 100755 index 00000000..8a0ab919 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_4mParticles/cleanThisCase @@ -0,0 +1,7 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory + +ls | grep -P "^(([0-9]+\.?[0-9]*)|(\.[0-9]+))$" | xargs -d"\n" rm -rf +rm -rf VTK + +#------------------------------------------------------------------------------ diff --git a/benchmarks/rotatingDrum/rotatingDrum_4mParticles/runThisCase b/benchmarks/rotatingDrum/rotatingDrum_4mParticles/runThisCase new file mode 100755 index 00000000..c48d71fe --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_4mParticles/runThisCase @@ -0,0 +1,21 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory +echo "\n<--------------------------------------------------------------------->" +echo "1) Creating particles" +echo "<--------------------------------------------------------------------->\n" +particlesPhasicFlow + +echo "\n<--------------------------------------------------------------------->" +echo "2) Creating geometry" +echo "<--------------------------------------------------------------------->\n" +geometryPhasicFlow + +echo "\n<--------------------------------------------------------------------->" +echo "3) Running the case" +echo "<--------------------------------------------------------------------->\n" +sphereGranFlow + + + + +#------------------------------------------------------------------------------ diff --git a/benchmarks/rotatingDrum/rotatingDrum_4mParticles/settings/domainDict b/benchmarks/rotatingDrum/rotatingDrum_4mParticles/settings/domainDict new file mode 100644 index 00000000..b92756a2 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_4mParticles/settings/domainDict @@ -0,0 +1,50 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ +objectName domainDict; +objectType dictionary; +fileFormat ASCII; +/*---------------------------------------------------------------------------*/ +globalBox // Simulation domain: every particles that goes outside this domain will be deleted +{ + min (-0.2 -0.2 0.0); + max ( 0.2 0.2 1.6); +} + +boundaries +{ + neighborListUpdateInterval 200; + + updateInterval 20; + + left + { + type exit; // other options: periodic, reflective + } + + right + { + type exit; // other options: periodic, reflective + } + + bottom + { + type exit; // other options: periodic, reflective + } + + top + { + type exit; // other options: periodic, reflective + } + + rear + { + type exit; // other options: periodic, reflective + } + + front + { + type exit; // other options: periodic, reflective + } +} diff --git a/benchmarks/rotatingDrum/rotatingDrum_4mParticles/settings/geometryDict b/benchmarks/rotatingDrum/rotatingDrum_4mParticles/settings/geometryDict new file mode 100644 index 00000000..dae67a91 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_4mParticles/settings/geometryDict @@ -0,0 +1,86 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ + +objectName geometryDict; +objectType dictionary; +fileFormat ASCII; + +motionModel rotatingAxis; // motion model: rotating object around an axis + +rotatingAxisInfo // information for rotatingAxisMotion motion model +{ + rotAxis + { + p1 (0.0 0.0 0.0); // first point for the axis of rotation + + p2 (0.0 0.0 1.0); // second point for the axis of rotation + + omega 1.256; // rotation speed (rad/s) => 12 rpm + } +} + +surfaces +{ + cylinder + { + type cylinderWall; // type of the wall + + p1 (0.0 0.0 0.0); // begin point of cylinder axis + + p2 (0.0 0.0 1.6); // end point of cylinder axis + + radius1 0.2; // radius at p1 + + radius2 0.2; // radius at p2 + + resolution 60; // number of divisions + + material wallMat; // material name of this wall + + motion rotAxis; // motion component name + } + + /* + This is a plane wall at the rear end of cylinder + */ + + wall1 + { + type planeWall; // type of the wall + + p1 (-0.2 -0.2 0.0); // first point of the wall + + p2 ( 0.2 -0.2 0.0); // second point + + p3 ( 0.2 0.2 0.0); // third point + + p4 (-0.2 0.2 0.0); // fourth point + + material wallMat; // material name of the wall + + motion rotAxis; // motion component name + } + + /* + This is a plane wall at the front end of cylinder + */ + + wall2 + { + type planeWall; // type of the wall + + p1 (-0.2 -0.2 1.6); // first point of the wall + + p2 ( 0.2 -0.2 1.6); // second point + + p3 ( 0.2 0.2 1.6); // third point + + p4 (-0.2 0.2 1.6); // fourth point + + material wallMat; // material name of the wall + + motion rotAxis; // motion component name + } +} diff --git a/benchmarks/rotatingDrum/rotatingDrum_4mParticles/settings/particlesDict b/benchmarks/rotatingDrum/rotatingDrum_4mParticles/settings/particlesDict new file mode 100644 index 00000000..fa4c3396 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_4mParticles/settings/particlesDict @@ -0,0 +1,47 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ + +objectName particlesDict; +objectType dictionary; +fileFormat ASCII; + +setFields +{ + defaultValue + { + velocity realx3 (0 0 0); // linear velocity (m/s) + acceleration realx3 (0 0 0); // linear acceleration (m/s2) + rotVelocity realx3 (0 0 0); // rotational velocity (rad/s) + shapeName word glassBead; // name of the particle shape + } + + selectors + {} +} + +positionParticles +{ + method ordered; + + orderedInfo + { + distance 0.003; // minimum space between centers of particles + + numPoints 4000000; // number of particles in the simulation + + axisOrder (z x y); // axis order for filling the space with particles + } + + regionType cylinder; // other options: box and sphere + + cylinderInfo // cylinder for positioning particles + { + p1 (0.0 0.0 0.01); // lower corner point of the box + + p2 (0.0 0.0 1.59); // upper corner point of the box + + radius 0.195; // radius of cylinder + } +} diff --git a/benchmarks/rotatingDrum/rotatingDrum_4mParticles/settings/settingsDict b/benchmarks/rotatingDrum/rotatingDrum_4mParticles/settings/settingsDict new file mode 100644 index 00000000..67cbee31 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_4mParticles/settings/settingsDict @@ -0,0 +1,34 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ +objectName settingsDict; +objectType dictionary; +fileFormat ASCII; +/*---------------------------------------------------------------------------*/ +run rotatingDrum_4mParticles; + +dt 0.00001; // time step for integration (s) + +startTime 0; // start time for simulation + +endTime 4; // end time for simulation + +saveInterval 0.2; // time interval for saving the simulation + +timePrecision 5; // maximum number of digits for time folder + +g (0 -9.8 0); // gravity vector (m/s2) + +includeObjects (diameter); // save necessary (i.e., required) data on disk + +// exclude unnecessary data from saving on disk +excludeObjects (rVelocity.dy1 pStructPosition.dy1 pStructVelocity.dy1); + +integrationMethod AdamsBashforth2; // integration method + +writeFormat binary; // data writting format (ascii or binary) + +timersReport Yes; + +timersReportInterval 0.01; diff --git a/benchmarks/rotatingDrum/rotatingDrum_500kParticles/caseSetup/interaction b/benchmarks/rotatingDrum/rotatingDrum_500kParticles/caseSetup/interaction new file mode 100644 index 00000000..4ef2c32f --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_500kParticles/caseSetup/interaction @@ -0,0 +1,60 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ + +objectName interaction; +objectType dictionary; +fileFormat ASCII; + +/*---------------------------------------------------------------------------*/ + +materials (glassMat wallMat); // a list of materials names + +densities (2500.0 2500); // density of materials [kg/m3] + +contactListType sortedContactList; + +contactSearch +{ + method NBS; + + updateInterval 20; + + sizeRatio 1.1; + + cellExtent 0.55; + + adjustableBox Yes; +} + +model +{ + contactForceModel nonLinearLimited; + + rollingFrictionModel normal; + + /* + Property (glassMat-glassMat glassMat-wallMat + wallMat-wallMat); + */ + + Yeff (1.0e6 1.0e6 + 1.0e6); // Young modulus [Pa] + + Geff (0.8e6 0.8e6 + 0.8e6); // Shear modulus [Pa] + + nu (0.25 0.25 + 0.25); // Poisson's ratio [-] + + en (0.97 0.85 + 1.00); // coefficient of normal restitution + + mu (0.65 0.65 + 0.65); // dynamic friction + + mur (0.1 0.1 + 0.1); // rolling friction +} + diff --git a/benchmarks/rotatingDrum/rotatingDrum_500kParticles/caseSetup/shapes b/benchmarks/rotatingDrum/rotatingDrum_500kParticles/caseSetup/shapes new file mode 100644 index 00000000..962433e2 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_500kParticles/caseSetup/shapes @@ -0,0 +1,15 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ + +objectName shapes; +objectType dictionary; +fileFormat ASCII; +/*---------------------------------------------------------------------------*/ + +names (glassBead); // names of shapes + +diameters (0.005); // diameter of shapes + +materials (glassMat); // material names for shapes diff --git a/benchmarks/rotatingDrum/rotatingDrum_500kParticles/cleanThisCase b/benchmarks/rotatingDrum/rotatingDrum_500kParticles/cleanThisCase new file mode 100755 index 00000000..8a0ab919 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_500kParticles/cleanThisCase @@ -0,0 +1,7 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory + +ls | grep -P "^(([0-9]+\.?[0-9]*)|(\.[0-9]+))$" | xargs -d"\n" rm -rf +rm -rf VTK + +#------------------------------------------------------------------------------ diff --git a/benchmarks/rotatingDrum/rotatingDrum_500kParticles/runThisCase b/benchmarks/rotatingDrum/rotatingDrum_500kParticles/runThisCase new file mode 100755 index 00000000..c48d71fe --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_500kParticles/runThisCase @@ -0,0 +1,21 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory +echo "\n<--------------------------------------------------------------------->" +echo "1) Creating particles" +echo "<--------------------------------------------------------------------->\n" +particlesPhasicFlow + +echo "\n<--------------------------------------------------------------------->" +echo "2) Creating geometry" +echo "<--------------------------------------------------------------------->\n" +geometryPhasicFlow + +echo "\n<--------------------------------------------------------------------->" +echo "3) Running the case" +echo "<--------------------------------------------------------------------->\n" +sphereGranFlow + + + + +#------------------------------------------------------------------------------ diff --git a/benchmarks/rotatingDrum/rotatingDrum_500kParticles/settings/domainDict b/benchmarks/rotatingDrum/rotatingDrum_500kParticles/settings/domainDict new file mode 100644 index 00000000..ec704467 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_500kParticles/settings/domainDict @@ -0,0 +1,50 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ +objectName domainDict; +objectType dictionary; +fileFormat ASCII; +/*---------------------------------------------------------------------------*/ +globalBox // Simulation domain: every particles that goes outside this domain will be deleted +{ + min (-0.2 -0.2 0.0); + max ( 0.2 0.2 0.8); +} + +boundaries +{ + neighborListUpdateInterval 200; + + updateInterval 20; + + left + { + type exit; // other options: periodic, reflective + } + + right + { + type exit; // other options: periodic, reflective + } + + bottom + { + type exit; // other options: periodic, reflective + } + + top + { + type exit; // other options: periodic, reflective + } + + rear + { + type exit; // other options: periodic, reflective + } + + front + { + type exit; // other options: periodic, reflective + } +} diff --git a/benchmarks/rotatingDrum/rotatingDrum_500kParticles/settings/geometryDict b/benchmarks/rotatingDrum/rotatingDrum_500kParticles/settings/geometryDict new file mode 100644 index 00000000..e2a0c797 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_500kParticles/settings/geometryDict @@ -0,0 +1,86 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ + +objectName geometryDict; +objectType dictionary; +fileFormat ASCII; + +motionModel rotatingAxis; // motion model: rotating object around an axis + +rotatingAxisInfo // information for rotatingAxisMotion motion model +{ + rotAxis + { + p1 (0.0 0.0 0.0); // first point for the axis of rotation + + p2 (0.0 0.0 1.0); // second point for the axis of rotation + + omega 1.256; // rotation speed (rad/s) => 12 rpm + } +} + +surfaces +{ + cylinder + { + type cylinderWall; // type of the wall + + p1 (0.0 0.0 0.0); // begin point of cylinder axis + + p2 (0.0 0.0 0.8); // end point of cylinder axis + + radius1 0.2; // radius at p1 + + radius2 0.2; // radius at p2 + + resolution 60; // number of divisions + + material wallMat; // material name of this wall + + motion rotAxis; // motion component name + } + + /* + This is a plane wall at the rear end of cylinder + */ + + wall1 + { + type planeWall; // type of the wall + + p1 (-0.2 -0.2 0.0); // first point of the wall + + p2 ( 0.2 -0.2 0.0); // second point + + p3 ( 0.2 0.2 0.0); // third point + + p4 (-0.2 0.2 0.0); // fourth point + + material wallMat; // material name of the wall + + motion rotAxis; // motion component name + } + + /* + This is a plane wall at the front end of cylinder + */ + + wall2 + { + type planeWall; // type of the wall + + p1 (-0.2 -0.2 0.8); // first point of the wall + + p2 ( 0.2 -0.2 0.8); // second point + + p3 ( 0.2 0.2 0.8); // third point + + p4 (-0.2 0.2 0.8); // fourth point + + material wallMat; // material name of the wall + + motion rotAxis; // motion component name + } +} diff --git a/benchmarks/rotatingDrum/rotatingDrum_500kParticles/settings/particlesDict b/benchmarks/rotatingDrum/rotatingDrum_500kParticles/settings/particlesDict new file mode 100644 index 00000000..e0ef3e91 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_500kParticles/settings/particlesDict @@ -0,0 +1,47 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ + +objectName particlesDict; +objectType dictionary; +fileFormat ASCII; + +setFields +{ + defaultValue + { + velocity realx3 (0 0 0); // linear velocity (m/s) + acceleration realx3 (0 0 0); // linear acceleration (m/s2) + rotVelocity realx3 (0 0 0); // rotational velocity (rad/s) + shapeName word glassBead; // name of the particle shape + } + + selectors + {} +} + +positionParticles +{ + method ordered; + + orderedInfo + { + distance 0.005; // minimum space between centers of particles + + numPoints 500000; // number of particles in the simulation + + axisOrder (z x y); // axis order for filling the space with particles + } + + regionType cylinder; // other options: box and sphere + + cylinderInfo // cylinder for positioning particles + { + p1 (0.0 0.0 0.01); // lower corner point of the box + + p2 (0.0 0.0 0.79); // upper corner point of the box + + radius 0.195; // radius of cylinder + } +} diff --git a/benchmarks/rotatingDrum/rotatingDrum_500kParticles/settings/settingsDict b/benchmarks/rotatingDrum/rotatingDrum_500kParticles/settings/settingsDict new file mode 100644 index 00000000..f42eacc5 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_500kParticles/settings/settingsDict @@ -0,0 +1,34 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ +objectName settingsDict; +objectType dictionary; +fileFormat ASCII; +/*---------------------------------------------------------------------------*/ +run rotatingDrum_500KParticles; + +dt 0.00001; // time step for integration (s) + +startTime 0; // start time for simulation + +endTime 4; // end time for simulation + +saveInterval 0.2; // time interval for saving the simulation + +timePrecision 5; // maximum number of digits for time folder + +g (0 -9.8 0); // gravity vector (m/s2) + +includeObjects (diameter); // save necessary (i.e., required) data on disk + +// exclude unnecessary data from saving on disk +excludeObjects (rVelocity.dy1 pStructPosition.dy1 pStructVelocity.dy1); + +integrationMethod AdamsBashforth2; // integration method + +writeFormat binary; // data writting format (ascii or binary) + +timersReport Yes; + +timersReportInterval 0.01; diff --git a/benchmarks/rotatingDrum/rotatingDrum_8mParticles/caseSetup/interaction b/benchmarks/rotatingDrum/rotatingDrum_8mParticles/caseSetup/interaction new file mode 100644 index 00000000..4ef2c32f --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_8mParticles/caseSetup/interaction @@ -0,0 +1,60 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ + +objectName interaction; +objectType dictionary; +fileFormat ASCII; + +/*---------------------------------------------------------------------------*/ + +materials (glassMat wallMat); // a list of materials names + +densities (2500.0 2500); // density of materials [kg/m3] + +contactListType sortedContactList; + +contactSearch +{ + method NBS; + + updateInterval 20; + + sizeRatio 1.1; + + cellExtent 0.55; + + adjustableBox Yes; +} + +model +{ + contactForceModel nonLinearLimited; + + rollingFrictionModel normal; + + /* + Property (glassMat-glassMat glassMat-wallMat + wallMat-wallMat); + */ + + Yeff (1.0e6 1.0e6 + 1.0e6); // Young modulus [Pa] + + Geff (0.8e6 0.8e6 + 0.8e6); // Shear modulus [Pa] + + nu (0.25 0.25 + 0.25); // Poisson's ratio [-] + + en (0.97 0.85 + 1.00); // coefficient of normal restitution + + mu (0.65 0.65 + 0.65); // dynamic friction + + mur (0.1 0.1 + 0.1); // rolling friction +} + diff --git a/benchmarks/rotatingDrum/rotatingDrum_8mParticles/caseSetup/shapes b/benchmarks/rotatingDrum/rotatingDrum_8mParticles/caseSetup/shapes new file mode 100644 index 00000000..0c0b3443 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_8mParticles/caseSetup/shapes @@ -0,0 +1,15 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ + +objectName shapes; +objectType dictionary; +fileFormat ASCII; +/*---------------------------------------------------------------------------*/ + +names (glassBead); // names of shapes + +diameters (0.002); // diameter of shapes + +materials (glassMat); // material names for shapes diff --git a/benchmarks/rotatingDrum/rotatingDrum_8mParticles/cleanThisCase b/benchmarks/rotatingDrum/rotatingDrum_8mParticles/cleanThisCase new file mode 100755 index 00000000..8a0ab919 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_8mParticles/cleanThisCase @@ -0,0 +1,7 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory + +ls | grep -P "^(([0-9]+\.?[0-9]*)|(\.[0-9]+))$" | xargs -d"\n" rm -rf +rm -rf VTK + +#------------------------------------------------------------------------------ diff --git a/benchmarks/rotatingDrum/rotatingDrum_8mParticles/runThisCase b/benchmarks/rotatingDrum/rotatingDrum_8mParticles/runThisCase new file mode 100755 index 00000000..c48d71fe --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_8mParticles/runThisCase @@ -0,0 +1,21 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory +echo "\n<--------------------------------------------------------------------->" +echo "1) Creating particles" +echo "<--------------------------------------------------------------------->\n" +particlesPhasicFlow + +echo "\n<--------------------------------------------------------------------->" +echo "2) Creating geometry" +echo "<--------------------------------------------------------------------->\n" +geometryPhasicFlow + +echo "\n<--------------------------------------------------------------------->" +echo "3) Running the case" +echo "<--------------------------------------------------------------------->\n" +sphereGranFlow + + + + +#------------------------------------------------------------------------------ diff --git a/benchmarks/rotatingDrum/rotatingDrum_8mParticles/settings/domainDict b/benchmarks/rotatingDrum/rotatingDrum_8mParticles/settings/domainDict new file mode 100644 index 00000000..b92756a2 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_8mParticles/settings/domainDict @@ -0,0 +1,50 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ +objectName domainDict; +objectType dictionary; +fileFormat ASCII; +/*---------------------------------------------------------------------------*/ +globalBox // Simulation domain: every particles that goes outside this domain will be deleted +{ + min (-0.2 -0.2 0.0); + max ( 0.2 0.2 1.6); +} + +boundaries +{ + neighborListUpdateInterval 200; + + updateInterval 20; + + left + { + type exit; // other options: periodic, reflective + } + + right + { + type exit; // other options: periodic, reflective + } + + bottom + { + type exit; // other options: periodic, reflective + } + + top + { + type exit; // other options: periodic, reflective + } + + rear + { + type exit; // other options: periodic, reflective + } + + front + { + type exit; // other options: periodic, reflective + } +} diff --git a/benchmarks/rotatingDrum/rotatingDrum_8mParticles/settings/geometryDict b/benchmarks/rotatingDrum/rotatingDrum_8mParticles/settings/geometryDict new file mode 100644 index 00000000..dae67a91 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_8mParticles/settings/geometryDict @@ -0,0 +1,86 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ + +objectName geometryDict; +objectType dictionary; +fileFormat ASCII; + +motionModel rotatingAxis; // motion model: rotating object around an axis + +rotatingAxisInfo // information for rotatingAxisMotion motion model +{ + rotAxis + { + p1 (0.0 0.0 0.0); // first point for the axis of rotation + + p2 (0.0 0.0 1.0); // second point for the axis of rotation + + omega 1.256; // rotation speed (rad/s) => 12 rpm + } +} + +surfaces +{ + cylinder + { + type cylinderWall; // type of the wall + + p1 (0.0 0.0 0.0); // begin point of cylinder axis + + p2 (0.0 0.0 1.6); // end point of cylinder axis + + radius1 0.2; // radius at p1 + + radius2 0.2; // radius at p2 + + resolution 60; // number of divisions + + material wallMat; // material name of this wall + + motion rotAxis; // motion component name + } + + /* + This is a plane wall at the rear end of cylinder + */ + + wall1 + { + type planeWall; // type of the wall + + p1 (-0.2 -0.2 0.0); // first point of the wall + + p2 ( 0.2 -0.2 0.0); // second point + + p3 ( 0.2 0.2 0.0); // third point + + p4 (-0.2 0.2 0.0); // fourth point + + material wallMat; // material name of the wall + + motion rotAxis; // motion component name + } + + /* + This is a plane wall at the front end of cylinder + */ + + wall2 + { + type planeWall; // type of the wall + + p1 (-0.2 -0.2 1.6); // first point of the wall + + p2 ( 0.2 -0.2 1.6); // second point + + p3 ( 0.2 0.2 1.6); // third point + + p4 (-0.2 0.2 1.6); // fourth point + + material wallMat; // material name of the wall + + motion rotAxis; // motion component name + } +} diff --git a/benchmarks/rotatingDrum/rotatingDrum_8mParticles/settings/particlesDict b/benchmarks/rotatingDrum/rotatingDrum_8mParticles/settings/particlesDict new file mode 100644 index 00000000..362efa72 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_8mParticles/settings/particlesDict @@ -0,0 +1,47 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ + +objectName particlesDict; +objectType dictionary; +fileFormat ASCII; + +setFields +{ + defaultValue + { + velocity realx3 (0 0 0); // linear velocity (m/s) + acceleration realx3 (0 0 0); // linear acceleration (m/s2) + rotVelocity realx3 (0 0 0); // rotational velocity (rad/s) + shapeName word glassBead; // name of the particle shape + } + + selectors + {} +} + +positionParticles +{ + method ordered; + + orderedInfo + { + distance 0.003; // minimum space between centers of particles + + numPoints 6000000; // number of particles in the simulation + + axisOrder (z x y); // axis order for filling the space with particles + } + + regionType cylinder; // other options: box and sphere + + cylinderInfo // cylinder for positioning particles + { + p1 (0.0 0.0 0.01); // lower corner point of the box + + p2 (0.0 0.0 1.59); // upper corner point of the box + + radius 0.195; // radius of cylinder + } +} diff --git a/benchmarks/rotatingDrum/rotatingDrum_8mParticles/settings/settingsDict b/benchmarks/rotatingDrum/rotatingDrum_8mParticles/settings/settingsDict new file mode 100644 index 00000000..67cbee31 --- /dev/null +++ b/benchmarks/rotatingDrum/rotatingDrum_8mParticles/settings/settingsDict @@ -0,0 +1,34 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ +objectName settingsDict; +objectType dictionary; +fileFormat ASCII; +/*---------------------------------------------------------------------------*/ +run rotatingDrum_4mParticles; + +dt 0.00001; // time step for integration (s) + +startTime 0; // start time for simulation + +endTime 4; // end time for simulation + +saveInterval 0.2; // time interval for saving the simulation + +timePrecision 5; // maximum number of digits for time folder + +g (0 -9.8 0); // gravity vector (m/s2) + +includeObjects (diameter); // save necessary (i.e., required) data on disk + +// exclude unnecessary data from saving on disk +excludeObjects (rVelocity.dy1 pStructPosition.dy1 pStructVelocity.dy1); + +integrationMethod AdamsBashforth2; // integration method + +writeFormat binary; // data writting format (ascii or binary) + +timersReport Yes; + +timersReportInterval 0.01; diff --git a/benchmarks/rotatingDrum_4MParticles/caseSetup/interaction b/benchmarks/rotatingDrum_4MParticles/caseSetup/interaction deleted file mode 100755 index 0477966f..00000000 --- a/benchmarks/rotatingDrum_4MParticles/caseSetup/interaction +++ /dev/null @@ -1,59 +0,0 @@ -/* -------------------------------*- C++ -*--------------------------------- *\ -| phasicFlow File | -| copyright: www.cemf.ir | -\* ------------------------------------------------------------------------- */ - -objectName interaction; -objectType dicrionary; - -materials (glassMat wallMat); // a list of materials names -densities (2500.0 2500); // density of materials [kg/m3] - -contactListType sortedContactList; - -model -{ - contactForceModel nonLinearLimited; - rollingFrictionModel normal; - - Yeff (1.0e6 1.0e6 // Young modulus [Pa] - 1.0e6); - - Geff (0.8e6 0.8e6 // Shear modulus [Pa] - 0.8e6); - - nu (0.25 0.25 // Poisson's ratio [-] - 0.25); - - en (0.97 0.85 // coefficient of normal restitution - 1.00); - - et (1.0 1.0 // coefficient of tangential restitution - 1.0); - - mu (0.65 0.65 // dynamic friction - 0.65); - - mur (0.1 0.1 // rolling friction - 0.1); - -} - -contactSearch -{ - method NBS; - wallMapping cellMapping; - - NBSInfo - { - updateFrequency 10; // each 20 timesteps, update neighbor list - sizeRatio 1.05; // bounding box size to particle diameter (max) - } - - cellMappingInfo - { - updateFrequency 10; // each 20 timesteps, update neighbor list - cellExtent 0.6; // bounding box for particle-wall search (> 0.5) - } - -} \ No newline at end of file diff --git a/benchmarks/rotatingDrum_4MParticles/caseSetup/particleInsertion b/benchmarks/rotatingDrum_4MParticles/caseSetup/particleInsertion deleted file mode 100755 index eec7b7f9..00000000 --- a/benchmarks/rotatingDrum_4MParticles/caseSetup/particleInsertion +++ /dev/null @@ -1,14 +0,0 @@ -/* -------------------------------*- C++ -*--------------------------------- *\ -| phasicFlow File | -| copyright: www.cemf.ir | -\* ------------------------------------------------------------------------- */ - -objectName particleInsertion; -objectType dicrionary; - - -active no; // is insertion active? - -collisionCheck No; // not implemented for yes - - diff --git a/benchmarks/rotatingDrum_4MParticles/caseSetup/sphereShape b/benchmarks/rotatingDrum_4MParticles/caseSetup/sphereShape deleted file mode 100755 index eab9b617..00000000 --- a/benchmarks/rotatingDrum_4MParticles/caseSetup/sphereShape +++ /dev/null @@ -1,11 +0,0 @@ -/* -------------------------------*- C++ -*--------------------------------- *\ -| phasicFlow File | -| copyright: www.cemf.ir | -\* ------------------------------------------------------------------------- */ - -objectName sphereDict; -objectType sphereShape; - -names (glassBead); // names of shapes -diameters (0.003); // diameter of shapes -materials (glassMat); // material names for shapes diff --git a/benchmarks/rotatingDrum_4MParticles/settings/geometryDict b/benchmarks/rotatingDrum_4MParticles/settings/geometryDict deleted file mode 100644 index 64702fd8..00000000 --- a/benchmarks/rotatingDrum_4MParticles/settings/geometryDict +++ /dev/null @@ -1,63 +0,0 @@ -/* -------------------------------*- C++ -*--------------------------------- *\ -| phasicFlow File | -| copyright: www.cemf.ir | -\* ------------------------------------------------------------------------- */ - -objectName geometryDict; -objectType dictionary; - -motionModel rotatingAxisMotion; - -surfaces -{ - - cylinder - { - type cylinderWall; - p1 (0.0 0.0 0.0); - p2 (0.0 0.0 1.6); - radius1 0.2; - radius2 0.2; - resolution 24; - material wallMat; - motion rotAxis; - } - - - wall1 - { - type planeWall; - p1 (-0.2 -0.2 0.0); - p2 ( 0.2 -0.2 0.0); - p3 ( 0.2 0.2 0.0); - p4 (-0.2 0.2 0.0); - material wallMat; - motion rotAxis; - } - - /* - This is a plane wall at the front end of cylinder - */ - wall2 - { - type planeWall; - p1 (-0.2 -0.2 1.6); - p2 ( 0.2 -0.2 1.6); - p3 ( 0.2 0.2 1.6); - p4 (-0.2 0.2 1.6); - material wallMat; - motion rotAxis; - } - -} - -// information for rotatingAxisMotion motion model -rotatingAxisMotionInfo -{ - rotAxis - { - p1 (0.0 0.0 0.0); - p2 (0.0 0.0 1.0); - omega 1.256; // rotation speed (rad/s) => 12 rpm - } -} \ No newline at end of file diff --git a/benchmarks/rotatingDrum_4MParticles/settings/particlesDict b/benchmarks/rotatingDrum_4MParticles/settings/particlesDict deleted file mode 100644 index 7ae00511..00000000 --- a/benchmarks/rotatingDrum_4MParticles/settings/particlesDict +++ /dev/null @@ -1,44 +0,0 @@ -/* -------------------------------*- C++ -*--------------------------------- *\ -| phasicFlow File | -| copyright: www.cemf.ir | -\* ------------------------------------------------------------------------- */ - -objectName particlesDict; -objectType dictionary; - -setFields -{ - - defaultValue - { - velocity realx3 (0 0 0); // linear velocity (m/s) - acceleration realx3 (0 0 0); // linear acceleration (m/s2) - rotVelocity realx3 (0 0 0); // rotational velocity (rad/s) - shapeName word glassBead; // name of the particle shape - } - - selectors - {} -} - -positionParticles -{ - method positionOrdered; - - maxNumberOfParticles 4000001; - mortonSorting Yes; - - cylinder // box for positioning particles - { - p1 ( 0.0 0.0 0.01); // lower corner point of the box - p2 ( 0.0 0.0 1.59); // upper corner point of the box - radius 0.195; - } - - positionOrderedInfo - { - diameter 0.003; // minimum space between centers of particles - numPoints 4000000; // number of particles in the simulation - axisOrder (z x y); // axis order for filling the space with particles - } -} diff --git a/benchmarks/rotatingDrum_4MParticles/settings/settingsDict b/benchmarks/rotatingDrum_4MParticles/settings/settingsDict deleted file mode 100644 index 8a881847..00000000 --- a/benchmarks/rotatingDrum_4MParticles/settings/settingsDict +++ /dev/null @@ -1,32 +0,0 @@ -/* -------------------------------*- C++ -*--------------------------------- *\ -| phasicFlow File | -| copyright: www.cemf.ir | -\* ------------------------------------------------------------------------- */ -objectName settingsDict; -objectType dictionary;; - -run rotatingDrum_1; - -dt 0.00001; // time step for integration (s) - -startTime 0; // start time for simulation - -endTime 10; // end time for simulation - -saveInterval 0.2; // time interval for saving the simulation - -timePrecision 5; // maximum number of digits for time folder - -g (0 -9.8 0); // gravity vector (m/s2) - -domain -{ - min (-0.2 -0.2 -0.0); - max ( 0.2 0.2 1.6); -} - -integrationMethod AdamsBashforth3; // integration method - -timersReport Yes; - -timersReportInterval 0.01; diff --git a/cmake/autoComplete b/cmake/autoComplete new file mode 100644 index 00000000..babf3843 --- /dev/null +++ b/cmake/autoComplete @@ -0,0 +1,112 @@ +PF_cFlags="--description --help --version" +AllTimeFolders= +__getAllTime(){ + # Initialize empty array for time folders + local time_folders=() + + # Loop through all directories in current folder + for dir in */; do + # Remove trailing slash + dir=${dir%/} + + # Check if directory name is a valid floating point number + # This pattern matches integers and floating point numbers + if [[ $dir =~ ^[0-9]+(\.[0-9]+)?$ ]]; then + time_folders+=("$dir") + fi + done + + # Set completion reply to the time folders + COMPREPLY=("${time_folders[@]}") + AllTimeFolders="${time_folders[@]}" +} + +__getFields(){ + __getAllTime + local -A unique_files=() + # Files to exclude from suggestions + local exclude_files=("shapeHash" "pStructure" "particleInsertion" "p" "alpha" "U" "Sp" "Su" "phi") + declare -A exclude_dict + + # Build exclude dictionary for faster lookups + for file in "${exclude_files[@]}"; do + exclude_dict["$file"]=1 + done + + for dir in $AllTimeFolders; do + # Skip if not a directory + [ ! -d "$dir" ] && continue + + # Find all files in this time directory + while IFS= read -r filename; do + # Skip empty lines and excluded files + [ -z "$filename" ] || [ "${exclude_dict[$filename]+exists}" ] && continue + + # Add to unique files + unique_files["$filename"]=1 + done < <(find "$dir" -maxdepth 1 -type f -printf '%f\n') + done + + # Set completion reply to the unique filenames + COMPREPLY=(${!unique_files[@]}) + + # Clear global variable + AllTimeFolders= +} + +_pFlowToVTK(){ + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + + # Check if we're completing a field + local is_field=0 + for ((i=1; i( + 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 . . ."< bool pFlow::geometryMotion::findMotionIndex() { - if(motionComponentName().size() != numSurfaces() ) { fatalErrorInFunction<< diff --git a/src/Geometry/geometryMotion/geometryMotions.cpp b/src/Geometry/geometryMotion/geometryMotions.cpp index 8b1d1d55..8636c1f7 100644 --- a/src/Geometry/geometryMotion/geometryMotions.cpp +++ b/src/Geometry/geometryMotion/geometryMotions.cpp @@ -26,4 +26,6 @@ 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 1bb078d8..4a916b6e 100644 --- a/src/Geometry/geometryMotion/geometryMotions.hpp +++ b/src/Geometry/geometryMotion/geometryMotions.hpp @@ -24,7 +24,8 @@ Licence: #include "geometryMotion.hpp" #include "stationaryWall.hpp" #include "rotatingAxisMotion.hpp" -//#include "multiRotatingAxisMotion.hpp" +#include "conveyorBeltMotion.hpp" +#include "multiRotatingAxisMotion.hpp" #include "vibratingMotion.hpp" @@ -37,10 +38,9 @@ using rotationAxisMotionGeometry = geometryMotion; using stationaryGeometry = geometryMotion; -//typedef geometryMotion multiRotationAxisMotionGeometry; - - +using conveyorBeltMotionGeometry = geometryMotion; +using multiRotationAxisMotionGeometry = geometryMotion; } diff --git a/src/Integration/AdamsBashforth2/AdamsBashforth2.cpp b/src/Integration/AdamsBashforth2/AdamsBashforth2.cpp index c6bb54a6..9f457fe8 100644 --- a/src/Integration/AdamsBashforth2/AdamsBashforth2.cpp +++ b/src/Integration/AdamsBashforth2/AdamsBashforth2.cpp @@ -37,7 +37,8 @@ bool intAllActive( real dt, realx3Field_D& y, realx3PointField_D& dy, - realx3PointField_D& dy1) + realx3PointField_D& dy1, + real damping = 1.0) { auto d_dy = dy.deviceView(); @@ -49,7 +50,7 @@ bool intAllActive( "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_y[i] += damping * dt*(static_cast(1.5) * d_dy[i] - static_cast(0.5) * d_dy1[i]); d_dy1[i] = d_dy[i]; }); Kokkos::fence(); @@ -62,7 +63,8 @@ bool intScattered real dt, realx3Field_D& y, realx3PointField_D& dy, - realx3PointField_D& dy1 + realx3PointField_D& dy1, + real damping = 1.0 ) { @@ -78,7 +80,7 @@ bool intScattered 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_y[i] += damping * dt*(static_cast(1.5) * d_dy[i] - static_cast(0.5) * d_dy1[i]); d_dy1[i] = d_dy[i]; } }); @@ -90,17 +92,16 @@ bool intScattered } - - pFlow::AdamsBashforth2::AdamsBashforth2 ( const word& baseName, pointStructure& pStruct, const word& method, - const realx3Field_D& initialValField + const realx3Field_D& initialValField, + bool keepHistory ) : - integration(baseName, pStruct, method, initialValField), + integration(baseName, pStruct, method, initialValField, keepHistory), realx3PointField_D ( objectFile @@ -108,20 +109,27 @@ pFlow::AdamsBashforth2::AdamsBashforth2 groupNames(baseName,"dy1"), pStruct.time().integrationFolder(), objectFile::READ_IF_PRESENT, - objectFile::WRITE_ALWAYS + keepHistory?objectFile::WRITE_ALWAYS:objectFile::WRITE_NEVER ), pStruct, zero3, zero3 - ) -{} + ), + initialValField_(initialValField), + boundaryList_(pStruct, method, *this) +{ + realx3PointField_D::addEvent(message::ITEMS_INSERT); +} -bool pFlow::AdamsBashforth2::predict -( - real UNUSED(dt), - realx3PointField_D& UNUSED(y), - realx3PointField_D& UNUSED(dy) -) +void pFlow::AdamsBashforth2::updateBoundariesSlaveToMasterIfRequested() +{ + realx3PointField_D::updateBoundariesSlaveToMasterIfRequested(); +} + +bool pFlow::AdamsBashforth2::predict( + real UNUSED(dt), + realx3PointField_D &UNUSED(y), + realx3PointField_D &UNUSED(dy)) { return true; } @@ -140,31 +148,63 @@ bool pFlow::AdamsBashforth2::correct ( real dt, realx3PointField_D& y, - realx3PointField_D& dy + realx3PointField_D& dy, + real damping ) -{ - return correct(dt, y.field(), dy); -} - -bool pFlow::AdamsBashforth2::correct(real dt, realx3Field_D &y, realx3PointField_D &dy) { auto& dy1l = dy1(); - + bool success = false; if(dy1l.isAllActive()) { - return intAllActive(dt, y, dy, dy1l); + success = intAllActive(dt, y.field(), dy, dy1(), damping); } else { - return intScattered(dt, y, dy, dy1l); + success = intScattered(dt, y.field(), dy, dy1(), damping); } - return false; + + success = success && boundaryList_.correct(dt, y, dy); + + return success; + } -bool pFlow::AdamsBashforth2::setInitialVals( - const int32IndexContainer& newIndices, - const realx3Vector& y) +bool pFlow::AdamsBashforth2::correctPStruct( + real dt, + pointStructure &pStruct, + realx3PointField_D &vel) { - return true; + auto& dy1l = dy1(); + bool success = false; + if(dy1l.isAllActive()) + { + success = intAllActive(dt, pStruct.pointPosition(), vel, dy1()); + } + else + { + success = intScattered(dt, pStruct.pointPosition(), vel, dy1()); + } + + success = success && boundaryList_.correctPStruct(dt, pStruct, vel); + + return success; } +/*bool pFlow::AdamsBashforth2::hearChanges +( + const timeInfo &ti, + const message &msg, + const anyList &varList +) +{ + if(msg.equivalentTo(message::ITEMS_INSERT)) + { + + return insertValues(varList, initialValField_.deviceViewAll(), dy1()); + } + else + { + return realx3PointField_D::hearChanges(ti, msg, varList); + } + +}*/ diff --git a/src/Integration/AdamsBashforth2/AdamsBashforth2.hpp b/src/Integration/AdamsBashforth2/AdamsBashforth2.hpp index 13685bab..0241bb8e 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 { @@ -41,10 +41,33 @@ class AdamsBashforth2 { private: + const realx3Field_D& initialValField_; + + boundaryIntegrationList boundaryList_; + + friend class processorAB2BoundaryIntegration; + +protected: + + const auto& dy1()const + { + return static_cast(*this); + } + auto& dy1() { return static_cast(*this); } + + auto& initialValField() + { + return initialValField_; + } + + boundaryIntegrationList& boundaryList() + { + return boundaryList_; + } public: @@ -58,10 +81,11 @@ public: const word& baseName, pointStructure& pStruct, const word& method, - const realx3Field_D& initialValField); + const realx3Field_D& initialValField, + bool keepHistory); /// Destructor - ~AdamsBashforth2()final = default; + ~AdamsBashforth2()override = default; /// Add this to the virtual constructor table add_vCtor( @@ -71,6 +95,9 @@ public: // - Methods + + void updateBoundariesSlaveToMasterIfRequested()override; + /// return integration method word method()const override { @@ -90,31 +117,21 @@ public: bool correct( real dt, realx3PointField_D& y, - realx3PointField_D& dy) final; + realx3PointField_D& dy, + real damping = 1.0) override; - bool correct( + bool correctPStruct( real dt, - realx3Field_D& y, - realx3PointField_D& dy) final; + pointStructure& pStruct, + realx3PointField_D& vel) override; /*bool hearChanges ( - real t, - real dt, - uint32 iter, + const timeInfo& ti, const message& msg, const anyList& varList ) override;*/ - bool setInitialVals( - const int32IndexContainer& newIndices, - const realx3Vector& y) final; - - bool needSetInitialVals()const final - { - return false; - } - }; diff --git a/src/Integration/AdamsBashforth3/AdamsBashforth3.cpp b/src/Integration/AdamsBashforth3/AdamsBashforth3.cpp index f8ec6b5a..c15b5ff2 100644 --- a/src/Integration/AdamsBashforth3/AdamsBashforth3.cpp +++ b/src/Integration/AdamsBashforth3/AdamsBashforth3.cpp @@ -20,90 +20,185 @@ Licence: #include "AdamsBashforth3.hpp" +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, + realx3PointField_D& dy2, + real damping = 1.0) +{ + + auto d_dy = dy.deviceView(); + auto d_y = y.deviceView(); + auto d_dy1= dy1.deviceView(); + auto d_dy2= dy2.deviceView(); + auto activeRng = dy1.activeRange(); + + Kokkos::parallel_for( + "AdamsBashforth3::correct", + rpIntegration (activeRng.start(), activeRng.end()), + LAMBDA_HD(uint32 i){ + d_y[i] += damping* dt*( static_cast(23.0 / 12.0) * d_dy[i] + - static_cast(16.0 / 12.0) * d_dy1[i] + + static_cast(5.0 / 12.0) * d_dy2[i]) ; + + d_dy2[i] = 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, + realx3PointField_D& dy2, + real damping = 1.0 +) +{ + + auto d_dy = dy.deviceView(); + auto d_y = y.deviceView(); + auto d_dy1 = dy1.deviceView(); + auto d_dy2 = dy2.deviceView(); + auto activeRng = dy1.activeRange(); + const auto& activeP = dy1.activePointsMaskDevice(); + + Kokkos::parallel_for( + "AdamsBashforth3::correct", + rpIntegration (activeRng.start(), activeRng.end()), + LAMBDA_HD(uint32 i){ + if( activeP(i)) + { + d_y[i] += damping * dt*( static_cast(23.0 / 12.0) * d_dy[i] + - static_cast(16.0 / 12.0) * d_dy1[i] + + static_cast(5.0 / 12.0) * d_dy2[i]); + + d_dy2[i] = d_dy1[i]; + d_dy1[i] = d_dy[i]; + } + }); + Kokkos::fence(); + + + return true; +} + +} + //const real AB3_coef[] = { 23.0 / 12.0, 16.0 / 12.0, 5.0 / 12.0 }; pFlow::AdamsBashforth3::AdamsBashforth3 ( const word& baseName, - repository& owner, - const pointStructure& pStruct, - const word& method + pointStructure& pStruct, + const word& method, + const realx3Field_D& initialValField, + bool keepHistory ) : - integration(baseName, owner, pStruct, method), - history_( - owner.emplaceObject>( - objectFile( - groupNames(baseName,"AB3History"), - "", - objectFile::READ_IF_PRESENT, - objectFile::WRITE_ALWAYS), - pStruct, - AB3History({zero3,zero3}))) + AdamsBashforth2(baseName, pStruct, method, initialValField, keepHistory), + dy2_ + ( + objectFile + ( + groupNames(baseName,"dy2"), + pStruct.time().integrationFolder(), + objectFile::READ_IF_PRESENT, + keepHistory ? objectFile::WRITE_ALWAYS : objectFile::WRITE_NEVER + ), + pStruct, + zero3, + zero3 + ) { } -bool pFlow::AdamsBashforth3::predict -( - real UNUSED(dt), - realx3Vector_D& UNUSED(y), - realx3Vector_D& UNUSED(dy) -) +void pFlow::AdamsBashforth3::updateBoundariesSlaveToMasterIfRequested() { - - return true; + AdamsBashforth2::updateBoundariesSlaveToMasterIfRequested(); + dy2_.updateBoundariesSlaveToMasterIfRequested(); } + + bool pFlow::AdamsBashforth3::correct ( - real dt, - realx3Vector_D& y, - realx3Vector_D& dy + real dt, + realx3PointField_D& y, + realx3PointField_D& dy, + real damping ) { - if(this->pStruct().allActive()) + bool success = false; + if(y.isAllActive()) { - return intAll(dt, y, dy, this->pStruct().activeRange()); + success = intAllActive(dt, y.field(), dy, dy1(), dy2(), damping); } else { - return intRange(dt, y, dy, this->pStruct().activePointsMaskD()); + success = intScattered(dt, y.field(), dy, dy1(), dy2(), damping); } - return true; + success = success && boundaryList().correct(dt, y, dy); + + return success; } -bool pFlow::AdamsBashforth3::setInitialVals( - const int32IndexContainer& newIndices, - const realx3Vector& y) -{ - return true; -} - -bool pFlow::AdamsBashforth3::intAll( +bool pFlow::AdamsBashforth3::correctPStruct( real dt, - realx3Vector_D& y, - realx3Vector_D& dy, - range activeRng) + pointStructure &pStruct, + realx3PointField_D &vel) { - auto d_dy = dy.deviceViewAll(); - auto d_y = y.deviceViewAll(); - auto d_history = history_.deviceViewAll(); + + bool success = false; + if(dy2().isAllActive()) + { + success = intAllActive(dt, pStruct.pointPosition(), vel, dy1(), dy2()); + } + else + { + success = intScattered(dt, pStruct.pointPosition(), vel, dy1(), dy2()); + } - Kokkos::parallel_for( - "AdamsBashforth3::correct", - rpIntegration (activeRng.first, activeRng.second), - LAMBDA_HD(int32 i){ - auto ldy = d_dy[i]; - d_y[i] += dt*( static_cast(23.0 / 12.0) * ldy - - static_cast(16.0 / 12.0) * d_history[i].dy1_ - + static_cast(5.0 / 12.0) * d_history[i].dy2_); - d_history[i] = {ldy ,d_history[i].dy1_}; - }); - Kokkos::fence(); + success = success && boundaryList().correctPStruct(dt, pStruct, vel); - return true; -} \ No newline at end of file + return success; +} + +/*bool pFlow::AdamsBashforth3::hearChanges +( + const timeInfo &ti, + const message &msg, + const anyList &varList +) +{ + if(msg.equivalentTo(message::ITEMS_INSERT)) + { + return insertValues(varList, initialValField().deviceViewAll(), dy1()) && + insertValues(varList, initialValField().deviceViewAll(), dy2()); + } + else + { + return realx3PointField_D::hearChanges(ti, msg, varList); + } +}*/ diff --git a/src/Integration/AdamsBashforth3/AdamsBashforth3.hpp b/src/Integration/AdamsBashforth3/AdamsBashforth3.hpp index 279fdcda..50a23c39 100644 --- a/src/Integration/AdamsBashforth3/AdamsBashforth3.hpp +++ b/src/Integration/AdamsBashforth3/AdamsBashforth3.hpp @@ -22,48 +22,14 @@ Licence: #define __AdamsBashforth3_hpp__ -#include "integration.hpp" +#include "AdamsBashforth2.hpp" #include "pointFields.hpp" +#include "boundaryIntegrationList.hpp" + namespace pFlow { -struct AB3History -{ - TypeInfoNV("AB3History"); - - realx3 dy1_={0,0,0}; - realx3 dy2_={0,0,0}; -}; - - -INLINE_FUNCTION -iIstream& operator>>(iIstream& str, AB3History& ab3) -{ - str.readBegin("AB3History"); - - str >> ab3.dy1_; - str >> ab3.dy2_; - - str.readEnd("AB3History"); - - str.check(FUNCTION_NAME); - - return str; - -} - -INLINE_FUNCTION -iOstream& operator<<(iOstream& str, const AB3History& ab3) -{ - str << token::BEGIN_LIST << ab3.dy1_ - << token::SPACE << ab3.dy2_ - << token::END_LIST; - - str.check(FUNCTION_NAME); - - return str; -} /** * Third order Adams-Bashforth integration method for solving ODE @@ -72,19 +38,26 @@ iOstream& operator<<(iOstream& str, const AB3History& ab3) */ class AdamsBashforth3 : - public integration + public AdamsBashforth2 { -protected: +private: - /// Integration history - pointField& history_; + friend class processorAB3BoundaryIntegration; - /// Range policy for integration kernel - using rpIntegration = Kokkos::RangePolicy< - DefaultExecutionSpace, - Kokkos::Schedule, - Kokkos::IndexType - >; + realx3PointField_D dy2_; + +protected: + + const auto& dy2()const + { + return dy2_; + } + + auto& dy2() + { + return dy2_; + } + public: @@ -96,17 +69,14 @@ public: /// Construct from components AdamsBashforth3( const word& baseName, - repository& owner, - const pointStructure& pStruct, - const word& method); + pointStructure& pStruct, + const word& method, + const realx3Field_D& initialValField, + bool keepHistory); - uniquePtr clone()const override - { - return makeUnique(*this); - } /// Destructor - virtual ~AdamsBashforth3()=default; + ~AdamsBashforth3() override =default; /// Add this to the virtual constructor table add_vCtor( @@ -117,43 +87,39 @@ public: // - Methods - bool predict( - real UNUSED(dt), - realx3Vector_D & UNUSED(y), - realx3Vector_D& UNUSED(dy)) override; + void updateBoundariesSlaveToMasterIfRequested()override; - bool correct(real dt, - realx3Vector_D & y, - realx3Vector_D& dy) override; - - bool setInitialVals( - const int32IndexContainer& newIndices, - const realx3Vector& y) override; - - bool needSetInitialVals()const override + /// return integration method + word method()const override { - return false; + return "AdamsBashforth3"; } - /// 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 ); + bool correct( + real dt, + realx3PointField_D& y, + realx3PointField_D& dy, + real damping = 1.0) override; + + bool correctPStruct( + real dt, + pointStructure& pStruct, + realx3PointField_D& vel) override; + + + /*bool hearChanges + ( + const timeInfo& ti, + const message& msg, + const anyList& varList + ) override;*/ }; -template +/*template bool pFlow::AdamsBashforth3::intRange( real dt, realx3Vector_D& y, @@ -181,7 +147,7 @@ bool pFlow::AdamsBashforth3::intRange( Kokkos::fence(); return true; -} +}*/ } // pFlow diff --git a/src/Integration/AdamsBashforth4/AdamsBashforth4.cpp b/src/Integration/AdamsBashforth4/AdamsBashforth4.cpp index 23bad29b..24461282 100644 --- a/src/Integration/AdamsBashforth4/AdamsBashforth4.cpp +++ b/src/Integration/AdamsBashforth4/AdamsBashforth4.cpp @@ -20,96 +20,187 @@ Licence: #include "AdamsBashforth4.hpp" - - -pFlow::AdamsBashforth4::AdamsBashforth4 -( - const word& baseName, - repository& owner, - const pointStructure& pStruct, - const word& method -) -: - integration(baseName, owner, pStruct, method), - history_( - owner.emplaceObject>( - objectFile( - groupNames(baseName,"AB4History"), - "", - objectFile::READ_IF_PRESENT, - objectFile::WRITE_ALWAYS), - pStruct, - AB4History({zero3,zero3, zero3}))) - +namespace pFlow { -} +/// Range policy for integration kernel (alias) +using rpIntegration = Kokkos::RangePolicy< + DefaultExecutionSpace, + Kokkos::Schedule, + Kokkos::IndexType + >; -bool pFlow::AdamsBashforth4::predict -( - real UNUSED(dt), - realx3Vector_D& UNUSED(y), - realx3Vector_D& UNUSED(dy) -) -{ - - return true; -} - -bool pFlow::AdamsBashforth4::correct -( - real dt, - realx3Vector_D& y, - realx3Vector_D& dy -) -{ - - if(this->pStruct().allActive()) - { - return intAll(dt, y, dy, this->pStruct().activeRange()); - } - else - { - return intRange(dt, y, dy, this->pStruct().activePointsMaskD()); - } - - return true; -} - -bool pFlow::AdamsBashforth4::setInitialVals( - const int32IndexContainer& newIndices, - const realx3Vector& y) -{ - return true; -} - -bool pFlow::AdamsBashforth4::intAll( +bool intAllActive( real dt, - realx3Vector_D& y, - realx3Vector_D& dy, - range activeRng) + realx3Field_D& y, + realx3PointField_D& dy, + realx3PointField_D& dy1, + realx3PointField_D& dy2, + realx3PointField_D& dy3, + real damping = 1.0) { - auto d_dy = dy.deviceViewAll(); - auto d_y = y.deviceViewAll(); - auto d_history = history_.deviceViewAll(); + + auto d_dy = dy.deviceView(); + auto d_y = y.deviceView(); + auto d_dy1= dy1.deviceView(); + auto d_dy2= dy2.deviceView(); + auto d_dy3= dy3.deviceView(); + auto activeRng = dy1.activeRange(); Kokkos::parallel_for( "AdamsBashforth4::correct", - rpIntegration (activeRng.first, activeRng.second), - LAMBDA_HD(int32 i){ - d_y[i] += dt*( - static_cast(55.0 / 24.0) * d_dy[i] - - static_cast(59.0 / 24.0) * d_history[i].dy1_ - + static_cast(37.0 / 24.0) * d_history[i].dy2_ - - static_cast( 9.0 / 24.0) * d_history[i].dy3_ - ); - d_history[i].dy3_ = d_history[i].dy2_; - d_history[i].dy2_ = d_history[i].dy1_; - d_history[i].dy1_ = d_dy[i]; - + rpIntegration (activeRng.start(), activeRng.end()), + LAMBDA_HD(uint32 i){ + d_y[i] += damping * dt*( + static_cast(55.0 / 24.0) * d_dy[i] + - static_cast(59.0 / 24.0) * d_dy1[i] + + static_cast(37.0 / 24.0) * d_dy2[i] + - static_cast( 9.0 / 24.0) * d_dy3[i]); + d_dy3[i] = d_dy2[i]; + d_dy2[i] = d_dy1[i]; + d_dy1[i] = d_dy[i]; }); Kokkos::fence(); return true; -} \ No newline at end of file +} + +bool intScattered +( + real dt, + realx3Field_D& y, + realx3PointField_D& dy, + realx3PointField_D& dy1, + realx3PointField_D& dy2, + realx3PointField_D& dy3, + real damping = 1.0 +) +{ + + auto d_dy = dy.deviceView(); + auto d_y = y.deviceView(); + auto d_dy1 = dy1.deviceView(); + auto d_dy2 = dy2.deviceView(); + auto d_dy3 = dy3.deviceView(); + auto activeRng = dy1.activeRange(); + const auto& activeP = dy1.activePointsMaskDevice(); + + Kokkos::parallel_for( + "AdamsBashforth4::correct", + rpIntegration (activeRng.start(), activeRng.end()), + LAMBDA_HD(uint32 i){ + if( activeP(i)) + { + d_y[i] += damping* dt*( + static_cast(55.0 / 24.0) * d_dy[i] + - static_cast(59.0 / 24.0) * d_dy1[i] + + static_cast(37.0 / 24.0) * d_dy2[i] + - static_cast( 9.0 / 24.0) * d_dy3[i] ); + d_dy3[i] = d_dy2[i]; + d_dy2[i] = d_dy1[i]; + d_dy1[i] = d_dy[i]; + } + }); + Kokkos::fence(); + + + return true; +} + +} + +pFlow::AdamsBashforth4::AdamsBashforth4 +( + const word& baseName, + pointStructure& pStruct, + const word& method, + const realx3Field_D& initialValField, + bool keepHistory +) +: + AdamsBashforth3(baseName, pStruct, method, initialValField, keepHistory), + dy3_ + ( + objectFile + ( + groupNames(baseName,"dy3"), + pStruct.time().integrationFolder(), + objectFile::READ_IF_PRESENT, + keepHistory?objectFile::WRITE_ALWAYS:objectFile::WRITE_NEVER + ), + pStruct, + zero3, + zero3 + ) +{} + +void pFlow::AdamsBashforth4::updateBoundariesSlaveToMasterIfRequested() +{ + AdamsBashforth3::updateBoundariesSlaveToMasterIfRequested(); + dy3_.updateBoundariesSlaveToMasterIfRequested(); +} + +bool pFlow::AdamsBashforth4::correct +( + real dt, + realx3PointField_D& y, + realx3PointField_D& dy, + real damping +) +{ + + bool success = false; + if(y.isAllActive()) + { + success = intAllActive(dt, y.field(), dy, dy1(), dy2(), dy3(), damping); + } + else + { + success = intScattered(dt, y.field(), dy, dy1(), dy2(), dy3(), damping); + } + + success = success && boundaryList().correct(dt, y, dy); + + return success; +} + +bool pFlow::AdamsBashforth4::correctPStruct( + real dt, + pointStructure &pStruct, + realx3PointField_D &vel) +{ + + bool success = false; + if(dy2().isAllActive()) + { + success = intAllActive(dt, pStruct.pointPosition(), vel, dy1(), dy2(), dy3()); + } + else + { + success = intScattered(dt, pStruct.pointPosition(), vel, dy1(), dy2(), dy3()); + } + + success = success && boundaryList().correctPStruct(dt, pStruct, vel); + + return success; +} + +/*bool pFlow::AdamsBashforth4::hearChanges +( + const timeInfo &ti, + const message &msg, + const anyList &varList +) +{ + if(msg.equivalentTo(message::ITEMS_INSERT)) + { + return insertValues(varList, initialValField().deviceViewAll(), dy1()) && + insertValues(varList, initialValField().deviceViewAll(), dy2()) && + insertValues(varList, initialValField().deviceViewAll(), dy3()); + } + else + { + return realx3PointField_D::hearChanges(ti, msg, varList); + } +}*/ diff --git a/src/Integration/AdamsBashforth4/AdamsBashforth4.hpp b/src/Integration/AdamsBashforth4/AdamsBashforth4.hpp index cf1f50d8..a9bb9a43 100644 --- a/src/Integration/AdamsBashforth4/AdamsBashforth4.hpp +++ b/src/Integration/AdamsBashforth4/AdamsBashforth4.hpp @@ -22,53 +22,14 @@ Licence: #define __AdamsBashforth4_hpp__ -#include "integration.hpp" +#include "AdamsBashforth3.hpp" #include "pointFields.hpp" +#include "boundaryIntegrationList.hpp" + namespace pFlow { -struct AB4History -{ - TypeInfoNV("AB4History"); - - realx3 dy1_={0,0,0}; - realx3 dy2_={0,0,0}; - realx3 dy3_={0,0,0}; - -}; - - -INLINE_FUNCTION -iIstream& operator>>(iIstream& str, AB4History& ab4) -{ - str.readBegin("AB4History"); - - str >> ab4.dy1_; - str >> ab4.dy2_; - str >> ab4.dy3_; - - str.readEnd("AB4History"); - - str.check(FUNCTION_NAME); - - return str; - -} - -INLINE_FUNCTION -iOstream& operator<<(iOstream& str, const AB4History& ab4) -{ - str << token::BEGIN_LIST << ab4.dy1_ - << token::SPACE << ab4.dy2_ - << token::SPACE << ab4.dy3_ - << token::END_LIST; - - str.check(FUNCTION_NAME); - - return str; -} - /** * Fourth order Adams-Bashforth integration method for solving ODE * @@ -76,19 +37,25 @@ iOstream& operator<<(iOstream& str, const AB4History& ab4) */ class AdamsBashforth4 : - public integration + public AdamsBashforth3 { +private: + + friend class processorAB4BoundaryIntegration; + + realx3PointField_D dy3_; + protected: - /// Integration history - pointField& history_; + const auto& dy3()const + { + return dy3_; + } - /// Range policy for integration kernel - using rpIntegration = Kokkos::RangePolicy< - DefaultExecutionSpace, - Kokkos::Schedule, - Kokkos::IndexType - >; + auto& dy3() + { + return dy3_; + } public: @@ -100,17 +67,15 @@ public: /// Construct from components AdamsBashforth4( const word& baseName, - repository& owner, - const pointStructure& pStruct, - const word& method); + pointStructure& pStruct, + const word& method, + const realx3Field_D& initialValField, + bool keepHistory); + - uniquePtr clone()const override - { - return makeUnique(*this); - } /// Destructor - virtual ~AdamsBashforth4()=default; + ~AdamsBashforth4() override =default; /// Add a this to the virtual constructor table add_vCtor( @@ -121,77 +86,36 @@ public: // - Methods - bool predict( - real UNUSED(dt), - realx3Vector_D & UNUSED(y), - realx3Vector_D& UNUSED(dy)) override; + void updateBoundariesSlaveToMasterIfRequested()override; + + /// return integration method + word method()const override + { + return "AdamsBashforth4"; + } bool correct( real dt, - realx3Vector_D & y, - realx3Vector_D& dy) override; + realx3PointField_D& y, + realx3PointField_D& dy, + real damping = 1.0) override; - bool setInitialVals( - const int32IndexContainer& newIndices, - const realx3Vector& y) override; - - bool needSetInitialVals()const override - { - return false; - } - - /// Integrate on all points in the active range - bool intAll( + bool correctPStruct( 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 ); + pointStructure& pStruct, + realx3PointField_D& vel) override; + + /*bool hearChanges + ( + const timeInfo& ti, + const message& msg, + const anyList& varList + ) override;*/ }; -template -bool pFlow::AdamsBashforth4::intRange( - real dt, - realx3Vector_D& y, - realx3Vector_D& dy, - activeFunctor activeP ) -{ - auto d_dy = dy.deviceViewAll(); - auto d_y = y.deviceViewAll(); - auto d_history = history_.deviceViewAll(); - auto activeRng = activeP.activeRange(); - Kokkos::parallel_for( - "AdamsBashforth4::correct", - rpIntegration (activeRng.first, activeRng.second), - LAMBDA_HD(int32 i){ - if( activeP(i)) - { - - d_y[i] += dt*( - static_cast(55.0 / 24.0) * d_dy[i] - - static_cast(59.0 / 24.0) * d_history[i].dy1_ - + static_cast(37.0 / 24.0) * d_history[i].dy2_ - - static_cast( 9.0 / 24.0) * d_history[i].dy3_ - ); - d_history[i].dy3_ = d_history[i].dy2_; - d_history[i].dy2_ = d_history[i].dy1_; - d_history[i].dy1_ = d_dy[i]; - } - }); - Kokkos::fence(); - - return true; -} } // pFlow diff --git a/src/Integration/AdamsBashforth5/AdamsBashforth5.cpp b/src/Integration/AdamsBashforth5/AdamsBashforth5.cpp index 7b87a4a3..dd1503e2 100644 --- a/src/Integration/AdamsBashforth5/AdamsBashforth5.cpp +++ b/src/Integration/AdamsBashforth5/AdamsBashforth5.cpp @@ -20,93 +20,179 @@ Licence: #include "AdamsBashforth5.hpp" - - -pFlow::AdamsBashforth5::AdamsBashforth5 -( - const word& baseName, - repository& owner, - const pointStructure& pStruct, - const word& method -) -: - integration(baseName, owner, pStruct, method), - history_( - owner.emplaceObject>( - objectFile( - groupNames(baseName,"AB5History"), - "", - objectFile::READ_IF_PRESENT, - objectFile::WRITE_ALWAYS), - pStruct, - AB5History({zero3,zero3, zero3}))) - +namespace pFlow { -} +/// Range policy for integration kernel (alias) +using rpIntegration = Kokkos::RangePolicy< + DefaultExecutionSpace, + Kokkos::Schedule, + Kokkos::IndexType + >; -bool pFlow::AdamsBashforth5::predict -( - real UNUSED(dt), - realx3Vector_D& UNUSED(y), - realx3Vector_D& UNUSED(dy) -) -{ - - return true; -} - -bool pFlow::AdamsBashforth5::correct -( - real dt, - realx3Vector_D& y, - realx3Vector_D& dy -) -{ - - if(this->pStruct().allActive()) - { - return intAll(dt, y, dy, this->pStruct().activeRange()); - } - else - { - return intRange(dt, y, dy, this->pStruct().activePointsMaskD()); - } - - return true; -} - -bool pFlow::AdamsBashforth5::setInitialVals( - const int32IndexContainer& newIndices, - const realx3Vector& y) -{ - return true; -} - -bool pFlow::AdamsBashforth5::intAll( +bool intAllActive( real dt, - realx3Vector_D& y, - realx3Vector_D& dy, - range activeRng) + realx3Field_D& y, + realx3PointField_D& dy, + realx3PointField_D& dy1, + realx3PointField_D& dy2, + realx3PointField_D& dy3, + realx3PointField_D& dy4, + real damping = 1.0) { - auto d_dy = dy.deviceViewAll(); - auto d_y = y.deviceViewAll(); - auto d_history = history_.deviceViewAll(); + + auto d_dy = dy.deviceView(); + auto d_y = y.deviceView(); + auto d_dy1= dy1.deviceView(); + auto d_dy2= dy2.deviceView(); + auto d_dy3= dy3.deviceView(); + auto d_dy4= dy4.deviceView(); + auto activeRng = dy1.activeRange(); Kokkos::parallel_for( "AdamsBashforth5::correct", - rpIntegration (activeRng.first, activeRng.second), - LAMBDA_HD(int32 i){ - d_y[i] += dt*( + rpIntegration (activeRng.start(), activeRng.end()), + LAMBDA_HD(uint32 i){ + d_y[i] += damping* dt*( static_cast(1901.0 / 720.0) * d_dy[i] - - static_cast(2774.0 / 720.0) * d_history[i].dy1_ - + static_cast(2616.0 / 720.0) * d_history[i].dy2_ - - static_cast(1274.0 / 720.0) * d_history[i].dy3_ - + static_cast( 251.0 / 720.0) * d_history[i].dy4_ - ); - d_history[i] = {d_dy[i] ,d_history[i].dy1_, d_history[i].dy2_, d_history[i].dy3_}; + - static_cast(2774.0 / 720.0) * d_dy1[i] + + static_cast(2616.0 / 720.0) * d_dy2[i] + - static_cast(1274.0 / 720.0) * d_dy3[i] + + static_cast( 251.0 / 720.0) * d_dy4[i]); + + d_dy4[i] = d_dy3[i]; + d_dy3[i] = d_dy2[i]; + d_dy2[i] = d_dy1[i]; + d_dy1[i] = d_dy[i]; }); Kokkos::fence(); return true; -} \ No newline at end of file +} + +bool intScattered +( + real dt, + realx3Field_D& y, + realx3PointField_D& dy, + realx3PointField_D& dy1, + realx3PointField_D& dy2, + realx3PointField_D& dy3, + realx3PointField_D& dy4, + real damping = 1.0 +) +{ + + auto d_dy = dy.deviceView(); + auto d_y = y.deviceView(); + auto d_dy1 = dy1.deviceView(); + auto d_dy2 = dy2.deviceView(); + auto d_dy3 = dy3.deviceView(); + auto d_dy4 = dy4.deviceView(); + auto activeRng = dy1.activeRange(); + const auto& activeP = dy1.activePointsMaskDevice(); + + Kokkos::parallel_for( + "AdamsBashforth5::correct", + rpIntegration (activeRng.start(), activeRng.end()), + LAMBDA_HD(uint32 i){ + if( activeP(i)) + { + d_y[i] += damping* dt*( + static_cast(1901.0 / 720.0) * d_dy[i] + - static_cast(2774.0 / 720.0) * d_dy1[i] + + static_cast(2616.0 / 720.0) * d_dy2[i] + - static_cast(1274.0 / 720.0) * d_dy3[i] + + static_cast( 251.0 / 720.0) * d_dy4[i]); + + d_dy4[i] = d_dy3[i]; + d_dy3[i] = d_dy2[i]; + d_dy2[i] = d_dy1[i]; + d_dy1[i] = d_dy[i]; + } + }); + Kokkos::fence(); + + return true; +} + +} + +pFlow::AdamsBashforth5::AdamsBashforth5 +( + const word &baseName, + pointStructure &pStruct, + const word &method, + const realx3Field_D &initialValField, + bool keepHistory +) +: + AdamsBashforth4(baseName, pStruct, method, initialValField, keepHistory), + dy4_ + ( + objectFile + ( + groupNames(baseName,"dy4"), + pStruct.time().integrationFolder(), + objectFile::READ_IF_PRESENT, + keepHistory?objectFile::WRITE_ALWAYS:objectFile::WRITE_NEVER + ), + pStruct, + zero3, + zero3 + ) +{} + +void pFlow::AdamsBashforth5::updateBoundariesSlaveToMasterIfRequested() +{ + AdamsBashforth4::updateBoundariesSlaveToMasterIfRequested(); + dy4_.updateBoundariesSlaveToMasterIfRequested(); +} + +bool pFlow::AdamsBashforth5::correct +( + real dt, + realx3PointField_D &y, + realx3PointField_D &dy, + real damping +) +{ + + bool success = false; + if(y.isAllActive()) + { + success = intAllActive(dt, y.field(), dy, dy1(), dy2(), dy3(), dy4(), damping); + } + else + { + success = intScattered(dt, y.field(), dy, dy1(), dy2(), dy3(), dy4(), damping); + } + + success = success && boundaryList().correct(dt, y, dy); + + return success; +} + +bool pFlow::AdamsBashforth5::correctPStruct +( + real dt, + pointStructure &pStruct, + realx3PointField_D &vel +) +{ +bool success = false; + if(dy2().isAllActive()) + { + success = intAllActive(dt, pStruct.pointPosition(), vel, dy1(), dy2(), dy3(), dy4()); + } + else + { + success = intScattered(dt, pStruct.pointPosition(), vel, dy1(), dy2(), dy3(), dy4()); + } + + success = success && boundaryList().correctPStruct(dt, pStruct, vel); + + return success; +} + + diff --git a/src/Integration/AdamsBashforth5/AdamsBashforth5.hpp b/src/Integration/AdamsBashforth5/AdamsBashforth5.hpp index 16b55927..939f96a3 100644 --- a/src/Integration/AdamsBashforth5/AdamsBashforth5.hpp +++ b/src/Integration/AdamsBashforth5/AdamsBashforth5.hpp @@ -22,54 +22,12 @@ Licence: #define __AdamsBashforth5_hpp__ -#include "integration.hpp" +#include "AdamsBashforth4.hpp" #include "pointFields.hpp" namespace pFlow { -struct AB5History -{ - TypeInfoNV("AB5History"); - - realx3 dy1_={0,0,0}; - realx3 dy2_={0,0,0}; - realx3 dy3_={0,0,0}; - realx3 dy4_={0,0,0}; -}; - - -INLINE_FUNCTION -iIstream& operator>>(iIstream& str, AB5History& ab5) -{ - str.readBegin("AB5History"); - - str >> ab5.dy1_; - str >> ab5.dy2_; - str >> ab5.dy3_; - str >> ab5.dy4_; - - str.readEnd("AB5History"); - - str.check(FUNCTION_NAME); - - return str; - -} - -INLINE_FUNCTION -iOstream& operator<<(iOstream& str, const AB5History& ab5) -{ - str << token::BEGIN_LIST << ab5.dy1_ - << token::SPACE << ab5.dy2_ - << token::SPACE << ab5.dy3_ - << token::SPACE << ab5.dy4_ - << token::END_LIST; - - str.check(FUNCTION_NAME); - - return str; -} /** * Fifth order Adams-Bashforth integration method for solving ODE @@ -78,19 +36,25 @@ iOstream& operator<<(iOstream& str, const AB5History& ab5) */ class AdamsBashforth5 : - public integration + public AdamsBashforth4 { +private: + + friend class processorAB4BoundaryIntegration; + + realx3PointField_D dy4_; + protected: - /// Integration history - pointField& history_; + const auto& dy4()const + { + return dy4_; + } - /// Range policy for integration kernel - using rpIntegration = Kokkos::RangePolicy< - DefaultExecutionSpace, - Kokkos::Schedule, - Kokkos::IndexType - >; + auto& dy4() + { + return dy4_; + } public: @@ -99,20 +63,20 @@ public: // - Constructors + /// Construct from components AdamsBashforth5( const word& baseName, - repository& owner, - const pointStructure& pStruct, - const word& method); + pointStructure& pStruct, + const word& method, + const realx3Field_D& initialValField, + bool keepHistory); + + - uniquePtr clone()const override - { - return makeUnique(*this); - } + /// Destructor + ~AdamsBashforth5() override =default; - virtual ~AdamsBashforth5()=default; - - /// Add this to the virtual constructor table + /// Add a this to the virtual constructor table add_vCtor( integration, AdamsBashforth5, @@ -121,44 +85,29 @@ public: // - Methods - bool predict( - real UNUSED(dt), - realx3Vector_D & UNUSED(y), - realx3Vector_D& UNUSED(dy)) override; + void updateBoundariesSlaveToMasterIfRequested()override; + + /// return integration method + word method()const override + { + return "AdamsBashforth5"; + } bool correct( real dt, - realx3Vector_D & y, - realx3Vector_D& dy) override; + realx3PointField_D& y, + realx3PointField_D& dy, + real damping = 1.0) override; - bool setInitialVals( - const int32IndexContainer& newIndices, - const realx3Vector& y) override; - - bool needSetInitialVals()const override - { - return false; - } - - /// Integrate on all points in the active range - bool intAll( + bool correctPStruct( 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 ); + pointStructure& pStruct, + realx3PointField_D& vel) override; }; -template +/*template bool pFlow::AdamsBashforth5::intRange( real dt, realx3Vector_D& y, @@ -190,7 +139,7 @@ bool pFlow::AdamsBashforth5::intRange( Kokkos::fence(); return true; -} +}*/ } // pFlow diff --git a/src/Integration/CMakeLists.txt b/src/Integration/CMakeLists.txt index fca650cd..b8229b2c 100644 --- a/src/Integration/CMakeLists.txt +++ b/src/Integration/CMakeLists.txt @@ -1,15 +1,23 @@ list(APPEND SourceFiles -integration/integration.cpp +integration/integration.cpp +boundaries/boundaryIntegration.cpp +boundaries/boundaryIntegrationList.cpp AdamsBashforth2/AdamsBashforth2.cpp -#AdamsBashforth5/AdamsBashforth5.cpp -#AdamsBashforth4/AdamsBashforth4.cpp -#AdamsBashforth3/AdamsBashforth3.cpp +AdamsBashforth3/AdamsBashforth3.cpp +AdamsBashforth4/AdamsBashforth4.cpp +AdamsBashforth5/AdamsBashforth5.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.hpp b/src/Integration/boundaries/boundaryIntegration.hpp index b3a20805..d7aa4d39 100644 --- a/src/Integration/boundaries/boundaryIntegration.hpp +++ b/src/Integration/boundaries/boundaryIntegration.hpp @@ -51,9 +51,7 @@ public: ); bool hearChanges( - real t, - real dt, - uint32 iter, + const timeInfo& ti, const message &msg, const anyList &varList) override { @@ -77,6 +75,11 @@ public: return true; } + bool isActive()const override + { + return false; + } + static uniquePtr create( const boundaryBase& boundary, diff --git a/src/Integration/boundaries/boundaryIntegrationList.cpp b/src/Integration/boundaries/boundaryIntegrationList.cpp index c7e2ad3b..636b0783 100644 --- a/src/Integration/boundaries/boundaryIntegrationList.cpp +++ b/src/Integration/boundaries/boundaryIntegrationList.cpp @@ -7,11 +7,11 @@ pFlow::boundaryIntegrationList::boundaryIntegrationList( integration &intgrtn ) : - ListPtr(6), + boundaryListPtr(), boundaries_(pStruct.boundaries()) { - - for(uint32 i=0; i<6; i++) + + ForAllBoundariesPtr(i, this) { this->set( i, @@ -19,23 +19,40 @@ pFlow::boundaryIntegrationList::boundaryIntegrationList( boundaries_[i], pStruct, method, - intgrtn - ) - ); + intgrtn + ) + ); } - } bool pFlow::boundaryIntegrationList::correct(real dt, realx3PointField_D &y, realx3PointField_D &dy) { - for(auto& bndry:*this) + ForAllActiveBoundariesPtr(i,this) { - if(!bndry->correct(dt, y, dy)) + if(!boundaryPtr(i)->correct(dt, y, dy)) { - fatalErrorInFunction; + fatalErrorInFunction<<"Error in correcting boundary "<< + boundaryPtr(i)->boundaryName()<correctPStruct(dt, vel)) + { + fatalErrorInFunction<<"Error in correcting boundary "<< + boundaryPtr(i)->boundaryName()<<" in pointStructure."< + public boundaryListPtr { private: @@ -35,6 +35,12 @@ public: real dt, realx3PointField_D& y, realx3PointField_D& dy); + + bool correctPStruct( + real dt, + pointStructure& pStruct, + const realx3PointField_D& vel); + }; diff --git a/src/Integration/integration/integration.cpp b/src/Integration/integration/integration.cpp index f3126e1e..710df9ad 100644 --- a/src/Integration/integration/integration.cpp +++ b/src/Integration/integration/integration.cpp @@ -22,17 +22,41 @@ Licence: #include "pointStructure.hpp" #include "repository.hpp" -pFlow::integration::integration +bool pFlow::integration::insertValues ( - const word& baseName, - pointStructure& pStruct, - const word&, - const realx3Field_D& + const anyList& varList, + const deviceViewType1D& srcVals, + realx3PointField_D& dstFeild ) -: - owner_(*pStruct.owner()), - pStruct_(pStruct), - baseName_(baseName) +{ + const word eventName = message::eventName(message::ITEMS_INSERT); + + if(!varList.checkObjectType(eventName)) + { + fatalErrorInFunction<<"Insertion failed in integration for "<< baseName_<< + ", variable "<< eventName << + " does not exist or the type is incorrect"<( + eventName); + + dstFeild.field().insertSetElement(indices, srcVals); + + return true; +} + +pFlow::integration::integration( + const word &baseName, + pointStructure &pStruct, + const word &, + const realx3Field_D &, + bool keepHistory) + : owner_(*pStruct.owner()), + pStruct_(pStruct), + baseName_(baseName), + keepHistory_(keepHistory) {} @@ -42,12 +66,13 @@ pFlow::uniquePtr const word& baseName, pointStructure& pStruct, const word& method, - const realx3Field_D& initialValField + const realx3Field_D& initialValField, + bool keepHistory ) { if( wordvCtorSelector_.search(method) ) { - return wordvCtorSelector_[method] (baseName, pStruct, method, initialValField); + return wordvCtorSelector_[method] (baseName, pStruct, method, initialValField, keepHistory); } else { diff --git a/src/Integration/integration/integration.hpp b/src/Integration/integration/integration.hpp index 4769c3ec..1161bd1e 100644 --- a/src/Integration/integration/integration.hpp +++ b/src/Integration/integration/integration.hpp @@ -24,6 +24,7 @@ Licence: #include "virtualConstructor.hpp" #include "pointFields.hpp" +#include "Logical.hpp" namespace pFlow @@ -63,6 +64,15 @@ private: /// The base name for integration const word baseName_; + bool keepHistory_; + +protected: + + bool insertValues( + const anyList& varList, + const deviceViewType1D& srcVals, + realx3PointField_D& dstFeild); + public: /// Type info @@ -76,7 +86,8 @@ public: const word& baseName, pointStructure& pStruct, const word& method, - const realx3Field_D& initialValField); + const realx3Field_D& initialValField, + bool keepHistory); /// Copy constructor integration(const integration&) = default; @@ -102,9 +113,10 @@ public: const word& baseName, pointStructure& pStruct, const word& method, - const realx3Field_D& initialValField + const realx3Field_D& initialValField, + bool keepHistory ), - (baseName, pStruct, method, initialValField) + (baseName, pStruct, method, initialValField, keepHistory) ); @@ -131,6 +143,13 @@ public: return owner_; } + bool keepHistory()const + { + return keepHistory_; + } + + virtual + void updateBoundariesSlaveToMasterIfRequested() = 0; /// return integration method virtual word method()const = 0 ; @@ -144,21 +163,10 @@ public: /// Correction/main integration step virtual - bool correct(real dt, realx3PointField_D& y, realx3PointField_D& dy) = 0; + bool correct(real dt, realx3PointField_D& y, realx3PointField_D& dy, real damping = 1.0) = 0; virtual - bool correct(real dt, realx3Field_D& y, realx3PointField_D& dy) = 0; - - /// Set the initial values for new indices - virtual - bool setInitialVals( - const int32IndexContainer& newIndices, - const realx3Vector& y) = 0; - - /// Check if the method requires any set initial vals - virtual - bool needSetInitialVals()const = 0; - + bool correctPStruct(real dt, pointStructure& pStruct, realx3PointField_D& vel) = 0; /// Create the polymorphic object based on inputs static @@ -166,7 +174,8 @@ public: const word& baseName, pointStructure& pStruct, const word& method, - const realx3Field_D& initialValField); + const realx3Field_D& initialValField, + bool keepHistory); }; // integration diff --git a/src/Interaction/CMakeLists.txt b/src/Interaction/CMakeLists.txt index 3b985647..c75f8239 100644 --- a/src/Interaction/CMakeLists.txt +++ b/src/Interaction/CMakeLists.txt @@ -21,6 +21,12 @@ interaction/interaction.cpp sphereInteraction/sphereInteractionsLinearModels.cpp sphereInteraction/sphereInteractionsNonLinearModels.cpp sphereInteraction/sphereInteractionsNonLinearModModels.cpp + +grainInteraction/grainInteractionsLinearModels.cpp +grainInteraction/grainInteractionsNonLinearModels.cpp +grainInteraction/grainInteractionsNonLinearModModels.cpp + + ) if(pFlow_Build_MPI) diff --git a/src/Interaction/Models/contactForce/cGAbsoluteLinearCF.hpp b/src/Interaction/Models/contactForce/cGAbsoluteLinearCF.hpp new file mode 100755 index 00000000..38566c23 --- /dev/null +++ b/src/Interaction/Models/contactForce/cGAbsoluteLinearCF.hpp @@ -0,0 +1,339 @@ +/*------------------------------- 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)*rho_[propId_i]; + real mj = 3*Pi/4*pow(Rj,3)*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_,static_cast(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)+ pow(Pi,2)); + + //REPORT(0)<<"\n en n is : "<(1.5)) * ethan_ * vrn)*Nij; + FCt = ( -pow(f_,3)*prop.kt_ * history.overlap_t_ - sqrt_meff * pow(f_,static_cast(1.5)) * prop.ethat_*Vt); + + real ft = length(FCt); + real ft_fric = prop.mu_ * length(FCn); + + if(ft > ft_fric) + { + if( length(history.overlap_t_) >zero) + { + 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/cGNonLinearCF.hpp b/src/Interaction/Models/contactForce/cGNonLinearCF.hpp new file mode 100644 index 00000000..18ae832f --- /dev/null +++ b/src/Interaction/Models/contactForce/cGNonLinearCF.hpp @@ -0,0 +1,307 @@ +/*------------------------------- 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 __cGNonLinearCF_hpp__ +#define __cGNonLinearCF_hpp__ + +#include "types.hpp" + +namespace pFlow::cfModels +{ + +template +class cGNonLinear +{ +public: + + struct contactForceStorage + { + realx3 overlap_t_ = 0.0; + }; + + struct cGNonLinearProperties + { + real Yeff_ = 1000000.0; + real Geff_ = 8000000.0; + real en_ = 1.0; + real mu_ = 0.00001; + + INLINE_FUNCTION_HD + cGNonLinearProperties(){} + + INLINE_FUNCTION_HD + cGNonLinearProperties(real Yeff, real Geff, real en, real mu ): + Yeff_(Yeff), Geff_(Geff), en_(en), mu_(mu) + {} + + INLINE_FUNCTION_HD + cGNonLinearProperties(const cGNonLinearProperties&)=default; + + INLINE_FUNCTION_HD + cGNonLinearProperties& operator=(const cGNonLinearProperties&)=default; + + INLINE_FUNCTION_HD + ~cGNonLinearProperties() = default; + }; + +protected: + + using cGNonLinearArrayType = symArray; + + int32 numMaterial_ = 0; + + ViewType1D rho_; + + int32 addDissipationModel_; + + cGNonLinearArrayType nonlinearProperties_; + + bool readNonLinearDictionary(const dictionary& dict) + { + auto Yeff = dict.getVal("Yeff"); + auto Geff = dict.getVal("Geff"); + auto nu = dict.getVal("nu"); + auto en = dict.getVal("en"); + auto mu = dict.getVal("mu"); + + auto nElem = Yeff.size(); + + if(nElem != nu.size()) + { + fatalErrorInFunction<< + "sizes of Yeff("< prop("prop",nElem); + ForAll(i,Yeff) + { + prop[i] = {Yeff[i], Geff[i], en[i], mu[i]}; + } + + nonlinearProperties_.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 "cGNonLinearLimited"; + } + else + { + return "cGNonLinearNonLimited"; + } + return ""; + } + +public: + + TypeInfoNV(modelName()); + + INLINE_FUNCTION_HD + cGNonLinear(){} + + cGNonLinear( + int32 nMaterial, + const ViewType1D& rho, + const dictionary& dict) + : + numMaterial_(nMaterial), + rho_("rho",nMaterial), + nonlinearProperties_("cGNonLinearProperties",nMaterial) + { + + Kokkos::deep_copy(rho_,rho); + if(!readNonLinearDictionary(dict)) + { + fatalExit; + } + } + + INLINE_FUNCTION_HD + cGNonLinear(const cGNonLinear&) = default; + + INLINE_FUNCTION_HD + cGNonLinear(cGNonLinear&&) = default; + + INLINE_FUNCTION_HD + cGNonLinear& operator=(const cGNonLinear&) = default; + + INLINE_FUNCTION_HD + cGNonLinear& operator=(cGNonLinear&&) = default; + + + INLINE_FUNCTION_HD + ~cGNonLinear()=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 + { + + const auto prop = nonlinearProperties_(propId_i,propId_j); + + const real f = 2/( 1/cGFi + 1/cGFj ); + + real vrn = dot(Vr, Nij); + realx3 Vt = Vr - vrn*Nij; + + history.overlap_t_ += Vt*dt; + + real mi = 3*Pi/4*pow(Ri,static_cast(3))*rho_[propId_i]; + real mj = 3*Pi/4*pow(Rj,static_cast(3))*rho_[propId_j]; + real Reff = 1/(1/Ri + 1/Rj); + + real K_hertz = 4.0/3.0*prop.Yeff_*sqrt(Reff); + real sqrt_meff_K_hertz = sqrt((mi*mj)/(mi+mj) * K_hertz); + + real en = prop.en_; + if (addDissipationModel_==2) + { + en = sqrt(1+((pow(prop.en_,2)-1)*f)); + } + else if (addDissipationModel_==3) + { + + en = exp((pow(f,static_cast(1.5))*log(prop.en_)*sqrt( (1-((pow(log(prop.en_),2))/(pow(log(prop.en_),2)+pow(Pi,2))))/(1-(pow(f,3)*(pow(log(prop.en_),2))/(pow(log(prop.en_),2)+pow(Pi,2)))) ) )); + } + + real Kn = static_cast(4.0/3.0) * prop.Yeff_ * sqrt(Reff*ovrlp_n); + + real ethan_ = -2.0*log(en)*sqrt(Kn)/ + sqrt(pow(log(en),2)+ pow(Pi,2)); + + FCn = ( - Kn*ovrlp_n - + sqrt_meff_K_hertz*ethan_*pow(ovrlp_n,static_cast(0.25))*vrn)*Nij; + + FCt = (f*f)*(- static_cast(8.0) * prop.Geff_ * sqrt(Reff*ovrlp_n) ) * history.overlap_t_; + + real ft = length(FCt); + real ft_fric = prop.mu_ * length(FCn); + + // apply friction + if(ft > ft_fric) + { + if( length(history.overlap_t_) >0.0) + { + if constexpr (limited) + { + real kt = static_cast(8.0) * prop.Geff_ * sqrt(Reff*ovrlp_n); + FCt *= (ft_fric/ft); + history.overlap_t_ = - FCt/(f*f*kt); + } + else + { + FCt = (FCt/ft)*ft_fric; + } + + } + 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..af51755d --- /dev/null +++ b/src/Interaction/Models/contactForce/cGRelativeLinearCF.hpp @@ -0,0 +1,326 @@ +/*------------------------------- 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_ = 1.0; + real mu_ = 0.00001; + + INLINE_FUNCTION_HD + linearProperties(){} + + INLINE_FUNCTION_HD + linearProperties(real kn, real kt, real en, real mu ): + kn_(kn), kt_(kt), en_(en), 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 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], 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)*rho_[propId_i]; + real mj = 3*Pi/4*pow(Rj,3)*rho_[propId_j]; + + real sqrt_meff = sqrt((mi*mj)/(mi+mj)); + + real en = prop.en_; + if (addDissipationModel_==2) + { + en = sqrt(1+((pow(prop.en_,2)-1)*f_)); + } + else if (addDissipationModel_==3) + { + + en = exp( + ( + pow(f_,static_cast(1.5))* + log(prop.en_)* + sqrt( + (1-((pow(log(prop.en_),static_cast(2.0)) + )/ + ( + pow(log(prop.en_),static_cast(2.0))+ + pow(Pi,static_cast(2.0)))))/ + (1-(pow(f_,3)*(pow(log(prop.en_),2))/ + (pow(log(prop.en_),static_cast(2.0))+ + pow(Pi,static_cast(2.0))))) ) )); + } + + real ethan_ = -2.0*log(en)*sqrt(prop.kn_)/ + sqrt(pow(log(en),2)+ pow(Pi,2)); + + + FCn = ( -f_*prop.kn_ * ovrlp_n - sqrt_meff * pow(f_,half) * ethan_ * vrn)*Nij; + FCt = ( -f_*prop.kt_ * history.overlap_t_); + + + + 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 88bf2108..bc3a030e 100644 --- a/src/Interaction/Models/contactForce/linearCF.hpp +++ b/src/Interaction/Models/contactForce/linearCF.hpp @@ -139,10 +139,10 @@ protected: ForAll(i , kn) { etha_n[i] = -2.0*log(en[i])*sqrt(kn[i])/ - sqrt(pow(log(en[i]),2.0)+ pow(Pi,2.0)); + sqrt(pow(log(en[i]),static_cast(2.0))+ pow(Pi,static_cast(2.0))); etha_t[i] = -2.0*log( et[i]*sqrt(kt[i]) )/ - sqrt(pow(log(et[i]),2.0)+ pow(Pi,2.0)); + sqrt(pow(log(et[i]),static_cast(2.0))+ pow(Pi,static_cast(2.0))); } Vector prop("prop", nElem); @@ -243,8 +243,8 @@ public: 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 mi = 3*Pi/4*pow(Ri,static_cast(3.0))*rho_[propId_i]; + real mj = 3*Pi/4*pow(Rj,static_cast(3.0))*rho_[propId_j]; real sqrt_meff = sqrt((mi*mj)/(mi+mj)); diff --git a/src/Interaction/Models/contactForce/nonLinearCF.hpp b/src/Interaction/Models/contactForce/nonLinearCF.hpp index 3ba1c5c5..4fdd4498 100644 --- a/src/Interaction/Models/contactForce/nonLinearCF.hpp +++ b/src/Interaction/Models/contactForce/nonLinearCF.hpp @@ -131,7 +131,7 @@ protected: // we take out sqrt(meff*K_hertz) here and then consider this term // when calculating damping part. etha_n[i] = -2.2664*log(en[i])/ - sqrt(pow(log(en[i]),2.0)+ pow(Pi,2.0)); + sqrt(pow(log(en[i]),static_cast(2.0))+ pow(Pi,static_cast(2.0))); // no damping for tangential part @@ -255,7 +255,7 @@ public: // apply friction if(ft > ft_fric) { - if( length(history.overlap_t_) >0.0) + if( length(history.overlap_t_) >zero) { if constexpr (limited) { diff --git a/src/phasicFlow/eventSubscriber/eventObserver.hpp b/src/Interaction/Models/grainContactForceModels.hpp old mode 100644 new mode 100755 similarity index 56% rename from src/phasicFlow/eventSubscriber/eventObserver.hpp rename to src/Interaction/Models/grainContactForceModels.hpp index aa4efd08..b6248238 --- a/src/phasicFlow/eventSubscriber/eventObserver.hpp +++ b/src/Interaction/Models/grainContactForceModels.hpp @@ -18,48 +18,33 @@ Licence: -----------------------------------------------------------------------------*/ +#ifndef __grainContactForceModels_hpp__ +#define __grainContactForceModels_hpp__ -#ifndef __eventObserver_hpp__ -#define __eventObserver_hpp__ +#include "cGAbsoluteLinearCF.hpp" +#include "cGRelativeLinearCF.hpp" +#include "cGNonLinearCF.hpp" -#include "eventMessage.hpp" +#include "grainRolling.hpp" -namespace pFlow + + +namespace pFlow::cfModels { -class eventSubscriber; + +using limitedCGAbsoluteLinearGrainRolling = grainRolling>; +using nonLimitedCGAbsoluteLinearGrainRolling = grainRolling>; + +using limitedCGRelativeLinearGrainRolling = grainRolling>; +using nonLimitedCGRelativeLinearGrainRolling = grainRolling>; + +using limitedCGNonLinearGrainRolling = grainRolling>; +using nonLimitedCGNonLinearGrainRolling = grainRolling>; -class eventObserver -{ -protected: - - const eventSubscriber* subscriber_ = nullptr; - - // if this object is linked to subscriber - bool subscribed_ = false; - -public: - - eventObserver(); - - eventObserver(const eventSubscriber& subscriber, bool subscribe = true ); - - virtual ~eventObserver(); - - inline bool subscribed()const {return subscribed_;} - - bool subscribe(const eventSubscriber& subscriber); - - inline void invalidateSubscriber() - { - subscribed_ = false; - } - - virtual bool update(const eventMessage& msg)=0; -}; - -} // pFlow +} -#endif // __eventObserver_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..cf4139e4 --- /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,static_cast(0.0)) ) + w_hat /= w_hat_mag; + else + w_hat = static_cast(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 80b8e321..1e4ad0fb 100644 --- a/src/Interaction/Models/rolling/normalRolling.hpp +++ b/src/Interaction/Models/rolling/normalRolling.hpp @@ -94,10 +94,10 @@ public: realx3 w_hat = wi-wj; real w_hat_mag = length(w_hat); - if( !equal(w_hat_mag,0.0) ) + if( !equal(w_hat_mag,static_cast(0.0)) ) w_hat /= w_hat_mag; else - w_hat = 0.0; + w_hat = static_cast(0.0); auto Reff = (Ri*Rj)/(Ri+Rj); diff --git a/src/Interaction/contactLists/sortedContactList.hpp b/src/Interaction/contactLists/sortedContactList.hpp index 4f41caac..aee1767e 100644 --- a/src/Interaction/contactLists/sortedContactList.hpp +++ b/src/Interaction/contactLists/sortedContactList.hpp @@ -80,13 +80,17 @@ public: TypeInfoNV("sortedContactList"); - - explicit sortedContactList(uint32 initialSize =1) + sortedContactList(uint32 initialSize =1) : - SortedPairs(initialSize), - values_("values", SortedPairs::capacity()), - sortedPairs0_("sortedPairs0", SortedPairs::capacity()), - values0_("values0", SortedPairs::capacity()) + sortedContactList("sortedContactList", initialSize) + {} + + sortedContactList(const word& name, uint32 initialSize =1) + : + SortedPairs(name, initialSize), + values_(groupNames(name, "values"), SortedPairs::capacity()), + sortedPairs0_(groupNames(name, "sortedPairs0"), SortedPairs::capacity()), + values0_(groupNames(name, "values0"), SortedPairs::capacity()) {} bool beforeBroadSearch() diff --git a/src/Interaction/contactLists/sortedPairs.hpp b/src/Interaction/contactLists/sortedPairs.hpp index 12593810..4a91718a 100644 --- a/src/Interaction/contactLists/sortedPairs.hpp +++ b/src/Interaction/contactLists/sortedPairs.hpp @@ -110,11 +110,11 @@ public: // constructors - explicit sortedPairs(uint32 initialSize =1) + explicit sortedPairs(const word& name, uint32 initialSize =1) : UnsortedPairs(initialSize), - flags_("flags_",UnsortedPairs::capacity()+1), - sortedPairs_("sortedPairs_",UnsortedPairs::capacity()) + flags_( groupNames(name, "flags_"), UnsortedPairs::capacity()+1), + sortedPairs_(groupNames(name, "sortedPairs_"), UnsortedPairs::capacity()) {} @@ -193,7 +193,7 @@ public: if( capacity+1 > flags_.size() ) { - reallocNoInit(flags_, capacity+1); + reallocInit(flags_, capacity+1); } // fill the flags @@ -219,7 +219,7 @@ public: { // get more space to prevent reallocations in next iterations uint32 len = size_*1.1+1; - reallocNoInit(sortedPairs_, len); + reallocInit(sortedPairs_, len); } Kokkos::parallel_for( @@ -231,6 +231,7 @@ public: // - sort paris based on the first and second sort(sortedPairs_, 0, size_ ); + } diff --git a/src/Interaction/contactLists/unsortedContactList.hpp b/src/Interaction/contactLists/unsortedContactList.hpp index 7aa98237..202b08ec 100644 --- a/src/Interaction/contactLists/unsortedContactList.hpp +++ b/src/Interaction/contactLists/unsortedContactList.hpp @@ -82,11 +82,16 @@ public: TypeInfoNV("unsortedContactList"); explicit unsortedContactList(uint32 capacity=1) + : + unsortedContactList("unsortedContactList", capacity) + {} + + unsortedContactList(const word& name, uint32 capacity=1) : UnsortedPairs(capacity), - values_("values", UnsortedPairs::capacity()), + values_(groupNames(name, "values"), UnsortedPairs::capacity()), container0_(capacity), - values0_("values0",container0_.capacity()) + values0_(groupNames(name, "values0"),container0_.capacity()) {} diff --git a/src/Interaction/contactLists/unsortedPairs.hpp b/src/Interaction/contactLists/unsortedPairs.hpp index fb622bdb..32898964 100644 --- a/src/Interaction/contactLists/unsortedPairs.hpp +++ b/src/Interaction/contactLists/unsortedPairs.hpp @@ -194,7 +194,9 @@ public: { uint newCap = container_.capacity()+len; this->clear(); + //output<<"----------------before "< ( - dict(), + csDict, this->extendedDomainBox(), minD, maxD, @@ -108,95 +149,19 @@ public: ); } - add_vCtor( contactSearch, ContactSearch, dictionary); + bool enterBroadSearchBoundary(const timeInfo& ti, bool force=false)const override; - bool broadSearch( - uint32 iter, - real t, - real dt, - csPairContainerType& ppPairs, - csPairContainerType& pwPairs, - bool force = false) override - { - - - ppTimer().start(); - - const auto& position = Particles().pointPosition().deviceViewAll(); - const auto& flags = Particles().dynPointStruct().activePointsMaskDevice(); - const auto& diam = Particles().boundingSphere().deviceViewAll(); - - - if( !ppwContactSearch_().broadSearch( - iter, - t, - dt, - ppPairs, - pwPairs, - position, - flags, - diam, - force) ) - { - fatalErrorInFunction; - return false; - } - ppTimer().end(); - - return true; - } - - bool boundaryBroadSearch( - uint32 i, - uint32 iter, - real t, - real dt, - csPairContainerType& ppPairs, - csPairContainerType& pwPairs, - bool force = false)override - { - if(i==0u) - Particles().boundingSphere().updateBoundaries(DataDirection::SlaveToMaster); - return csBoundaries_[i].broadSearch( - iter, - t, - dt, - ppPairs, - pwPairs, - force); - } - - bool enterBroadSearch(uint32 iter, real t, real dt)const override - { - if(ppwContactSearch_) - { - return ppwContactSearch_().performSearch(iter); - } - return false; - } - - bool performedBroadSearch()const override - { - return ppwContactSearch_().performedSearch(); - } - - - uint32 updateInterval()const override - { - return ppwContactSearch_().updateInterval(); - } real sizeRatio()const override { return ppwContactSearch_().sizeRatio(); } - real cellExtent()const override { return ppwContactSearch_().cellExtent(); @@ -204,7 +169,12 @@ public: }; +template +inline bool ContactSearch::enterBroadSearchBoundary(const timeInfo &ti, bool force) const +{ + return performSearch(ti.iter(),force) || csBoundaries_.boundariesUpdated(); } +} #endif //__ContactSearch_hpp__ diff --git a/src/Interaction/contactSearch/boundaries/boundaryContactSearch/boundaryContactSearch.hpp b/src/Interaction/contactSearch/boundaries/boundaryContactSearch/boundaryContactSearch.hpp index 55ecb47e..9395d939 100644 --- a/src/Interaction/contactSearch/boundaries/boundaryContactSearch/boundaryContactSearch.hpp +++ b/src/Interaction/contactSearch/boundaries/boundaryContactSearch/boundaryContactSearch.hpp @@ -73,9 +73,7 @@ public: } bool hearChanges( - real t, - real dt, - uint32 iter, + const timeInfo& ti, const message &msg, const anyList &varList) override { @@ -83,8 +81,10 @@ public: if (msg.equivalentTo(message::BNDR_RESET)) { // do nothing + return true; } - return true; + fatalErrorInFunction; + return false; } virtual bool broadSearch( @@ -98,6 +98,11 @@ public: return true; } + bool isActive()const override + { + return false; + } + static uniquePtr create( const dictionary &dict, const boundaryBase &boundary, diff --git a/src/Interaction/contactSearch/boundaries/boundaryContactSearchList.cpp b/src/Interaction/contactSearch/boundaries/boundaryContactSearchList.cpp index 4f114430..b0d3a4da 100644 --- a/src/Interaction/contactSearch/boundaries/boundaryContactSearchList.cpp +++ b/src/Interaction/contactSearch/boundaries/boundaryContactSearchList.cpp @@ -1,3 +1,23 @@ +/*------------------------------- 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 "boundaryContactSearchList.hpp" #include "boundaryList.hpp" @@ -5,7 +25,7 @@ void pFlow::boundaryContactSearchList::setList( const dictionary &dict, const contactSearch &cSearch) { - for(auto i=0; iset ( @@ -20,10 +40,13 @@ pFlow::boundaryContactSearchList::boundaryContactSearchList( const boundaryList& bndrs, const contactSearch &cSearch) : - ListPtr(bndrs.size()), + boundaryListPtr(), 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 index 40e9f32e..f588395d 100644 --- a/src/Interaction/contactSearch/boundaries/boundaryContactSearchList.hpp +++ b/src/Interaction/contactSearch/boundaries/boundaryContactSearchList.hpp @@ -1,4 +1,24 @@ -#include "ListPtr.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. + +-----------------------------------------------------------------------------*/ + +#include "boundaryListPtr.hpp" #include "boundaryContactSearch.hpp" namespace pFlow @@ -9,7 +29,7 @@ class contactSearch; class boundaryContactSearchList : - public ListPtr + public boundaryListPtr { private: @@ -28,6 +48,14 @@ public: const contactSearch& cSearch); ~boundaryContactSearchList()=default; + + inline + const boundaryList& boundaries()const + { + return boundaries_; + } + + bool boundariesUpdated()const; }; diff --git a/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/periodicBoundaryContactSearch.hpp b/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/periodicBoundaryContactSearch.hpp index 3cab83ef..00d30e5c 100644 --- a/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/periodicBoundaryContactSearch.hpp +++ b/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/periodicBoundaryContactSearch.hpp @@ -74,6 +74,11 @@ public: csPairContainerType &ppPairs, csPairContainerType &pwPairs, bool force = false) override; + + bool isActive()const override + { + return true; + } }; } diff --git a/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/wallBoundaryContactSearch.cpp b/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/wallBoundaryContactSearch.cpp index acfad226..e6aabb9b 100644 --- a/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/wallBoundaryContactSearch.cpp +++ b/src/Interaction/contactSearch/boundaries/periodicBoundaryContactSearch/wallBoundaryContactSearch.cpp @@ -11,7 +11,7 @@ pFlow::wallBoundaryContactSearch::wallBoundaryContactSearch const ViewType1D &normals ) : - cellExtent_( max(cellExtent, 0.5 ) ), + cellExtent_( max(cellExtent, half ) ), numElements_(numElements), numPoints_(numPoints), vertices_(vertices), diff --git a/src/Interaction/contactSearch/contactSearch/contactSearch.cpp b/src/Interaction/contactSearch/contactSearch/contactSearch.cpp index 8e8ca3dc..cd764146 100644 --- a/src/Interaction/contactSearch/contactSearch/contactSearch.cpp +++ b/src/Interaction/contactSearch/contactSearch/contactSearch.cpp @@ -31,11 +31,11 @@ pFlow::contactSearch::contactSearch( Timers& timers) : extendedDomainBox_(extDomain), + updateInterval_(dict.getValMax("updateInterval", 1u)), particles_(prtcl), geometry_(geom), - ppTimer_("particle-particle contact search", &timers), - pwTimer_("particle-wall contact search", &timers), - dict_(dict) + bTimer_("Boundary particles contact search", &timers), + ppTimer_("Internal particles contact search", &timers) { } @@ -45,6 +45,78 @@ const pFlow::pointStructure &pFlow::contactSearch::pStruct() const return particles_.pStruct(); } +bool pFlow::contactSearch::broadSearch +( + const timeInfo &ti, + csPairContainerType &ppPairs, + csPairContainerType &pwPairs, + bool force +) +{ + + if(enterBroadSearch(ti, force)) + { + ppTimer_.start(); + if( !BroadSearch( + ti, + ppPairs, + pwPairs, + force ) ) + { + fatalErrorInFunction; + performedSearch_ = false; + return false; + } + ppTimer_.end(); + performedSearch_ = true; + lastUpdated_ = ti.currentIter(); + } + else + { + performedSearch_ = false; + } + + return true; +} + +bool pFlow::contactSearch::boundaryBroadSearch +( + uint32 bndryIndex, + const timeInfo &ti, + csPairContainerType &ppPairs, + csPairContainerType &pwPairs, + bool force +) +{ + if(enterBroadSearchBoundary(ti, force)) + { + bTimer_.start(); + for(uint32 i=0u; i<6u; i++) + { + //output<<" boundarySearch "<< i <<" for iter "<< ti.iter()< pFlow::contactSearch::create( const dictionary &dict, const box &extDomain, diff --git a/src/Interaction/contactSearch/contactSearch/contactSearch.hpp b/src/Interaction/contactSearch/contactSearch/contactSearch.hpp index 865ec291..ef274086 100644 --- a/src/Interaction/contactSearch/contactSearch/contactSearch.hpp +++ b/src/Interaction/contactSearch/contactSearch/contactSearch.hpp @@ -26,6 +26,7 @@ Licence: #include "contactSearchGlobals.hpp" #include "dictionary.hpp" #include "virtualConstructor.hpp" +#include "timeInfo.hpp" #include "Timer.hpp" namespace pFlow @@ -44,15 +45,44 @@ private: const box& extendedDomainBox_; + /// @brief update interval in terms of iteration numebr + uint32 updateInterval_= 1; + + /// @brief last iteration number which contact search has been performed + uint32 lastUpdated_ = 0; + + /// @brief performed search? + bool performedSearch_ = false; + + /// @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_; - Timer pwTimer_; + virtual + bool BroadSearch( + const timeInfo& ti, + csPairContainerType& ppPairs, + csPairContainerType& pwPairs, + bool force + )=0; - dictionary dict_; + virtual + bool BoundaryBroadSearch( + uint32 bndryIndex, + const timeInfo& ti, + csPairContainerType& ppPairs, + csPairContainerType& pwPairs, + bool force = false + )=0; public: @@ -82,66 +112,86 @@ public: (dict, domain, prtcl, geom, timers) ); - - const auto& dict()const + inline + bool performedSearch()const { - return dict_; + return performedSearch_; } - const auto& extendedDomainBox()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 box& extendedDomainBox()const { return extendedDomainBox_; } - const auto& Particles()const + inline + const particles& Particles()const { return particles_; } const pointStructure& pStruct()const; - const auto& Geometry()const + inline + const geometry& Geometry()const { return geometry_; } - auto& ppTimer() + inline + Timer& ppTimer() { return ppTimer_; } - auto& pwTimer() + inline + Timer& bTimer() { - return pwTimer_; + return bTimer_; } - - virtual + bool broadSearch( - uint32 iter, - real t, - real dt, + const timeInfo& ti, csPairContainerType& ppPairs, csPairContainerType& pwPairs, - bool force = false) = 0; + bool force = false); - virtual bool boundaryBroadSearch( - uint32 i, - uint32 iter, - real t, - real dt, + uint32 bndryIndex, + const timeInfo& ti, csPairContainerType& ppPairs, csPairContainerType& pwPairs, - bool force = false)=0; - - virtual - bool enterBroadSearch(uint32 iter, real t, real dt)const = 0; - - virtual - bool performedBroadSearch()const = 0; - - virtual - uint32 updateInterval()const = 0; + bool force = false); virtual real sizeRatio()const = 0; diff --git a/src/Interaction/contactSearch/methods/cellBased/NBS/NBS.cpp b/src/Interaction/contactSearch/methods/cellBased/NBS/NBS.cpp index 733313b4..3b4410e5 100644 --- a/src/Interaction/contactSearch/methods/cellBased/NBS/NBS.cpp +++ b/src/Interaction/contactSearch/methods/cellBased/NBS/NBS.cpp @@ -44,9 +44,9 @@ pFlow::NBS::NBS position, flags, diam), - sizeRatio_(max(dict.getVal("sizeRatio"), 1.0)), - cellExtent_(max(dict.getVal("cellExtent"), 0.5)), - adjustableBox_(dict.getVal("adjustableBox")), + sizeRatio_(max(dict.getVal("sizeRatio"), one)), + cellExtent_(max(dict.getVal("cellExtent"), half)), + adjustableBox_(false),//adjustableBox_(dict.getVal("adjustableBox")), NBSLevel0_ ( this->domainBox_, diff --git a/src/Interaction/contactSearch/methods/cellBased/NBS/cellsWallLevel0.cpp b/src/Interaction/contactSearch/methods/cellBased/NBS/cellsWallLevel0.cpp index e1b6e3a7..c565bf87 100644 --- a/src/Interaction/contactSearch/methods/cellBased/NBS/cellsWallLevel0.cpp +++ b/src/Interaction/contactSearch/methods/cellBased/NBS/cellsWallLevel0.cpp @@ -31,7 +31,7 @@ pFlow::cellsWallLevel0::cellsWallLevel0 const ViewType1D& normals ) : - cellExtent_( max(cellExtent, 0.5 ) ), + cellExtent_( max(cellExtent, half ) ), numElements_(numElements), numPoints_(numPoints), vertices_(vertices), diff --git a/src/Interaction/contactSearch/methods/cellBased/NBS/mapperNBS.cpp b/src/Interaction/contactSearch/methods/cellBased/NBS/mapperNBS.cpp index b0f16804..b0ebf6cf 100644 --- a/src/Interaction/contactSearch/methods/cellBased/NBS/mapperNBS.cpp +++ b/src/Interaction/contactSearch/methods/cellBased/NBS/mapperNBS.cpp @@ -23,7 +23,7 @@ Licence: #include "streams.hpp" pFlow::uint32 pFlow::mapperNBS::checkInterval_ = 1000; -pFlow::real pFlow::mapperNBS::enlargementFactor_ = 1.1; +pFlow::real pFlow::mapperNBS::enlargementFactor_ = 1.5; bool pFlow::mapperNBS::setSearchBox ( diff --git a/src/Interaction/contactSearch/methods/cellBased/NBS/mapperNBSKernels.cpp b/src/Interaction/contactSearch/methods/cellBased/NBS/mapperNBSKernels.cpp index 01141eac..960cef14 100644 --- a/src/Interaction/contactSearch/methods/cellBased/NBS/mapperNBSKernels.cpp +++ b/src/Interaction/contactSearch/methods/cellBased/NBS/mapperNBSKernels.cpp @@ -21,7 +21,7 @@ Licence: -----------------------------------------------------------------------------*/ #include "mapperNBSKernels.hpp" - +#include "streams.hpp" void pFlow::mapperNBSKernels::findPointExtends ( @@ -153,16 +153,19 @@ bool pFlow::mapperNBSKernels::buildLists const pFlagTypeDevice &flags ) { + auto aRange = flags.activeRange(); + + auto pp = points; if(flags.isAllActive() ) - { + { Kokkos::parallel_for ( "pFlow::mapperNBSKernels::buildLists", deviceRPolicyStatic(aRange.start(), aRange.end()), LAMBDA_HD(uint32 i) - { - auto ind = searchCell.pointIndex(points[i]); + { + auto ind = searchCell.pointIndex(pp[i]); uint32 old = Kokkos::atomic_exchange(&head(ind.x(), ind.y(), ind.z()), i); next[i] = old; } diff --git a/src/Interaction/contactSearch/methods/particleWallContactSearchs.cpp b/src/Interaction/contactSearch/methods/particleWallContactSearchs.cpp index ee414f3b..95a37309 100644 --- a/src/Interaction/contactSearch/methods/particleWallContactSearchs.cpp +++ b/src/Interaction/contactSearch/methods/particleWallContactSearchs.cpp @@ -31,48 +31,36 @@ pFlow::particleWallContactSearchs::particleWallContactSearchs const ViewType1D &diam ) : - domainBox_(domain), - updateInterval_ - ( - max(dict.getValOrSet("updateInterval", 1),1u) - ) -{ - -} + 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 - ) +( + 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)) { - - performedSearch_ = false; - if( !performSearch(iter, force) ) return true; - - if(!getMethod().impl_broadSearch( - ppPairs, - pwPairs, - pointPos, - flags, - diameter)) - { - fatalErrorInFunction<< - "Error in performing particle-particle broadSearch in method"<< - getMethod().typeName()<& diameter, bool force = false ); - - bool performedSearch()const - { - return performedSearch_; - } - - bool performSearch(uint32 iter, bool force = false)const - { - if((iter-lastUpdated_) % updateInterval_ == 0 || iter == 0 || force ) - { - return true; - } - return false; - } - - uint32 updateInterval()const - { - return updateInterval_; - } real sizeRatio()const { 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..e024c62a --- /dev/null +++ b/src/Interaction/grainInteraction/boundaries/boundaryGrainInteraction/boundaryGrainInteraction.hpp @@ -0,0 +1,188 @@ +/*------------------------------- 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 + ( + const timeInfo& ti, + const message& msg, + const anyList& varList + ) override + { + if(msg.equivalentTo(message::BNDR_RESET)) + { + return true; + } + fatalErrorInFunction<<"Event "<< msg.eventNames() << " is not handled !"< 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..7f59e061 --- /dev/null +++ b/src/Interaction/grainInteraction/boundaries/boundaryGrainInteractionList.cpp @@ -0,0 +1,23 @@ + + +template +pFlow::boundaryGrainInteractionList::boundaryGrainInteractionList +( + const grainParticles &grnPrtcls, + const gMModel &geomMotion +) +: + boundaryListPtr>(), + boundaries_(grnPrtcls.pStruct().boundaries()) +{ + //gSettings::sleepMiliSeconds(1000*pFlowProcessors().localRank()); + ForAllBoundariesPtr(i, this) + { + 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..29e1f8e0 --- /dev/null +++ b/src/Interaction/grainInteraction/boundaries/boundaryGrainInteractionList.hpp @@ -0,0 +1,40 @@ +#ifndef __boundaryGrainInteractionList_hpp__ +#define __boundaryGrainInteractionList_hpp__ + + +#include "boundaryList.hpp" +#include "boundaryListPtr.hpp" +#include "boundaryGrainInteraction.hpp" + + +namespace pFlow +{ + + +template +class boundaryGrainInteractionList +: + public boundaryListPtr> +{ +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/utilities/postprocessPhasicFlow/ProcessFields.cpp b/src/Interaction/grainInteraction/boundaries/createBoundaryGrainInteraction.hpp similarity index 72% rename from utilities/postprocessPhasicFlow/ProcessFields.cpp rename to src/Interaction/grainInteraction/boundaries/createBoundaryGrainInteraction.hpp index 31969b57..12049af0 100644 --- a/utilities/postprocessPhasicFlow/ProcessFields.cpp +++ b/src/Interaction/grainInteraction/boundaries/createBoundaryGrainInteraction.hpp @@ -15,19 +15,17 @@ Licence: 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 "ProcessField.hpp" +#include "boundaryGrainInteraction.hpp" +#include "periodicBoundaryGrainInteraction.hpp" - -template class pFlow::ProcessField; - -template class pFlow::ProcessField; - -template class pFlow::ProcessField; - -template class pFlow::ProcessField; - -template class pFlow::ProcessField; +#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..36c97eaf --- /dev/null +++ b/src/Interaction/grainInteraction/boundaries/periodicBoundaryGrainInteraction/periodicBoundaryGrainInteraction.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 __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; + + bool isActive()const override + { + return true; + } + +}; + +} + +#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..dc329cc5 --- /dev/null +++ b/src/Interaction/grainInteraction/grainInteraction/grainInteraction.cpp @@ -0,0 +1,355 @@ +/*------------------------------- 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("Grain-Grain",nPrtcl+1); + + pwContactList_ = makeUnique("Grain-wall",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 +( + const timeInfo& ti, + const message& msg, + const anyList& varList +) +{ + fatalErrorInFunction<<"Event "<< msg.eventNames()<< + " is not handled in grainInteraction"< 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( + const timeInfo& ti, + 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/phasicFlow/eventSubscriber/eventObserver.cpp b/src/Interaction/grainInteraction/grainInteractionsNonLinearModModels.cpp old mode 100644 new mode 100755 similarity index 60% rename from src/phasicFlow/eventSubscriber/eventObserver.cpp rename to src/Interaction/grainInteraction/grainInteractionsNonLinearModModels.cpp index 0010aefc..462b5eb3 --- a/src/phasicFlow/eventSubscriber/eventObserver.cpp +++ b/src/Interaction/grainInteraction/grainInteractionsNonLinearModModels.cpp @@ -18,39 +18,26 @@ Licence: -----------------------------------------------------------------------------*/ -#include "eventObserver.hpp" -#include "eventSubscriber.hpp" +#include "grainInteraction.hpp" +#include "geometryMotions.hpp" +#include "grainContactForceModels.hpp" +#include "unsortedContactList.hpp" +#include "sortedContactList.hpp" +#include "createBoundaryGrainInteraction.hpp" -pFlow::eventObserver::eventObserver(): - subscriber_(nullptr), - subscribed_(false) -{} -pFlow::eventObserver::eventObserver -( - const eventSubscriber& subscriber, - bool subscribe -) -: - subscriber_(&subscriber), - subscribed_(false) -{ - if(subscribe && subscriber_) - { - subscribed_ = subscriber_->subscribe(this); - } -} -pFlow::eventObserver::~eventObserver() -{ - if(subscribed_ && subscriber_) - subscriber_->unsubscribe(this); -} +#define createInteraction(ForceModel,GeomModel) \ + \ + template class pFlow::grainInteraction< \ + ForceModel, \ + GeomModel, \ + pFlow::unsortedContactList>; \ + \ + template class pFlow::grainInteraction< \ + ForceModel, \ + GeomModel, \ + pFlow::sortedContactList>; \ + createBoundaryGrainInteraction(ForceModel, GeomModel) -bool pFlow::eventObserver::subscribe(const eventSubscriber& subscriber) -{ - subscriber_ = &subscriber; - subscribed_ = subscriber_->subscribe(this); - return subscribed_; -} diff --git a/src/Interaction/grainInteraction/grainInteractionsNonLinearModels.cpp b/src/Interaction/grainInteraction/grainInteractionsNonLinearModels.cpp new file mode 100755 index 00000000..8b5d1d6a --- /dev/null +++ b/src/Interaction/grainInteraction/grainInteractionsNonLinearModels.cpp @@ -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 "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::limitedCGNonLinearGrainRolling, pFlow::rotationAxisMotionGeometry); + +createInteraction(pFlow::cfModels::nonLimitedCGNonLinearGrainRolling, pFlow::rotationAxisMotionGeometry); + +createInteraction(pFlow::cfModels::limitedCGNonLinearGrainRolling, pFlow::stationaryGeometry); +createInteraction(pFlow::cfModels::nonLimitedCGNonLinearGrainRolling, pFlow::stationaryGeometry); diff --git a/src/Interaction/interaction/interaction.hpp b/src/Interaction/interaction/interaction.hpp index a2a4e1f3..afb10ea0 100644 --- a/src/Interaction/interaction/interaction.hpp +++ b/src/Interaction/interaction/interaction.hpp @@ -51,7 +51,7 @@ private: const geometry& geometry_; static inline - const message msg_ = message::ITEM_REARRANGE; + const message msg_ = message::ITEMS_REARRANGE; public: diff --git a/src/Interaction/sphereInteraction/boundaries/boundarySphereInteraction/boundarySphereInteraction.hpp b/src/Interaction/sphereInteraction/boundaries/boundarySphereInteraction/boundarySphereInteraction.hpp index 708fb61e..2ea6015f 100644 --- a/src/Interaction/sphereInteraction/boundaries/boundarySphereInteraction/boundarySphereInteraction.hpp +++ b/src/Interaction/sphereInteraction/boundaries/boundarySphereInteraction/boundarySphereInteraction.hpp @@ -110,7 +110,7 @@ public: return geometryMotion_; } - ContactListType& ppPairs() + ContactListType& ppPairs() { return ppPairs_(); } @@ -148,7 +148,7 @@ public: const ContactForceModel& cfModel, uint32 step) { - // for default boundary, no thing to be done + // for default boundary, nothing to be done return false; } @@ -156,20 +156,26 @@ public: bool hearChanges ( - real t, - real dt, - uint32 iter, + const timeInfo& ti, const message& msg, const anyList& varList ) override { - + if(msg.equivalentTo(message::BNDR_RESET)) + { + // do nothing + return true; + } pOutput<<"Function (hearChanges in boundarySphereInteractions)is not implmented Message "<< - msg <name() <<" type "<< this->type()<boundaryName() <<" type "<< this->type()< create( const boundaryBase& boundary, diff --git a/src/Interaction/sphereInteraction/boundaries/boundarySphereInteractionList.cpp b/src/Interaction/sphereInteraction/boundaries/boundarySphereInteractionList.cpp index 00b86bc4..61dedc0b 100644 --- a/src/Interaction/sphereInteraction/boundaries/boundarySphereInteractionList.cpp +++ b/src/Interaction/sphereInteraction/boundaries/boundarySphereInteractionList.cpp @@ -7,11 +7,11 @@ pFlow::boundarySphereInteractionList::boundarySphereInteractio const gMModel &geomMotion ) : - ListPtr>(6), + boundaryListPtr>(), boundaries_(sphPrtcls.pStruct().boundaries()) { - //gSettings::sleepMiliSeconds(1000*pFlowProcessors().localRank()); - for(uint32 i=0; i<6; i++) + output<set( i, diff --git a/src/Interaction/sphereInteraction/boundaries/boundarySphereInteractionList.hpp b/src/Interaction/sphereInteraction/boundaries/boundarySphereInteractionList.hpp index 1a5086fa..1073c156 100644 --- a/src/Interaction/sphereInteraction/boundaries/boundarySphereInteractionList.hpp +++ b/src/Interaction/sphereInteraction/boundaries/boundarySphereInteractionList.hpp @@ -3,7 +3,7 @@ #include "boundaryList.hpp" -#include "ListPtr.hpp" +#include "boundaryListPtr.hpp" #include "boundarySphereInteraction.hpp" @@ -14,7 +14,7 @@ namespace pFlow template class boundarySphereInteractionList : - public ListPtr> + public boundaryListPtr> { private: diff --git a/src/Interaction/sphereInteraction/boundaries/periodicBoundarySphereInteraction/periodicBoundarySphereInteraction.hpp b/src/Interaction/sphereInteraction/boundaries/periodicBoundarySphereInteraction/periodicBoundarySphereInteraction.hpp index 5f1e7a45..e61447b3 100644 --- a/src/Interaction/sphereInteraction/boundaries/periodicBoundarySphereInteraction/periodicBoundarySphereInteraction.hpp +++ b/src/Interaction/sphereInteraction/boundaries/periodicBoundarySphereInteraction/periodicBoundarySphereInteraction.hpp @@ -76,15 +76,17 @@ public: boundaryBase ); - ~periodicBoundarySphereInteraction()override = default; - - - + ~periodicBoundarySphereInteraction()override = default; bool sphereSphereInteraction( real dt, const ContactForceModel& cfModel, uint32 step)override; + + bool isActive()const override + { + return true; + } }; diff --git a/src/Interaction/sphereInteraction/sphereInteraction/sphereInteraction.cpp b/src/Interaction/sphereInteraction/sphereInteraction/sphereInteraction.cpp index 2aa10ef8..fe907354 100644 --- a/src/Interaction/sphereInteraction/sphereInteraction/sphereInteraction.cpp +++ b/src/Interaction/sphereInteraction/sphereInteraction/sphereInteraction.cpp @@ -41,9 +41,9 @@ bool pFlow::sphereInteraction::createSphereInteraction() geometryMotion_, timers()); - ppContactList_ = makeUnique(nPrtcl+1); + ppContactList_ = makeUnique("sphere-sphere",nPrtcl+1); - pwContactList_ = makeUnique(nPrtcl/5+1); + pwContactList_ = makeUnique("sphere-wall",nPrtcl/5+1); return true; } @@ -134,18 +134,22 @@ pFlow::sphereInteraction::sphereInteraction geometryMotion_(dynamic_cast(geom)), sphParticles_(dynamic_cast(prtcl)), boundaryInteraction_(sphParticles_,geometryMotion_), - ppInteractionTimer_("sphere-sphere interaction", &this->timers()), - pwInteractionTimer_("sphere-wall interaction", &this->timers()), - contactListMangementTimer_("contact-list management", &this->timers()), - boundaryContactSearchTimer_("contact search for boundary", &this->timers()), - boundaryInteractionTimer_("interaction for boundary", &this->timers()), - contactListBoundaryTimer_("contact-list management for boundary", &this->timers()) + 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> @@ -158,45 +162,58 @@ template class cLT> bool pFlow::sphereInteraction::iterate() { - auto iter = this->currentIter(); - auto t = this->currentTime(); - auto dt = this->dt(); + timeInfo ti = this->TimeInfo(); + auto iter = ti.iter(); + auto t = ti.t(); + auto dt = ti.dt(); - - bool broadSearch = contactSearch_().enterBroadSearch(iter, t, 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_.mass().updateBoundaries(DataDirection::SlaveToMaster); - sphParticles_.I().updateBoundaries(DataDirection::SlaveToMaster); sphParticles_.propertyId().updateBoundaries(DataDirection::SlaveToMaster); - + /// lists if(broadSearch) { contactListMangementTimer_.start(); - ppContactList_().beforeBroadSearch(); - pwContactList_().beforeBroadSearch(); + ComputationTimer().start(); + ppContactList_().beforeBroadSearch(); + pwContactList_().beforeBroadSearch(); + ComputationTimer().end(); contactListMangementTimer_.pause(); } - contactListBoundaryTimer_.start(); - for(uint32 i=0; i<6u; i++) + if(broadSearchBoundary) { - auto& BI = boundaryInteraction_[i]; - if(BI.ppPairsAllocated()) BI.ppPairs().beforeBroadSearch(); - if(BI.pwPairsAllocated()) BI.pwPairs().beforeBroadSearch(); + contactListMangementBoundaryTimer_.start(); + ComputationTimer().start(); + + ForAllActiveBoundaries(i, boundaryInteraction_) + //for(size_t i=0; i<6; i++) + { + if(activeBoundaries_[i]) + { + auto& BI = boundaryInteraction_[i]; + BI.ppPairs().beforeBroadSearch(); + BI.pwPairs().beforeBroadSearch(); + } + } + + ComputationTimer().end(); + contactListMangementBoundaryTimer_.pause(); } - contactListBoundaryTimer_.pause(); if( sphParticles_.numActive()<=0)return true; - - if( !contactSearch_().broadSearch( - iter, - t, - dt, + ComputationTimer().start(); + if( !contactSearchRef.broadSearch( + ti, ppContactList_(), pwContactList_()) ) { @@ -205,62 +222,69 @@ bool pFlow::sphereInteraction::iterate() fatalExit; } - boundaryContactSearchTimer_.start(); - for(uint32 i=0; i<6u; i++) + ForAllActiveBoundaries(i, boundaryInteraction_) + //for(size_t i=0; i<6; i++) { - auto& BI =boundaryInteraction_[i]; - if(BI.ppPairsAllocated()) + if(activeBoundaries_[i]) { - if( !contactSearch_().boundaryBroadSearch( + auto& BI = boundaryInteraction_[i]; + if(!contactSearchRef.boundaryBroadSearch( i, - iter, - t, - dt, + ti, BI.ppPairs(), - BI.pwPairs())) + BI.pwPairs()) + ) { fatalErrorInFunction<< "failed to perform broadSearch for boundary index "< requireStep{ - boundaryInteraction_[0].isBoundaryMaster(), - boundaryInteraction_[1].isBoundaryMaster(), - boundaryInteraction_[2].isBoundaryMaster(), - boundaryInteraction_[3].isBoundaryMaster(), - boundaryInteraction_[4].isBoundaryMaster(), - boundaryInteraction_[5].isBoundaryMaster()}; - int step = 1; - const auto& cfModel = this->forceModel_(); - while( std::any_of(requireStep.begin(), requireStep.end(), [](bool v) { return v==true; })) - { - for(uint32 i=0; i<6u; i++) + contactListMangementBoundaryTimer_.resume(); + ComputationTimer().start(); + + ForAllActiveBoundaries(i, boundaryInteraction_) + //for(size_t i=0; i<6; i++) { - if(step==1u || requireStep[i] ) + if(activeBoundaries_[i]) + { + auto& BI = boundaryInteraction_[i]; + BI.ppPairs().afterBroadSearch(); + BI.pwPairs().afterBroadSearch(); + } + } + + ComputationTimer().end(); + contactListMangementBoundaryTimer_.end(); + } + + /// peform contact search on boundareis with active contact search (master boundaries) + auto requireStep = boundariesMask<6>(true); + const auto& cfModel = this->forceModel_(); + uint32 step=1; + boundaryInteractionTimer_.start(); + ComputationTimer().start(); + while(requireStep.anyElement(true) && step <= 10) + { + ForAllBoundaries(i, boundaryInteraction_) + //for(size_t i=0; i<6; i++) + { + if(requireStep[i] ) { requireStep[i] = boundaryInteraction_[i].sphereSphereInteraction( dt, @@ -271,44 +295,47 @@ bool pFlow::sphereInteraction::iterate() } 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(); - std::array requireStep{ - !boundaryInteraction_[0].isBoundaryMaster(), - !boundaryInteraction_[1].isBoundaryMaster(), - !boundaryInteraction_[2].isBoundaryMaster(), - !boundaryInteraction_[3].isBoundaryMaster(), - !boundaryInteraction_[4].isBoundaryMaster(), - !boundaryInteraction_[5].isBoundaryMaster()}; + ComputationTimer().start(); + auto requireStep = boundariesMask<6>(true); - int step = 2; + uint32 step = 11; const auto& cfModel = this->forceModel_(); - while(std::any_of(requireStep.begin(), requireStep.end(), [](bool v) { return v==true; })) + while( requireStep.anyElement(true) && step < 20 ) { - for(uint32 i=0; i<6u; i++) + ForAllBoundaries(i, boundaryInteraction_) + //for(size_t i=0; i<6; i++) { if(requireStep[i]) { requireStep[i] = boundaryInteraction_[i].sphereSphereInteraction( dt, - this->forceModel_(), + cfModel, step ); } } step++; } + ComputationTimer().end(); boundaryInteractionTimer_.end(); } @@ -324,17 +351,18 @@ bool pFlow::sphereInteraction::afterIteration() template class cLT> bool pFlow::sphereInteraction::hearChanges ( - real t, - real dt, - uint32 iter, + const timeInfo& ti, const message& msg, const anyList& varList ) { - if(msg.equivalentTo(message::ITEM_REARRANGE)) + if(msg.equivalentTo(message::ITEMS_REARRANGE)) { notImplementedFunction; + return false; } - return true; -} - + + fatalErrorInFunction<<"Event "<< msg.eventNames()<< + " is not handled in sphereInteraction"< activeBoundaries_; + /// contact search object for pp and pw interactions uniquePtr contactSearch_ = nullptr; @@ -93,14 +98,13 @@ private: /// timer for particle-wall interaction computations Timer pwInteractionTimer_; - /// timer for managing contact lists (only inernal points) - Timer contactListMangementTimer_; - - Timer boundaryContactSearchTimer_; /// timer for boundary interaction time Timer boundaryInteractionTimer_; - Timer contactListBoundaryTimer_; + /// timer for managing contact lists (only inernal points) + Timer contactListMangementTimer_; + + Timer contactListMangementBoundaryTimer_; @@ -110,10 +114,6 @@ private: bool sphereWallInteraction(); - //bool managePPContactLists(); - - //bool managePWContactLists(); - /// range policy for p-p interaction execution using rpPPInteraction = Kokkos::RangePolicy, Kokkos::Schedule>; @@ -152,9 +152,7 @@ public: /// Check for changes in the point structures. (overriden from observer) bool hearChanges( - real t, - real dt, - uint32 iter, + const timeInfo& ti, const message& msg, const anyList& varList)override; diff --git a/src/Interaction/sphereInteraction/sphereInteractionsLinearModels.cpp b/src/Interaction/sphereInteraction/sphereInteractionsLinearModels.cpp index 8c30776f..1c45936b 100644 --- a/src/Interaction/sphereInteraction/sphereInteractionsLinearModels.cpp +++ b/src/Interaction/sphereInteraction/sphereInteractionsLinearModels.cpp @@ -53,6 +53,10 @@ createInteraction(pFlow::cfModels::nonLimitedLinearNormalRolling,pFlow::rotation 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 index b96e5d98..fd277432 100644 --- a/src/Interaction/sphereInteraction/sphereInteractionsNonLinearModModels.cpp +++ b/src/Interaction/sphereInteraction/sphereInteractionsNonLinearModModels.cpp @@ -53,6 +53,10 @@ createInteraction(pFlow::cfModels::nonLimitedNonLinearModNormalRolling,pFlow::ro 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); +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 index 3e8e2707..c13ec77e 100644 --- a/src/Interaction/sphereInteraction/sphereInteractionsNonLinearModels.cpp +++ b/src/Interaction/sphereInteraction/sphereInteractionsNonLinearModels.cpp @@ -53,6 +53,10 @@ createInteraction(pFlow::cfModels::nonLimitedNonLinearNormalRolling,pFlow::rotat 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 b0b084fd..d28af4f5 100644 --- a/src/MotionModel/CMakeLists.txt +++ b/src/MotionModel/CMakeLists.txt @@ -11,8 +11,11 @@ vibratingMotion/vibratingMotion.cpp stationaryWall/stationaryWall.cpp entities/stationary/stationary.cpp -#entities/multiRotatingAxis/multiRotatingAxis.cpp -#multiRotatingAxisMotion/multiRotatingAxisMotion.cpp +conveyorBeltMotion/conveyorBeltMotion.cpp +entities/conveyorBelt/conveyorBelt.cpp + +entities/multiRotatingAxis/multiRotatingAxis.cpp +multiRotatingAxisMotion/multiRotatingAxisMotion.cpp ) diff --git a/src/MotionModel/MotionModel/MotionModel.cpp b/src/MotionModel/MotionModel/MotionModel.cpp index 6a530eaa..426b0218 100644 --- a/src/MotionModel/MotionModel/MotionModel.cpp +++ b/src/MotionModel/MotionModel/MotionModel.cpp @@ -32,7 +32,6 @@ bool pFlow::MotionModel::impl_nameToIndex(const word& name, ui indx = static_cast(i); return true; } - } template 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/eventSubscriber/eventSubscriber.cpp b/src/MotionModel/entities/conveyorBelt/conveyorBelt.cpp similarity index 53% rename from src/phasicFlow/eventSubscriber/eventSubscriber.cpp rename to src/MotionModel/entities/conveyorBelt/conveyorBelt.cpp index 2b187cde..2e63a5a1 100644 --- a/src/phasicFlow/eventSubscriber/eventSubscriber.cpp +++ b/src/MotionModel/entities/conveyorBelt/conveyorBelt.cpp @@ -18,75 +18,53 @@ Licence: -----------------------------------------------------------------------------*/ +#include "conveyorBelt.hpp" +#include "dictionary.hpp" -#include "eventSubscriber.hpp" -#include "Set.hpp" -pFlow::eventSubscriber::~eventSubscriber() +FUNCTION_H +pFlow::conveyorBelt::conveyorBelt(const dictionary& dict) { - for(auto& observer:observerList_) + if(!read(dict)) { - observer->invalidateSubscriber(); + fatalErrorInFunction<< + " error in reading conveyorBelt from dictionary "<< dict.globalName()<("tangentVelocity"); + + return true; +} + +FUNCTION_H +bool pFlow::conveyorBelt::write(dictionary& dict) const { - if(observer) - { - observerList_.push_back(observer); - return true; - } - else + if( !dict.add("tangentVelocity", tangentVelocity_) ) { + fatalErrorInFunction<< + " error in writing tangentVelocity to dictionary "<< dict.globalName()<update(msg) ) return false; - } - + + notImplementedFunction; return true; } -bool pFlow::eventSubscriber::notify -( - const eventMessage& msg, - const List& exclutionList -) +FUNCTION_H +bool pFlow::conveyorBelt::write(iOstream& os)const { - Set sortedExcList(exclutionList.begin(),exclutionList.end()); - - for(auto& observer:observerList_) - { - if( observer && sortedExcList.count(observer) == 0 ) - { - if(!observer->update(msg)) return false; - } - } - - return true; + os.writeWordEntry("tangentVelocity", tangentVelocity_); + return true; } \ No newline at end of file diff --git a/src/MotionModel/entities/conveyorBelt/conveyorBelt.hpp b/src/MotionModel/entities/conveyorBelt/conveyorBelt.hpp new file mode 100644 index 00000000..3cc46de0 --- /dev/null +++ b/src/MotionModel/entities/conveyorBelt/conveyorBelt.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 __conveyorBelt_hpp__ +#define __conveyorBelt_hpp__ + + +#include "types.hpp" +#include "typeInfo.hpp" +#include "streams.hpp" + +namespace pFlow +{ + +// forward +class dictionary; + + +/** + * conveyor belt model for a wall + * + */ +class conveyorBelt +{ +private: + + realx3 tangentVelocity_{0, 0, 0}; + +public: + + TypeInfoNV("conveyorBelt"); + + FUNCTION_HD + conveyorBelt()=default; + + FUNCTION_H + explicit conveyorBelt(const dictionary& dict); + + + 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 + { + return tangentVelocity_; + } + + INLINE_FUNCTION_HD + realx3 transferPoint(const realx3& p, real)const + { + return p; + } + + // - IO operation + FUNCTION_H + bool read(const dictionary& 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; +} + +inline iIstream& operator >>(iIstream& is, conveyorBelt& obj) +{ + + return is; +} + +} + + +#endif diff --git a/src/MotionModel/entities/multiRotatingAxis/multiRotatingAxis.cpp b/src/MotionModel/entities/multiRotatingAxis/multiRotatingAxis.cpp index 62733216..10e70aa7 100644 --- a/src/MotionModel/entities/multiRotatingAxis/multiRotatingAxis.cpp +++ b/src/MotionModel/entities/multiRotatingAxis/multiRotatingAxis.cpp @@ -22,31 +22,32 @@ Licence: #include "multiRotatingAxisMotion.hpp" #include "dictionary.hpp" +/// Construct from dictionary FUNCTION_H -pFlow::multiRotatingAxis::multiRotatingAxis -( - multiRotatingAxisMotion* axisMotion -) -{ - //axisList_ = axisMotion->getAxisListPtr(); -} +pFlow::multiRotatingAxis::multiRotatingAxis(const dictionary& dict) +: + rotatingAxis(dict) +{} + FUNCTION_H pFlow::multiRotatingAxis::multiRotatingAxis ( - multiRotatingAxisMotion* axisMotion, + multiRotatingAxis* axisListPtr, + const wordList& componentsNames, const dictionary& dict ) +: + rotatingAxis(dict), + axisList_(axisListPtr) { - if(!read(axisMotion, dict)) + if(!read(dict, componentsNames)) { fatalErrorInFunction<< " error in reading rotatingAxis from dictionary "<< dict.globalName()<getAxisListPtr(); } @@ -54,22 +55,29 @@ pFlow::multiRotatingAxis::multiRotatingAxis FUNCTION_H bool pFlow::multiRotatingAxis::read ( - multiRotatingAxisMotion* axisMotion, - const dictionary& dict + const dictionary& dict, + const wordList& componentNames ) { - - if(!rotatingAxis::read(dict))return false; word rotAxis = dict.getValOrSet("rotationAxis", "none"); if(rotAxis == "none") { - parentAxisIndex_ = -1; + parentAxisIndex_ = static_cast(-1); } else { - parentAxisIndex_ = axisMotion-> nameToIndex(rotAxis); + if( auto i = componentNames.findi(rotAxis); i != -1 ) + { + parentAxisIndex_ = i; + } + else + { + fatalErrorInFunction<<"crotationAxis "<< rotAxis<<" in dictionary "<< + dict.globalName()<<" is not found in list of axis names "<< componentNames<indexToName(parentAxisIndex_); - dict.add("rotationAxis", rotAxis); + dict.add("rotationAxis", componentNames[parentAxisIndex_]); } return true; } - diff --git a/src/MotionModel/entities/multiRotatingAxis/multiRotatingAxis.hpp b/src/MotionModel/entities/multiRotatingAxis/multiRotatingAxis.hpp index c79e87c8..d39c6dbd 100644 --- a/src/MotionModel/entities/multiRotatingAxis/multiRotatingAxis.hpp +++ b/src/MotionModel/entities/multiRotatingAxis/multiRotatingAxis.hpp @@ -24,7 +24,7 @@ Licence: #include "rotatingAxis.hpp" #include "KokkosTypes.hpp" - +#include "List.hpp" namespace pFlow { @@ -79,26 +79,31 @@ class multiRotatingAxis protected: /// This is device pointer to all axes - multiRotatingAxis* axisList_; + multiRotatingAxis* axisList_ = nullptr; /// Index of parent axis - int32 parentAxisIndex_ = -1; + uint32 parentAxisIndex_ = static_cast(-1); public: + TypeInfoNV("multiRotatingAxis"); + // - Constructors /// Empty Constructor - INLINE_FUNCTION_HD - multiRotatingAxis(){} + FUNCTION_HD + multiRotatingAxis() = default; - /// Empty with list of axes + /// Construct from dictionary FUNCTION_H - multiRotatingAxis(multiRotatingAxisMotion* axisMotion); + explicit multiRotatingAxis(const dictionary& dict); /// Construct from dictionary and list of axes FUNCTION_H - multiRotatingAxis(multiRotatingAxisMotion* axisMotion, const dictionary& dict); + multiRotatingAxis( + multiRotatingAxis* axisListPtr, + const wordList& componentsNames, + const dictionary& dict); /// Copy constructor FUNCTION_HD @@ -123,11 +128,11 @@ public: while(parIndex != -1) { auto& ax = axisList_[parIndex]; - parentVel += ax.linTangentialVelocityPoint(p); + parentVel += ax.linVelocityPoint(p); parIndex = ax.parentAxisIndex(); } - return parentVel + rotatingAxis::linTangentialVelocityPoint(p); + return parentVel + rotatingAxis::linVelocityPoint(p); } /// Translate point p for dt seconds based on the axis information @@ -143,7 +148,7 @@ public: } auto parIndex = parentAxisIndex_; - while(parIndex != -1) + while(parIndex != static_cast(-1)) { auto& ax = axisList_[parIndex]; newP = pFlow::rotate(newP, ax, dt); @@ -157,12 +162,12 @@ public: INLINE_FUNCTION_HD bool hasParent()const { - return parentAxisIndex_ > -1; + return parentAxisIndex_ != static_cast(-1); } /// Return the index of parent axis INLINE_FUNCTION_HD - int32 parentAxisIndex()const + uint32 parentAxisIndex()const { return parentAxisIndex_; } @@ -182,6 +187,7 @@ public: * It is assumed that the axis with deepest level (with more parrents) is * moved first and then the axis with lower levels. */ + INLINE_FUNCTION_HD void move(real dt) { @@ -201,11 +207,12 @@ public: /// Read from dictionary FUNCTION_H - bool read(multiRotatingAxisMotion* axisMotion, const dictionary& dict); + bool read(const dictionary& dict, const wordList& componentNames); /// Write to dictionary FUNCTION_H - bool write(const multiRotatingAxisMotion* axisMotion, dictionary& dict) const; + bool write(dictionary& dict, const wordList& componentNames) const; + }; diff --git a/src/MotionModel/entities/rotatingAxis/rotatingAxis.cpp b/src/MotionModel/entities/rotatingAxis/rotatingAxis.cpp index d5aa3ca2..c7216411 100644 --- a/src/MotionModel/entities/rotatingAxis/rotatingAxis.cpp +++ b/src/MotionModel/entities/rotatingAxis/rotatingAxis.cpp @@ -47,7 +47,7 @@ pFlow::rotatingAxis::rotatingAxis timeInterval(), line(p1, p2), omega_(omega), - rotating_(!equal(omega,0.0)) + rotating_(!equal(omega,static_cast(0.0))) { } @@ -58,7 +58,7 @@ pFlow::real pFlow::rotatingAxis::setOmega(real omega) { auto tmp = omega_; omega_ = omega; - rotating_ = !equal(omega, 0.0); + rotating_ = !equal(omega, static_cast(0.0)); return tmp; } @@ -72,7 +72,7 @@ bool pFlow::rotatingAxis::read if(!timeInterval::read(dict))return false; if(!line::read(dict)) return false; - real omega = dict.getValOrSet("omega", 0.0); + real omega = dict.getValOrSet("omega", static_cast(0.0)); setOmega(omega); return true; diff --git a/src/MotionModel/multiRotatingAxisMotion/multiRotatingAxisMotion.cpp b/src/MotionModel/multiRotatingAxisMotion/multiRotatingAxisMotion.cpp index 360f1ee0..feed07a8 100644 --- a/src/MotionModel/multiRotatingAxisMotion/multiRotatingAxisMotion.cpp +++ b/src/MotionModel/multiRotatingAxisMotion/multiRotatingAxisMotion.cpp @@ -19,40 +19,63 @@ Licence: -----------------------------------------------------------------------------*/ #include "multiRotatingAxisMotion.hpp" -#include "dictionary.hpp" -#include "vocabs.hpp" - -bool pFlow::multiRotatingAxisMotion::readDictionary +void pFlow::multiRotatingAxisMotion::impl_setTime ( - const dictionary& dict -) + uint32 iter, + real t, + real dt +)const { + auto motion = motionComponents_.deviceViewAll(); + Kokkos::parallel_for( + "multiRotatingAxisMotion::impl_setTime", + deviceRPolicyStatic(0, numComponents_), + LAMBDA_D(uint32 i){ + motion[i].setTime(t); + }); + Kokkos::fence(); +} - auto motionModel = dict.getVal("motionModel"); +bool pFlow::multiRotatingAxisMotion::impl_move(uint32 iter, real t , real dt ) const +{ + auto motion = motionComponents_.deviceViewAll(); + Kokkos::parallel_for( + "multiRotatingAxisMotion::impl_move", + deviceRPolicyStatic(0, numComponents_), + LAMBDA_D(uint32 i){ + motion[i].move(dt); + }); + Kokkos::fence(); + return true; +} - if(motionModel != "multiRotatingAxisMotion") +bool pFlow::multiRotatingAxisMotion::impl_readDictionary(const dictionary &dict) +{ + auto modelName = dict.getVal("motionModel"); + + if(modelName != getTypeName()) { fatalErrorInFunction<< - " motionModel should be multiRotatingAxisMotion, but found " - << motionModel <())<< + ", but found "<< Yellow_Text(modelName)<(axDict); axPtr) { - rotationAxis.push_back( + rotationAxisNames.push_back( axDict.getValOrSet("rotationAxis", "none")); } else @@ -63,26 +86,26 @@ bool pFlow::multiRotatingAxisMotion::readDictionary } } - if( !axisNames.search("none") ) + if( !compNames.search("none") ) { - axisNames.push_back("none"); - rotationAxis.push_back("none"); + compNames.push_back("none"); + rotationAxisNames.push_back("none"); } using intPair = std::pair; std::vector numRotAxis; - for(size_t i=0; i< axisNames.size(); i++) + for(size_t i=0; i< compNames.size(); i++) { - word rotAxis = rotationAxis[i]; + word rotAxis = rotationAxisNames[i]; int32 n=0; while(rotAxis != "none") { n++; - if(int32 iAxis = axisNames.findi(rotAxis) ; iAxis != -1) + if(int32 iAxis = compNames.findi(rotAxis) ; iAxis != -1) { - rotAxis = rotationAxis[iAxis]; + rotAxis = rotationAxisNames[iAxis]; }else { fatalErrorInFunction<< @@ -98,60 +121,73 @@ bool pFlow::multiRotatingAxisMotion::readDictionary auto compareFunc = [](const intPair& a, const intPair& b) { return a.first > b.first; }; - algorithms::STD::sort(numRotAxis.data(), numRotAxis.size(), compareFunc); + std::sort(numRotAxis.begin(), numRotAxis.end(), compareFunc); + Vector sortedIndex; + componentNames_.clear(); - sortedIndex_.clear(); - axisName_.clear(); + output< components("Read::modelComponent", + compNames.size()+1, + 0, + RESERVE()); + + + for(auto& compName: componentNames_) { - if(aName != "none") + + if(compName != "none") { - auto& axDict = motionInfo.subDict(aName); - axis_.push_back( - multiRotatingAxis(this, axDict)); + auto& compDict = motionInfo.subDict(compName); + components.emplace_back( + motionComponents_.data(), + componentNames_, + compDict); } else { - axis_.push_back( - multiRotatingAxis(this)); + components.emplace_back(impl_noneComponent()); } } - return true; + motionComponents_.assign(components); + return true; } -bool pFlow::multiRotatingAxisMotion::writeDictionary + +bool pFlow::multiRotatingAxisMotion::impl_writeDictionary ( dictionary& dict )const { - dict.add("motionModel", "multiRotatingAxisMotion"); + word modelName = "multiRotatingAxis"; - auto& motionInfo = dict.subDictOrCreate("multiRotatingAxisMotionInfo"); - - ForAll(i, axis_) + dict.add("motionModel", modelName ); + + auto modelDictName = modelName+"Info"; + + auto& motionInfo = dict.subDictOrCreate(modelDictName); + auto hostComponents = motionComponents_.hostView(); + + ForAll(i, motionComponents_) { - auto& axDict = motionInfo.subDictOrCreate(axisName_[i]); - if( !axis_.hostVectorAll()[i].write(this,axDict)) + auto& axDict = motionInfo.subDictOrCreate(componentNames_[i]); + if( !hostComponents[i].write(axDict, componentNames_)) { fatalErrorInFunction<< - " error in writing axis "<< axisName_[i] << " to dicrionary " + " error in writing axis "<< componentNames_[i] << " to dicrionary " << motionInfo.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].pointTangentialVel(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 axis_[n].transferPoint(p, dt); - } - - INLINE_FUNCTION_HD int32 numComponents()const - { - return numAxis_; - } - }; - protected: - using axisVector_HD = VectorDual; + VectorSingle sortedIndex_; - /// Vector of multiRotaingAxis axes - axisVector_HD axis_; - - /// Sorted index based on number of parrents each axis ha - VectorDual sortedIndex_; + friend MotionModel; - /// List of axes names - wordList axisName_; + /// is the geometry attached to this component moving + bool impl_isMoving()const + { + return true; + } - /// Number of axes - label numAxis_= 0; - /// Read from a dictionary - bool readDictionary(const dictionary& dict); - /// Write to a dictionary - bool writeDictionary(dictionary& dict)const; + /// Read from dictionary + bool impl_readDictionary(const dictionary& dict); + + bool impl_writeDictionary(dictionary& dict)const; public: - /// Type info - TypeInfoNV("multiRotatingAxisMotion"); + TypeInfo("multiRotatingAxisMotion"); - // - Constructor + multiRotatingAxisMotion(const objectFile& objf, repository* owner); - /// Empty constructor - FUNCTION_H - multiRotatingAxisMotion(); + multiRotatingAxisMotion( + const objectFile& objf, + const dictionary& dict, + repository* owner); - /// Construct with dictionary - FUNCTION_H - multiRotatingAxisMotion(const dictionary& dict); + using fileDictionary::write; - /// Copy constructor - FUNCTION_H - multiRotatingAxisMotion(const multiRotatingAxisMotion&) = default; + bool write(iOstream& os, const IOPattern& iop)const override; - /// No Move - multiRotatingAxisMotion(multiRotatingAxisMotion&&) = delete; + static + multiRotatingAxis noneComponent() + { + return multiRotatingAxis(); + } - /// Copy assignment - FUNCTION_H - multiRotatingAxisMotion& operator=(const multiRotatingAxisMotion&) = default; + // TODO: make this method protected + void impl_setTime(uint32 iter, real t, real dt)const; - /// No move assignment - multiRotatingAxisMotion& operator=(multiRotatingAxisMotion&&) = delete; - - /// Destructor - FUNCTION_H - ~multiRotatingAxisMotion() = default; - - // - Methods - - /// Retrun motion model at time t - Model getModel(real t) - { - for(int32 i= 0; isubDictOrCreate("stationaryInfo"); if(!impl_readDictionary(*this) ) { fatalErrorInFunction; @@ -46,6 +46,8 @@ pFlow::stationaryWall::stationaryWall : fileDictionary(objf, dict, owner) { + const auto& dummy = this->subDictOrCreate("stationaryInfo"); + if(!impl_readDictionary(*this) ) { fatalErrorInFunction; diff --git a/src/Particles/CMakeLists.txt b/src/Particles/CMakeLists.txt index 4a11e460..b0728d5a 100644 --- a/src/Particles/CMakeLists.txt +++ b/src/Particles/CMakeLists.txt @@ -6,9 +6,23 @@ particles/shape/shape.cpp particles/particles.cpp particles/particleIdHandler/particleIdHandler.cpp particles/regularParticleIdHandler/regularParticleIdHandler.cpp + +globalDamping/globalDamping.cpp + SphereParticles/sphereShape/sphereShape.cpp SphereParticles/sphereParticles/sphereParticles.cpp SphereParticles/sphereParticles/sphereParticlesKernels.cpp + +GrainParticles/grainShape/grainShape.cpp +GrainParticles/grainParticles/grainParticles.cpp +GrainParticles/grainParticles/grainParticlesKernels.cpp + +SphereParticles/boundarySphereParticles.cpp +SphereParticles/boundarySphereParticlesList.cpp + +GrainParticles/boundaryGrainParticles.cpp +GrainParticles/boundaryGrainParticlesList.cpp + Insertion/collisionCheck/collisionCheck.cpp Insertion/insertionRegion/insertionRegion.cpp Insertion/insertion/insertion.cpp @@ -18,7 +32,8 @@ Insertion/Insertion/Insertions.cpp if(pFlow_Build_MPI) list(APPEND SourceFiles - particles/MPIParticleIdHandler/MPIParticleIdHandler.cpp) + particles/MPIParticleIdHandler/MPIParticleIdHandler.cpp + SphereParticles/processorBoundarySphereParticles.cpp) endif() set(link_libs Kokkos::kokkos phasicFlow Integration Property) diff --git a/src/Particles/GrainParticles/boundaryGrainParticles.cpp b/src/Particles/GrainParticles/boundaryGrainParticles.cpp new file mode 100644 index 00000000..49c8b7b2 --- /dev/null +++ b/src/Particles/GrainParticles/boundaryGrainParticles.cpp @@ -0,0 +1,64 @@ +#include "boundaryGrainParticles.hpp" +#include "boundaryBase.hpp" +#include "grainParticles.hpp" + + +pFlow::boundaryGrainParticles::boundaryGrainParticles( + const boundaryBase &boundary, + grainParticles &prtcls +) +: + generalBoundary(boundary, prtcls.pStruct(), "", ""), + particles_(prtcls) +{ + +} + +pFlow::grainParticles &pFlow::boundaryGrainParticles::Particles() +{ + return particles_; +} + +const pFlow::grainParticles &pFlow::boundaryGrainParticles::Particles() const +{ + return particles_; +} + +pFlow::uniquePtr 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( + const timeInfo& ti, + const message &msg, + const anyList &varList) override + { + return true; + } + + virtual + bool acceleration(const timeInfo& ti, const realx3& g) + { + return true; + } + + bool isActive()const override + { + return false; + } + + 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..f41b96c8 --- /dev/null +++ b/src/Particles/GrainParticles/boundaryGrainParticlesList.cpp @@ -0,0 +1,20 @@ +#include "boundaryGrainParticlesList.hpp" + +pFlow::boundaryGrainParticlesList::boundaryGrainParticlesList( + const boundaryList &bndrs, + grainParticles &prtcls +) +: + boundaryListPtr(), + boundaries_(bndrs) +{ + ForAllBoundariesPtr(i, this) + { + this->set + ( + 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..c1b8baf0 --- /dev/null +++ b/src/Particles/GrainParticles/boundaryGrainParticlesList.hpp @@ -0,0 +1,36 @@ + + +#ifndef __boundaryGrainParticlesList_hpp__ +#define __boundaryGrainParticlesList_hpp__ + +#include "boundaryListPtr.hpp" +#include "boundaryList.hpp" +#include "boundaryGrainParticles.hpp" + +namespace pFlow +{ + +class boundaryGrainParticlesList +: + public boundaryListPtr +{ +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..d4d5bf05 --- /dev/null +++ b/src/Particles/GrainParticles/grainParticles/grainParticles.cpp @@ -0,0 +1,421 @@ +/*------------------------------- 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); + 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() +{ + + const timeInfo ti = TimeInfo(); + const realx3 g = control().g(); + + particles::iterate(); + accelerationTimer_.start(); + pFlow::grainParticlesKernels::acceleration( + g, + mass().deviceViewAll(), + contactForce().deviceViewAll(), + I().deviceViewAll(), + contactTorque().deviceViewAll(), + dynPointStruct().activePointsMaskDevice(), + acceleration().deviceViewAll(), + rAcceleration().deviceViewAll() + ); + + ForAllActiveBoundaries(i,boundaryGrainParticles_) + { + boundaryGrainParticles_[i].acceleration(ti, g); + } + accelerationTimer_.end(); + + intCorrectTimer_.start(); + + if(!dynPointStruct().correct(ti.dt())) + { + return false; + } + real damping = dynPointStruct().dampingFactor(ti); + if(!rVelIntegration_().correct( + ti.dt(), + rVelocity_, + rAcceleration_, + damping)) + { + 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..3c7c1efe --- /dev/null +++ b/src/Particles/GrainParticles/grainParticles/grainParticles.hpp @@ -0,0 +1,247 @@ +/*------------------------------- 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 + const 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 grainShape& gShape); + + ~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( + const timeInfo& ti, + 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..246b5be8 --- /dev/null +++ b/src/Particles/GrainParticles/grainShape/grainShape.cpp @@ -0,0 +1,261 @@ +/*------------------------------- 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( + const word& shapeType, + const word& fileName, + repository* owner, + const property& prop); + + + ~grainShape() override = default; + + add_vCtor + ( + shape, + grainShape, + word + ); + //// - 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; + + realVector volume()const override; + + real coarseGrainFactor(uint32 index)const ; + + realVector coarseGrainFactor()const ; + + real originalDiameter(uint32 index)const ; + + realVector originalDiameter()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/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/insertion/insertion.cpp b/src/Particles/Insertion/insertion/insertion.cpp index bb551a47..8514a99c 100644 --- a/src/Particles/Insertion/insertion/insertion.cpp +++ b/src/Particles/Insertion/insertion/insertion.cpp @@ -81,7 +81,7 @@ pFlow::insertion::readInsertionDict() if (active_) { - checkForCollision_ = getVal("checkForCollision"); + //checkForCollision_ = getVal("checkForCollision"); REPORT(1) << "Particle insertion mechanism is " << Yellow_Text("active") << " in the simulation." << END_REPORT; diff --git a/src/Particles/Insertion/insertion/insertion.hpp b/src/Particles/Insertion/insertion/insertion.hpp index f39f5c35..0c3ee885 100644 --- a/src/Particles/Insertion/insertion/insertion.hpp +++ b/src/Particles/Insertion/insertion/insertion.hpp @@ -42,7 +42,7 @@ private: Logical active_ = "No"; /// Check for collision? It is not active now - Logical checkForCollision_ = "No"; + Logical checkForCollision_ = "Yes"; /// if increase velocity in case particles are failed /// to be inserted due to collision diff --git a/src/Particles/Insertion/insertionRegion/insertionRegion.cpp b/src/Particles/Insertion/insertionRegion/insertionRegion.cpp index 710f28e6..95e311b5 100644 --- a/src/Particles/Insertion/insertionRegion/insertionRegion.cpp +++ b/src/Particles/Insertion/insertionRegion/insertionRegion.cpp @@ -24,6 +24,7 @@ Licence: #include "particles.hpp" #include "twoPartEntry.hpp" #include "types.hpp" +#include "shape.hpp" namespace pFlow { diff --git a/src/Particles/Insertion/insertionRegion/insertionRegion.hpp b/src/Particles/Insertion/insertionRegion/insertionRegion.hpp index 9b4a73db..d6588edd 100644 --- a/src/Particles/Insertion/insertionRegion/insertionRegion.hpp +++ b/src/Particles/Insertion/insertionRegion/insertionRegion.hpp @@ -173,7 +173,7 @@ public: inline bool insertionTime(uint32 iter, real t, real dt) const { - return tControl_.timeEvent(iter, t, dt); + return tControl_.eventTime(iter, t, dt); } uint32 numberToBeInserted(uint32 iter, real t, real dt); diff --git a/src/Particles/SphereParticles/boundarySphereParticles.hpp b/src/Particles/SphereParticles/boundarySphereParticles.hpp index f4662307..b49aa393 100644 --- a/src/Particles/SphereParticles/boundarySphereParticles.hpp +++ b/src/Particles/SphereParticles/boundarySphereParticles.hpp @@ -50,9 +50,7 @@ public: const sphereParticles& Particles()const; bool hearChanges( - real t, - real dt, - uint32 iter, + const timeInfo& ti, const message &msg, const anyList &varList) override { @@ -65,6 +63,11 @@ public: return true; } + bool isActive()const override + { + return false; + } + static uniquePtr create( const boundaryBase &boundary, diff --git a/src/Particles/SphereParticles/boundarySphereParticlesList.cpp b/src/Particles/SphereParticles/boundarySphereParticlesList.cpp index 5cbebc32..cd6618b3 100644 --- a/src/Particles/SphereParticles/boundarySphereParticlesList.cpp +++ b/src/Particles/SphereParticles/boundarySphereParticlesList.cpp @@ -5,10 +5,10 @@ pFlow::boundarySphereParticlesList::boundarySphereParticlesList( sphereParticles &prtcls ) : - ListPtr(bndrs.size()), + boundaryListPtr(), boundaries_(bndrs) { - for(auto i=0; iset ( diff --git a/src/Particles/SphereParticles/boundarySphereParticlesList.hpp b/src/Particles/SphereParticles/boundarySphereParticlesList.hpp index cd6770df..ddba226f 100644 --- a/src/Particles/SphereParticles/boundarySphereParticlesList.hpp +++ b/src/Particles/SphereParticles/boundarySphereParticlesList.hpp @@ -3,7 +3,7 @@ #ifndef __boundarySphereParticlesList_hpp__ #define __boundarySphereParticlesList_hpp__ -#include "ListPtr.hpp" +#include "boundaryListPtr.hpp" #include "boundaryList.hpp" #include "boundarySphereParticles.hpp" @@ -12,7 +12,7 @@ namespace pFlow class boundarySphereParticlesList : - public ListPtr + public boundaryListPtr { private: diff --git a/src/Particles/SphereParticles/sphereParticles/sphereParticles.cpp b/src/Particles/SphereParticles/sphereParticles/sphereParticles.cpp index df7b98b8..ffb73e3c 100644 --- a/src/Particles/SphereParticles/sphereParticles/sphereParticles.cpp +++ b/src/Particles/SphereParticles/sphereParticles/sphereParticles.cpp @@ -24,180 +24,6 @@ Licence: #include "sphereParticlesKernels.hpp" -//#include "setFieldList.hpp" -/*pFlow::uniquePtr> -pFlow::sphereParticles::getFieldObjectList()const -{ - auto objListPtr = particles::getFieldObjectList(); - - objListPtr().push_back( - static_cast(&I_) ); - - return objListPtr; -} - -bool pFlow::sphereParticles::diameterMassInertiaPropId -( - const word& shName, - real& diam, - real& mass, - real& I, - int8& propIdx -) -{ - uint32 idx; - if( !shapes_.nameToIndex(shName, idx) ) - { - printKeys(fatalErrorInFunction<< - " wrong shape name in the input: "<< shName<(pIdx); - return true; -} - -bool pFlow::sphereParticles::initializeParticles() -{ - - int32IndexContainer indices( - 0, - static_cast(shapeName_.size())); - - return insertSphereParticles(shapeName_, indices, false); -}*/ - - -/*bool pFlow::sphereParticles::beforeIteration() -{ - particles::beforeIteration(); - - intPredictTimer_.start(); - - //INFO<<"before dyn predict"<dt(), accelertion_); - //INFO<<"after dyn predict"<dt(),rVelocity_, rAcceleration_); - //INFO<<"after rvel predict"<timers() ), intPredictTimer_( @@ -403,7 +229,8 @@ pFlow::sphereParticles::sphereParticles( "rVelocity", dynPointStruct(), intMethod, - rVelocity_.field() + rAcceleration_.field(), + control.keepIntegrationHistory() ); if( !rVelIntegration_ ) @@ -413,8 +240,6 @@ pFlow::sphereParticles::sphereParticles( fatalExit; } - WARNING<<"setFields for rVelIntegration_"<needSetInitialVals()) - { - - - auto indexHD = pStruct().insertedPointIndex(); - - auto n = indexHD.size(); - auto index = indexHD.indicesHost(); - - realx3Vector rvel(n,RESERVE()); - const auto hrVel = rVelocity_.hostView(); - - for(auto i=0; isetInitialVals(indexHD, rvel); - - } - - return true; -}*/ - -/*bool pFlow::sphereParticles::insertParticles -( - const realx3Vector& position, - const wordVector& shapes, - const setFieldList& setField - ) -{ - - if( position.size() != shapes.size() ) - { - fatalErrorInFunction<< - " size of vectors position ("<activeRange(); - - REPORT(1)<< "Active range is "<numActive())<< - " and pointStructure capacity is "<capacity())<dt(); - dynPointStruct().predict(dt, accelertion()); + dynPointStruct().predict(dt); rVelIntegration_().predict(dt,rVelocity_, rAcceleration_); intPredictTimer_.end(); @@ -523,6 +264,7 @@ bool pFlow::sphereParticles::beforeIteration() I_.updateBoundariesSlaveToMasterIfRequested(); rVelocity_.updateBoundariesSlaveToMasterIfRequested(); rAcceleration_.updateBoundariesSlaveToMasterIfRequested(); + rVelIntegration_().updateBoundariesSlaveToMasterIfRequested(); fieldUpdateTimer_.end(); return true; @@ -531,30 +273,40 @@ bool pFlow::sphereParticles::beforeIteration() bool pFlow::sphereParticles::iterate() { + const timeInfo ti = TimeInfo(); + const realx3 g = control().g(); + particles::iterate(); accelerationTimer_.start(); pFlow::sphereParticlesKernels::acceleration( - control().g(), + g, mass().deviceViewAll(), contactForce().deviceViewAll(), I().deviceViewAll(), contactTorque().deviceViewAll(), dynPointStruct().activePointsMaskDevice(), - accelertion().deviceViewAll(), + acceleration().deviceViewAll(), rAcceleration().deviceViewAll() ); + ForAllActiveBoundaries(i,boundarySphereParticles_) + { + boundarySphereParticles_[i].acceleration(ti, g); + } + accelerationTimer_.end(); intCorrectTimer_.start(); - if(!dynPointStruct().correct(dt(), accelertion())) + if(!dynPointStruct().correct(ti.dt())) { return false; } + real damping = dynPointStruct().dampingFactor(ti); if(!rVelIntegration_().correct( - dt(), + ti.dt(), rVelocity_, - rAcceleration_)) + rAcceleration_, + damping)) { return false; } diff --git a/src/Particles/SphereParticles/sphereParticles/sphereParticles.hpp b/src/Particles/SphereParticles/sphereParticles/sphereParticles.hpp index d71e751a..5f2eac52 100644 --- a/src/Particles/SphereParticles/sphereParticles/sphereParticles.hpp +++ b/src/Particles/SphereParticles/sphereParticles/sphereParticles.hpp @@ -33,6 +33,7 @@ Licence: #include "particles.hpp" #include "property.hpp" #include "sphereShape.hpp" +#include "boundarySphereParticlesList.hpp" #include "systemControl.hpp" namespace pFlow @@ -47,7 +48,7 @@ public: private: /// reference to shapes - ShapeType spheres_; + const ShapeType& spheres_; /// property id on device uint32PointField_D propertyId_; @@ -67,6 +68,9 @@ private: /// pointField of rotational acceleration of particles on device realx3PointField_D rAcceleration_; + /// boundaries + boundarySphereParticlesList boundarySphereParticles_; + /// rotational velocity integrator uniquePtr rVelIntegration_ = nullptr; @@ -101,11 +105,26 @@ private: 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(systemControl& control, const sphereShape& shpShape); ~sphereParticles() override = default; @@ -156,9 +175,7 @@ public: } bool hearChanges( - real t, - real dt, - uint32 iter, + const timeInfo& ti, const message& msg, const anyList& varList ) override diff --git a/src/Particles/SphereParticles/sphereShape/sphereShape.cpp b/src/Particles/SphereParticles/sphereShape/sphereShape.cpp index fac52d3c..8a5b478a 100644 --- a/src/Particles/SphereParticles/sphereShape/sphereShape.cpp +++ b/src/Particles/SphereParticles/sphereShape/sphereShape.cpp @@ -68,6 +68,18 @@ pFlow::sphereShape::sphereShape } } +pFlow::sphereShape::sphereShape +( + const word &shapeType, + const word &fileName, + repository *owner, + const property &prop +) +: + sphereShape(fileName, owner, prop) +{ +} + pFlow::real pFlow::sphereShape::maxBoundingSphere() const { return max(diameters_); @@ -105,6 +117,11 @@ pFlow::realVector pFlow::sphereShape::boundingDiameter() const return diameters_; } +pFlow::realVector pFlow::sphereShape::volume() const +{ + return realVector("volume", Pi/6*pow(diameters_,(real)3.0)); +} + bool pFlow::sphereShape::mass(uint32 index, real &m) const { if( indexValid(index) ) diff --git a/src/Particles/SphereParticles/sphereShape/sphereShape.hpp b/src/Particles/SphereParticles/sphereShape/sphereShape.hpp index b59625ce..10f308a1 100644 --- a/src/Particles/SphereParticles/sphereShape/sphereShape.hpp +++ b/src/Particles/SphereParticles/sphereShape/sphereShape.hpp @@ -51,9 +51,22 @@ public: repository* owner, const property& prop); + sphereShape( + const word& shapeType, + const word& fileName, + repository* owner, + const property& prop); + ~sphereShape() override = default; + add_vCtor + ( + shape, + sphereShape, + word + ); + //// - Methods real maxBoundingSphere()const override; @@ -66,6 +79,8 @@ public: realVector boundingDiameter()const override; + realVector volume()const override; + bool mass(uint32 index, real& m)const override; real mass(uint32 index) const override; diff --git a/src/Particles/dynamicPointStructure/dynamicPointStructure.cpp b/src/Particles/dynamicPointStructure/dynamicPointStructure.cpp index 6ad16556..cdc8472a 100644 --- a/src/Particles/dynamicPointStructure/dynamicPointStructure.cpp +++ b/src/Particles/dynamicPointStructure/dynamicPointStructure.cpp @@ -21,12 +21,14 @@ Licence: #include "dynamicPointStructure.hpp" #include "systemControl.hpp" + pFlow::dynamicPointStructure::dynamicPointStructure ( - systemControl& control + systemControl& control, + real maxBSphere ) : - pointStructure(control), + pointStructure(control, maxBSphere), velocity_ ( objectFile( @@ -38,6 +40,16 @@ pFlow::dynamicPointStructure::dynamicPointStructure *this, zero3 ), + acceleration_( + objectFile( + "acceleration", + "", + objectFile::READ_IF_PRESENT, + objectFile::WRITE_ALWAYS + ), + *this, + zero3 + ), velocityUpdateTimer_("velocity boundary update", &timers()), integrationMethod_ ( @@ -46,13 +58,14 @@ pFlow::dynamicPointStructure::dynamicPointStructure { REPORT(1)<< "Creating integration method "<< Green_Text(integrationMethod_)<<" for dynamicPointStructure."<(control); + } } @@ -85,6 +104,9 @@ bool pFlow::dynamicPointStructure::beforeIteration() if(!pointStructure::beforeIteration())return false; velocityUpdateTimer_.start(); velocity_.updateBoundariesSlaveToMasterIfRequested(); + acceleration_.updateBoundariesSlaveToMasterIfRequested(); + integrationPos_->updateBoundariesSlaveToMasterIfRequested(); + integrationVel_->updateBoundariesSlaveToMasterIfRequested(); velocityUpdateTimer_.end(); return true; } @@ -93,34 +115,32 @@ 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) +bool pFlow::dynamicPointStructure::afterIteration() { - + //const auto ti = TimeInfo(); + + auto succs = pointStructure::afterIteration(); + + return succs; +} + +bool pFlow::dynamicPointStructure::predict(real dt) +{ + if(!integrationPos_().predict(dt, pointPosition(), velocity_ ))return false; - if(!integrationVel_().predict(dt, velocity_, acceleration))return false; + if(!integrationVel_().predict(dt, velocity_, acceleration_))return false; return true; } -bool pFlow::dynamicPointStructure::correct -( - real dt, - realx3PointField_D& acceleration -) +bool pFlow::dynamicPointStructure::correct(real dt) { - //auto& pos = pStruct().pointPosition(); + const auto& ti = TimeInfo(); - if(!integrationPos_().correct(dt, pointPosition(), velocity_) )return false; - - if(!integrationVel_().correct(dt, velocity_, acceleration))return false; + if(!integrationPos_().correctPStruct(dt, *this, velocity_) )return false; + if(!integrationVel_().correct(dt, velocity_, acceleration_, dampingFactor(ti)))return false; return true; } diff --git a/src/Particles/dynamicPointStructure/dynamicPointStructure.hpp b/src/Particles/dynamicPointStructure/dynamicPointStructure.hpp index f82f1dca..2208ca35 100644 --- a/src/Particles/dynamicPointStructure/dynamicPointStructure.hpp +++ b/src/Particles/dynamicPointStructure/dynamicPointStructure.hpp @@ -26,11 +26,13 @@ Licence: #include "pointFields.hpp" #include "integration.hpp" #include "uniquePtr.hpp" +#include "globalDamping.hpp" namespace pFlow { class systemControl; +//class globalDamping; class dynamicPointStructure : @@ -40,10 +42,15 @@ private: realx3PointField_D velocity_; + /// acceleration on device + realx3PointField_D acceleration_; + uniquePtr integrationPos_ = nullptr; uniquePtr integrationVel_ = nullptr; + uniquePtr velDamping_ = nullptr; + Timer velocityUpdateTimer_; /// @brief integration method for velocity and position @@ -53,7 +60,7 @@ public: TypeInfo("dynamicPointStructure"); - explicit dynamicPointStructure(systemControl& control); + explicit dynamicPointStructure(systemControl& control, real maxBSphere); dynamicPointStructure(const dynamicPointStructure& ps) = delete; @@ -82,18 +89,42 @@ public: return velocity_; } + inline + const realx3PointField_D& acceleration()const + { + return acceleration_; + } + + inline + realx3PointField_D& acceleration() + { + return acceleration_; + } + + inline + real dampingFactor(const timeInfo& ti)const + { + if(velDamping_) + { + return velDamping_().dampingFactor(ti); + } + return 1.0; + } + /// 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; + + bool afterIteration()override; /// prediction step (if any), is called in beforeIteration - bool predict(real dt, realx3PointField_D& acceleration); + bool predict(real dt); /// correction step, is called in iterate - bool correct(real dt, realx3PointField_D& acceleration); + bool correct(real dt); }; diff --git a/src/Particles/globalDamping/globalDamping.cpp b/src/Particles/globalDamping/globalDamping.cpp new file mode 100644 index 00000000..040030cc --- /dev/null +++ b/src/Particles/globalDamping/globalDamping.cpp @@ -0,0 +1,54 @@ +/*------------------------------- 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 "globalDamping.hpp" + + +pFlow::globalDamping::globalDamping(const systemControl& control) +: + timeControl_(control.settingsDict().subDict("globalDamping"), control.time().dt(), "damping") +{ + const dictionary& dict = control.settingsDict().subDict("globalDamping"); + + dampingFactor_ = dict.getValMin("dampingFactor", static_cast(1.0)); + + dampingFactor_ = max( dampingFactor_ , static_cast(0.01)); + + performDamping_ = !equal(dampingFactor_, static_cast(1.0)); + + if( performDamping_ ) + { + REPORT(2)<<"Global damping "<; -using int16Vector_HD = VectorDual; +class globalDamping +{ +private: -using int32Vector_HD = VectorDual; + bool performDamping_ = false; -using int64Vector_HD = VectorDual; + real dampingFactor_; -using uint32Vector_HD = VectorDual; + baseTimeControl timeControl_; -using labelVector_HD = VectorDual