diff --git a/.github/scripts/sync-wiki.py b/.github/scripts/sync-wiki.py
new file mode 100755
index 00000000..fe8a239e
--- /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, ".github/workflows/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/markdownList.yml b/.github/workflows/markdownList.yml
new file mode 100644
index 00000000..68b92ed5
--- /dev/null
+++ b/.github/workflows/markdownList.yml
@@ -0,0 +1,18 @@
+# This file maps source markdown files to their target wiki pages
+# format:
+# - source: path/to/markdown/file.md
+# target: Wiki-Page-Name
+mappings:
+ - source: benchmarks/readme.md
+ target: Performance-of-phasicFlow
+ - source: benchmarks/helicalMixer/readme.md
+ target: Helical-Mixer-Benchmark
+ - source: benchmarks/rotatingDrum/readme.md
+ target: Rotating-Drum-Benchmark
+ - source: doc/mdDocs/howToBuild-V1.0.md
+ target: How-to-build-PhasicFlow‐v‐1.0
+ - source: tutorials/README.md
+ target: Tutorials
+ - source: doc/mdDocs/phasicFlowFeatures.md
+ target: Features-of-PhasicFlow
+ # Add more mappings as needed
\ No newline at end of file
diff --git a/.github/workflows/sync-wiki.yml b/.github/workflows/sync-wiki.yml
new file mode 100644
index 00000000..f55d4c3c
--- /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"
+ - ".github/workflows/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 5bdcde81..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 Release 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} ./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,6 +55,7 @@ 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}")
diff --git a/DEMSystems/DEMSystem/DEMSystem.hpp b/DEMSystems/DEMSystem/DEMSystem.hpp
index 23814d3e..424af8ae 100644
--- a/DEMSystems/DEMSystem/DEMSystem.hpp
+++ b/DEMSystems/DEMSystem/DEMSystem.hpp
@@ -183,4 +183,4 @@ public:
} // pFlow
-#endif // __DEMSystem_hpp__
\ No newline at end of file
+#endif // __DEMSystem_hpp__
diff --git a/README.md b/README.md
index e1281936..ff041c6b 100644
--- a/README.md
+++ b/README.md
@@ -1,48 +1,76 @@
-
-

+
+
+## **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/tutorials/sphereGranFlow/toteblender/caseSetup/particleInsertion b/benchmarks/rotatingDrum/rotatingDrum_1mParticles/caseSetup/shapes
similarity index 62%
rename from tutorials/sphereGranFlow/toteblender/caseSetup/particleInsertion
rename to benchmarks/rotatingDrum/rotatingDrum_1mParticles/caseSetup/shapes
index cabe23da..c2302c64 100644
--- a/tutorials/sphereGranFlow/toteblender/caseSetup/particleInsertion
+++ b/benchmarks/rotatingDrum/rotatingDrum_1mParticles/caseSetup/shapes
@@ -2,12 +2,14 @@
| phasicFlow File |
| copyright: www.cemf.ir |
\* ------------------------------------------------------------------------- */
-objectName particleInsertion;
-objectType dicrionary;
-fileFormat ASCII;
+
+objectName shapes;
+objectType dictionary;
+fileFormat ASCII;
/*---------------------------------------------------------------------------*/
-active No; // is insertion active -> Yes or No
-collisionCheck No; // is checked -> Yes or No
+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/tutorials/sphereGranFlow/rotatingDrumSmall/caseSetup/particleInsertion b/benchmarks/rotatingDrum/rotatingDrum_250kParticles/caseSetup/shapes
old mode 100755
new mode 100644
similarity index 62%
rename from tutorials/sphereGranFlow/rotatingDrumSmall/caseSetup/particleInsertion
rename to benchmarks/rotatingDrum/rotatingDrum_250kParticles/caseSetup/shapes
index cabe23da..b8aadc13
--- a/tutorials/sphereGranFlow/rotatingDrumSmall/caseSetup/particleInsertion
+++ b/benchmarks/rotatingDrum/rotatingDrum_250kParticles/caseSetup/shapes
@@ -2,12 +2,14 @@
| phasicFlow File |
| copyright: www.cemf.ir |
\* ------------------------------------------------------------------------- */
-objectName particleInsertion;
-objectType dicrionary;
-fileFormat ASCII;
+
+objectName shapes;
+objectType dictionary;
+fileFormat ASCII;
/*---------------------------------------------------------------------------*/
-active No; // is insertion active -> Yes or No
-collisionCheck No; // is checked -> Yes or No
+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/tutorials/sphereGranFlow/rotatingDrumSmall/caseSetup/sphereShape b/benchmarks/rotatingDrum/rotatingDrum_2mParticles/caseSetup/shapes
old mode 100755
new mode 100644
similarity index 62%
rename from tutorials/sphereGranFlow/rotatingDrumSmall/caseSetup/sphereShape
rename to benchmarks/rotatingDrum/rotatingDrum_2mParticles/caseSetup/shapes
index 7a87b7ad..d08fdf86
--- a/tutorials/sphereGranFlow/rotatingDrumSmall/caseSetup/sphereShape
+++ b/benchmarks/rotatingDrum/rotatingDrum_2mParticles/caseSetup/shapes
@@ -2,11 +2,14 @@
| phasicFlow File |
| copyright: www.cemf.ir |
\* ------------------------------------------------------------------------- */
-objectName sphereDict;
-objectType sphereShape;
-fileFormat ASCII;
+
+objectName shapes;
+objectType dictionary;
+fileFormat ASCII;
/*---------------------------------------------------------------------------*/
-names (sphere1); // names of shapes
-diameters (0.004); // diameter of shapes
-materials (prop1); // material names for shapes
+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
index 6c289ce5..babf3843 100644
--- a/cmake/autoComplete
+++ b/cmake/autoComplete
@@ -1,48 +1,89 @@
PF_cFlags="--description --help --version"
AllTimeFolders=
__getAllTime(){
- files=( $(ls) )
- deleteFiles=(settings caseSetup cleanThisCase VTK runThisCase stl postprocess postProcess)
- declare -A delk
- for del in "${deleteFiles[@]}" ; do delk[$del]=1 ; done
- # Tag items to remove, based on
- for k in "${!files[@]}" ; do
- [ "${delk[${files[$k]}]-}" ] && unset 'files[k]'
- done
- # Compaction
- COMPREPLY=("${files[@]}")
- AllTimeFolders="${files[@]}"
+ # 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=()
+ __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
- # Check if the directory exists
- if [ ! -d "$dir" ]; then
- continue # Skip to the next directory
- fi
-
- files_in_dir=$(find "$dir" -maxdepth 1 -type f -printf '%f\n' | sort -u)
-
- # Add filenames to the associative array (duplicates will be overwritten)
- while IFS= read -r filename; do
- unique_files["$filename"]=1 # Just the key is important, value can be anything
- done <<< "$files_in_dir"
-
- done
- COMPREPLY=("${!unique_files[@]}")
- AllTimeFolders=
+ 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(){
- if [ "$3" == "--time" ] ; then
+ 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
bool pFlow::geometryMotion::findMotionIndex()
{
-
if(motionComponentName().size() != numSurfaces() )
{
fatalErrorInFunction<<
diff --git a/src/Geometry/geometryMotion/geometryMotions.cpp b/src/Geometry/geometryMotion/geometryMotions.cpp
index 6cdb4a3b..8636c1f7 100644
--- a/src/Geometry/geometryMotion/geometryMotions.cpp
+++ b/src/Geometry/geometryMotion/geometryMotions.cpp
@@ -28,4 +28,4 @@ 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 3b0a2867..4a916b6e 100644
--- a/src/Geometry/geometryMotion/geometryMotions.hpp
+++ b/src/Geometry/geometryMotion/geometryMotions.hpp
@@ -25,7 +25,7 @@ Licence:
#include "stationaryWall.hpp"
#include "rotatingAxisMotion.hpp"
#include "conveyorBeltMotion.hpp"
-//#include "multiRotatingAxisMotion.hpp"
+#include "multiRotatingAxisMotion.hpp"
#include "vibratingMotion.hpp"
@@ -40,10 +40,7 @@ using stationaryGeometry = geometryMotion;
using conveyorBeltMotionGeometry = geometryMotion;
-//typedef geometryMotion multiRotationAxisMotionGeometry;
-
-
-
+using multiRotationAxisMotionGeometry = geometryMotion;
}
diff --git a/src/Integration/AdamsBashforth2/AdamsBashforth2.cpp b/src/Integration/AdamsBashforth2/AdamsBashforth2.cpp
index 0eaa4bdb..9f457fe8 100644
--- a/src/Integration/AdamsBashforth2/AdamsBashforth2.cpp
+++ b/src/Integration/AdamsBashforth2/AdamsBashforth2.cpp
@@ -97,10 +97,11 @@ 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,7 +109,7 @@ 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,
diff --git a/src/Integration/AdamsBashforth2/AdamsBashforth2.hpp b/src/Integration/AdamsBashforth2/AdamsBashforth2.hpp
index a8218465..0241bb8e 100644
--- a/src/Integration/AdamsBashforth2/AdamsBashforth2.hpp
+++ b/src/Integration/AdamsBashforth2/AdamsBashforth2.hpp
@@ -81,7 +81,8 @@ public:
const word& baseName,
pointStructure& pStruct,
const word& method,
- const realx3Field_D& initialValField);
+ const realx3Field_D& initialValField,
+ bool keepHistory);
/// Destructor
~AdamsBashforth2()override = default;
diff --git a/src/Integration/AdamsBashforth3/AdamsBashforth3.cpp b/src/Integration/AdamsBashforth3/AdamsBashforth3.cpp
index e728e533..c15b5ff2 100644
--- a/src/Integration/AdamsBashforth3/AdamsBashforth3.cpp
+++ b/src/Integration/AdamsBashforth3/AdamsBashforth3.cpp
@@ -109,10 +109,11 @@ pFlow::AdamsBashforth3::AdamsBashforth3
const word& baseName,
pointStructure& pStruct,
const word& method,
- const realx3Field_D& initialValField
+ const realx3Field_D& initialValField,
+ bool keepHistory
)
:
- AdamsBashforth2(baseName, pStruct, method, initialValField),
+ AdamsBashforth2(baseName, pStruct, method, initialValField, keepHistory),
dy2_
(
objectFile
@@ -120,7 +121,7 @@ pFlow::AdamsBashforth3::AdamsBashforth3
groupNames(baseName,"dy2"),
pStruct.time().integrationFolder(),
objectFile::READ_IF_PRESENT,
- objectFile::WRITE_ALWAYS
+ keepHistory ? objectFile::WRITE_ALWAYS : objectFile::WRITE_NEVER
),
pStruct,
zero3,
diff --git a/src/Integration/AdamsBashforth3/AdamsBashforth3.hpp b/src/Integration/AdamsBashforth3/AdamsBashforth3.hpp
index e71166ae..50a23c39 100644
--- a/src/Integration/AdamsBashforth3/AdamsBashforth3.hpp
+++ b/src/Integration/AdamsBashforth3/AdamsBashforth3.hpp
@@ -71,7 +71,8 @@ public:
const word& baseName,
pointStructure& pStruct,
const word& method,
- const realx3Field_D& initialValField);
+ const realx3Field_D& initialValField,
+ bool keepHistory);
/// Destructor
diff --git a/src/Integration/AdamsBashforth4/AdamsBashforth4.cpp b/src/Integration/AdamsBashforth4/AdamsBashforth4.cpp
index a0d5c4a1..24461282 100644
--- a/src/Integration/AdamsBashforth4/AdamsBashforth4.cpp
+++ b/src/Integration/AdamsBashforth4/AdamsBashforth4.cpp
@@ -115,10 +115,11 @@ pFlow::AdamsBashforth4::AdamsBashforth4
const word& baseName,
pointStructure& pStruct,
const word& method,
- const realx3Field_D& initialValField
+ const realx3Field_D& initialValField,
+ bool keepHistory
)
:
- AdamsBashforth3(baseName, pStruct, method, initialValField),
+ AdamsBashforth3(baseName, pStruct, method, initialValField, keepHistory),
dy3_
(
objectFile
@@ -126,7 +127,7 @@ pFlow::AdamsBashforth4::AdamsBashforth4
groupNames(baseName,"dy3"),
pStruct.time().integrationFolder(),
objectFile::READ_IF_PRESENT,
- objectFile::WRITE_ALWAYS
+ keepHistory?objectFile::WRITE_ALWAYS:objectFile::WRITE_NEVER
),
pStruct,
zero3,
diff --git a/src/Integration/AdamsBashforth4/AdamsBashforth4.hpp b/src/Integration/AdamsBashforth4/AdamsBashforth4.hpp
index fc2b913b..a9bb9a43 100644
--- a/src/Integration/AdamsBashforth4/AdamsBashforth4.hpp
+++ b/src/Integration/AdamsBashforth4/AdamsBashforth4.hpp
@@ -69,7 +69,8 @@ public:
const word& baseName,
pointStructure& pStruct,
const word& method,
- const realx3Field_D& initialValField);
+ const realx3Field_D& initialValField,
+ bool keepHistory);
diff --git a/src/Integration/AdamsBashforth5/AdamsBashforth5.cpp b/src/Integration/AdamsBashforth5/AdamsBashforth5.cpp
index 3fde7276..dd1503e2 100644
--- a/src/Integration/AdamsBashforth5/AdamsBashforth5.cpp
+++ b/src/Integration/AdamsBashforth5/AdamsBashforth5.cpp
@@ -123,10 +123,11 @@ pFlow::AdamsBashforth5::AdamsBashforth5
const word &baseName,
pointStructure &pStruct,
const word &method,
- const realx3Field_D &initialValField
+ const realx3Field_D &initialValField,
+ bool keepHistory
)
:
- AdamsBashforth4(baseName, pStruct, method, initialValField),
+ AdamsBashforth4(baseName, pStruct, method, initialValField, keepHistory),
dy4_
(
objectFile
@@ -134,7 +135,7 @@ pFlow::AdamsBashforth5::AdamsBashforth5
groupNames(baseName,"dy4"),
pStruct.time().integrationFolder(),
objectFile::READ_IF_PRESENT,
- objectFile::WRITE_ALWAYS
+ keepHistory?objectFile::WRITE_ALWAYS:objectFile::WRITE_NEVER
),
pStruct,
zero3,
diff --git a/src/Integration/AdamsBashforth5/AdamsBashforth5.hpp b/src/Integration/AdamsBashforth5/AdamsBashforth5.hpp
index ed16d99c..939f96a3 100644
--- a/src/Integration/AdamsBashforth5/AdamsBashforth5.hpp
+++ b/src/Integration/AdamsBashforth5/AdamsBashforth5.hpp
@@ -68,7 +68,8 @@ public:
const word& baseName,
pointStructure& pStruct,
const word& method,
- const realx3Field_D& initialValField);
+ const realx3Field_D& initialValField,
+ bool keepHistory);
diff --git a/src/Integration/integration/integration.cpp b/src/Integration/integration/integration.cpp
index d9fc8ba8..710df9ad 100644
--- a/src/Integration/integration/integration.cpp
+++ b/src/Integration/integration/integration.cpp
@@ -51,10 +51,12 @@ pFlow::integration::integration(
const word &baseName,
pointStructure &pStruct,
const word &,
- const realx3Field_D &)
+ const realx3Field_D &,
+ bool keepHistory)
: owner_(*pStruct.owner()),
pStruct_(pStruct),
- baseName_(baseName)
+ baseName_(baseName),
+ keepHistory_(keepHistory)
{}
@@ -64,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 fb0d84df..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,8 @@ private:
/// The base name for integration
const word baseName_;
+ bool keepHistory_;
+
protected:
bool insertValues(
@@ -83,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;
@@ -109,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)
);
@@ -138,6 +143,11 @@ public:
return owner_;
}
+ bool keepHistory()const
+ {
+ return keepHistory_;
+ }
+
virtual
void updateBoundariesSlaveToMasterIfRequested() = 0;
/// return integration method
@@ -164,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/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 "<::createGrainInteraction()
geometryMotion_,
timers());
- ppContactList_ = makeUnique(nPrtcl+1);
+ ppContactList_ = makeUnique("Grain-Grain",nPrtcl+1);
- pwContactList_ = makeUnique(nPrtcl/5+1);
+ pwContactList_ = makeUnique("Grain-wall",nPrtcl/5+1);
return true;
}
diff --git a/src/Interaction/sphereInteraction/sphereInteraction/sphereInteraction.cpp b/src/Interaction/sphereInteraction/sphereInteraction/sphereInteraction.cpp
index cd362c66..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;
}
diff --git a/src/Interaction/sphereInteraction/sphereInteractionsNonLinearModModels.cpp b/src/Interaction/sphereInteraction/sphereInteractionsNonLinearModModels.cpp
index d7f79ff7..fd277432 100644
--- a/src/Interaction/sphereInteraction/sphereInteractionsNonLinearModModels.cpp
+++ b/src/Interaction/sphereInteraction/sphereInteractionsNonLinearModModels.cpp
@@ -58,5 +58,5 @@ createInteraction(pFlow::cfModels::limitedNonLinearModNormalRolling, pFlow::conv
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/MotionModel/CMakeLists.txt b/src/MotionModel/CMakeLists.txt
index 1e92a989..d28af4f5 100644
--- a/src/MotionModel/CMakeLists.txt
+++ b/src/MotionModel/CMakeLists.txt
@@ -14,8 +14,8 @@ entities/stationary/stationary.cpp
conveyorBeltMotion/conveyorBeltMotion.cpp
entities/conveyorBelt/conveyorBelt.cpp
-#entities/multiRotatingAxis/multiRotatingAxis.cpp
-#multiRotatingAxisMotion/multiRotatingAxisMotion.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/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/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/GrainParticles/grainParticles/grainParticles.cpp b/src/Particles/GrainParticles/grainParticles/grainParticles.cpp
index 1e6cc065..d4d5bf05 100644
--- a/src/Particles/GrainParticles/grainParticles/grainParticles.cpp
+++ b/src/Particles/GrainParticles/grainParticles/grainParticles.cpp
@@ -248,7 +248,8 @@ pFlow::grainParticles::grainParticles(
"rVelocity",
dynPointStruct(),
intMethod,
- rAcceleration_.field()
+ rAcceleration_.field(),
+ control.keepIntegrationHistory()
);
if( !rVelIntegration_ )
diff --git a/src/Particles/GrainParticles/grainShape/grainShape.cpp b/src/Particles/GrainParticles/grainShape/grainShape.cpp
index 4558940b..246b5be8 100644
--- a/src/Particles/GrainParticles/grainShape/grainShape.cpp
+++ b/src/Particles/GrainParticles/grainShape/grainShape.cpp
@@ -73,6 +73,18 @@ pFlow::grainShape::grainShape
}
}
+pFlow::grainShape::grainShape
+(
+ const word &shapeType,
+ const word &fileName,
+ repository *owner,
+ const property &prop
+)
+:
+ grainShape(fileName, owner, prop)
+{
+}
+
pFlow::real pFlow::grainShape::maxBoundingSphere() const
{
return max(grainDiameters_);
@@ -99,9 +111,12 @@ pFlow::real pFlow::grainShape::boundingDiameter(uint32 index) const
{
return grainDiameters_[index];
}
- fatalErrorInFunction<<"Invalid index for diameter "<<
- index< pFlow::shape::create
+(
+ const word &shapeType,
+ const word &fileName,
+ repository *owner,
+ const property &prop
+)
+{
+ word type = angleBracketsNames("shape", shapeType);
+
+ if( wordvCtorSelector_.search(type) )
+ {
+ auto objPtr =
+ wordvCtorSelector_[type]
+ (shapeType, fileName, owner, prop);
+ return objPtr;
+ }
+ else
+ {
+ printKeys
+ (
+ fatalError << "Ctor Selector "<<
+ type << " dose not exist. \n"
+ <<"Avaiable ones are: \n\n"
+ ,
+ wordvCtorSelector_
+ );
+ fatalExit;
+ return nullptr;
+ }
+
+}
diff --git a/src/Particles/particles/shape/shape.hpp b/src/Particles/particles/shape/shape.hpp
index 5a4007aa..4c7d74e9 100644
--- a/src/Particles/particles/shape/shape.hpp
+++ b/src/Particles/particles/shape/shape.hpp
@@ -60,9 +60,28 @@ public:
const word& fileName,
repository* owner,
const property& prop);
+
+ shape(
+ const word& shapeType,
+ const word& fileName,
+ repository* owner,
+ const property& prop);
~shape() override=default;
+ create_vCtor
+ (
+ shape,
+ word,
+ (
+ const word& shapeType,
+ const word& fileName,
+ repository* owner,
+ const property& prop
+ ),
+ (shapeType, fileName, owner, prop)
+ );
+
inline
const auto& properties()const
{
@@ -148,6 +167,9 @@ public:
virtual
realVector boundingDiameter()const = 0;
+ virtual
+ realVector volume()const = 0;
+
virtual
bool mass(uint32 index, real& m)const = 0;
@@ -187,6 +209,13 @@ public:
virtual
real Inertial_zz(uint32 index)const = 0;
+ static
+ uniquePtr create(
+ const word& shapeType,
+ const word& fileName,
+ repository* owner,
+ const property& prop);
+
};
}
diff --git a/src/PostprocessData/CMakeLists.txt b/src/PostprocessData/CMakeLists.txt
new file mode 100644
index 00000000..a68a6d75
--- /dev/null
+++ b/src/PostprocessData/CMakeLists.txt
@@ -0,0 +1,35 @@
+set(SourceFiles
+ # Main postprocess data
+ postprocessData/postprocessData.cpp
+
+ # Fields database
+ fieldsDataBase/fieldsDataBase.cpp
+ fieldsDataBase/simulationFieldsDataBase.cpp
+
+ # Regions
+ region/regionPoints/regionPoints/regionPoints.cpp
+ region/regionPoints/sphereRegionPoints/sphereRegionPoints.cpp
+ region/regionPoints/lineRegionPoints/lineRegionPoints.cpp
+ region/regionPoints/centerPointsRegionPoints/centerPointsRegionPoints.cpp
+ region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.cpp
+
+ # Postprocess components
+ postprocessComponent/postprocessComponent/postprocessComponent.cpp
+ postprocessComponent/particleProbePostprocessComponent/particleProbePostprocessComponent.cpp
+ postprocessComponent/PostprocessComponent/PostprocessComponents.cpp
+
+ # Operations
+ operation/postprocessOperation/postprocessOperation.cpp
+ operation/PostprocessOperation/PostprocessOperationSum.cpp
+ operation/PostprocessOperation/PostprocessOperationAverage.cpp
+ operation/PostprocessOperation/PostprocessOperationAvMassVelocity.cpp
+
+ operation/includeMask/includeMask.cpp
+ operation/includeMask/IncludeMasks.cpp
+
+
+)
+
+set(link_libs Kokkos::kokkos phasicFlow Particles)
+
+pFlow_add_library_install(PostprocessData SourceFiles link_libs)
\ No newline at end of file
diff --git a/src/PostprocessData/fieldsDataBase/fieldFunctions.hpp b/src/PostprocessData/fieldsDataBase/fieldFunctions.hpp
new file mode 100644
index 00000000..7454188d
--- /dev/null
+++ b/src/PostprocessData/fieldsDataBase/fieldFunctions.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 __fieldFunctions_hpp__
+#define __fieldFunctions_hpp__
+
+#include "types.hpp"
+#include "span.hpp"
+
+namespace pFlow::postprocessData
+{
+
+template
+inline
+void funcCast(span src, span dst)
+{
+ for(uint32 i=0; i(src[i]);
+ }
+}
+
+template
+inline
+void funcAbs(span src, span dst)
+{
+ for(uint32 i=0; i
+inline
+void funcSquare(span src, span dst)
+{
+ for( uint32 i=0; i(src[i]),2);
+ }
+}
+
+template
+inline
+void funcCube(span src, span dst)
+{
+ for( uint32 i=0; i(src[i]),3);
+ }
+}
+
+template
+inline
+void funcSquareRoot(span src, span dst)
+{
+ for( uint32 i=0; i(src[i]));
+ }
+}
+
+template
+inline
+void funcMagnitude(span src, span dst)
+{
+ for( uint32 i=0; i
+inline
+void funcMagnitudeSquare(span src, span dst)
+{
+ for( uint32 i=0; i
+inline
+void funcMagnitudeCube(span src, span dst)
+{
+ for( uint32 i=0; i
+inline
+void funcMagnitudeSquareRoot(span src, span dst)
+{
+ for( uint32 i=0; i src, span dst, char component)
+{
+ for( uint32 i=0; i src, span dst, char component)
+{
+ for( uint32 i=0; i
+
+#include "vocabs.hpp"
+#include "systemControl.hpp"
+#include "fieldsDataBase.hpp"
+#include "fieldFunctions.hpp"
+#include "dictionary.hpp"
+
+
+bool pFlow::postprocessData::fieldsDataBase::loadPointStructureToTime()
+{
+ return false;
+}
+
+
+bool pFlow::postprocessData::fieldsDataBase::checkForUpdate
+(
+ const word &compoundName,
+ bool forceUpdate
+)
+{
+ auto t = currentTime();
+ bool shouldUpdate = false;
+
+ if(auto [iter, found]= captureTime_.findIf(compoundName); found)
+ {
+ shouldUpdate = iter->second < t || forceUpdate;
+ iter->second = t;
+ }
+ else
+ {
+ shouldUpdate = true;
+ captureTime_.insertIf(compoundName, t);
+ }
+
+ return shouldUpdate;
+}
+
+pFlow::span pFlow::postprocessData::fieldsDataBase::createOrGetRealField
+(
+ const word &name
+)
+{
+
+ bool shouldUpdate = checkForUpdate(name);
+
+ if(shouldUpdate)
+ {
+ allFields_.emplaceBackOrReplace>
+ (
+ name,
+ FieldTypeHost
+ (
+ name,
+ "value",
+ pointFieldSize()
+ )
+ );
+ }
+
+ auto& field = allFields_.getObject>(name);
+ return span(
+ field.data(),
+ field.size());
+}
+
+pFlow::span pFlow::postprocessData::fieldsDataBase::createOrGetVolume
+(
+ bool forceUpdate
+)
+{
+ const word fName = "volume";
+ bool shouldUpdate = checkForUpdate(fName, forceUpdate);
+
+ if(shouldUpdate)
+ {
+ const auto index = updateFieldUint32("shapeIndex", true);
+ auto vols = getShape().volume();
+
+ FieldTypeHost volField
+ (
+ fName,
+ "value",
+ pointFieldSize()
+ );
+
+ for(uint32 i=0; i< volField.size(); i++)
+ {
+ volField[i] = vols[index[i]];
+ }
+
+ allFields_.emplaceBackOrReplace>
+ (
+ fName,
+ std::move(volField)
+ );
+ }
+
+ auto& field = allFields_.getObject>(fName);
+ return span(
+ field.data(),
+ field.size());
+
+}
+
+pFlow::span pFlow::postprocessData::fieldsDataBase::createOrGetDensity(bool forceUpdate)
+{
+ const word fName = "density";
+
+ bool shouldUpdate = checkForUpdate(fName, forceUpdate);
+
+ if(shouldUpdate)
+ {
+ const auto index = updateFieldUint32("shapeIndex", true);
+ const auto dens = getShape().density();
+
+ FieldTypeHost denFeild
+ (
+ fName,
+ "value",
+ pointFieldSize()
+ );
+
+ for(uint32 i=0; i< denFeild.size(); i++)
+ {
+ denFeild[i] = dens[index[i]];
+ }
+
+ allFields_.emplaceBackOrReplace>
+ (
+ fName,
+ std::move(denFeild)
+ );
+ }
+
+ auto& field = allFields_.getObject>(fName);
+ return span(
+ field.data(),
+ field.size());
+}
+
+pFlow::span pFlow::postprocessData::fieldsDataBase::createOrGetOne(bool forceUpdate)
+{
+ const word fName = "one";
+
+ bool shouldUpdate = checkForUpdate(fName, forceUpdate);
+
+ if(shouldUpdate)
+ {
+ allFields_.emplaceBackOrReplace>
+ (
+ fName,
+ FieldTypeHost
+ (
+ fName,
+ "value",
+ pointFieldSize(),
+ 1.0
+ )
+ );
+ }
+
+ auto& field = allFields_.getObject>(fName);
+ return span(
+ field.data(),
+ field.size());
+}
+
+pFlow::span pFlow::postprocessData::fieldsDataBase::createOrGetMass(bool forceUpdate)
+{
+ const word fName = "mass";
+
+ bool shouldUpdate = checkForUpdate(fName, forceUpdate);
+
+ if(shouldUpdate)
+ {
+ const auto index = updateFieldUint32("shapeIndex", true);
+ const auto ms = getShape().mass();
+
+ FieldTypeHost massField
+ (
+ fName,
+ "value",
+ pointFieldSize()
+ );
+
+ for(uint32 i=0; i< massField.size(); i++)
+ {
+ massField[i] = ms[index[i]];
+ }
+
+ allFields_.emplaceBackOrReplace>
+ (
+ fName,
+ std::move(massField)
+ );
+ }
+
+ auto& field = allFields_.getObject>(fName);
+ return span(
+ field.data(),
+ field.size());
+}
+
+pFlow::span pFlow::postprocessData::fieldsDataBase::createOrGetI(bool forceUpdate)
+{
+ const word fName = "I";
+
+ bool shouldUpdate = checkForUpdate(fName, forceUpdate);
+
+ if(shouldUpdate)
+ {
+ const auto index = updateFieldUint32("shapeIndex", true);
+ const auto Is = getShape().Inertia();
+
+ FieldTypeHost IField
+ (
+ fName,
+ "value",
+ pointFieldSize()
+ );
+
+ for(uint32 i=0; i< IField.size(); i++)
+ {
+ IField[i] = Is[index[i]];
+ }
+
+ allFields_.emplaceBackOrReplace>
+ (
+ fName,
+ std::move(IField)
+ );
+ }
+
+ auto& field = allFields_.getObject>(fName);
+ return span(
+ field.data(),
+ field.size());
+}
+
+bool pFlow::postprocessData::fieldsDataBase::findFunction(
+ const word &compoundFieldName,
+ word &fieldName,
+ fieldsDataBase::Functions &func)
+{
+
+ std::regex pattern(R"((\w+)?\((\w+)(?:,([xyzw]))?\)|(\w+))");
+ std::smatch match;
+
+ if (std::regex_match(compoundFieldName, match, pattern))
+ {
+ if (match[1].matched) // Function is present
+ {
+ word functionName = match[1].str();
+ fieldName = match[2].str();
+
+ // Map the function name to the enum value
+ if(functionName=="component")
+ {
+ if (!match[3].matched) // Component is not present
+ {
+ fatalErrorInFunction <<
+ "Component (x, y, z, or w) is not specified in the function component: " << compoundFieldName <<
+ " the format is component(u,x), where u is the vector field name and x is the compoenent." << endl;
+ return false;
+ }
+
+ switch (match[3].str()[0])
+ {
+ case 'x': func = fieldsDataBase::Functions::ComponentX; break;
+ case 'y': func = fieldsDataBase::Functions::ComponentY; break;
+ case 'z': func = fieldsDataBase::Functions::ComponentZ; break;
+ case 'w': func = fieldsDataBase::Functions::ComponentW; break;
+ default:
+ fatalErrorInFunction <<
+ "Invalid component specified: " << match[3].str() << endl;
+ return false;
+ }
+ return true;
+ }
+ else if (functionName == "abs")
+ {
+ func = fieldsDataBase::Functions::Abs;
+ }
+ else if (functionName == "square")
+ {
+ func = fieldsDataBase::Functions::Square;
+ }
+ else if (functionName == "cube")
+ {
+ func = fieldsDataBase::Functions::Cube;
+ }
+ else if (functionName == "sqrt")
+ {
+ func = fieldsDataBase::Functions::SqureRoot;
+ }
+ else if (functionName == "mag")
+ {
+ func = fieldsDataBase::Functions::Magnitude;
+ }
+ else if (functionName == "magSquare")
+ {
+ func = fieldsDataBase::Functions::MagnitudeSquare;
+ }
+ else if (functionName == "magCube")
+ {
+ func = fieldsDataBase::Functions::MagnitudeCube;
+ }
+ else if (functionName == "magSqrt")
+ {
+ func = fieldsDataBase::Functions::MagnitudeSquareRoot;
+ }
+ else
+ {
+ fatalErrorInFunction <<
+ "Unknown function specified: " << functionName<<
+ " in: "<() ||
+ inputType == getTypeName() )
+ {
+ outputType = getTypeName();
+ return true;
+ }
+ else
+ {
+ fatalErrorInFunction<<"Wrong function: component(u,comp), for input field type: "<() )
+ {
+ outputType = getTypeName();
+ return true;
+ }
+ else
+ {
+ fatalErrorInFunction<<"Wrong function: component(u,w), for input field type: "<() ||
+ inputType == getTypeName() ||
+ inputType == getTypeName() ||
+ inputType == getTypeName() )
+ {
+ outputType = getTypeName();
+ return true;
+ }
+ else
+ {
+ fatalErrorInFunction<<"Wrong input field type for functions abs, squqre, cube, and sqrt."<<
+ " field type is "<< inputType<() ||
+ inputType == getTypeName() )
+ {
+ outputType = getTypeName();
+ return true;
+ }
+ else
+ {
+ fatalErrorInFunction<<"Wroing input field type for functions mag, magSquare, magCube, magSqrt. "<<
+ " Input field type is "<< inputType<() ||
+ inputType == getTypeName() ||
+ inputType == getTypeName())
+ {
+ outputType = inputType;
+ return true;
+ }
+ else if( inputType == getTypeName() ||
+ inputType == getTypeName() )
+ {
+ outputType = getTypeName();
+ return true;
+ }
+ else
+ {
+ fatalErrorInFunction<< "Wroing input field type "<< inputType<("shapeType", "");
+
+ if(shapeType_.empty())
+ {
+ WARNING
+ << "shapeType is not set in dictionary: "
+ << postDict.globalName()
+ << " and you may need to set for some postprocess operations"<second;
+ }
+ else
+ {
+ // the name is in the Time object
+ if(pointFieldNameExists(pointFieldName))
+ {
+ originalType = getPointFieldType(pointFieldName);
+ }
+ else
+ {
+ fatalErrorInFunction
+ << "The field name: "<< pointFieldName
+ << " is not in the Time object.\n"
+ <<" Avaiable ones are: \n"<< time().objectNames()< pFlow::postprocessData::fieldsDataBase::updatePoints(bool forceUpdate)
+{
+ const word fName = "position";
+ bool shouldUpdate = checkForUpdate(fName, forceUpdate);
+
+ if(shouldUpdate)
+ {
+ // load pointStructure
+ if(!loadPointStructureToTime())
+ {
+ fatalErrorInFunction<< "Error in loading pointStructure to Time object."<
+ (
+ fName,
+ pstruct.activePointsHost()
+ );
+ }
+
+ auto& points = allFields_.getObject(fName);
+
+ return span(
+ points.data(),
+ points.size());
+
+}
+
+pFlow::span pFlow::postprocessData::fieldsDataBase::updateFieldRealx3
+(
+ const word &compoundName,
+ bool forceUpdate
+)
+{
+ word originalType, typeAfterFunction, fieldName;
+ Functions func;
+
+ if( !getFieldTypeNameFunction(
+ compoundName,
+ fieldName,
+ originalType,
+ typeAfterFunction,
+ func) )
+ {
+ fatalErrorInFunction<< "Error in getting the type name of field: "<<
+ compoundName<<", with type name: "<< originalType <(nullptr, 0);
+ }
+
+ if( originalType == getTypeName() && func == Functions::None )
+ {
+ return updateField(fieldName, forceUpdate);
+ }
+ else
+ {
+ fatalErrorInFunction<< "Error in getting the type name of field: "<<
+ compoundName<<", with type name: "<< originalType <(nullptr, 0);
+ }
+
+}
+
+pFlow::span pFlow::postprocessData::fieldsDataBase::updateFieldRealx4
+(
+ const word &compoundName,
+ bool forceUpdate
+)
+{
+ word originalType, typeAfterFunction, fieldName;
+ Functions func;
+
+ if( !getFieldTypeNameFunction(
+ compoundName,
+ fieldName,
+ originalType,
+ typeAfterFunction,
+ func))
+ {
+ fatalErrorInFunction<< "Error in getting the type name of field: "<<
+ compoundName<<", with type name: "<< originalType <(nullptr, 0);
+ }
+
+ if( originalType == getTypeName() && func == Functions::None )
+ {
+ return updateField(fieldName, forceUpdate);
+ }
+ else
+ {
+ fatalErrorInFunction<< "Error in getting the type name of field: "<<
+ compoundName<<", with type name: "<< originalType <(nullptr, 0);
+ }
+
+}
+
+pFlow::span pFlow::postprocessData::fieldsDataBase::updateFieldReal
+(
+ const word &compoundName,
+ bool forceUpdate
+)
+{
+ word originalType, typeAfterFunction, fieldName;
+ Functions func;
+
+ if( !getFieldTypeNameFunction(
+ compoundName,
+ fieldName,
+ originalType,
+ typeAfterFunction,
+ func) )
+ {
+ fatalErrorInFunction<< "Error in getting the type name of field: "<<
+ compoundName<<", with type name: "<< originalType <(nullptr, 0);
+ }
+
+ // if the output type is not real, then it is not supported yet
+ if(typeAfterFunction != getTypeName())
+ {
+ fatalErrorInFunction<< "The output type of field "<< compoundName<<
+ " is not real, it is: "<< typeAfterFunction<(nullptr, 0);
+ }
+
+ // if the orginal type is real and no function, then it is a normal field
+ if( originalType == getTypeName() && func == Functions::None )
+ {
+ return updateField(fieldName, forceUpdate);
+ }
+
+ // if the original type is uint32, and no funciton, cast to real
+ if( originalType == getTypeName())
+ {
+ if(func == Functions::None)
+ {
+ auto sp = updateField(fieldName, forceUpdate);
+ auto spReal = createOrGetRealField(fieldName+".real");
+ funcCast(sp, spReal);
+ return spReal;
+ }
+ else
+ {
+ fatalErrorInFunction<<"No function can be applied to field of type uint32. "<<
+ " The field is: "<< compoundName<(nullptr, 0);
+ fatalExit;
+ }
+ }
+
+ if( originalType == getTypeName() )
+ {
+ switch(func)
+ {
+ case Functions::Abs:
+ {
+ auto sp = updateField(fieldName, forceUpdate);
+ auto spReal = createOrGetRealField(compoundName);
+ funcAbs(sp, spReal);
+ return spReal;
+ }
+ case Functions::Square:
+ {
+ auto sp = updateField(fieldName, forceUpdate);
+ auto spReal = createOrGetRealField(compoundName);
+ funcSquare(sp, spReal);
+ return spReal;
+ }
+ case Functions::Cube:
+ {
+ auto sp = updateField(fieldName, forceUpdate);
+ auto spReal = createOrGetRealField(compoundName);
+ funcCube(sp, spReal);
+ return spReal;
+ }
+ case Functions::SqureRoot:
+ {
+ auto sp = updateField(fieldName, forceUpdate);
+ auto spReal = createOrGetRealField(compoundName+".sqrt");
+ funcSquareRoot(sp, spReal);
+ return spReal;
+ }
+ default:
+ {
+ fatalErrorInFunction<< "Wrong function for field type real in :"<<
+ compoundName<(nullptr, 0);
+ }
+ }
+ }
+
+ if( originalType == getTypeName())
+ {
+ switch(func)
+ {
+ case Functions::Magnitude:
+ {
+ auto sp = updateField(fieldName, forceUpdate);
+ auto spReal = createOrGetRealField(compoundName);
+ funcMagnitude(sp, spReal);
+ return spReal;
+ }
+ case Functions::MagnitudeSquare:
+ {
+ auto sp = updateField(fieldName, forceUpdate);
+ auto spReal = createOrGetRealField(compoundName);
+ funcMagnitudeSquare(sp, spReal);
+ return spReal;
+ }
+ case Functions::MagnitudeCube:
+ {
+ auto sp = updateField(fieldName, forceUpdate);
+ auto spReal = createOrGetRealField(compoundName);
+ funcMagnitudeCube(sp, spReal);
+ return spReal;
+ }
+ case Functions::MagnitudeSquareRoot:
+ {
+ auto sp = updateField(fieldName, forceUpdate);
+ auto spReal = createOrGetRealField(compoundName);
+ funcMagnitudeSquareRoot(sp, spReal);
+ return spReal;
+ }
+ case Functions::ComponentX:
+ {
+ auto sp = updateField(fieldName, forceUpdate);
+ auto spReal = createOrGetRealField(compoundName);
+ funcComponent(sp, spReal, 'x');
+ return spReal;
+ }
+ case Functions::ComponentY:
+ {
+ auto sp = updateField(fieldName, forceUpdate);
+ auto spReal = createOrGetRealField(compoundName);
+ funcComponent(sp, spReal, 'y');
+ return spReal;
+ }
+ case Functions::ComponentZ:
+ {
+ auto sp = updateField(fieldName, forceUpdate);
+ auto spReal = createOrGetRealField(compoundName);
+ funcComponent(sp, spReal, 'z');
+ return spReal;
+ }
+ default:
+ {
+ fatalErrorInFunction<< "Wrong function for field type realx3 in :"<<
+ compoundName<(nullptr, 0);
+ }
+ }
+ }
+
+ fatalErrorInFunction<<"NOT SUPPORTED "<(nullptr, 0);
+}
+
+pFlow::span pFlow::postprocessData::fieldsDataBase::updateFieldUint32
+(
+ const word& name,
+ bool forceUpdate
+)
+{
+ return updateField(name, forceUpdate);
+}
+
+pFlow::postprocessData::allPointFieldTypes pFlow::postprocessData::fieldsDataBase::updateFieldAll
+(
+ const word &compoundName,
+ bool forceUpdate
+)
+{
+ word typeAfterFunction, originalType;
+
+ if( !getFieldType(compoundName, originalType, typeAfterFunction))
+ {
+ fatalErrorInFunction<< "Error in getting the type name of field: "<<
+ compoundName<<", with type name: "<< originalType <(nullptr, 0);
+ }
+
+ if( typeAfterFunction == getTypeName() )
+ {
+ return updateFieldRealx3(compoundName, forceUpdate);
+ }
+ else if( typeAfterFunction == getTypeName() )
+ {
+ return updateFieldRealx4(compoundName, forceUpdate);
+ }
+ else if( typeAfterFunction == getTypeName() )
+ {
+ return updateFieldReal(compoundName, forceUpdate);
+ }
+ else
+ {
+ fatalErrorInFunction<< "Invalid feild "<< compoundName<(nullptr, 0);
+ }
+}
+
+bool pFlow::postprocessData::fieldsDataBase::pointFieldGetType
+(
+ const word& TYPENAME,
+ word& fieldType,
+ word& fieldSpace
+)
+{
+ std::regex match("pointField\\<([A-Za-z1-9_]*)\\,([A-Za-z1-9_]*)\\>");
+ std::smatch search;
+ if(!std::regex_match(TYPENAME, search, match)) return false;
+ if(search.size()!= 3) return false;
+ fieldType = search[1];
+ fieldSpace = search[2];
+ return true;
+}
+
+pFlow::uniquePtr
+ pFlow::postprocessData::fieldsDataBase::create
+(
+ systemControl& control,
+ const dictionary& postDict,
+ bool inSimulation,
+ timeValue startTime
+)
+{
+ word dbType;
+ if(inSimulation)
+ {
+ dbType = "fieldsDataBase";
+ }
+ else
+ {
+ dbType = "fieldsDataBase";
+ }
+
+ if( boolvCtorSelector_.search(dbType) )
+ {
+ auto objPtr =
+ boolvCtorSelector_[dbType](control, postDict, inSimulation, startTime);
+ return objPtr;
+ }
+ else
+ {
+ printKeys
+ (
+ fatalError << "Ctor Selector "<<
+ dbType << " does not exist. \n"
+ <<"Available ones are: \n\n"
+ ,
+ boolvCtorSelector_
+ );
+ fatalExit;
+ }
+
+ return nullptr;
+}
+
+
+
diff --git a/src/PostprocessData/fieldsDataBase/fieldsDataBase.hpp b/src/PostprocessData/fieldsDataBase/fieldsDataBase.hpp
new file mode 100644
index 00000000..fb707b1e
--- /dev/null
+++ b/src/PostprocessData/fieldsDataBase/fieldsDataBase.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 __fieldsDataBase_hpp__
+#define __fieldsDataBase_hpp__
+
+#include "fieldsDataBaseDclr.hpp"
+
+#include "pointStructure.hpp"
+#include "pointFields.hpp"
+#include "anyList.hpp"
+#include "Map.hpp"
+#include "shape.hpp"
+
+namespace pFlow
+{
+ class dictionary;
+ class systemControl;
+ class Time;
+}
+
+namespace pFlow::postprocessData
+{
+
+
+class fieldsDataBase
+{
+private:
+
+ // - Typedefs
+
+ /// Point position data type
+ using PointsTypeHost = typename pointStructure::PointsTypeHost;
+
+ /// Point field data type
+ template
+ using FieldTypeHost = typename internalField::FieldTypeHost;
+
+ /// @brief Enumeration of functions that can be applied to point fields.
+ enum class Functions
+ {
+ None, /// no function
+ ComponentX, /// component(u,x)
+ ComponentY, /// component(u,y)
+ ComponentZ, /// component(u,z)
+ ComponentW, /// component(u,w)
+ Abs, /// abs(s)
+ Square, /// square(s)
+ Cube, /// cube(s)
+ SqureRoot, /// sqrt(s)
+ Magnitude, /// mag(u)
+ MagnitudeSquare, /// magSquare(u)
+ MagnitudeCube, /// magCube(u)
+ MagnitudeSquareRoot /// magSqrt(u)
+ };
+
+
+ // - Member variables
+
+ /// List to store all the point fields
+ anyList allFields_;
+
+ /// Map to store the last capture time of each field
+ wordMap captureTime_;
+
+ /// Reference to the Time object
+ Time& time_;
+
+ /// Flag indicating if we're in simulation mode
+ bool inSimulation_ = false;
+
+ word shapeType_;
+
+protected:
+
+ /// check if pointField name exists in Time or time folder
+ virtual
+ bool pointFieldNameExists(const word& name)const = 0;
+
+ /// Loads a pointField with a given name to the Time object
+ virtual
+ bool loadPointFieldToTime(const word& name)= 0;
+
+ virtual
+ bool loadPointStructureToTime()=0;
+
+ virtual
+ const shape& getShape() const= 0;
+
+ const word& shapeTypeName()const
+ {
+ return shapeType_;
+ }
+
+ /// get the type name of the pointField in the Time object
+ virtual
+ word getPointFieldType(const word& name)const = 0;
+
+ /// Checks if a field needs to be updated based on capture time
+ bool checkForUpdate(const word& compoundName, bool forceUpdate = false);
+
+ /// @brief return the size of pointStructure
+ uint32 pointFieldSize()
+ {
+ auto s = updatePoints();
+ return s.size();
+ }
+
+ template
+ span updateField(const word& name, bool forceUpdate = false);
+
+ template
+ span updateReservedField(const word& name, bool forceUpdate = false);
+
+ span createOrGetRealField(const word& name);
+
+ span createOrGetVolume(bool forceUpdate=false);
+
+ span createOrGetDensity(bool forceUpdate=false);
+
+ span createOrGetOne(bool forceUpdate=false);
+
+ span createOrGetMass(bool forceUpdate=false);
+
+ span createOrGetI(bool forceUpdate=false);
+
+ /// Map of reserved field names with their corresponding types
+ static const inline std::map reservedFieldNames_
+ {
+ {"position", "realx3"},
+ {"one", "real"},
+ {"volume", "real"},
+ {"density", "real"},
+ {"mass", "real"},
+ {"I", "real"}
+ };
+
+ static
+ bool findFunction(
+ const word& compoundFieldName,
+ word& fieldName,
+ fieldsDataBase::Functions& func );
+
+ static
+ bool inputOutputType(
+ fieldsDataBase::Functions func,
+ const word& inputType,
+ word& outputType);
+
+
+
+public:
+
+ // - Type info
+
+ TypeInfo("fieldsDataBase");
+
+ // - constructors
+
+ fieldsDataBase(
+ systemControl& control,
+ const dictionary& postDict,
+ bool inSimulation,
+ timeValue startTime);
+
+ /// no copy constructor
+ fieldsDataBase(const fieldsDataBase&) = delete;
+
+ /// no move constructor
+ fieldsDataBase(fieldsDataBase&&) = delete;
+
+ /// no copy assignment
+ fieldsDataBase& operator=(const fieldsDataBase&) = delete;
+
+ /// no move assignment
+ fieldsDataBase& operator=(fieldsDataBase&&) = delete;
+
+ /// destructor
+ virtual ~fieldsDataBase() = default;
+
+ create_vCtor
+ (
+ fieldsDataBase,
+ bool,
+ (
+ systemControl& control,
+ const dictionary& postDict,
+ bool inSimulation,
+ timeValue startTime
+ ),
+ (control, postDict, inSimulation, startTime)
+ );
+
+
+ // - Public Access Functions
+ /// returns the current time
+ timeValue currentTime()const;
+
+ /// const ref to object Time
+ const Time& time()const
+ {
+ return time_;
+ }
+
+ Time& time()
+ {
+ return time_;
+ }
+
+ // - Public Member Functions
+
+ bool getFieldTypeNameFunction
+ (
+ const word& compoundName,
+ word& pointFieldName,
+ word& originalType,
+ word& typeAfterFunction,
+ Functions& func
+ )const;
+
+
+ bool getFieldType
+ (
+ const word& compoundName,
+ word& originalType,
+ word& typeAfterFunction
+ ) const;
+
+ bool getFieldType
+ (
+ const word& compoundName,
+ word& typeAfterFunction
+ ) const;
+
+
+ /// update pointStructure if necessary
+ span updatePoints(bool forceUpdate = false);
+
+ /// update a field with realx3 type
+ span updateFieldRealx3(
+ const word& compoundName,
+ bool forceUpdate = false);
+
+ span updateFieldRealx4(
+ const word& compoundName,
+ bool forceUpdate = false);
+
+ span updateFieldReal(
+ const word& compoundName,
+ bool forceUpdate = false);
+
+ span updateFieldUint32(
+ const word& name,
+ bool forceUpdate = false);
+
+ /// Updates and retrieves a point field of any type from the database.
+ /// It returns types real, realx3 and realx4 only.
+ allPointFieldTypes updateFieldAll(
+ const word& compoundName,
+ bool forceUpdate = false);
+
+ virtual
+ const pointStructure& pStruct()const = 0;
+
+ /// Get the next avaiable time folder after the current time folder
+ /// This is only used for post-simulation processing
+ virtual
+ timeValue getNextTimeFolder()const
+ {
+ return -1.0;
+ }
+
+ /// Sets the current folder to the next time folder.
+ /// This is used only for post-simulation processing
+ /// @returns the time value of the next folder.
+ virtual
+ timeValue setToNextTimeFolder()
+ {
+ return -1.0;
+ }
+
+ /// Skips the next time folder.
+ /// This is used only for post-simulation processing
+ /// @returns the time value of the skipped folder
+ virtual
+ timeValue skipNextTimeFolder()
+ {
+ return -1.0;
+ }
+
+ static
+ bool pointFieldGetType(
+ const word& TYPENAME,
+ word& fieldType,
+ word& fieldSpace);
+
+ static
+ uniquePtr create(
+ systemControl& control,
+ const dictionary& postDict,
+ bool inSimulation,
+ timeValue startTime);
+};
+
+} // namespace pFlow::postprocessData
+
+#include "fieldsDataBaseTemplates.cpp"
+
+#endif //__fieldsDataBased_hpp__
diff --git a/src/PostprocessData/fieldsDataBase/fieldsDataBaseDclr.hpp b/src/PostprocessData/fieldsDataBase/fieldsDataBaseDclr.hpp
new file mode 100644
index 00000000..e5d483c0
--- /dev/null
+++ b/src/PostprocessData/fieldsDataBase/fieldsDataBaseDclr.hpp
@@ -0,0 +1,45 @@
+
+#ifndef __fieldsDataBaseDclr_hpp__
+#define __fieldsDataBaseDclr_hpp__
+
+#include
+#include
+#include
+
+#include "types.hpp"
+#include "span.hpp"
+
+namespace pFlow::postprocessData
+{
+
+
+template
+concept ValidFieldType =
+ std::same_as ||
+ std::same_as ||
+ std::same_as ||
+ std::same_as;
+
+template
+concept VectorType =
+ std::same_as ||
+ std::same_as;
+
+template
+concept ScalarType =
+ std::same_as;
+
+
+template
+concept ValidRegionFieldType =
+ std::same_as ||
+ std::same_as ||
+ std::same_as ;
+
+
+using allPointFieldTypes = std::variant, span, span>;
+
+
+} // namespace pFlow
+
+#endif //__fieldsDataBaseDclr_hpp__
\ No newline at end of file
diff --git a/src/PostprocessData/fieldsDataBase/fieldsDataBaseTemplates.cpp b/src/PostprocessData/fieldsDataBase/fieldsDataBaseTemplates.cpp
new file mode 100644
index 00000000..33cb0d87
--- /dev/null
+++ b/src/PostprocessData/fieldsDataBase/fieldsDataBaseTemplates.cpp
@@ -0,0 +1,171 @@
+/*------------------------------- 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 __fieldsDataBaseTemplates_hpp__
+#define __fieldsDataBaseTemplates_hpp__
+
+#include "fieldsDataBase.hpp"
+
+template
+inline
+pFlow::span pFlow::postprocessData::fieldsDataBase::updateField(const word& name, bool forceUpdate)
+{
+
+ bool shouldUpdate = checkForUpdate(name, forceUpdate);
+
+ if(shouldUpdate)
+ {
+ if(reservedFieldNames_.contains(name))
+ {
+ return updateReservedField(name, true);
+ }
+ else
+ {
+ if( loadPointFieldToTime(name) )
+ {
+ const auto& pField = time_.template lookupObject>(name);
+ allFields_.template emplaceBackOrReplace>(
+ name,
+ pField.activeValuesHost());
+ }
+ else
+ {
+ fatalErrorInFunction<<"Error in loading the pointField "<>(name);
+
+ return span(
+ field.data(),
+ field.size());
+
+}
+
+
+template
+inline
+pFlow::span pFlow::postprocessData::fieldsDataBase::updateReservedField
+(
+ const word& name,
+ bool forceUpdate
+)
+{
+ if(name == "one")
+ {
+ if constexpr( std::same_as)
+ {
+ return createOrGetOne(forceUpdate);
+ }
+ else
+ {
+ fatalErrorInFunction
+ << "This type: "
+ << getTypeName()
+ <<" is not supported for field one."<)
+ {
+ return createOrGetVolume(forceUpdate);
+ }
+ else
+ {
+ fatalErrorInFunction
+ << "This type: "
+ << getTypeName()
+ <<" is not supported for field volume."<)
+ {
+ return createOrGetDensity(forceUpdate);
+ }
+ else
+ {
+ fatalErrorInFunction
+ << "This type: "
+ << getTypeName()
+ <<" is not supported for field density."<)
+ {
+ return createOrGetMass(forceUpdate);
+ }
+ else
+ {
+ fatalErrorInFunction
+ << "This type: "
+ << getTypeName()
+ <<" is not supported for field mass."<)
+ {
+ return createOrGetI(forceUpdate);
+ }
+ else
+ {
+ fatalErrorInFunction
+ << "This type: "
+ << getTypeName()
+ <<" is not supported for field I."<)
+ {
+ return updatePoints(forceUpdate);
+ }
+ else
+ {
+ fatalErrorInFunction
+ << "This type: "
+ << getTypeName()
+ <<" is not supported for field position."<(nullptr, 0);
+
+}
+
+#endif //__fieldsDataBaseTemplates_hpp__
\ No newline at end of file
diff --git a/src/PostprocessData/fieldsDataBase/simulationFieldsDataBase.cpp b/src/PostprocessData/fieldsDataBase/simulationFieldsDataBase.cpp
new file mode 100644
index 00000000..b4e19f6a
--- /dev/null
+++ b/src/PostprocessData/fieldsDataBase/simulationFieldsDataBase.cpp
@@ -0,0 +1,71 @@
+#include "Time.hpp"
+#include "simulationFieldsDataBase.hpp"
+#include "dynamicPointStructure.hpp"
+#include "vocabs.hpp"
+
+
+
+bool pFlow::postprocessData::simulationFieldsDataBase::pointFieldNameExists(const word &name) const
+{
+ return time().lookupObjectName(name);
+}
+
+bool pFlow::postprocessData::simulationFieldsDataBase::loadPointFieldToTime(const word &name)
+{
+ return time().lookupObjectName(name);
+}
+
+bool pFlow::postprocessData::simulationFieldsDataBase::loadPointStructureToTime()
+{
+ // it is already in the Time object
+ return time().lookupObjectName(pointStructureFile__);
+}
+
+
+const pFlow::shape& pFlow::postprocessData::simulationFieldsDataBase::getShape() const
+{
+ return shape_;
+}
+
+pFlow::word pFlow::postprocessData::simulationFieldsDataBase::getPointFieldType
+(
+ const word &name
+) const
+{
+ word pfType = time().lookupObjectTypeName(name);
+ word type, space;
+ if(!fieldsDataBase::pointFieldGetType(pfType, type, space))
+ {
+ fatalErrorInFunction
+ <<"Error in retriving the type of pointField "
+ << pfType<(*control.caseSetup().lookupObjectPtr(shapeFile__))
+ )
+{
+}
+
+const pFlow::pointStructure &pFlow::postprocessData::simulationFieldsDataBase::pStruct() const
+{
+ return
+ static_cast
+ (
+ time().lookupObject(pointStructureFile__)
+ );
+}
+
diff --git a/src/PostprocessData/fieldsDataBase/simulationFieldsDataBase.hpp b/src/PostprocessData/fieldsDataBase/simulationFieldsDataBase.hpp
new file mode 100644
index 00000000..298a4957
--- /dev/null
+++ b/src/PostprocessData/fieldsDataBase/simulationFieldsDataBase.hpp
@@ -0,0 +1,82 @@
+/*------------------------------- 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 __simulationFieldsDataBase_hpp__
+#define __simulationFieldsDataBase_hpp__
+
+#include "fieldsDataBase.hpp"
+
+namespace pFlow::postprocessData
+{
+
+class simulationFieldsDataBase
+:
+ public fieldsDataBase
+{
+private:
+
+ const shape& shape_;
+
+protected:
+
+ /// check if pointField name exists in Time or time folder
+ bool pointFieldNameExists(const word& name)const override;
+
+
+ /// Loads a pointField with a given name to the Time object.
+ /// For simulation, it just checks if the name exists
+ bool loadPointFieldToTime(const word& name) override;
+
+ /// Loads pointStructure to the Time object
+ /// For simulation, it just checks if the name exists
+ bool loadPointStructureToTime() override;
+
+ const shape& getShape() const override;
+
+ word getPointFieldType(const word& name)const override;
+
+public:
+
+ TypeInfo("fieldsDataBase");
+
+ simulationFieldsDataBase(
+ systemControl& control,
+ const dictionary& postDict,
+ bool inSimulation,
+ timeValue startTime);
+
+ ~simulationFieldsDataBase() override = default;
+
+ add_vCtor
+ (
+ fieldsDataBase,
+ simulationFieldsDataBase,
+ bool
+ );
+
+ const pointStructure& pStruct()const override;
+
+};
+
+
+}
+
+
+#endif //__simulationFieldsDataBase_hpp__
\ No newline at end of file
diff --git a/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAvMassVelocity.cpp b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAvMassVelocity.cpp
new file mode 100644
index 00000000..b64ba902
--- /dev/null
+++ b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAvMassVelocity.cpp
@@ -0,0 +1,25 @@
+#include "PostprocessOperationAvMassVelocity.hpp"
+
+namespace pFlow::postprocessData
+{
+
+PostprocessOperationAvMassVelocity::PostprocessOperationAvMassVelocity
+(
+ const dictionary &opDict,
+ const regionPoints ®Points,
+ fieldsDataBase &fieldsDB
+)
+:
+ PostprocessOperationAverage
+ (
+ opDict,
+ opDict.getValOrSet