129 Commits

Author SHA1 Message Date
0d9de2c601 Merge pull request #222 from PhasicFlow/main
from main
2025-05-02 23:04:23 +03:30
b4bc724a68 readme helical 2025-05-02 22:28:56 +03:30
ee33469295 readme helical 2025-05-02 22:26:38 +03:30
3933d65303 yaml update5 2025-05-02 22:03:16 +03:30
cf4d22c963 yaml update4 2025-05-02 21:59:31 +03:30
86367c7e2c yaml update3 2025-05-02 21:51:03 +03:30
a7e51a91aa yaml update2 2025-05-02 21:46:43 +03:30
5e56bf1b8c yaml update1 2025-05-02 21:28:40 +03:30
343ac1fc04 yaml update 2025-05-02 21:27:23 +03:30
6b04d17c7f sync-wiki to process img<> tags 2025-05-02 20:47:21 +03:30
97f46379c7 image resize 2025-05-02 20:25:20 +03:30
32fd6cb12e features update 2025-05-02 20:06:49 +03:30
be16fb0684 tutorials link added 2025-05-02 18:29:08 +03:30
4c96c6fa1e test 2025-04-30 19:01:51 +03:30
196b7a1833 how to build readme.md to wiki 2025-04-30 18:52:15 +03:30
316e71ff7a test readme.md 2025-04-30 18:36:53 +03:30
7a4a33ef37 a new workflow for readme.md files to wiki 2025-04-30 18:34:53 +03:30
edfbdb22e9 readmd.md update8 2025-04-30 08:56:11 +03:30
c6725625b3 readmd.md update7 2025-04-30 08:45:28 +03:30
253d6fbaf7 readmd.md update6 2025-04-30 08:40:46 +03:30
701baf09e6 readmd.md update5 2025-04-30 08:37:17 +03:30
20c94398a9 readmd.md update4 2025-04-30 08:34:51 +03:30
dd36e32da4 readmd.md update3 2025-04-30 08:31:19 +03:30
a048c2f5d7 readmd.md update2 2025-04-30 08:27:07 +03:30
8b324bc2b6 readmd.md update1 2025-04-30 08:18:29 +03:30
c7f790a1fa readmd.md update 2025-04-30 08:14:10 +03:30
166d7e72c2 rrr 2025-04-29 20:23:08 +03:30
c126f9a8a3 rr 2025-04-29 20:19:25 +03:30
7104a33a4b r 2025-04-29 20:14:34 +03:30
16b6084d98 readme update 2025-04-29 20:10:06 +03:30
2afea7b273 workflow update 2025-04-29 20:09:22 +03:30
2c5b4f55d1 readme.test 2025-04-29 20:01:13 +03:30
a7dc69a801 Merge branch 'main' of github.com:PhasicFlow/phasicFlow 2025-04-29 19:59:36 +03:30
32287404fa workflow update 2025-04-29 19:54:20 +03:30
8b3530c289 Merge pull request #221 from wanqing0421/benchmarks
update phasicFlow snapshot
2025-04-29 19:47:25 +03:30
d8c3fc02d5 update phasicFlow snapshot 2025-04-29 20:46:30 +08:00
4dab700a47 update image 2025-04-29 20:30:10 +08:00
a50ceeee2c update readme and figure 2025-04-29 20:25:00 +08:00
468730289b test for wiki 2025-04-28 23:06:29 +03:30
27f0202002 workflow for wiki 2025-04-28 23:04:42 +03:30
c69bfc79e1 endsolid bug fix for space separated names 2025-04-28 19:42:49 +03:30
69909b3c01 bug fix in reading stl file 2025-04-28 13:56:21 +03:30
8986c47b69 readmd.md for benchmark is updated 2025-04-28 12:25:53 +03:30
37282f16ac Merge branch 'PhasicFlow:main' into importStl 2025-04-28 09:35:49 +08:00
cd051a6497 Merge pull request #220 from wanqing0421/benchmarks
update readme
2025-04-27 21:57:40 +03:30
8b5d14afe6 update readme figure 2025-04-28 02:20:42 +08:00
eb37affb94 update readme 2025-04-28 02:17:04 +08:00
c0d12f4243 Merge pull request #219 from PhasicFlow/postprocessPhasicFlow
diameter -> distance for benchmarks
2025-04-27 21:08:04 +03:30
a1b5a9bd5d Merge pull request #218 from wanqing0421/benchmarks
upload readme for benchmarks
2025-04-27 20:59:37 +03:30
dc0edbc845 diameter -> distance for benchmarks 2025-04-26 21:22:59 +03:30
b423b6ceb7 upload readme for benchmarks 2025-04-26 15:17:57 +08:00
1f6a953154 fix bug when endsolid with a suffix name 2025-04-26 14:58:56 +08:00
bbd3afea0e Merge pull request #216 from PhasicFlow/postprocessPhasicFlow
readme.md for geometryPhasicFlow
2025-04-25 21:04:53 +03:30
53f0e959b0 readme.md for geometryPhasicFlow 2025-04-25 21:04:18 +03:30
c12022fb19 Merge pull request #215 from wanqing0421/importStl
add scale and transform function during the stl model importing process
2025-04-25 20:45:53 +03:30
d876bb6246 correction for tab 2025-04-26 01:13:42 +08:00
cb40e01b7e Merge pull request #206 from wanqing0421/main
fixed selectorStride bug
2025-04-25 20:35:11 +03:30
5f6400c032 add scale and transform function during the stl model importing process 2025-04-26 00:43:56 +08:00
8863234c1c update stride selector 2025-04-25 23:11:19 +08:00
1cd64fb2ec Merge branch 'PhasicFlow:main' into main 2025-04-25 23:00:10 +08:00
3fc121ef2b Merge pull request #214 from PhasicFlow/postprocessPhasicFlow
readme.md files update
2025-04-25 16:42:06 +03:30
953059cec5 tutorials readme.md 2025-04-25 16:37:24 +03:30
2593e2acf1 diameter->distance, update in tutorials, v-Blender readme.md 2025-04-25 16:14:16 +03:30
7c3b90a22d tutorials-1 after diameter->distance 2025-04-25 14:17:09 +03:30
72b9b74cc9 Merge pull request #213 from PhasicFlow/postprocessPhasicFlow
readme.md for particlesPhasicFlow and change diameter to distance in …
2025-04-25 11:38:49 +03:30
a545acb374 readme.md for particlesPhasicFlow and change diameter to distance in dict files 2025-04-25 11:36:46 +03:30
59fbee9711 Merge pull request #212 from PhasicFlow/postprocessPhasicFlow
Postprocess phasic flow
2025-04-25 09:29:02 +03:30
6cc4b3954a readme.md file for pFlowToVTK 2025-04-25 09:26:56 +03:30
d8c9135700 readme.md file for postprocessPhasicFlow 2025-04-25 00:40:41 +03:30
544624d579 Merge pull request #211 from PhasicFlow/postProcessing
pFlow -> pFlow::postprocessData
2025-04-24 23:40:34 +03:30
cbac1e97b5 pFlow -> pFlow::postprocessData 2025-04-24 23:39:31 +03:30
8c543e1649 Merge pull request #210 from PhasicFlow/postProcessing
Post processing readme.md
2025-04-24 23:32:46 +03:30
be807e4a71 change of namespace from pFlow to pFlow::postprocessData 2025-04-24 23:31:43 +03:30
d5ea338ab3 spell check readme.md 2025-04-24 14:41:31 +03:30
a448ce5f8d minor changes to readme.md 2025-04-24 14:28:28 +03:30
e2582f5fd9 minor change to readme.md 2025-04-24 14:18:08 +03:30
f2e8e69899 prime2 is added and readme update 2025-04-24 14:08:17 +03:30
a9e5b9bb59 Update readme.md 2025-04-23 01:19:10 +03:30
77eda47a87 Merge pull request #209 from PhasicFlow/postProcessing
corrections for readme.md file postprocessing
2025-04-23 01:08:36 +03:30
acb8d0e4eb corrections for readme.md file postprocessing 2025-04-23 01:08:03 +03:30
19fa3e2822 Merge pull request #208 from PhasicFlow/postProcessing
readme.md file is added for postprocessing
2025-04-23 00:48:16 +03:30
73f4b35fd4 readme.md file is added for postprocessing 2025-04-23 00:47:03 +03:30
5f8ea2d841 fixed selectorStride bug 2025-04-22 14:46:12 +08:00
8da8afbe63 V-blender finalized for v-1.0 2025-04-21 15:52:51 +03:30
cde93e953e Merge pull request #202 from PhasicFlow/postprocessPhasicFlow
postprocessPhasicFlow is now updated with new postprocessData auxFunc…
2025-04-21 10:29:55 +03:30
c80ee030db Merge pull request #200 from wanqing0421/benchmarks
Benchmarks of rotatingDrum
2025-04-21 10:26:21 +03:30
b679b9dcd3 Merge pull request #203 from Nimajhi/main
corrections for V-blender
2025-04-21 10:05:21 +03:30
1a2ad8ffa3 Merge pull request #201 from wanqing0421/main
fixed the cuda compilation error
2025-04-21 00:17:48 +03:30
9de1fa2dc7 postprocessPhasicFlow is now updated with new postprocessData auxFunction. It now uses postprocessDataDict. 2025-04-21 00:13:54 +03:30
b33fb61672 fixed the cuda compilation error 2025-04-21 03:07:06 +08:00
245ff9608f update rotatingDrum benchmarks 2025-04-21 01:50:57 +08:00
58ef463021 Merge branch 'PhasicFlow:main' into benchmarks 2025-04-21 01:47:29 +08:00
1100556d72 minor correction 2025-04-20 18:49:36 +03:30
14954b3ca6 minor correction 2025-04-20 14:15:31 +03:30
3710b19614 minor correction 2025-04-20 14:09:04 +03:30
40deb1f9c0 PostprocessData-update to work after simulation too
Postprocessing: IncludeMask documentation
2025-04-18 15:36:02 +03:30
d69203168e PostprocessData update
Modifications on fieldsDataBase to work both during simulation and post-simulation
Some bug fixes and changes to the code based
Correction for region volume
2025-04-18 15:32:53 +03:30
61be8c60fb Merge branch 'main' into postProcessing 2025-04-17 02:43:37 +03:30
549cb2ffdc Merge branch 'main' of github.com:PhasicFlow/phasicFlow 2025-04-17 02:42:25 +03:30
98a30bc98c keepHistory for integration to automatically remove the fields related to integration. The default is no save on the disk 2025-04-17 02:41:36 +03:30
7c9a724174 Postprocessing: IncludeMask documentation 2025-04-15 22:20:00 +03:30
abd36d4ae7 Merge pull request #198 from PhasicFlow/postProcessing
Post processing
2025-04-15 21:36:37 +03:30
35f10e5a94 Operations averge, mass velocity and region multisphereRegion are added 2025-04-15 21:30:54 +03:30
093160ba32 Postprocess framework
- Executed has been completed and testd.
- regions multipleSpheres are compelete
- Docs for regions is comelete.
2025-04-15 21:27:49 +03:30
077f25842a Merge branch 'main' of github.com:PhasicFlow/phasicFlow 2025-04-11 10:17:20 +03:30
d136ac0262 autoComplete improved for better time folder filtering and fields improved for better field filtering 2025-04-11 10:13:53 +03:30
c3acea1415 Merge pull request #197 from PhasicFlow/postProcessing
Post processing - merge to main
2025-04-10 21:23:58 +03:30
8e87333973 Push after adding PostptocessData lib 2025-04-10 21:22:35 +03:30
162cfd3b6a The main structure is tested. functons like execute and write are added and tested.
other components are left
2025-04-10 21:16:31 +03:30
ab7f700ead first commit for post-processing
- the whole structure is ready.
- next step whould be execute methods and then write methods
- post-processing after simulation is not started yet.
2025-04-09 19:47:57 +03:30
671b929f52 Merge branch 'PhasicFlow:main' into benchmarks 2025-04-07 11:30:52 +08:00
c78ab398f6 Merge pull request #195 from dalg24/patch-1
Update Kokkos dependencies description in README
2025-03-28 17:08:57 +03:30
d1189c0b2c Update Kokkos dependencies description in README 2025-03-28 07:55:36 -04:00
ccb7a6dd41 Update README.md 2025-03-27 02:50:30 +03:30
9e3bb1cfa1 Contribution-readme
Update README.md
2025-03-27 02:09:52 +03:30
7bb0a0453a Update README.md 2025-03-27 02:09:29 +03:30
577a94d07b Contribute README.md 2025-03-27 02:07:32 +03:30
5fee39cdd8 Update codingStyle.md
doxygen documentation is added
2025-03-24 17:21:50 +03:30
8fe63cca53 Create codingStyle.md 2025-03-24 14:45:05 +03:30
7b534a9e91 Merge branch 'PhasicFlow:main' into benchmarks 2025-03-22 21:17:33 +08:00
97e6592524 Merge pull request #192 from wanqing0421/main
fix the cuda build error with multiRotatingAxis
2025-03-20 01:03:30 +03:30
b7d47a65ad fix the cuda build error with multiRotatingAxis 2025-03-20 00:55:46 +08:00
3441b03167 Merge pull request #191 from PhasicFlow/multiRotatingAxis
Multi rotating axis
2025-03-19 18:14:09 +03:30
340f3a551a Multirotating axis motion for version 1.0 2025-03-19 18:10:50 +03:30
be7b2eb632 multiRotaingAxis debug 2025-03-16 22:08:07 +08:00
71057e9575 fill the multiRotatingAxis 2025-03-16 15:15:49 +08:00
0613b15c93 init commit of rotatingDrum 2025-03-16 00:56:31 +08:00
797334af87 adapt the multiRotatingAxisMotion to v-1.0 2025-03-16 00:36:38 +08:00
5eef26a6ed Bug fix for memory leak on CPU
- the call for tbb is disabled.
- parallel sort of Kokkos is also very slow.
- for now, std::sort is used for sort, which is more performant than both avaible options. This would be changed anytime any possible solution is found.
2025-03-15 17:15:32 +03:30
298 changed files with 14701 additions and 4621 deletions

153
.github/scripts/sync-wiki.py vendored Executable file
View File

@ -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'<img\s+src=[\'"]([^\'"]+)[\'"]'
def replace_link(match):
link_text = match.group(1)
link_url = match.group(2)
# Skip if already absolute URL or anchor
if link_url.startswith(('http://', 'https://', '#', 'mailto:')):
return match.group(0)
# Get the directory of the source file
source_dir = os.path.dirname(source_path)
# Create absolute path from repository root
if link_url.startswith('/'):
# If link starts with /, it's already relative to repo root
abs_path = link_url
else:
# Otherwise, it's relative to the file location
abs_path = os.path.normpath(os.path.join(source_dir, link_url))
if not abs_path.startswith('/'):
abs_path = '/' + abs_path
# Convert to GitHub URL
github_url = f"{REPO_URL}/blob/main{abs_path}"
return f"[{link_text}]({github_url})"
def replace_img_src(match):
img_src = match.group(1)
# Skip if already absolute URL
if img_src.startswith(('http://', 'https://')):
return match.group(0)
# Get the directory of the source file
source_dir = os.path.dirname(source_path)
# Create absolute path from repository root
if img_src.startswith('/'):
# If link starts with /, it's already relative to repo root
abs_path = img_src
else:
# Otherwise, it's relative to the file location
abs_path = os.path.normpath(os.path.join(source_dir, img_src))
if not abs_path.startswith('/'):
abs_path = '/' + abs_path
# Convert to GitHub URL (use raw URL for images)
github_url = f"{REPO_URL}/raw/main{abs_path}"
return f'<img src="{github_url}"'
# Replace all markdown links
content = re.sub(md_pattern, replace_link, content)
# Replace all img src tags
content = re.sub(img_pattern, replace_img_src, content)
return content
def process_file(source_file, target_wiki_page):
"""Process a markdown file and copy its contents to a wiki page."""
source_path = os.path.join(REPO_PATH, source_file)
target_path = os.path.join(WIKI_PATH, f"{target_wiki_page}.md")
print(f"Processing {source_path} -> {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()

18
.github/workflows/markdownList.yml vendored Normal file
View File

@ -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-PhasicFlowv1.0
- source: tutorials/README.md
target: Tutorials
- source: doc/mdDocs/phasicFlowFeatures.md
target: Features-of-PhasicFlow
# Add more mappings as needed

60
.github/workflows/sync-wiki.yml vendored Normal file
View File

@ -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

View File

@ -17,27 +17,36 @@ Ongoing development includes the integration of MPI-based parallelization with d
5. **Hybrid Parallelism:** MPI + OpenMP.
6. **Multi-GPU Parallelism:** MPI + CUDA.
# **Build and Installation**
## **Build and Installation**
PhasicFlow can be compiled for both CPU and GPU execution.
* **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**
## **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**
### **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).
# **PhasicFlowPlus: Coupled CFD-DEM Simulations**
## 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):
@ -58,9 +67,10 @@ If you are using PhasicFlow in your research or industrial work, cite the follow
}
```
# **Dependencies**
## **Dependencies**
PhasicFlow relies on the following external libraries:
* **Kokkos:** A performance portability ecosystem developed by National Technology & Engineering Solutions of Sandia, LLC (NTESS). ([https://github.com/kokkos/kokkos](https://github.com/kokkos/kokkos))
* **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))

View File

@ -0,0 +1 @@
# Helical Mixer Benchmark (phasicFlow v-1.0)

7
benchmarks/readme.md Normal file
View File

@ -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)

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

View File

@ -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
<div align="center">
<img src="./images/commericalDEMsnapshot.png"/>
<div align="center">
<p>Figure 1. Commercial DEM simulation snapshot</p>
</div>
</div>
<div align="center">
<img src="./images/phasicFlow_snapshot.png"/>
<div align="center">
<p>Figure 2. phasicFlow simulation snapshot and visualized using Paraview</p>
</div>
</div>
### Hardware Specifications
<div align="center">
Table 1. Hardware specifications used for benchmarking.
</div>
| 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
<div align="center">
Table 2. Parameters for rotating drum simulations.
</div>
| 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
<div align="center">
Table 3. Total calculation time (minutes) for different configurations.
</div>
| 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
<div align="center">
<img src="./images/performance1.png"/>
<p>Figure 3. Calculation time comparison between phasicFlow and the well-established commercial DEM software.</p>
</div>
### Memory Usage
<div align="center">
Table 4. Memory consumption for different configurations.
</div>
| 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.

View File

@ -19,7 +19,7 @@ contactSearch
{
method NBS;
updateInterval 10;
updateInterval 20;
sizeRatio 1.1;

View File

@ -2,12 +2,14 @@
| phasicFlow File |
| copyright: www.cemf.ir |
\* ------------------------------------------------------------------------- */
objectName particleInsertion;
objectType dicrionary;
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

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -6,13 +6,13 @@ objectName settingsDict;
objectType dictionary;
fileFormat ASCII;
/*---------------------------------------------------------------------------*/
run rotatingDrum_4MParticles;
run rotatingDrum_1mParticles;
dt 0.00001; // time step for integration (s)
startTime 0; // start time for simulation
endTime 10; // end time for simulation
endTime 4; // end time for simulation
saveInterval 0.2; // time interval for saving the simulation
@ -31,4 +31,4 @@ writeFormat binary; // data writting format (ascii or
timersReport Yes;
timersReportInterval 0.05;
timersReportInterval 0.01;

View File

@ -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
}

View File

@ -2,9 +2,14 @@
| phasicFlow File |
| copyright: www.cemf.ir |
\* ------------------------------------------------------------------------- */
objectName particleInsertion;
objectType dicrionary;
objectName shapes;
objectType dictionary;
fileFormat ASCII;
/*---------------------------------------------------------------------------*/
active No; // is checked -> Yes or No
names (glassBead); // names of shapes
diameters (0.006); // diameter of shapes
materials (glassMat); // material names for shapes

View File

@ -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
#------------------------------------------------------------------------------

View File

@ -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
#------------------------------------------------------------------------------

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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;

View File

@ -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
}

View File

@ -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
#------------------------------------------------------------------------------

View File

@ -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
#------------------------------------------------------------------------------

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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;

View File

@ -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
}

View File

@ -3,10 +3,13 @@
| copyright: www.cemf.ir |
\* ------------------------------------------------------------------------- */
objectName particleInsertion;
objectType dicrionary;
objectName shapes;
objectType dictionary;
fileFormat ASCII;
/*---------------------------------------------------------------------------*/
active No; // is insertion active?
names (glassBead); // names of shapes
diameters (0.003); // diameter of shapes
materials (glassMat); // material names for shapes

View File

@ -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
#------------------------------------------------------------------------------

View File

@ -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
#------------------------------------------------------------------------------

View File

@ -8,12 +8,16 @@ fileFormat ASCII;
/*---------------------------------------------------------------------------*/
globalBox // Simulation domain: every particles that goes outside this domain will be deleted
{
min (-0.2 -0.2 -0.0);
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

View File

@ -35,7 +35,7 @@ surfaces
radius2 0.2; // radius at p2
resolution 24; // number of divisions
resolution 60; // number of divisions
material wallMat; // material name of this wall

View File

@ -27,7 +27,7 @@ positionParticles
orderedInfo
{
diameter 0.003; // minimum space between centers of particles
distance 0.003; // minimum space between centers of particles
numPoints 4000000; // number of particles in the simulation

View File

@ -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;

View File

@ -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
}

View File

@ -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

View File

@ -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
#------------------------------------------------------------------------------

View File

@ -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
#------------------------------------------------------------------------------

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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;

View File

@ -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
}

View File

@ -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

View File

@ -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
#------------------------------------------------------------------------------

View File

@ -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
#------------------------------------------------------------------------------

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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;

View File

@ -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]'
# 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
# Compaction
COMPREPLY=("${files[@]}")
AllTimeFolders="${files[@]}"
# Set completion reply to the time folders
COMPREPLY=("${time_folders[@]}")
AllTimeFolders="${time_folders[@]}"
}
__getFields(){
__getAllTime
local -A unique_files=()
# Files to exclude from suggestions
local exclude_files=("shapeHash" "pStructure" "particleInsertion" "p" "alpha" "U" "Sp" "Su" "phi")
declare -A exclude_dict
# Build exclude dictionary for faster lookups
for file in "${exclude_files[@]}"; do
exclude_dict["$file"]=1
done
for dir in $AllTimeFolders; do
# Check if the directory exists
if [ ! -d "$dir" ]; then
continue # Skip to the next directory
fi
# Skip if not a directory
[ ! -d "$dir" ] && continue
files_in_dir=$(find "$dir" -maxdepth 1 -type f -printf '%f\n' | sort -u)
# Add filenames to the associative array (duplicates will be overwritten)
# Find all files in this time directory
while IFS= read -r filename; do
unique_files["$filename"]=1 # Just the key is important, value can be anything
done <<< "$files_in_dir"
# 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
COMPREPLY=("${!unique_files[@]}")
# 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<COMP_CWORD; i++)); do
if [[ "${COMP_WORDS[i]}" == "--fields" ]]; then
is_field=1
break
fi
done
if [ "$prev" == "--time" ]; then
__getAllTime
elif [ "$3" == "--fields" ]; then
elif [ "$prev" == "--fields" ] || [ $is_field -eq 1 ]; then
# We're completing field names
__getFields
# Filter the results based on the current word prefix
if [ -n "$cur" ]; then
local filtered=()
for item in "${COMPREPLY[@]}"; do
if [[ "$item" == "$cur"* ]]; then
filtered+=("$item")
fi
done
COMPREPLY=("${filtered[@]}")
fi
else
COMPREPLY=( $(compgen -W "$PF_cFlags --binary --no-geometry --no-particles --out-folder --time --separate-surfaces --fields" -- "$2") )
COMPREPLY=( $(compgen -W "$PF_cFlags --binary --no-geometry --no-particles --out-folder --time --separate-surfaces --fields" -- "$cur") )
fi
}
complete -F _pFlowToVTK pFlowToVTK

231
doc/mdDocs/codingStyle.md Normal file
View File

@ -0,0 +1,231 @@
# PhasicFlow Coding Style Guidelines
This document outlines the coding style guidelines for the PhasicFlow codebase.
Adhering to these guidelines ensures consistency, readability, and maintainability of the project.
## 1. FormattingIndentation:
* Use 4 spaces for every logical level and block.
* Line Spacing: Leave two empty lines between sections (e.g., between functions in a .cpp file, between class members).
## 2. Naming ConventionsGeneral Naming:
* All names should start with lowercase letters, except for special names (e.g., Ergun, Hertz).
* Macro names start with Upper case or all the letters are in UPPER case.
* Compound Names: For compound names, the first word starts with a lowercase letter, and subsequent words start with an uppercase letter (e.g., boundaryBase, motionModel).
## 3. File Structure
* Header Files: Use the .hpp extension for header files.
* Source Files: Use the .cpp extension for source files.
* Header and Source File Headers: All header and source files must include a standardized header that describes the project's intention and licensing information.
* File Naming: Header and source file names should correspond to the class they contain. Aim for one class per file.
* Inline Functions: Place inline functions in a separate classNameI.hpp file to avoid cluttering the main header file.
## 4. Class DesignClass Member Order:
* Private members and methods
* Private static members and methods
* Public methods
* Public static methods
* Enumerations and Nested Classes: Declare enumerations and nested classes before all class members and methods.
* Special Functions: Each class must explicitly define all special functions:Constructor, Copy constructor and assignment operator, Move constructor and assignment operator
* Destructor: Each class must have an explicit destructor declaration:`~className() = default`; or `~className();`
* Interface classes or classes with virtual methods must have a virtual destructor.
* Virtual Method Overrides: When implementing a `virtual` method from a base class in a derived class, use the `override` keyword. The same applies to derived class destructors.
## 5. NamespacesOfficial Namespace:
The official namespace for the codebase is pFlow. All entities should be defined within this namespace.
### Example File Structure
```
src/
├── componentName1/
│ ├── componentName1.hpp
│ ├── componentName1.cpp
│ ├── componentName1I.hpp
│ └── ...
└── componentName2/
├── componentName2.hpp
├── componentName2.cpp
└── ...
```
### Example Class Structure
```C++
namespace pFlow
{
class MyClass
{
public:
enum class MyEnum
{
Value1,
Value2
};
class NestedClass
{
// ...
};
private:
int privateMember_;
void privateMethod();
static int privateStaticMember_;
static void privateStaticMethod();
public:
MyClass();
MyClass(const MyClass& other);
MyClass(MyClass&& other);
MyClass& operator=(const MyClass& other);
MyClass& operator=(MyClass&& other);
~MyClass();
void publicMethod();
static void publicStaticMethod();
};
// assuming base class has virtual methods
class DerivedClass
:
public BaseClass
{
public:
...
~DerivedClass() override;
void virtualMethod() override;
};
} // namespace pFlow
```
## 6. Doxygen Documentation
### 6.1. Ruls
provide the documentations in the header files only. In rare cases where you are generating documentations for executables, the doxygen documentation can be supplied in the .cpp file.
* **General Doxygen Style:**
* Use `///` for short documentations for methods and members.
* Use `/** */` for classes and main methods which play a significant role in the class or code.
* Place Doxygen comments *before* the declaration of the entity being documented (e.g., class, function, variable).
* Use `@param` to document function parameters, `@return` for return values, `@brief` for a short description, and `@details` for a more in-depth explanation.
* Use Markdown syntax within Doxygen comments for formatting.
* **File Headers:** Each file should contain a Doxygen comment at the top, including:
* `@file` : The name of the file.
* `@brief`: A brief description of the file's purpose.
* `@author`: The author(s) of the file.
* `@date` : The date of creation or last modification.
* **Class Documentation:**
* Use `/** */` for class documentation.
* Provide a `@brief` description of the class.
* Use `@tparam` to document template parameters.
* Document the purpose of the class, its invariants, and how it should be used.
* **Function/Method Documentation:**
* Use `///` for short documentations.
* Use `/** */` for main methods which play a significant role.
* Provide a `@brief` description of the function.
* Use `@param` to describe each parameter, including its purpose and whether it is an input, output, or input/output parameter.
* Use `@return` to describe the return value, including its meaning and possible values.
* Use `@pre` to document any preconditions that must be met before calling the function.
* Use `@post` to document any postconditions that will be true after the function returns.
* Use `@throws` to document any exceptions that the function may throw.
* Use `@details` for a more detailed explanation of the function's behavior, algorithms, or any other relevant information.
* **Variable Documentation:**
* Use `///<` for single-line documentation of variables.
### 6.2. Doxygen Documentation Examples
* **Class example**
```cpp
/**
* @brief Represents a particle in the simulation.
* @details This class stores the position, velocity, and other physical
* properties of a particle.
*/
class Particle
{
private:
Point position_; ///< The current position of the particle.
Vector velocity_; ///< The current velocity of the particle.
double mass_; ///< The mass of the particle.
public:
/// Constructs a particle with default values.
Particle();
/**
* @brief Updates the position of the particle based on its velocity
* and the given time step.
* @param deltaTime The time elapsed since the last update, in seconds.
*/
void updatePosition(const timeInfo& ti );
/// Gets the current position of the particle.
Point getPosition() const;
};
```
* **Function Example**
```cpp
/**
* @brief Calculates the distance between two points.
* @param p1 The first point.
* @param p2 The second point.
* @return The distance between the two points.
*/
double calculateDistance(const Point& p1, const Point& p2)
{
// Implementation
return 0.0;
}
/// Returns the velocity of the particle.
Vector getVelocity() const
{
return velocity_;
}
```

View File

@ -0,0 +1,136 @@
# How to build PhasicFlow-v-1.0
You can build PhasicFlow for CPU or GPU. You can have a single build or oven multiple builds on a machine. Here you learn how to have a single build of PhasicFlow, in various modes of execution. You can install PhasicFlow-v-1.0 on **Ubuntu-22.04 LTS** and **Ubuntu-24.04 LTS**. Installing it on older versions of Ubuntu needs some additional steps to meet the requirements which are not covered here.
If you want to install PhasicFlow on **Windows OS**, just see [this page](https://www.cemf.ir/installing-phasicflow-v-1-0-on-ubuntu/) for more information.
# Required packages
You need a list of packages installed on your computer before building PhasicFlow:
* git, for cloning the code and package management
* g++, for compiling the code
* cmake, for generating build system
* Cuda-12.x or above (if GPU is targeted), for compiling the code for CUDA execution.
### Installing packages
Execute the following commands to install the required packages (Except Cuda). tbb is installed automatically.
```bash
sudo apt update
sudo apt install -y git g++ cmake cmake-qt-gui
```
### Installing Cuda for GPU execution
If you want to build PhasicFlow to be executed on an nvidia-GPU, you need to install the latest version of Cuda compiler (Version 12.x or above), which is compatible with your hardware and OS, on your computer.
# How to build?
Here you will learn how to build PhasicFlow for single execution mode. Follow the steps below to install it on your computer.
Tested operating systems are:
* Ubuntu-22.04 LTS
* Ubuntu-24.04 LTS
### Step 1: Package check
Make sure that you have installed all the required packages on your computer. See above for more information.
### Step 2: Cloning PhasicFlow
Create the PhasicFlow folder in your home folder and then clone the source code into that folder:
```bash
cd ~
mkdir PhasicFlow
cd PhasicFlow
git clone https://github.com/PhasicFlow/phasicFlow.git
mv phasicFlow phasicFlow-v-1.0
```
### Step 3: Environmental variables
Opne the bashrc file using the following command:
```bash
$ gedit ~/.bashrc
```
and add the following line to the end of the file, **save** and **close** it.
```bash
source $HOME/PhasicFlow/phasicFlow-v-1.0/cmake/bashrc
```
this will introduce a new source file for setting the environmental variables of PhasicFlow. If you want to load these variables in the current open terminal, you need to source it. Or, simply **close the terminal** and **open a new terminal**.
### Step 4: Building PhasicFlow
Follow one of the followings to build PhasicFlow for one mode of execution.
#### Serial build for CPU
In a **new terminal** enter the following commands:
```bash
cd ~/PhasicFlow/phasicFlow-v-1.0
mkdir build
cd build
cmake ../ -DpFlow_Build_Serial=On -DCMAKE_BUILD_TYPE=Release
make install -j4
```
For faster builds, use `make install -j`. This will use all the CPU cores on your computer for building.
#### OpenMP build for CPU
```bash
cd ~/PhasicFlow/phasicFlow-v-1.0
mkdir build
cd build
cmake ../ -DpFlow_Build_OpenMP=On -DCMAKE_BUILD_TYPE=Release
make install -j4
```
#### GPU build for parallel execution on CUDA-enabled GPUs
```bash
cd ~/PhasicFlow/phasicFlow-v-1.0
mkdir build
cd build
cmake ../ -DpFlow_Build_Cuda=On -DCMAKE_BUILD_TYPE=Release
cmake ../ -DpFlow_Build_Cuda=On -DCMAKE_BUILD_TYPE=Release
make install -j4
```
After building, `bin`, `include`, and `lib` folders will be created in `~/PhasicFlow/phasicFlow-v-1.0/` folder. Now you are ready to use PhasicFlow.
**note 1**: When compiling the code in parallel, you need to have enough RAM on your computer. As a rule, you need 1 GB free RAM per each processor on your computer for compiling in parallel.
You may want to use fewer number of cores on your computer by using the following command:
```bash
make install -j3
```
the above command only uses 3 cores for compiling.
**note 2**: By default PhasicFlow is compiled with **double** as floating point variable. You can compile it with **float**. Just in the command line of camke added `-DpFlow_Build_Double=Off` flag to compile it with float. For example if you are building for cuda, you can enter the following command:
```bash
cmake ../ -DpFlow_Build_Cuda=On -DpFlow_Build_Double=Off
```
### Step 5: Testing
In the current terminal or a new terminal enter the following command:
```bash
checkPhasicFlow
```
This command shows the host and device environments and software version. If PhasicFlow was build correctly, you would get the following output:
```
Initializing host/device execution spaces . . .
Host execution space is Serial
Device execution space is Serial
You are using phasicFlow v-1.0 (copyright(C): www.cemf.ir)
In this build, double is used for floating point operations and uint32for indexing.
This is not a build for MPI execution
Finalizing host/device execution space ....
```

View File

@ -1,151 +0,0 @@
# How to build PhasicFlow {#howToBuildPhasicFlow}
You can build PhasicFlow for CPU or GPU. You can have a single build or oven multiple builds on a machine. Here you learn how to have a single build of PhasicFlow, in various modes of execution.
# Required packages
You need a list of packaged installed on your computer before building PhasicFlow:
* git, for cloning the code and package management
* g++, for compiling the code
* cmake, for generating build system
* tbb, a parallel library for STL algorithms
* Cuda (if GPU is targeted), for compiling the code for CUDA execution.
* Kokkos, the parallelization backend of PhasicFlow
### git
if git is not installed on your computer, enter the following commands
```
$ sudo apt update
$ sudo apt install git
```
### g++ (C++ compiler)
The code is tested with g++ (gnu C++ compiler). The default version of g++ on Ubuntu 18.04 LTS or upper is sufficient for compiling. If it is not installed on your operating system, enter the following command:
```
$ sudo apt update
$ sudo apt install g++
```
### CMake
You also need to have CMake-3.22 or higher installed on your computer.
```
$ sudo apt update
$ sudo apt install cmake
```
### tbb (2020.1-2 or higher)
For **Ubuntu 20.04 LTS or higher versions**, you can install tbb using apt. For now, some parallel algorithms on host side rely on tbb parallel library (C++ parallel backend). Use e following commands to install it:
```
$ sudo apt update
$ sudo apt install libtbb-dev
```
If you are compiling on **Ubuntu-18.04 LTS**, you need to enter the following commands to get the right version (2020.1-2 or higher) of tbb:
```
$ wget "http://archive.ubuntu.com/ubuntu/pool/universe/t/tbb/libtbb2_2020.1-2_amd64.deb"
$ sudo dpkg --install libtbb2_2020.1-2_amd64.deb
$ wget "http://archive.ubuntu.com/ubuntu/pool/universe/t/tbb/libtbb-dev_2020.1-2_amd64.deb"
$ sudo dpkg --install libtbb-dev_2020.1-2_amd64.deb
```
### Cuda
If you want to build PhasicFlow to be executed on an nvidia-GPU, you need to install the latest version of Cuda compiler, which is compatible with your hardware and OS, on your computer.
# How to build?
Here you will learn how to build PhasicFlow for single execution mode. Follow the steps below to install it on your computer.
Tested operating systems are:
* Ubuntu 18.04 LTS
* Ubuntu 20.04 LTS
* Ubuntu 22.04 LTS
### Step 1: Package check
Make sure that you have installed all the required packages on your computer. See above for more information.
### Step 2: Cloning Kokkos
It is assumed that Kokkos source is located in the home folder of your computer. Clone the latest version of Kokkos into your home folder:
```
$ cd ~
$ mkdir Kokkos
$ cd Kokkos
$ git clone https://github.com/kokkos/kokkos.git
```
or simply download and extract the source code of Kokkos in `~/Kokkos` folder. In the end, the top level CMakeLists.txt file should be located in `~/Kokkos/kokkos` folder.
### Step 3: Cloning PhasicFlow
Create the PhasicFlow folder in your home folder and then clone the source code into that folder:
```
$ cd ~
$ mkdir PhasicFlow
$ cd PhasicFlow
$ git clone https://github.com/PhasicFlow/phasicFlow.git
```
### Step 4: Environmental variables
Opne the bashrc file using the following command:
`$ gedit ~/.bashrc`
and add the following line to the end of the file, **save** and **close** it.
`source $HOME/PhasicFlow/phasicFlow/cmake/bashrc`
this will introduce a new source file for setting the environmental variables of PhasicFlow. If you want to load these variables in the current open terminal, you need to source it. Or, simply **close the terminal** and **open a new terminal**.
### Step 5: Building PhasicFlow
Follow one of the followings to build PhasicFlow for one mode of execution.
#### Serial build for CPU
In a **new terminal** enter the following commands:
```
$ cd ~/PhasicFlow/phasicFlow
$ mkdir build
$ cd build
$ cmake ../ -DpFlow_Build_Serial=On
$ make install
```
For faster builds, use `make install -j`. This will use all the CPU cores on your computer for building.
#### OpenMP build for CPU
```
$ cd ~/PhasicFlow/phasicFlow
$ mkdir build
$ cd build
$ cmake ../ -DpFlow_Build_OpenMP=On
$ make install
```
#### GPU build for parallel execution on CUDA-enabled GPUs
```
$ cd ~/PhasicFlow/phasicFlow
$ mkdir build
$ cd build
$ cmake ../ -DpFlow_Build_Cuda=On
$ make install
```
After building, `bin`, `include`, and `lib` folders will be created in `~/PhasicFlow/phasicFlow/` folder. Now you are ready to use PhasicFlow.
**note 1**: When compiling the code in parallel, you need to have enough RAM on your computer. As a rule, you need 1 GB free RAM per each processor in your computer for compiling in parallel.
You may want to use fewer number of cores on your computer by using the following command:
`$ make install -j 3`
the above command only uses 3 cores for compiling.
**note 2**: By default PhasicFlow is compiled with **double** as floating point variable. You can compile it with **float**. Just in the command line of camke added `-DpFlow_Build_Double=Off` flag to compile it with float. For example if you are building for cuda, you can enter the following command:
`$ cmake ../ -DpFlow_Build_Cuda=On -DpFlow_Build_Double=Off`
### Step 6: Testing
In the current terminal or a new terminal enter the following command:
`$ checkPhasicFlow`
This command shows the host and device environments and software version. If PhasicFlow was build correctly, you would get the following output:
```
Initializing host/device execution spaces . . .
Host execution space is Serial
Device execution space is Cuda
ou are using phasicFlow v-0.1 (copyright(C): www.cemf.ir)
In this build, double is used for floating point operations.
Finalizing host/device execution space ....
```

View File

@ -1,41 +1,74 @@
# PhasicFlow Features {#phasicFlowFeatures}
# PhasicFlow Features (v-1.0)
The features of PhasicFlow described here are the main features that are implemented in the code for version 1.0. This document is not a complete list of all the features of PhasicFlow. The features are being added to the code continuously and this document may be behind the latest updates. Of course, the code review will give you the complete list.
## Table of Contents
- [1. Building options](#1-building-options)
- [2. Preprocessing tools](#2-preprocessing-tools)
- [3. Solvers for simulations](#3-solvers-for-simulations)
- [4. Postprocessing tools](#4-postprocessing-tools)
- [5. Models and features for simulations](#5-models-and-features-for-simulations)
- [5.1. General representation of walls](#51-general-representation-of-walls)
- [5.2. High precision integeration methods](#52-high-precision-integeration-methods)
- [5.3. Contact force models](#53-contact-force-models-needs-improvement)
- [5.4. Particle insertion](#54-particle-insertion)
- [5.5. Restarting/resuming a simulation](#55-restartingresuming-a-simulation)
- [5.6. Postprocessing data during simulation](#56-postprocessing-data-during-simulation)
## 1. Building options
## Building options
You can build PhasicFlow to be executed on multi-core CPUs or GPUs. It is also possible to select the type of floating point variables in PhasicFlow: double or float. float type requires less memory and mostly consumes less time of a processor to complete a mathematical operation. So, there is a benefit for using floats in DEM simulation specially when GPU is targeted for computations.
Build options for PhasicFlow:
* **serial (double or float type)**: execution on one cpu core
* **OpenMp (double or float type)**: execution on multiple cores of a CPU
* **cuda (double or float type)**: execution on cuda-enabled GPUs
- **serial (double or float type)**: execution on one cpu core
- **OpenMp (double or float type)**: execution on multiple cores of a CPU
- **cuda (double or float type)**: execution on cuda-enabled GPUs
for more information on building PhasicFlow, please refer to the [installation guide](./howToBuild-V1.0.md).
## Preprocessing tools
Preprocessing tools are used to facilitate the process of case setup. They include tools for defining initial state of particles and geometry conversion.
* **particlesPhasicFlow** tool can be used to define the initial position of particles (for example at t = 0 s) and to set the initial field values for particles (like velocity, orientation, acceleration and etc).
* **geometryPhasicFlow** converts user inputs for walls into a data structures that is used by PhasicFlow.
## 2. Preprocessing tools
PhasicFlow provides a set of tools for preprocessing the simulation case. These tools are used to define the initial state of particles, walls and other parameters that are required for running a simulation.
- [**particlesPhasicFlow**](./../../utilities/particlesPhasicFlow/) tool can be used to define the initial position of particles (for example at t = 0 s) and to set the initial field values for particles (like velocity, orientation, acceleration, etc.).
## Models and features for simulations
- [**geometryPhasicFlow**](./../../utilities/geometryPhasicFlow/) converts user inputs for walls into a data structure that is used by PhasicFlow.
## 3. Solvers for simulations
### General representation of walls
- [**sphereGranFlow**](./../../solvers/sphereGranFlow/) is a solver for simulating the flow of spherical particles with particle insertion mechanism. A full set of tutorial on various possible simulations can be found here: [sphereGranFlow tutorial](./../../tutorials/sphereGranFlow/).
- [**grainGranFlow**](./../../solvers/grainGranFlow/) is a solver for simulating the flow of course-grained particles with particle insertion mechanism. A full set of tutorial on various possible simulations can be found here: [grainGranFlow tutorial](./../../tutorials/grainGranFlow/).
- [**iterateGeometry**](./../../solvers/iterateGeometry/) is a solver testing motion of walls without simulating particles. Since simulating with particles may take a long time and we may want to check the motion of geometry to be correct before actual simulation, we created this utility to test the motion of walls. A set of tutorial on various possible simulations can be found here: [iterateGeometry tutorial](./../../tutorials/iterateGeometry/).
## 4. Postprocessing tools
- [**pFlowToVTK**](./../../utilities/pFlowToVTK) is used to convert simulation results into vtk file format. vtk file format can be read by Paraview for visualizing the results.
- [**postprocessPhasicFlow**](./../../utilities/postprocessPhasicFlow/) is a tool for performing various averaging and summation on the fields. Particle probing is also possible.
## 5. Models and features for simulations
### 5.1. General representation of walls
Walls can be defined in three ways in PhasicFlow:
* **Builtin walls** in PhasicFlow that include plane wall, cylinder/cone wall, cuboid, circle.
* **stl wall** that reads the data of the wall from an ASCII stl file.
* **foamPatch wall** that reads the OpenFOAM mesh and converts the boundary patches into PhasicFlow walls (this feature is only available when performing CFD-DEM simulation using OpenFOAM).
Walls can be fixed or in motion during simulations. Various motion models are implemented to cover most of the wall motions in phasicFlow ([see the source code] (./../../../src/MotionModel/)):
* **fixedWall** model, in which all walls are fixed. This model is mostly useful for granular flow under gravity or gas-solid flows (CFD-DEM).
* **rotatingAxisMotion** model, in which walls are rotating around an axis of rotation with specified rotation speed. This model covers a wide range of granular flows in which the whole or a part of geometry is rotating, like mixers.
* **multiRotatingAxisMotion** model, in which a combination of rotations can be specified. One axis of rotation can itself have another axis of rotation, and so on. This creates the possibility of defining very complex motion pattern for walls, like what we see in Nauta blenders.
* **vibratingMotion** model, in which walls vibrates based on a sinusoidal model with specified frequency and amplitude.
- **Builtin walls** in PhasicFlow that include plane wall, cylinder/cone wall, cuboid, circle.
- **stl wall** that reads the data of the wall from an ASCII stl file.
- **foamPatch wall** that reads the OpenFOAM mesh and converts the boundary patches into PhasicFlow walls (this feature is only available when performing CFD-DEM simulation using OpenFOAM).
Walls can be fixed or in motion during simulations. Various motion models are implemented to cover most of the wall motions in phasicFlow ([see the source code](./../../src/MotionModel/)):
- **stationay** model, in which all walls are fixed. This model is mostly useful for granular flow under gravity or gas-solid flows (CFD-DEM).
- **rotatingAxis** model, in which walls are rotating around an axis of rotation with specified rotation speed. This model covers a wide range of granular flows in which the whole or a part of geometry is rotating, like mixers.
- **multiRotatingAxis** model, in which a combination of rotations can be specified. One axis of rotation can itself have another axis of rotation, and so on. This creates the possibility of defining very complex motion pattern for walls, like what we see in Nauta blenders.
- **vibrating** model, in which walls vibrates based on a sinusoidal model with specified frequency and amplitude.
In addition to these models, the user can add other motion models to the code based on their need.
### 5.2. High precision integeration methods
### High precision integeration methods
The precision of integration in a DEM simulation is very important. Since sudden changes in the interaction forces occur during simulations (when objects contact or when they rebound). High precision integration methods makes it possible to accurately track position and velocity of objects (specially when they are in contact). When using these methods, it is possible to choose larger time steps for integration without loosing accuracy and causing instability in the simulation. Although a high-precision integration requires more computations, but the benefits of choosing larger time steps in simulation can totally compensate it.
Various integration methods are implemented in PhasicFlow:
|Integration Method | Order | Type|
@ -44,21 +77,40 @@ Various integration methods are implemented in PhasicFlow:
| AdamsBashforth3 | 3 | one-step |
| AdamsBashforth4 | 4 | one-step |
| AdamsBashforth5 | 5 | one-step |
| AdamsMoulton3 | 3 | predictor-corrector |
| AdamsMoulton4 | 4 | predictor-corrector |
| AdamsMoulton5 | 5 | predictor-corrector |
| AdamsMoulton3 | 3 | predictor-corrector (not active)|
| AdamsMoulton4 | 4 | predictor-corrector (not active)|
| AdamsMoulton5 | 5 | predictor-corrector (not active)|
### 5.3. Contact force models (needs improvement)
### Contact force models
Linear and non-linear visco-elastic contact force models are considered in the simulation. In addition to these, limited and non-limited Coulomb's friction model can be used to account for the friction between objects. For spherical objects, rolling friction can also be specified between bodies in contact.
In addition, for course-grained particles simulation, we developed a speciall set of***
### Particle insertion
Particles can be inserted during simulation from specified region at specified rate and time interval. Any number of insertion regions can be defined in a simulation. Various region types are considered here: box, cylinder and sphere. Particles are inserted into the simulation through the specified region.
### 5.4. Particle insertion
### restarting/resuming a simulation
It is possible to resume a simulation fron any time-folder that is avaiable in the simulation case setup directory. PhasicFlow restart the simulation from that time folder.
Particles can be inserted during simulation from specified region at specified rate and time interval. Any number of insertion regions can be defined in a simulation. Various region types are considered here: `box`, `cylinder` and `sphere`. Particles are inserted into the simulation through the specified region.
## Postprocessing tools
### 5.5. restarting/resuming a simulation
* **pFlowToVTK** is used to convert simulation results into vtk file format. vtk file format can be read by Paraview for visualizing the results.
* **postprocessPhasicFlow** is a tool for performing various cell-based averaging on the fields.
It is possible to resume a simulation from any time-folder that is available in the simulation case setup directory. PhasicFlow restarts the simulation from that time folder.
### 5.6. Postprocessing data during simulation
PhasicFlow provides a powerful in-simulation postprocessing module that allows users to analyze particle data in real-time while the simulation is running. This feature enables:
- **Real-time data analysis** without waiting for simulation completion
- **Region-based processing** in spheres, along lines, or at specific points
- **Various statistical operations** including weighted averages and sums of particle properties
- **Individual particle tracking** to monitor specific particles throughout simulation
- **Multiple processing methods** including arithmetic mean, uniform distribution, and Gaussian distribution
- **Particle filtering** based on properties like diameter, mass, etc.
- **Flexible time control** options for when postprocessing should be executed
To activate in-simulation postprocessing, users need to:
1. Create a `postprocessDataDict` file in the `settings` directory with appropriate configurations
2. Add `libs ("libPostprocessData.so")` and `auxFunctions postprocessData` to the `settings/settingsDict` file
Results are written to output files in the case directory with timestamps, allowing users to monitor simulation behavior as it progresses without interrupting the simulation. for more information on how to use this feature, please refer to the [PostprocessData](./../../src/PostprocessData/) module.
The same postprocessing module can also be used after simulation completion through the [`postprocessPhasicFlow`](./../../utilities/postprocessPhasicFlow/) utility.

View File

@ -13,3 +13,5 @@ add_subdirectory(Interaction)
add_subdirectory(MotionModel)
add_subdirectory(PostprocessData)

View File

@ -21,7 +21,6 @@ Licence:
template<typename MotionModel>
bool pFlow::geometryMotion<MotionModel>::findMotionIndex()
{
if(motionComponentName().size() != numSurfaces() )
{
fatalErrorInFunction<<

View File

@ -28,4 +28,4 @@ template class pFlow::geometryMotion<pFlow::stationaryWall>;
template class pFlow::geometryMotion<pFlow::conveyorBeltMotion>;
//template class pFlow::geometryMotion<pFlow::multiRotatingAxisMotion>;
template class pFlow::geometryMotion<pFlow::multiRotatingAxisMotion>;

View File

@ -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<stationaryWall>;
using conveyorBeltMotionGeometry = geometryMotion<conveyorBeltMotion>;
//typedef geometryMotion<multiRotatingAxisMotion> multiRotationAxisMotionGeometry;
using multiRotationAxisMotionGeometry = geometryMotion<multiRotatingAxisMotion>;
}

View File

@ -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,

View File

@ -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;

View File

@ -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,

View File

@ -71,7 +71,8 @@ public:
const word& baseName,
pointStructure& pStruct,
const word& method,
const realx3Field_D& initialValField);
const realx3Field_D& initialValField,
bool keepHistory);
/// Destructor

View File

@ -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,

View File

@ -69,7 +69,8 @@ public:
const word& baseName,
pointStructure& pStruct,
const word& method,
const realx3Field_D& initialValField);
const realx3Field_D& initialValField,
bool keepHistory);

View File

@ -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,

View File

@ -68,7 +68,8 @@ public:
const word& baseName,
pointStructure& pStruct,
const word& method,
const realx3Field_D& initialValField);
const realx3Field_D& initialValField,
bool keepHistory);

View File

@ -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<pFlow::integration>
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
{

View File

@ -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

View File

@ -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(
@ -232,6 +232,7 @@ public:
sort(sortedPairs_, 0, size_ );
}
INLINE_FUNCTION_HD

View File

@ -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);

View File

@ -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
)

View File

@ -32,7 +32,6 @@ bool pFlow::MotionModel<Model, Component>::impl_nameToIndex(const word& name, ui
indx = static_cast<uint32>(i);
return true;
}
}
template<typename Model, typename Component>

View File

@ -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()<<endl;
fatalExit;
}
//axisList_ = axisMotion->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<word>("rotationAxis", "none");
if(rotAxis == "none")
{
parentAxisIndex_ = -1;
parentAxisIndex_ = static_cast<uint32>(-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<<endl;
return false;
}
}
return true;
@ -78,8 +86,8 @@ bool pFlow::multiRotatingAxis::read
FUNCTION_H
bool pFlow::multiRotatingAxis::write
(
const multiRotatingAxisMotion* axisMotion,
dictionary& dict
dictionary& dict,
const wordList& componentNames
) const
{
if( !rotatingAxis::write(dict) ) return false;
@ -90,10 +98,8 @@ bool pFlow::multiRotatingAxis::write
}
else
{
auto rotAxis = axisMotion->indexToName(parentAxisIndex_);
dict.add("rotationAxis", rotAxis);
dict.add("rotationAxis", componentNames[parentAxisIndex_]);
}
return true;
}

View File

@ -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<uint32>(-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<uint32>(-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<uint32>(-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;
};

View File

@ -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<word>("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<word>("motionModel");
if(modelName != getTypeName<ModelComponent>())
{
fatalErrorInFunction<<
" motionModel should be multiRotatingAxisMotion, but found "
<< motionModel <<endl;
" motionModel should be "<< Yellow_Text(getTypeName<ModelComponent>())<<
", but found "<< Yellow_Text(modelName)<<endl;
return false;
}
auto& motionInfo = dict.subDict("multiRotatingAxisMotionInfo");
auto axisNames = motionInfo.dictionaryKeywords();
wordList rotationAxis;
auto& motionInfo = dict.subDict(modelName+"Info");
auto compNames = motionInfo.dictionaryKeywords();
// first check if
wordList rotationAxisNames;
for(auto& aName: axisNames)
// in the first round read all dictionaries
for(auto& compName: compNames)
{
auto& axDict = motionInfo.subDict(aName);
auto& axDict = motionInfo.subDict(compName);
if(auto axPtr = makeUnique<rotatingAxis>(axDict); axPtr)
{
rotationAxis.push_back(
rotationAxisNames.push_back(
axDict.getValOrSet<word>("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<int32, int32>;
std::vector<intPair> 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);
sortedIndex_.clear();
axisName_.clear();
std::sort(numRotAxis.begin(), numRotAxis.end(), compareFunc);
Vector<int> sortedIndex;
componentNames_.clear();
output<<compNames<<endl;
for(auto ax:numRotAxis)
{
axisName_.push_back(axisNames[ax.second]);
sortedIndex_.push_back(ax.second);
componentNames_.push_back(compNames[ax.second]);
sortedIndex.push_back(ax.second);
}
numAxis_ = axisName_.size();
axis_.clear();
axis_.reserve(numAxis_);
numComponents_ = componentNames_.size();
motionComponents_.reserve(numComponents_);
sortedIndex_.assign(sortedIndex);
Vector<ModelComponent> components("Read::modelComponent",
compNames.size()+1,
0,
RESERVE());
// create the actual axis vector
for(auto& aName: axisName_)
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());
}
}
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");
dict.add("motionModel", modelName );
ForAll(i, axis_)
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()<<endl;
return false;
}
@ -160,79 +196,52 @@ bool pFlow::multiRotatingAxisMotion::writeDictionary
return true;
}
pFlow::multiRotatingAxisMotion::multiRotatingAxisMotion()
{}
pFlow::multiRotatingAxisMotion::multiRotatingAxisMotion(
const objectFile &objf,
repository *owner)
: fileDictionary(objf, owner)
{
pFlow::multiRotatingAxisMotion::multiRotatingAxisMotion
(
const dictionary& dict
)
{
if(! readDictionary(dict) )
if(! getModel().impl_readDictionary(*this) )
{
fatalErrorInFunction;
fatalExit;
}
}
FUNCTION_H
bool pFlow::multiRotatingAxisMotion::move(real t, real dt)
{
// every thing is done on host
for(int32 i=0; i<numAxis_; i++)
{
auto& ax = axis_[sortedIndex_[i]];
ax.setTime(t);
ax.setAxisList(getAxisListPtrHost());
ax.move(dt);
}
// transfer to device
axis_.modifyOnHost();
axis_.syncViews();
return true;
}
bool pFlow::multiRotatingAxisMotion::read
pFlow::multiRotatingAxisMotion::multiRotatingAxisMotion
(
iIstream& is
const objectFile &objf,
const dictionary &dict,
repository *owner
)
:
fileDictionary(objf, dict, owner)
{
// create an empty file dictionary
dictionary motionInfo(motionModelFile__, true);
// read dictionary from stream
if( !motionInfo.read(is) )
if(!getModel().impl_readDictionary(*this) )
{
ioErrorInFile(is.name(), is.lineNumber()) <<
" error in reading dictionray " << motionModelFile__ <<" from file. \n";
return false;
fatalErrorInFunction;
fatalExit;
}
if( !readDictionary(motionInfo) ) return false;
return true;
}
bool pFlow::multiRotatingAxisMotion::write
(
iOstream& os
iOstream &os,
const IOPattern &iop
) const
{
// create an empty file dictionary
dictionary motionInfo(motionModelFile__, true);
if( !writeDictionary(motionInfo))
// a global dictionary
dictionary newDict(fileDictionary::dictionary::name(), true);
if( iop.thisProcWriteData() )
{
if( !getModel().impl_writeDictionary(newDict) ||
!newDict.write(os))
{
fatalErrorInFunction<<
" error in writing to dictionary "<< newDict.globalName()<<endl;
return false;
}
if( !motionInfo.write(os) )
{
ioErrorInFile( os.name(), os.lineNumber() )<<
" error in writing dictionray to file. \n";
return false;
}
return true;
}

View File

@ -22,18 +22,16 @@ Licence:
#define __multiRotatingAxisMotion_hpp__
#include "types.hpp"
#include "typeInfo.hpp"
#include "VectorDual.hpp"
#include "List.hpp"
#include "MotionModel.hpp"
#include "multiRotatingAxis.hpp"
#include "fileDictionary.hpp"
namespace pFlow
{
// forward
class dictionary;
// class dictionary;
/**
* Rotating axis motion model for walls
@ -63,200 +61,55 @@ multiRotatingAxisMotionInfo
*
*/
class multiRotatingAxisMotion
{
public:
/** Motion model class to be passed to computational units/kernels for
* transfing points and returning velocities at various positions
*/
class Model
:
public fileDictionary,
public MotionModel<multiRotatingAxisMotion, multiRotatingAxis>
{
protected:
deviceViewType1D<multiRotatingAxis> axis_;
int32 numAxis_=0;
VectorSingle<int32> sortedIndex_;
public:
friend MotionModel<multiRotatingAxisMotion, multiRotatingAxis>;
INLINE_FUNCTION_HD
Model(deviceViewType1D<multiRotatingAxis> 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<multiRotatingAxis>;
/// Vector of multiRotaingAxis axes
axisVector_HD axis_;
/// Sorted index based on number of parrents each axis ha
VectorDual<int32> sortedIndex_;
/// List of axes names
wordList axisName_;
/// Number of axes
label numAxis_= 0;
/// Read from a dictionary
bool readDictionary(const dictionary& dict);
/// Write to a dictionary
bool writeDictionary(dictionary& dict)const;
public:
/// Type info
TypeInfoNV("multiRotatingAxisMotion");
// - Constructor
/// Empty constructor
FUNCTION_H
multiRotatingAxisMotion();
/// Construct with dictionary
FUNCTION_H
multiRotatingAxisMotion(const dictionary& dict);
/// Copy constructor
FUNCTION_H
multiRotatingAxisMotion(const multiRotatingAxisMotion&) = default;
/// No Move
multiRotatingAxisMotion(multiRotatingAxisMotion&&) = delete;
/// Copy assignment
FUNCTION_H
multiRotatingAxisMotion& operator=(const multiRotatingAxisMotion&) = default;
/// 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; i<numAxis_; i++ )
{
axis_[i].setTime(t);
axis_[i].setAxisList(getAxisListPtrDevice());
}
axis_.modifyOnHost();
axis_.syncViews();
return Model(axis_.deviceVector(), numAxis_);
}
/// Pointer to axis list on host side
INLINE_FUNCTION_H
multiRotatingAxis* getAxisListPtrHost()
{
return axis_.hostVectorAll().data();
}
/// Pointer to axis list on device
INLINE_FUNCTION_H
multiRotatingAxis* getAxisListPtrDevice()
{
return axis_.deviceVectorAll().data();
}
/// Name of motion component to index
INLINE_FUNCTION_H
int32 nameToIndex(const word& name)const
{
if( auto i = axisName_.findi(name); i == -1)
{
fatalErrorInFunction<<
"axis name " << name << " does not exist. \n";
fatalExit;
return i;
}
else
{
return i;
}
}
/// Index of motion component to component name
INLINE_FUNCTION_H
word indexToName(label i)const
{
if(i < numAxis_ )
return axisName_[i];
else
{
fatalErrorInFunction<<
"out of range access to the list of axes " << i <<endl<<
" size of axes_ is "<<numAxis_<<endl;
fatalExit;
return "";
}
}
/// Is moving
INLINE_FUNCTION_HD
bool isMoving()const
/// is the geometry attached to this component moving
bool impl_isMoving()const
{
return true;
}
/// Move points
FUNCTION_H
bool move(real t, real dt);
// - IO operation
/// Read from input stream is
FUNCTION_H
bool read(iIstream& is);
/// Write to output stream os
FUNCTION_H
bool write(iOstream& os)const;
/// Read from dictionary
bool impl_readDictionary(const dictionary& dict);
bool impl_writeDictionary(dictionary& dict)const;
public:
TypeInfo("multiRotatingAxisMotion");
multiRotatingAxisMotion(const objectFile& objf, repository* owner);
multiRotatingAxisMotion(
const objectFile& objf,
const dictionary& dict,
repository* owner);
using fileDictionary::write;
bool write(iOstream& os, const IOPattern& iop)const override;
static
multiRotatingAxis noneComponent()
{
return multiRotatingAxis();
}
// TODO: make this method protected
void impl_setTime(uint32 iter, real t, real dt)const;
/// move the component itself
bool impl_move(uint32 iter, real t, real dt)const;
};
} // pFlow

View File

@ -248,7 +248,8 @@ pFlow::grainParticles::grainParticles(
"rVelocity",
dynPointStruct(),
intMethod,
rAcceleration_.field()
rAcceleration_.field(),
control.keepIntegrationHistory()
);
if( !rVelIntegration_ )

View File

@ -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<<endl;
fatalErrorInFunction
<<"Invalid index for diameter "
<<index<<endl;
fatalExit;
return 0.0;
}
@ -122,13 +137,17 @@ pFlow::real pFlow::grainShape::coarseGrainFactor(uint32 index) const
return 0.0;
}
pFlow::realVector pFlow::grainShape::volume() const
{
return realVector("volume", Pi/6*pow(grainDiameters_,(real)3.0));
}
pFlow::realVector pFlow::grainShape::coarseGrainFactor() const
{
return coarseGrainFactor_;
}
pFlow::real pFlow::grainShape::orginalDiameter(uint32 index) const
pFlow::real pFlow::grainShape::originalDiameter(uint32 index) const
{
if(indexValid(index))
{
@ -142,7 +161,7 @@ pFlow::real pFlow::grainShape::orginalDiameter(uint32 index) const
pFlow::realVector pFlow::grainShape::orginalDiameter() const
pFlow::realVector pFlow::grainShape::originalDiameter() const
{
return sphereDiameters_;
}

View File

@ -32,9 +32,13 @@ class grainShape
{
private:
// - diameter of spheres
/// diameter of grains
realVector grainDiameters_;
/// diameter of spheres
realVector sphereDiameters_;
/// course-grain factor
realVector coarseGrainFactor_;
@ -54,9 +58,21 @@ public:
repository* owner,
const property& prop);
grainShape(
const word& shapeType,
const word& fileName,
repository* owner,
const property& prop);
~grainShape() override = default;
add_vCtor
(
shape,
grainShape,
word
);
//// - Methods
real maxBoundingSphere()const override;
@ -69,13 +85,15 @@ public:
realVector boundingDiameter()const override;
realVector volume()const override;
real coarseGrainFactor(uint32 index)const ;
realVector coarseGrainFactor()const ;
real orginalDiameter(uint32 index)const ;
real originalDiameter(uint32 index)const ;
realVector orginalDiameter()const ;
realVector originalDiameter()const ;
bool mass(uint32 index, real& m)const override;

View File

@ -229,7 +229,8 @@ pFlow::sphereParticles::sphereParticles(
"rVelocity",
dynPointStruct(),
intMethod,
rAcceleration_.field()
rAcceleration_.field(),
control.keepIntegrationHistory()
);
if( !rVelIntegration_ )

View File

@ -68,6 +68,18 @@ pFlow::sphereShape::sphereShape
}
}
pFlow::sphereShape::sphereShape
(
const word &shapeType,
const word &fileName,
repository *owner,
const property &prop
)
:
sphereShape(fileName, owner, prop)
{
}
pFlow::real pFlow::sphereShape::maxBoundingSphere() const
{
return max(diameters_);
@ -105,6 +117,11 @@ pFlow::realVector pFlow::sphereShape::boundingDiameter() const
return diameters_;
}
pFlow::realVector pFlow::sphereShape::volume() const
{
return realVector("volume", Pi/6*pow(diameters_,(real)3.0));
}
bool pFlow::sphereShape::mass(uint32 index, real &m) const
{
if( indexValid(index) )

View File

@ -51,9 +51,22 @@ public:
repository* owner,
const property& prop);
sphereShape(
const word& shapeType,
const word& fileName,
repository* owner,
const property& prop);
~sphereShape() override = default;
add_vCtor
(
shape,
sphereShape,
word
);
//// - Methods
real maxBoundingSphere()const override;
@ -66,6 +79,8 @@ public:
realVector boundingDiameter()const override;
realVector volume()const override;
bool mass(uint32 index, real& m)const override;
real mass(uint32 index) const override;

View File

@ -64,7 +64,8 @@ pFlow::dynamicPointStructure::dynamicPointStructure
"pStructPosition",
*this,
integrationMethod_,
velocity_.field()
velocity_.field(),
control.keepIntegrationHistory()
);
if( !integrationPos_ )
@ -79,7 +80,8 @@ pFlow::dynamicPointStructure::dynamicPointStructure
"pStructVelocity",
*this,
integrationMethod_,
acceleration_.field()
acceleration_.field(),
control.keepIntegrationHistory()
);
if( !integrationVel_ )

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