mirror of
https://github.com/PhasicFlow/phasicFlow.git
synced 2025-08-17 03:47:04 +00:00
Compare commits
82 Commits
5f8ea2d841
...
develop
Author | SHA1 | Date | |
---|---|---|---|
0d9de2c601 | |||
b4bc724a68 | |||
ee33469295 | |||
3933d65303 | |||
cf4d22c963 | |||
86367c7e2c | |||
a7e51a91aa | |||
5e56bf1b8c | |||
343ac1fc04 | |||
6b04d17c7f | |||
97f46379c7 | |||
32fd6cb12e | |||
be16fb0684 | |||
4c96c6fa1e | |||
196b7a1833 | |||
316e71ff7a | |||
7a4a33ef37 | |||
edfbdb22e9 | |||
c6725625b3 | |||
253d6fbaf7 | |||
701baf09e6 | |||
20c94398a9 | |||
dd36e32da4 | |||
a048c2f5d7 | |||
8b324bc2b6 | |||
c7f790a1fa | |||
166d7e72c2 | |||
c126f9a8a3 | |||
7104a33a4b | |||
16b6084d98 | |||
2afea7b273 | |||
2c5b4f55d1 | |||
a7dc69a801 | |||
32287404fa | |||
8b3530c289 | |||
d8c3fc02d5 | |||
4dab700a47 | |||
a50ceeee2c | |||
468730289b | |||
27f0202002 | |||
c69bfc79e1 | |||
69909b3c01 | |||
8986c47b69 | |||
37282f16ac | |||
cd051a6497 | |||
8b5d14afe6 | |||
eb37affb94 | |||
c0d12f4243 | |||
a1b5a9bd5d | |||
dc0edbc845 | |||
b423b6ceb7 | |||
1f6a953154 | |||
bbd3afea0e | |||
53f0e959b0 | |||
c12022fb19 | |||
d876bb6246 | |||
cb40e01b7e | |||
5f6400c032 | |||
8863234c1c | |||
1cd64fb2ec | |||
3fc121ef2b | |||
953059cec5 | |||
2593e2acf1 | |||
7c3b90a22d | |||
72b9b74cc9 | |||
a545acb374 | |||
59fbee9711 | |||
6cc4b3954a | |||
d8c9135700 | |||
544624d579 | |||
cbac1e97b5 | |||
8c543e1649 | |||
be807e4a71 | |||
d5ea338ab3 | |||
a448ce5f8d | |||
e2582f5fd9 | |||
f2e8e69899 | |||
a9e5b9bb59 | |||
77eda47a87 | |||
acb8d0e4eb | |||
19fa3e2822 | |||
73f4b35fd4 |
153
.github/scripts/sync-wiki.py
vendored
Executable file
153
.github/scripts/sync-wiki.py
vendored
Executable 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
18
.github/workflows/markdownList.yml
vendored
Normal 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-PhasicFlow‐v‐1.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
60
.github/workflows/sync-wiki.yml
vendored
Normal 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
|
1
benchmarks/helicalMixer/readme.md
Normal file
1
benchmarks/helicalMixer/readme.md
Normal file
@ -0,0 +1 @@
|
||||
# Helical Mixer Benchmark (phasicFlow v-1.0)
|
7
benchmarks/readme.md
Normal file
7
benchmarks/readme.md
Normal 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)
|
BIN
benchmarks/rotatingDrum/images/commericalDEMsnapshot.png
Normal file
BIN
benchmarks/rotatingDrum/images/commericalDEMsnapshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 124 KiB |
BIN
benchmarks/rotatingDrum/images/performance1.png
Normal file
BIN
benchmarks/rotatingDrum/images/performance1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 55 KiB |
BIN
benchmarks/rotatingDrum/images/phasicFlow_snapshot.png
Normal file
BIN
benchmarks/rotatingDrum/images/phasicFlow_snapshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 180 KiB |
96
benchmarks/rotatingDrum/readme.md
Normal file
96
benchmarks/rotatingDrum/readme.md
Normal 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.
|
@ -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
|
||||
|
||||
|
@ -27,7 +27,7 @@ positionParticles
|
||||
|
||||
orderedInfo
|
||||
{
|
||||
diameter 0.004; // minimum space between centers of particles
|
||||
distance 0.004; // minimum space between centers of particles
|
||||
|
||||
numPoints 1000000; // number of particles in the simulation
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -27,7 +27,7 @@ positionParticles
|
||||
|
||||
orderedInfo
|
||||
{
|
||||
diameter 0.006; // minimum space between centers of particles
|
||||
distance 0.006; // minimum space between centers of particles
|
||||
|
||||
numPoints 250000; // number of particles in the simulation
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 2000000; // number of particles in the simulation
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -27,7 +27,7 @@ positionParticles
|
||||
|
||||
orderedInfo
|
||||
{
|
||||
diameter 0.005; // minimum space between centers of particles
|
||||
distance 0.005; // minimum space between centers of particles
|
||||
|
||||
numPoints 500000; // number of particles in the simulation
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 6000000; // number of particles in the simulation
|
||||
|
||||
|
136
doc/mdDocs/howToBuild-V1.0.md
Normal file
136
doc/mdDocs/howToBuild-V1.0.md
Normal 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 ....
|
||||
```
|
@ -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 ....
|
||||
```
|
@ -1,64 +1,116 @@
|
||||
# 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
|
||||
|
||||
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.
|
||||
|
||||
## 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.
|
||||
In addition to these models, the user can add other motion models to the code based on their need.
|
||||
- **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
|
||||
|
||||
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.
|
||||
|
||||
### 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|
|
||||
|Integration Method | Order | Type|
|
||||
| :--- | :---: | :---: |
|
||||
| AdamsBashforth2 | 2 | one-step |
|
||||
| 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.
|
||||
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.
|
||||
|
@ -24,7 +24,7 @@ Licence:
|
||||
#include "types.hpp"
|
||||
#include "span.hpp"
|
||||
|
||||
namespace pFlow
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
|
@ -26,20 +26,18 @@ Licence:
|
||||
#include "fieldFunctions.hpp"
|
||||
#include "dictionary.hpp"
|
||||
|
||||
namespace pFlow
|
||||
{
|
||||
|
||||
bool pointFieldGetType(const word& TYPENAME, word& fieldType, word& fieldSpace);
|
||||
|
||||
}
|
||||
|
||||
bool pFlow::fieldsDataBase::loadPointStructureToTime()
|
||||
bool pFlow::postprocessData::fieldsDataBase::loadPointStructureToTime()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool pFlow::fieldsDataBase::checkForUpdate(const word &compoundName, bool forceUpdate)
|
||||
bool pFlow::postprocessData::fieldsDataBase::checkForUpdate
|
||||
(
|
||||
const word &compoundName,
|
||||
bool forceUpdate
|
||||
)
|
||||
{
|
||||
auto t = currentTime();
|
||||
bool shouldUpdate = false;
|
||||
@ -58,7 +56,10 @@ bool pFlow::fieldsDataBase::checkForUpdate(const word &compoundName, bool forceU
|
||||
return shouldUpdate;
|
||||
}
|
||||
|
||||
pFlow::span<pFlow::real> pFlow::fieldsDataBase::createOrGetRealField(const word &name)
|
||||
pFlow::span<pFlow::real> pFlow::postprocessData::fieldsDataBase::createOrGetRealField
|
||||
(
|
||||
const word &name
|
||||
)
|
||||
{
|
||||
|
||||
bool shouldUpdate = checkForUpdate(name);
|
||||
@ -83,7 +84,10 @@ pFlow::span<pFlow::real> pFlow::fieldsDataBase::createOrGetRealField(const word
|
||||
field.size());
|
||||
}
|
||||
|
||||
pFlow::span<pFlow::real> pFlow::fieldsDataBase::createOrGetVolume(bool forceUpdate)
|
||||
pFlow::span<pFlow::real> pFlow::postprocessData::fieldsDataBase::createOrGetVolume
|
||||
(
|
||||
bool forceUpdate
|
||||
)
|
||||
{
|
||||
const word fName = "volume";
|
||||
bool shouldUpdate = checkForUpdate(fName, forceUpdate);
|
||||
@ -119,7 +123,7 @@ pFlow::span<pFlow::real> pFlow::fieldsDataBase::createOrGetVolume(bool forceUpda
|
||||
|
||||
}
|
||||
|
||||
pFlow::span<pFlow::real> pFlow::fieldsDataBase::createOrGetDensity(bool forceUpdate)
|
||||
pFlow::span<pFlow::real> pFlow::postprocessData::fieldsDataBase::createOrGetDensity(bool forceUpdate)
|
||||
{
|
||||
const word fName = "density";
|
||||
|
||||
@ -155,7 +159,7 @@ pFlow::span<pFlow::real> pFlow::fieldsDataBase::createOrGetDensity(bool forceUpd
|
||||
field.size());
|
||||
}
|
||||
|
||||
pFlow::span<pFlow::real> pFlow::fieldsDataBase::createOrGetOne(bool forceUpdate)
|
||||
pFlow::span<pFlow::real> pFlow::postprocessData::fieldsDataBase::createOrGetOne(bool forceUpdate)
|
||||
{
|
||||
const word fName = "one";
|
||||
|
||||
@ -182,7 +186,7 @@ pFlow::span<pFlow::real> pFlow::fieldsDataBase::createOrGetOne(bool forceUpdate)
|
||||
field.size());
|
||||
}
|
||||
|
||||
pFlow::span<pFlow::real> pFlow::fieldsDataBase::createOrGetMass(bool forceUpdate)
|
||||
pFlow::span<pFlow::real> pFlow::postprocessData::fieldsDataBase::createOrGetMass(bool forceUpdate)
|
||||
{
|
||||
const word fName = "mass";
|
||||
|
||||
@ -218,7 +222,7 @@ pFlow::span<pFlow::real> pFlow::fieldsDataBase::createOrGetMass(bool forceUpdate
|
||||
field.size());
|
||||
}
|
||||
|
||||
pFlow::span<pFlow::real> pFlow::fieldsDataBase::createOrGetI(bool forceUpdate)
|
||||
pFlow::span<pFlow::real> pFlow::postprocessData::fieldsDataBase::createOrGetI(bool forceUpdate)
|
||||
{
|
||||
const word fName = "I";
|
||||
|
||||
@ -254,7 +258,7 @@ pFlow::span<pFlow::real> pFlow::fieldsDataBase::createOrGetI(bool forceUpdate)
|
||||
field.size());
|
||||
}
|
||||
|
||||
bool pFlow::fieldsDataBase::findFunction(
|
||||
bool pFlow::postprocessData::fieldsDataBase::findFunction(
|
||||
const word &compoundFieldName,
|
||||
word &fieldName,
|
||||
fieldsDataBase::Functions &func)
|
||||
@ -360,7 +364,7 @@ bool pFlow::fieldsDataBase::findFunction(
|
||||
return false; // No match
|
||||
}
|
||||
|
||||
bool pFlow::fieldsDataBase::inputOutputType
|
||||
bool pFlow::postprocessData::fieldsDataBase::inputOutputType
|
||||
(
|
||||
fieldsDataBase::Functions func,
|
||||
const word &inputType,
|
||||
@ -458,7 +462,7 @@ bool pFlow::fieldsDataBase::inputOutputType
|
||||
return false;
|
||||
}
|
||||
|
||||
pFlow::fieldsDataBase::fieldsDataBase
|
||||
pFlow::postprocessData::fieldsDataBase::fieldsDataBase
|
||||
(
|
||||
systemControl& control,
|
||||
const dictionary& postDict,
|
||||
@ -488,12 +492,12 @@ pFlow::fieldsDataBase::fieldsDataBase
|
||||
}
|
||||
}
|
||||
|
||||
pFlow::timeValue pFlow::fieldsDataBase::currentTime() const
|
||||
pFlow::timeValue pFlow::postprocessData::fieldsDataBase::currentTime() const
|
||||
{
|
||||
return time_.currentTime();
|
||||
}
|
||||
|
||||
bool pFlow::fieldsDataBase::getFieldTypeNameFunction
|
||||
bool pFlow::postprocessData::fieldsDataBase::getFieldTypeNameFunction
|
||||
(
|
||||
const word& compoundName,
|
||||
word& pointFieldName,
|
||||
@ -543,7 +547,7 @@ bool pFlow::fieldsDataBase::getFieldTypeNameFunction
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pFlow::fieldsDataBase::getFieldType
|
||||
bool pFlow::postprocessData::fieldsDataBase::getFieldType
|
||||
(
|
||||
const word& compoundName,
|
||||
word& originalType,
|
||||
@ -559,7 +563,7 @@ bool pFlow::fieldsDataBase::getFieldType
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pFlow::fieldsDataBase::getFieldType
|
||||
bool pFlow::postprocessData::fieldsDataBase::getFieldType
|
||||
(
|
||||
const word &compoundName,
|
||||
word &typeAfterFunction
|
||||
@ -575,7 +579,7 @@ bool pFlow::fieldsDataBase::getFieldType
|
||||
return true;
|
||||
}
|
||||
|
||||
pFlow::span<pFlow::realx3> pFlow::fieldsDataBase::updatePoints(bool forceUpdate)
|
||||
pFlow::span<pFlow::realx3> pFlow::postprocessData::fieldsDataBase::updatePoints(bool forceUpdate)
|
||||
{
|
||||
const word fName = "position";
|
||||
bool shouldUpdate = checkForUpdate(fName, forceUpdate);
|
||||
@ -604,7 +608,7 @@ pFlow::span<pFlow::realx3> pFlow::fieldsDataBase::updatePoints(bool forceUpdate)
|
||||
|
||||
}
|
||||
|
||||
pFlow::span<pFlow::realx3> pFlow::fieldsDataBase::updateFieldRealx3
|
||||
pFlow::span<pFlow::realx3> pFlow::postprocessData::fieldsDataBase::updateFieldRealx3
|
||||
(
|
||||
const word &compoundName,
|
||||
bool forceUpdate
|
||||
@ -640,7 +644,7 @@ pFlow::span<pFlow::realx3> pFlow::fieldsDataBase::updateFieldRealx3
|
||||
|
||||
}
|
||||
|
||||
pFlow::span<pFlow::realx4> pFlow::fieldsDataBase::updateFieldRealx4
|
||||
pFlow::span<pFlow::realx4> pFlow::postprocessData::fieldsDataBase::updateFieldRealx4
|
||||
(
|
||||
const word &compoundName,
|
||||
bool forceUpdate
|
||||
@ -676,7 +680,7 @@ pFlow::span<pFlow::realx4> pFlow::fieldsDataBase::updateFieldRealx4
|
||||
|
||||
}
|
||||
|
||||
pFlow::span<pFlow::real> pFlow::fieldsDataBase::updateFieldReal
|
||||
pFlow::span<pFlow::real> pFlow::postprocessData::fieldsDataBase::updateFieldReal
|
||||
(
|
||||
const word &compoundName,
|
||||
bool forceUpdate
|
||||
@ -843,7 +847,7 @@ pFlow::span<pFlow::real> pFlow::fieldsDataBase::updateFieldReal
|
||||
return span<real>(nullptr, 0);
|
||||
}
|
||||
|
||||
pFlow::span<pFlow::uint32> pFlow::fieldsDataBase::updateFieldUint32
|
||||
pFlow::span<pFlow::uint32> pFlow::postprocessData::fieldsDataBase::updateFieldUint32
|
||||
(
|
||||
const word& name,
|
||||
bool forceUpdate
|
||||
@ -852,7 +856,7 @@ pFlow::span<pFlow::uint32> pFlow::fieldsDataBase::updateFieldUint32
|
||||
return updateField<uint32>(name, forceUpdate);
|
||||
}
|
||||
|
||||
pFlow::allPointFieldTypes pFlow::fieldsDataBase::updateFieldAll
|
||||
pFlow::postprocessData::allPointFieldTypes pFlow::postprocessData::fieldsDataBase::updateFieldAll
|
||||
(
|
||||
const word &compoundName,
|
||||
bool forceUpdate
|
||||
@ -888,10 +892,24 @@ pFlow::allPointFieldTypes pFlow::fieldsDataBase::updateFieldAll
|
||||
}
|
||||
}
|
||||
|
||||
bool pFlow::postprocessData::fieldsDataBase::pointFieldGetType
|
||||
(
|
||||
const word& TYPENAME,
|
||||
word& fieldType,
|
||||
word& fieldSpace
|
||||
)
|
||||
{
|
||||
std::regex match("pointField\\<([A-Za-z1-9_]*)\\,([A-Za-z1-9_]*)\\>");
|
||||
std::smatch search;
|
||||
if(!std::regex_match(TYPENAME, search, match)) return false;
|
||||
if(search.size()!= 3) return false;
|
||||
fieldType = search[1];
|
||||
fieldSpace = search[2];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
pFlow::uniquePtr<pFlow::fieldsDataBase>
|
||||
pFlow::fieldsDataBase::create
|
||||
pFlow::uniquePtr<pFlow::postprocessData::fieldsDataBase>
|
||||
pFlow::postprocessData::fieldsDataBase::create
|
||||
(
|
||||
systemControl& control,
|
||||
const dictionary& postDict,
|
||||
@ -931,14 +949,5 @@ pFlow::uniquePtr<pFlow::fieldsDataBase>
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool pFlow::pointFieldGetType(const word& TYPENAME, word& fieldType, word& fieldSpace)
|
||||
{
|
||||
std::regex match("pointField\\<([A-Za-z1-9_]*)\\,([A-Za-z1-9_]*)\\>");
|
||||
std::smatch search;
|
||||
if(!std::regex_match(TYPENAME, search, match)) return false;
|
||||
if(search.size()!= 3) return false;
|
||||
fieldType = search[1];
|
||||
fieldSpace = search[2];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -29,13 +29,15 @@ Licence:
|
||||
#include "Map.hpp"
|
||||
#include "shape.hpp"
|
||||
|
||||
|
||||
namespace pFlow
|
||||
{
|
||||
class dictionary;
|
||||
class systemControl;
|
||||
class Time;
|
||||
}
|
||||
|
||||
class dictionary;
|
||||
class systemControl;
|
||||
class Time;
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
|
||||
class fieldsDataBase
|
||||
@ -302,6 +304,12 @@ public:
|
||||
{
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
static
|
||||
bool pointFieldGetType(
|
||||
const word& TYPENAME,
|
||||
word& fieldType,
|
||||
word& fieldSpace);
|
||||
|
||||
static
|
||||
uniquePtr<fieldsDataBase> create(
|
||||
@ -311,7 +319,7 @@ public:
|
||||
timeValue startTime);
|
||||
};
|
||||
|
||||
} // namespace pFlow
|
||||
} // namespace pFlow::postprocessData
|
||||
|
||||
#include "fieldsDataBaseTemplates.cpp"
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "types.hpp"
|
||||
#include "span.hpp"
|
||||
|
||||
namespace pFlow
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
|
||||
|
@ -23,9 +23,9 @@ Licence:
|
||||
|
||||
#include "fieldsDataBase.hpp"
|
||||
|
||||
template<pFlow::ValidFieldType T>
|
||||
template<pFlow::postprocessData::ValidFieldType T>
|
||||
inline
|
||||
pFlow::span<T> pFlow::fieldsDataBase::updateField(const word& name, bool forceUpdate)
|
||||
pFlow::span<T> pFlow::postprocessData::fieldsDataBase::updateField(const word& name, bool forceUpdate)
|
||||
{
|
||||
|
||||
bool shouldUpdate = checkForUpdate(name, forceUpdate);
|
||||
@ -40,8 +40,8 @@ pFlow::span<T> pFlow::fieldsDataBase::updateField(const word& name, bool forceUp
|
||||
{
|
||||
if( loadPointFieldToTime(name) )
|
||||
{
|
||||
const auto& pField = time_.lookupObject<pointField_D<T>>(name);
|
||||
allFields_.emplaceBackOrReplace<FieldTypeHost<T>>(
|
||||
const auto& pField = time_.template lookupObject<pointField_D<T>>(name);
|
||||
allFields_.template emplaceBackOrReplace<FieldTypeHost<T>>(
|
||||
name,
|
||||
pField.activeValuesHost());
|
||||
}
|
||||
@ -63,9 +63,9 @@ pFlow::span<T> pFlow::fieldsDataBase::updateField(const word& name, bool forceUp
|
||||
}
|
||||
|
||||
|
||||
template<pFlow::ValidFieldType T>
|
||||
template<pFlow::postprocessData::ValidFieldType T>
|
||||
inline
|
||||
pFlow::span<T> pFlow::fieldsDataBase::updateReservedField
|
||||
pFlow::span<T> pFlow::postprocessData::fieldsDataBase::updateReservedField
|
||||
(
|
||||
const word& name,
|
||||
bool forceUpdate
|
||||
|
@ -3,38 +3,38 @@
|
||||
#include "dynamicPointStructure.hpp"
|
||||
#include "vocabs.hpp"
|
||||
|
||||
namespace pFlow
|
||||
{
|
||||
bool pointFieldGetType(const word& TYPENAME, word& fieldType, word& fieldSpace);
|
||||
}
|
||||
|
||||
bool pFlow::simulationFieldsDataBase::pointFieldNameExists(const word &name) const
|
||||
|
||||
bool pFlow::postprocessData::simulationFieldsDataBase::pointFieldNameExists(const word &name) const
|
||||
{
|
||||
return time().lookupObjectName(name);
|
||||
}
|
||||
|
||||
bool pFlow::simulationFieldsDataBase::loadPointFieldToTime(const word &name)
|
||||
bool pFlow::postprocessData::simulationFieldsDataBase::loadPointFieldToTime(const word &name)
|
||||
{
|
||||
return time().lookupObjectName(name);
|
||||
}
|
||||
|
||||
bool pFlow::simulationFieldsDataBase::loadPointStructureToTime()
|
||||
bool pFlow::postprocessData::simulationFieldsDataBase::loadPointStructureToTime()
|
||||
{
|
||||
// it is already in the Time object
|
||||
return time().lookupObjectName(pointStructureFile__);
|
||||
}
|
||||
|
||||
|
||||
const pFlow::shape& pFlow::simulationFieldsDataBase::getShape() const
|
||||
const pFlow::shape& pFlow::postprocessData::simulationFieldsDataBase::getShape() const
|
||||
{
|
||||
return shape_;
|
||||
}
|
||||
|
||||
pFlow::word pFlow::simulationFieldsDataBase::getPointFieldType(const word &name) const
|
||||
pFlow::word pFlow::postprocessData::simulationFieldsDataBase::getPointFieldType
|
||||
(
|
||||
const word &name
|
||||
) const
|
||||
{
|
||||
word pfType = time().lookupObjectTypeName(name);
|
||||
word type, space;
|
||||
if(!pointFieldGetType(pfType, type, space))
|
||||
if(!fieldsDataBase::pointFieldGetType(pfType, type, space))
|
||||
{
|
||||
fatalErrorInFunction
|
||||
<<"Error in retriving the type of pointField "
|
||||
@ -44,7 +44,7 @@ pFlow::word pFlow::simulationFieldsDataBase::getPointFieldType(const word &name)
|
||||
return type;
|
||||
}
|
||||
|
||||
pFlow::simulationFieldsDataBase::simulationFieldsDataBase
|
||||
pFlow::postprocessData::simulationFieldsDataBase::simulationFieldsDataBase
|
||||
(
|
||||
systemControl &control,
|
||||
const dictionary& postDict,
|
||||
@ -60,7 +60,7 @@ pFlow::simulationFieldsDataBase::simulationFieldsDataBase
|
||||
{
|
||||
}
|
||||
|
||||
const pFlow::pointStructure &pFlow::simulationFieldsDataBase::pStruct() const
|
||||
const pFlow::pointStructure &pFlow::postprocessData::simulationFieldsDataBase::pStruct() const
|
||||
{
|
||||
return
|
||||
static_cast<const pointStructure&>
|
||||
|
@ -23,7 +23,7 @@ Licence:
|
||||
|
||||
#include "fieldsDataBase.hpp"
|
||||
|
||||
namespace pFlow
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
class simulationFieldsDataBase
|
||||
|
@ -1,6 +1,9 @@
|
||||
#include "PostprocessOperationAvMassVelocity.hpp"
|
||||
|
||||
pFlow::PostprocessOperationAvMassVelocity::PostprocessOperationAvMassVelocity
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
PostprocessOperationAvMassVelocity::PostprocessOperationAvMassVelocity
|
||||
(
|
||||
const dictionary &opDict,
|
||||
const regionPoints ®Points,
|
||||
@ -17,4 +20,6 @@ pFlow::PostprocessOperationAvMassVelocity::PostprocessOperationAvMassVelocity
|
||||
fieldsDB
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
@ -132,7 +132,7 @@ Licence:
|
||||
#include "regionField.hpp"
|
||||
#include "includeMask.hpp"
|
||||
|
||||
namespace pFlow
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
|
||||
@ -168,6 +168,6 @@ public:
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
} // namespace pFlow::postprocessData
|
||||
|
||||
#endif //__PostprocessOperationAvMassVelocity_hpp__
|
@ -3,8 +3,11 @@
|
||||
#include "fieldsDataBase.hpp"
|
||||
#include "operationFunctions.hpp"
|
||||
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
/// Constructs average processor and initializes result field based on input field type
|
||||
pFlow::PostprocessOperationAverage::PostprocessOperationAverage
|
||||
PostprocessOperationAverage::PostprocessOperationAverage
|
||||
(
|
||||
const dictionary &opDict,
|
||||
const regionPoints ®Points,
|
||||
@ -39,7 +42,7 @@ pFlow::PostprocessOperationAverage::PostprocessOperationAverage
|
||||
}
|
||||
}
|
||||
|
||||
pFlow::PostprocessOperationAverage::PostprocessOperationAverage
|
||||
PostprocessOperationAverage::PostprocessOperationAverage
|
||||
(
|
||||
const dictionary &opDict,
|
||||
const word &fieldName,
|
||||
@ -77,8 +80,9 @@ pFlow::PostprocessOperationAverage::PostprocessOperationAverage
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Performs weighted average of field values within each region
|
||||
bool pFlow::PostprocessOperationAverage::execute
|
||||
bool PostprocessOperationAverage::execute
|
||||
(
|
||||
const std::vector<span<real>>& weights,
|
||||
const regionField<real>& volFactor
|
||||
@ -109,7 +113,7 @@ bool pFlow::PostprocessOperationAverage::execute
|
||||
allField)
|
||||
);
|
||||
|
||||
if(calculateFluctuation2_)
|
||||
if(calculateFluctuation2_())
|
||||
{
|
||||
auto& processedRegField = processedRegFieldPtr_();
|
||||
fluctuation2FieldPtr_ = makeUnique<processedRegFieldType>
|
||||
@ -137,4 +141,41 @@ bool pFlow::PostprocessOperationAverage::execute
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool PostprocessOperationAverage::write(const fileSystem &parDir) const
|
||||
{
|
||||
if(! postprocessOperation::write(parDir))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(!calculateFluctuation2_())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
auto ti = time().TimeInfo();
|
||||
|
||||
if(!os2Ptr_)
|
||||
{
|
||||
fileSystem path = parDir+(
|
||||
processedFieldName()+"_prime2" + ".Start_" + ti.timeName());
|
||||
os2Ptr_ = makeUnique<oFstream>(path);
|
||||
|
||||
regPoints().write(os2Ptr_());
|
||||
}
|
||||
|
||||
|
||||
std::visit
|
||||
(
|
||||
[&](auto&& arg)->bool
|
||||
{
|
||||
return writeField(os2Ptr_(), ti.t(), arg, threshold());
|
||||
},
|
||||
fluctuation2FieldPtr_()
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace pFlow::postprocessData
|
@ -132,10 +132,9 @@ Licence:
|
||||
#include "regionField.hpp"
|
||||
#include "includeMask.hpp"
|
||||
|
||||
namespace pFlow
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
|
||||
class PostprocessOperationAverage
|
||||
:
|
||||
public postprocessOperation
|
||||
@ -150,6 +149,9 @@ private:
|
||||
|
||||
uniquePtr<processedRegFieldType> fluctuation2FieldPtr_ = nullptr;
|
||||
|
||||
/// Pointer to the output stream for writing fluctuation2 results
|
||||
mutable uniquePtr<oFstream> os2Ptr_ = nullptr;
|
||||
|
||||
public:
|
||||
|
||||
TypeInfo("PostprocessOperation<average>");
|
||||
@ -190,6 +192,10 @@ public:
|
||||
return processedRegFieldPtr_();
|
||||
}
|
||||
|
||||
/// write to os stream
|
||||
bool write(const fileSystem &parDir)const override;
|
||||
|
||||
|
||||
/// @brief Execute average operation on field values
|
||||
/// @param weights Weight factors for particles
|
||||
/// @return True if successful
|
||||
@ -200,6 +206,6 @@ public:
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
} // namespace pFlow::postprocessData
|
||||
|
||||
#endif //__PostprocessOperationAverage_hpp__
|
@ -3,8 +3,11 @@
|
||||
#include "fieldsDataBase.hpp"
|
||||
#include "operationFunctions.hpp"
|
||||
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
/// Constructs sum processor and initializes result field based on input field type
|
||||
pFlow::PostprocessOperationSum::PostprocessOperationSum
|
||||
PostprocessOperationSum::PostprocessOperationSum
|
||||
(
|
||||
const dictionary &opDict,
|
||||
const regionPoints ®Points,
|
||||
@ -39,7 +42,7 @@ pFlow::PostprocessOperationSum::PostprocessOperationSum
|
||||
}
|
||||
|
||||
/// Performs weighted sum of field values within each region
|
||||
bool pFlow::PostprocessOperationSum::execute
|
||||
bool PostprocessOperationSum::execute
|
||||
(
|
||||
const std::vector<span<real>>& weights,
|
||||
const regionField<real>& volFactor
|
||||
@ -72,3 +75,6 @@ bool pFlow::PostprocessOperationSum::execute
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -129,7 +129,7 @@ Licence:
|
||||
#include "regionField.hpp"
|
||||
#include "includeMask.hpp"
|
||||
|
||||
namespace pFlow
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
|
||||
@ -182,6 +182,6 @@ public:
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
} // namespace pFlow::postprocessData
|
||||
|
||||
#endif //__PostprocessOperationSum_hpp__
|
@ -28,7 +28,7 @@ Licence:
|
||||
#include "regionField.hpp"
|
||||
#include "includeMask.hpp"
|
||||
|
||||
namespace pFlow
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
@ -190,6 +190,6 @@ regionField<T> executeFluctuation2Operation
|
||||
return processedField;
|
||||
}
|
||||
|
||||
} // namespace pFlow
|
||||
} // namespace pFlow::postprocessData
|
||||
|
||||
#endif //__operationFunctions_hpp__
|
||||
|
@ -61,7 +61,7 @@ Licence:
|
||||
#include "Time.hpp"
|
||||
|
||||
|
||||
namespace pFlow
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
template<typename T, typename Operator>
|
||||
@ -270,7 +270,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
} // pFlow
|
||||
} // pFlow::postprocessData
|
||||
|
||||
#endif //__IncludeMask_hpp__
|
||||
|
||||
|
@ -20,31 +20,34 @@ Licence:
|
||||
|
||||
#include "IncludeMask.hpp"
|
||||
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
// real
|
||||
template class pFlow::IncludeMask<pFlow::real, pFlow::compareOne<pFlow::real, pFlow::lessThanOp> >;
|
||||
template class pFlow::IncludeMask<pFlow::real, pFlow::compareOne<pFlow::real, pFlow::lessThanEqOp> >;
|
||||
template class IncludeMask<real, compareOne<real, lessThanOp> >;
|
||||
template class IncludeMask<real, compareOne<real, lessThanEqOp> >;
|
||||
|
||||
template class pFlow::IncludeMask<pFlow::real, pFlow::compareOne<pFlow::real, pFlow::greaterThanOp> >;
|
||||
template class pFlow::IncludeMask<pFlow::real, pFlow::compareOne<pFlow::real, pFlow::greaterThanEqOp> >;
|
||||
template class IncludeMask<real, compareOne<real, greaterThanOp> >;
|
||||
template class IncludeMask<real, compareOne<real, greaterThanEqOp> >;
|
||||
|
||||
template class pFlow::IncludeMask<pFlow::real, pFlow::compareOne<pFlow::real, pFlow::equalOp> >;
|
||||
template class IncludeMask<real, compareOne<real, equalOp> >;
|
||||
|
||||
template class pFlow::IncludeMask<pFlow::real, pFlow::compareTwo<pFlow::real, pFlow::betweenOp> >;
|
||||
template class pFlow::IncludeMask<pFlow::real, pFlow::compareTwo<pFlow::real, pFlow::betweenEqOp> >;
|
||||
template class IncludeMask<real, compareTwo<real, betweenOp> >;
|
||||
template class IncludeMask<real, compareTwo<real, betweenEqOp> >;
|
||||
|
||||
template class pFlow::IncludeMask<pFlow::real, pFlow::allOp<pFlow::real>>;
|
||||
template class IncludeMask<real, allOp<real>>;
|
||||
|
||||
// realx3
|
||||
template class pFlow::IncludeMask<pFlow::realx3, pFlow::compareOne<pFlow::realx3, pFlow::lessThanOp> >;
|
||||
template class pFlow::IncludeMask<pFlow::realx3, pFlow::compareOne<pFlow::realx3, pFlow::lessThanEqOp> >;
|
||||
template class IncludeMask<realx3, compareOne<realx3, lessThanOp> >;
|
||||
template class IncludeMask<realx3, compareOne<realx3, lessThanEqOp> >;
|
||||
|
||||
template class pFlow::IncludeMask<pFlow::realx3, pFlow::compareOne<pFlow::realx3, pFlow::greaterThanOp> >;
|
||||
template class pFlow::IncludeMask<pFlow::realx3, pFlow::compareOne<pFlow::realx3, pFlow::greaterThanEqOp> >;
|
||||
template class IncludeMask<realx3, compareOne<realx3, greaterThanOp> >;
|
||||
template class IncludeMask<realx3, compareOne<realx3, greaterThanEqOp> >;
|
||||
|
||||
template class pFlow::IncludeMask<pFlow::realx3, pFlow::compareOne<pFlow::realx3, pFlow::equalOp> >;
|
||||
template class IncludeMask<realx3, compareOne<realx3, equalOp> >;
|
||||
|
||||
template class pFlow::IncludeMask<pFlow::realx3, pFlow::compareTwo<pFlow::realx3, pFlow::betweenOp> >;
|
||||
template class pFlow::IncludeMask<pFlow::realx3, pFlow::compareTwo<pFlow::realx3, pFlow::betweenEqOp> >;
|
||||
template class IncludeMask<realx3, compareTwo<realx3, betweenOp> >;
|
||||
template class IncludeMask<realx3, compareTwo<realx3, betweenEqOp> >;
|
||||
|
||||
|
||||
// realx4
|
||||
} // postprocessData
|
||||
|
@ -24,7 +24,10 @@ Licence:
|
||||
#include "fieldsDataBase.hpp"
|
||||
|
||||
|
||||
pFlow::includeMask::includeMask
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
includeMask::includeMask
|
||||
(
|
||||
const dictionary& dict,
|
||||
fieldsDataBase& fieldDB
|
||||
@ -33,7 +36,7 @@ pFlow::includeMask::includeMask
|
||||
database_(fieldDB)
|
||||
{}
|
||||
|
||||
pFlow::includeMask::includeMask
|
||||
includeMask::includeMask
|
||||
(
|
||||
const word &type,
|
||||
const dictionary &opDict,
|
||||
@ -44,7 +47,7 @@ pFlow::includeMask::includeMask
|
||||
{
|
||||
}
|
||||
|
||||
pFlow::uniquePtr<pFlow::includeMask> pFlow::includeMask::create
|
||||
uniquePtr<includeMask> includeMask::create
|
||||
(
|
||||
const dictionary& opDict,
|
||||
fieldsDataBase& fieldsDB
|
||||
@ -97,8 +100,7 @@ pFlow::uniquePtr<pFlow::includeMask> pFlow::includeMask::create
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
pFlow::uniquePtr<pFlow::includeMask>
|
||||
pFlow::includeMask::create
|
||||
uniquePtr<includeMask> includeMask::create
|
||||
(
|
||||
const word &type,
|
||||
const dictionary &opDict,
|
||||
@ -150,3 +152,5 @@ pFlow::uniquePtr<pFlow::includeMask>
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
@ -47,11 +47,15 @@ Licence:
|
||||
#include "virtualConstructor.hpp"
|
||||
|
||||
namespace pFlow
|
||||
{
|
||||
class dictionary;
|
||||
}
|
||||
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
// forward declaration
|
||||
class fieldsDataBase;
|
||||
class dictionary;
|
||||
|
||||
|
||||
class includeMask
|
||||
@ -188,7 +192,7 @@ public:
|
||||
|
||||
|
||||
|
||||
} // pFlow
|
||||
} // pFlow::postprocessData
|
||||
|
||||
#endif //__IncludeMask_hpp__
|
||||
|
||||
|
@ -24,7 +24,7 @@ Licence:
|
||||
#include "types.hpp"
|
||||
#include "dictionary.hpp"
|
||||
|
||||
namespace pFlow
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
@ -176,6 +176,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace pFlow::postprocessData
|
||||
|
||||
#endif //__maskOperation_hpp__
|
@ -23,66 +23,11 @@ Licence:
|
||||
#include "regionPoints.hpp"
|
||||
#include "fieldsDataBase.hpp"
|
||||
|
||||
namespace pFlow
|
||||
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
inline
|
||||
bool writeField
|
||||
(
|
||||
iOstream& os,
|
||||
timeValue t,
|
||||
const regionField<T> field,
|
||||
uint32 threshold,
|
||||
const T& defValue=T{}
|
||||
)
|
||||
{
|
||||
const auto& regPoints = field.regPoints();
|
||||
const uint32 n = field.size();
|
||||
os<<t<<tab;
|
||||
for(uint32 i=0; i<n; i++)
|
||||
{
|
||||
auto numPar = regPoints.indices(i).size();
|
||||
if(numPar >= threshold)
|
||||
{
|
||||
if constexpr(std::is_same_v<T,realx3>)
|
||||
{
|
||||
os<<field[i].x()<<' '<<field[i].y()<<' '<<field[i].z()<<tab;
|
||||
}
|
||||
else if constexpr( std::is_same_v<T,realx4>)
|
||||
{
|
||||
os << field[i].x() << ' ' << field[i].y() << ' ' << field[i].z() << ' ' << field[i].w() << tab;
|
||||
}
|
||||
else
|
||||
{
|
||||
os<<field[i]<<tab;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if constexpr(std::is_same_v<T,realx3>)
|
||||
{
|
||||
os<<defValue.x()<<' '<<defValue.y()<<' '<<defValue.z()<<tab;
|
||||
}
|
||||
else if constexpr( std::is_same_v<T,realx4>)
|
||||
{
|
||||
os << defValue.x() << ' ' << defValue.y() << ' ' << defValue.z() << ' ' << defValue.w() << tab;
|
||||
}
|
||||
else
|
||||
{
|
||||
os<<defValue<<tab;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
os<<endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pFlow::postprocessOperation::postprocessOperation
|
||||
postprocessOperation::postprocessOperation
|
||||
(
|
||||
const dictionary &opDict,
|
||||
const regionPoints& regPoints,
|
||||
@ -100,7 +45,7 @@ pFlow::postprocessOperation::postprocessOperation
|
||||
)
|
||||
{}
|
||||
|
||||
pFlow::postprocessOperation::postprocessOperation
|
||||
postprocessOperation::postprocessOperation
|
||||
(
|
||||
const dictionary &opDict,
|
||||
const word &fieldName,
|
||||
@ -147,12 +92,12 @@ pFlow::postprocessOperation::postprocessOperation
|
||||
fatalExit;
|
||||
}
|
||||
}
|
||||
const pFlow::Time& pFlow::postprocessOperation::time() const
|
||||
const Time& postprocessOperation::time() const
|
||||
{
|
||||
return database_.time();
|
||||
}
|
||||
|
||||
bool pFlow::postprocessOperation::write(const fileSystem &parDir) const
|
||||
bool postprocessOperation::write(const fileSystem &parDir) const
|
||||
{
|
||||
auto ti = time().TimeInfo();
|
||||
|
||||
@ -179,11 +124,12 @@ bool pFlow::postprocessOperation::write(const fileSystem &parDir) const
|
||||
return true;
|
||||
}
|
||||
|
||||
pFlow::uniquePtr<pFlow::postprocessOperation>
|
||||
pFlow::postprocessOperation::create(
|
||||
uniquePtr<postprocessOperation> postprocessOperation::create
|
||||
(
|
||||
const dictionary &opDict,
|
||||
const regionPoints ®Points,
|
||||
fieldsDataBase &fieldsDB)
|
||||
fieldsDataBase &fieldsDB
|
||||
)
|
||||
{
|
||||
word func = opDict.getVal<word>("function");
|
||||
word method = angleBracketsNames("PostprocessOperation", func);
|
||||
@ -209,3 +155,5 @@ pFlow::postprocessOperation::create(
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -76,23 +76,19 @@ Licence:
|
||||
#include "oFstream.hpp"
|
||||
#include "regionField.hpp"
|
||||
#include "includeMask.hpp"
|
||||
#include "postprocessOperationFunctions.hpp"
|
||||
|
||||
namespace pFlow
|
||||
{
|
||||
class Time;
|
||||
}
|
||||
|
||||
/// Type alias for processed region field types.
|
||||
/// Only regionField<real>, regionField<realx3>, and regionField<realx4> are supported
|
||||
/// in the postprocessOperation class.
|
||||
using processedRegFieldType = std::variant
|
||||
<
|
||||
regionField<real>,
|
||||
regionField<realx3>,
|
||||
regionField<realx4>
|
||||
>;
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
/// - forward declaration
|
||||
class fieldsDataBase;
|
||||
class Time;
|
||||
|
||||
|
||||
class postprocessOperation
|
||||
{
|
||||
@ -103,7 +99,7 @@ public:
|
||||
private:
|
||||
|
||||
/// Dictionary containing operation-specific parameters.
|
||||
dictionary operationDict_;
|
||||
pFlow::dictionary operationDict_;
|
||||
|
||||
/// This Threshold is used to exclude the regions which contain
|
||||
/// fewer than this value.
|
||||
@ -273,6 +269,6 @@ public:
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace pFlow::postprocessData
|
||||
|
||||
#endif //__postprocessOperation_hpp__
|
@ -0,0 +1,100 @@
|
||||
/*------------------------------- phasicFlow ---------------------------------
|
||||
O C enter of
|
||||
O O E ngineering and
|
||||
O O M ultiscale modeling of
|
||||
OOOOOOO F luid flow
|
||||
------------------------------------------------------------------------------
|
||||
Copyright (C): www.cemf.ir
|
||||
email: hamid.r.norouzi AT gmail.com
|
||||
------------------------------------------------------------------------------
|
||||
Licence:
|
||||
This file is part of phasicFlow code. It is a free software for simulating
|
||||
granular and multiphase flows. You can redistribute it and/or modify it under
|
||||
the terms of GNU General Public License v3 or any other later versions.
|
||||
|
||||
phasicFlow is distributed to help others in their research in the field of
|
||||
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __postprocessOperationFunctions_hpp__
|
||||
#define __postprocessOperationFunctions_hpp__
|
||||
|
||||
#include <variant>
|
||||
|
||||
#include "types.hpp"
|
||||
#include "iOstream.hpp"
|
||||
#include "regionField.hpp"
|
||||
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
/// Type alias for processed region field types.
|
||||
/// Only regionField<real>, regionField<realx3>, and regionField<realx4> are supported
|
||||
/// in the postprocessOperation class.
|
||||
using processedRegFieldType = std::variant
|
||||
<
|
||||
regionField<real>,
|
||||
regionField<realx3>,
|
||||
regionField<realx4>
|
||||
>;
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline
|
||||
bool writeField
|
||||
(
|
||||
iOstream& os,
|
||||
timeValue t,
|
||||
const regionField<T> field,
|
||||
uint32 threshold,
|
||||
const T& defValue=T{}
|
||||
)
|
||||
{
|
||||
const auto& regPoints = field.regPoints();
|
||||
const uint32 n = field.size();
|
||||
os<<t<<tab;
|
||||
for(uint32 i=0; i<n; i++)
|
||||
{
|
||||
auto numPar = regPoints.indices(i).size();
|
||||
if(numPar >= threshold)
|
||||
{
|
||||
if constexpr(std::is_same_v<T,realx3>)
|
||||
{
|
||||
os<<field[i].x()<<' '<<field[i].y()<<' '<<field[i].z()<<tab;
|
||||
}
|
||||
else if constexpr( std::is_same_v<T,realx4>)
|
||||
{
|
||||
os << field[i].x() << ' ' << field[i].y() << ' ' << field[i].z() << ' ' << field[i].w() << tab;
|
||||
}
|
||||
else
|
||||
{
|
||||
os<<field[i]<<tab;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if constexpr(std::is_same_v<T,realx3>)
|
||||
{
|
||||
os<<defValue.x()<<' '<<defValue.y()<<' '<<defValue.z()<<tab;
|
||||
}
|
||||
else if constexpr( std::is_same_v<T,realx4>)
|
||||
{
|
||||
os << defValue.x() << ' ' << defValue.y() << ' ' << defValue.z() << ' ' << defValue.w() << tab;
|
||||
}
|
||||
else
|
||||
{
|
||||
os<<defValue<<tab;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
os<<endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace pFlow::postprocessData
|
||||
|
||||
#endif //__postprocessOperationFunctions_hpp__
|
@ -20,7 +20,7 @@ Licence:
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
template<typename RegionType, typename ProcessMethodType>
|
||||
pFlow::PostprocessComponent<RegionType,ProcessMethodType>::PostprocessComponent
|
||||
pFlow::postprocessData::PostprocessComponent<RegionType,ProcessMethodType>::PostprocessComponent
|
||||
(
|
||||
const dictionary& dict,
|
||||
fieldsDataBase& fieldsDB,
|
||||
@ -61,7 +61,7 @@ pFlow::PostprocessComponent<RegionType,ProcessMethodType>::PostprocessComponent
|
||||
|
||||
|
||||
template <typename RegionType, typename ProcessMethodType>
|
||||
bool pFlow::PostprocessComponent<RegionType, ProcessMethodType>::execute
|
||||
bool pFlow::postprocessData::PostprocessComponent<RegionType, ProcessMethodType>::execute
|
||||
(
|
||||
const timeInfo &ti,
|
||||
bool forceUpdate
|
||||
@ -129,7 +129,7 @@ bool pFlow::PostprocessComponent<RegionType, ProcessMethodType>::execute
|
||||
|
||||
template <typename RegionType, typename ProcessMethodType>
|
||||
inline
|
||||
bool pFlow::PostprocessComponent<RegionType, ProcessMethodType>::write
|
||||
bool pFlow::postprocessData::PostprocessComponent<RegionType, ProcessMethodType>::write
|
||||
(
|
||||
const fileSystem &parDir
|
||||
) const
|
||||
|
@ -32,7 +32,7 @@ Licence:
|
||||
#include "regionPoints.hpp"
|
||||
#include "regionField.hpp"
|
||||
|
||||
namespace pFlow
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
template<typename RegionType, typename ProcessMethodType>
|
||||
|
@ -24,7 +24,7 @@ Licence:
|
||||
#include "PostprocessComponent.hpp"
|
||||
#include "arithmetic.hpp"
|
||||
|
||||
namespace pFlow
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
template<typename RegionType>
|
||||
|
@ -25,7 +25,7 @@ Licence:
|
||||
#include "GaussianDistribution.hpp"
|
||||
#include "numericConstants.hpp"
|
||||
|
||||
namespace pFlow
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
template<typename RegionType>
|
||||
|
@ -24,7 +24,7 @@ Licence:
|
||||
#include "PostprocessComponent.hpp"
|
||||
#include "uniformDistribution.hpp"
|
||||
|
||||
namespace pFlow
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
template<typename RegionType>
|
||||
|
@ -27,16 +27,18 @@ Licence:
|
||||
#include "lineRegionPoints.hpp"
|
||||
#include "multipleSpheresRegionPoints.hpp"
|
||||
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
template class PostprocessComponentGaussian<sphereRegionPoints>;
|
||||
template class PostprocessComponentUniform<sphereRegionPoints>;
|
||||
template class PostprocessComponentArithmetic<sphereRegionPoints>;
|
||||
|
||||
template class pFlow::PostprocessComponentGaussian<pFlow::sphereRegionPoints>;
|
||||
template class pFlow::PostprocessComponentUniform<pFlow::sphereRegionPoints>;
|
||||
template class pFlow::PostprocessComponentArithmetic<pFlow::sphereRegionPoints>;
|
||||
template class PostprocessComponentGaussian<multipleSpheresRegionPoints>;
|
||||
template class PostprocessComponentUniform<multipleSpheresRegionPoints>;
|
||||
template class PostprocessComponentArithmetic<multipleSpheresRegionPoints>;
|
||||
|
||||
template class pFlow::PostprocessComponentGaussian<pFlow::multipleSpheresRegionPoints>;
|
||||
template class pFlow::PostprocessComponentUniform<pFlow::multipleSpheresRegionPoints>;
|
||||
template class pFlow::PostprocessComponentArithmetic<pFlow::multipleSpheresRegionPoints>;
|
||||
|
||||
template class pFlow::PostprocessComponentGaussian<pFlow::lineRegionPoints>;
|
||||
template class pFlow::PostprocessComponentUniform<pFlow::lineRegionPoints>;
|
||||
template class pFlow::PostprocessComponentArithmetic<pFlow::lineRegionPoints>;
|
||||
template class PostprocessComponentGaussian<lineRegionPoints>;
|
||||
template class PostprocessComponentUniform<lineRegionPoints>;
|
||||
template class PostprocessComponentArithmetic<lineRegionPoints>;
|
||||
|
||||
}
|
@ -1,7 +1,27 @@
|
||||
/*------------------------------- phasicFlow ---------------------------------
|
||||
O C enter of
|
||||
O O E ngineering and
|
||||
O O M ultiscale modeling of
|
||||
OOOOOOO F luid flow
|
||||
------------------------------------------------------------------------------
|
||||
Copyright (C): www.cemf.ir
|
||||
email: hamid.r.norouzi AT gmail.com
|
||||
------------------------------------------------------------------------------
|
||||
Licence:
|
||||
This file is part of phasicFlow code. It is a free software for simulating
|
||||
granular and multiphase flows. You can redistribute it and/or modify it under
|
||||
the terms of GNU General Public License v3 or any other later versions.
|
||||
|
||||
phasicFlow is distributed to help others in their research in the field of
|
||||
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
#include "particleProbePostprocessComponent.hpp"
|
||||
#include "Time.hpp"
|
||||
|
||||
namespace pFlow
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
@ -62,7 +82,7 @@ inline bool writeField
|
||||
|
||||
}
|
||||
|
||||
pFlow::particleProbePostprocessComponent::particleProbePostprocessComponent
|
||||
pFlow::postprocessData::particleProbePostprocessComponent::particleProbePostprocessComponent
|
||||
(
|
||||
const dictionary &dict,
|
||||
fieldsDataBase &fieldsDB,
|
||||
@ -81,7 +101,7 @@ pFlow::particleProbePostprocessComponent::particleProbePostprocessComponent
|
||||
name_(dict.name())
|
||||
{}
|
||||
|
||||
bool pFlow::particleProbePostprocessComponent::execute
|
||||
bool pFlow::postprocessData::particleProbePostprocessComponent::execute
|
||||
(
|
||||
const timeInfo &ti,
|
||||
bool forceExecute
|
||||
@ -126,7 +146,7 @@ bool pFlow::particleProbePostprocessComponent::execute
|
||||
}
|
||||
|
||||
|
||||
bool pFlow::particleProbePostprocessComponent::write(const fileSystem& parDir)const
|
||||
bool pFlow::postprocessData::particleProbePostprocessComponent::write(const fileSystem& parDir)const
|
||||
{
|
||||
if(! executed_ ) return true;
|
||||
|
||||
|
@ -27,7 +27,7 @@ Licence:
|
||||
#include "regionField.hpp"
|
||||
#include "oFstream.hpp"
|
||||
|
||||
namespace pFlow
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
|
||||
|
@ -1,9 +1,29 @@
|
||||
/*------------------------------- phasicFlow ---------------------------------
|
||||
O C enter of
|
||||
O O E ngineering and
|
||||
O O M ultiscale modeling of
|
||||
OOOOOOO F luid flow
|
||||
------------------------------------------------------------------------------
|
||||
Copyright (C): www.cemf.ir
|
||||
email: hamid.r.norouzi AT gmail.com
|
||||
------------------------------------------------------------------------------
|
||||
Licence:
|
||||
This file is part of phasicFlow code. It is a free software for simulating
|
||||
granular and multiphase flows. You can redistribute it and/or modify it under
|
||||
the terms of GNU General Public License v3 or any other later versions.
|
||||
|
||||
phasicFlow is distributed to help others in their research in the field of
|
||||
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
#include "postprocessComponent.hpp"
|
||||
#include "fieldsDataBase.hpp"
|
||||
#include "Time.hpp"
|
||||
|
||||
|
||||
pFlow::postprocessComponent::postprocessComponent
|
||||
pFlow::postprocessData::postprocessComponent::postprocessComponent
|
||||
(
|
||||
const dictionary &dict,
|
||||
fieldsDataBase &fieldsDB,
|
||||
@ -23,7 +43,7 @@ pFlow::postprocessComponent::postprocessComponent
|
||||
}
|
||||
|
||||
|
||||
pFlow::uniquePtr<pFlow::postprocessComponent> pFlow::postprocessComponent::create
|
||||
pFlow::uniquePtr<pFlow::postprocessData::postprocessComponent> pFlow::postprocessData::postprocessComponent::create
|
||||
(
|
||||
const dictionary& dict,
|
||||
fieldsDataBase& fieldsDB,
|
||||
|
@ -25,12 +25,17 @@ Licence:
|
||||
#include "dictionary.hpp"
|
||||
#include "virtualConstructor.hpp"
|
||||
|
||||
namespace pFlow
|
||||
namespace
|
||||
{
|
||||
class dictionary;
|
||||
}
|
||||
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
class fieldsDataBase;
|
||||
|
||||
class regionPoints;
|
||||
class dictionary;
|
||||
class fieldsDataBase;
|
||||
|
||||
class postprocessComponent
|
||||
{
|
||||
@ -112,6 +117,6 @@ public:
|
||||
|
||||
};
|
||||
|
||||
} // namespace pFlow
|
||||
} // namespace pFlow::postprocessData
|
||||
|
||||
#endif // __postprocessComponent_hpp__
|
@ -1,4 +1,3 @@
|
||||
|
||||
/*------------------------------- phasicFlow ---------------------------------
|
||||
O C enter of
|
||||
O O E ngineering and
|
||||
@ -25,7 +24,7 @@ Licence:
|
||||
#include "postprocessGlobals.hpp"
|
||||
#include "postprocessComponent.hpp"
|
||||
|
||||
pFlow::postprocessData::postprocessData
|
||||
pFlow::postprocessData::postprocessData::postprocessData
|
||||
(
|
||||
const systemControl &control,
|
||||
timeValue startTime
|
||||
@ -45,7 +44,7 @@ pFlow::postprocessData::postprocessData
|
||||
)
|
||||
)
|
||||
{
|
||||
postProcessGlobals::defaultDir__ = CWD()/pFlow::postProcessGlobals::defaultRelDir__;
|
||||
defaultDir__ = CWD()/defaultRelDir__;
|
||||
|
||||
// if dictionary is not provided, no extra action is required.
|
||||
if( !dict_.fileExist() || !dict_.headerOk() )
|
||||
@ -98,8 +97,10 @@ pFlow::postprocessData::postprocessData
|
||||
|
||||
}
|
||||
|
||||
bool pFlow::postprocessData::execute()
|
||||
bool pFlow::postprocessData::postprocessData::execute()
|
||||
{
|
||||
if( inSimulation_ && !activeInSimulation_() ) return true;
|
||||
|
||||
const auto& ti = time_.TimeInfo();
|
||||
|
||||
for(auto& component:postprocesses_)
|
||||
@ -116,8 +117,10 @@ bool pFlow::postprocessData::execute()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pFlow::postprocessData::write() const
|
||||
bool pFlow::postprocessData::postprocessData::write() const
|
||||
{
|
||||
if( inSimulation_ && !activeInSimulation_() ) return true;
|
||||
|
||||
for(auto& component:postprocesses_)
|
||||
{
|
||||
if(!component->executed())
|
||||
@ -125,7 +128,7 @@ bool pFlow::postprocessData::write() const
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!component->write(postProcessGlobals::defaultDir__/component->name()))
|
||||
if(!component->write(defaultDir__/component->name()))
|
||||
{
|
||||
fatalErrorInFunction
|
||||
<<"Error occured in writing postprocess component: "
|
||||
@ -136,7 +139,7 @@ bool pFlow::postprocessData::write() const
|
||||
return true;
|
||||
}
|
||||
|
||||
void pFlow::postprocessData::setOutputDirectory(const fileSystem &path) const
|
||||
void pFlow::postprocessData::postprocessData::setOutputDirectory(const fileSystem &path) const
|
||||
{
|
||||
postProcessGlobals::defaultDir__ = path;
|
||||
defaultDir__ = path;
|
||||
}
|
||||
|
@ -28,14 +28,18 @@ Licence:
|
||||
#include "fieldsDataBase.hpp"
|
||||
#include "postprocessComponent.hpp"
|
||||
|
||||
|
||||
namespace pFlow
|
||||
namespace pFlow
|
||||
{
|
||||
|
||||
class systemControl;
|
||||
class Time;
|
||||
class timeInfo;
|
||||
|
||||
}
|
||||
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @class postprocessData
|
||||
@ -109,6 +113,6 @@ public:
|
||||
void setOutputDirectory(const fileSystem& path)const;
|
||||
};
|
||||
|
||||
} // namespace pFlow
|
||||
} // namespace pFlow::postprocessData
|
||||
|
||||
#endif // __postprocessData_hpp__
|
@ -23,7 +23,7 @@ Licence:
|
||||
|
||||
#include "fileSystem.hpp"
|
||||
|
||||
namespace pFlow::postProcessGlobals
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
static fileSystem defaultDir__;
|
||||
|
@ -22,9 +22,11 @@ Licence:
|
||||
#define __postprocessTimeControl_hpp__
|
||||
|
||||
#include "baseTimeControl.hpp"
|
||||
#include "dictionary.hpp"
|
||||
|
||||
namespace pFlow
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
class postprocessTimeControl
|
||||
:
|
||||
public baseTimeControl
|
||||
@ -60,6 +62,6 @@ postprocessTimeControl(
|
||||
// Additional methods and members can be added here
|
||||
};
|
||||
|
||||
} // namespace pFlow
|
||||
} // namespace pFlow::postprocessData
|
||||
|
||||
#endif // __postprocessTimeControl_hpp__
|
@ -28,7 +28,7 @@ Licence:
|
||||
#include "span.hpp"
|
||||
#include "numericConstants.hpp"
|
||||
|
||||
namespace pFlow
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
class GaussianDistribution
|
||||
|
@ -32,6 +32,9 @@ namespace pFlow
|
||||
|
||||
class dictionary;
|
||||
|
||||
namespace postprocessData
|
||||
{
|
||||
|
||||
class arithmetic
|
||||
{
|
||||
private:
|
||||
@ -86,6 +89,8 @@ public:
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace postprocessData
|
||||
|
||||
} // namespace pFlow
|
||||
|
||||
#endif //__arithmetic_hpp__
|
@ -32,6 +32,9 @@ namespace pFlow
|
||||
|
||||
class dictionary;
|
||||
|
||||
namespace postprocessData
|
||||
{
|
||||
|
||||
class uniformDistribution
|
||||
{
|
||||
private:
|
||||
@ -86,6 +89,8 @@ public:
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace postprocessData
|
||||
|
||||
} // namespace pFlow
|
||||
|
||||
#endif //__uniformDistribution_hpp__
|
569
src/PostprocessData/readme.md
Normal file
569
src/PostprocessData/readme.md
Normal file
@ -0,0 +1,569 @@
|
||||
# PostprocessData Module in phasicFlow
|
||||
|
||||
The `PostprocessData` module in phasicFlow provides powerful tools for analyzing particle-based simulations both during runtime (in-simulation) and after simulation completion (post-simulation). This document explains how to configure and use the postprocessing features through the dictionary-based input system.
|
||||
|
||||
- in-simulation: this is postprocessing that is active during simulation. When running a solver, it allows for real-time data analysis and adjustments based on the simulation's current state. See below to see how you can activate in-simulation postprocessing.
|
||||
- post-simulation: this is postprocessing that is done after the simulation is completed. It allows for detailed analysis of the simulation results, including data extraction and visualization based on the results that are stored in time-folders. If you want to use post-simulation, you need to run utility `postprocessPhasicFlow` in terminal (in the simulation case setup folder) to run the postprocessing. This utility reads the `postprocessDataDict` file and performs the specified operations on the simulation data.
|
||||
|
||||
## 1. Overview
|
||||
|
||||
Postprocessing in phasicFlow allows you to:
|
||||
|
||||
- Extract information about particles in specific regions of the domain
|
||||
- Calculate statistical properties such as averages and sums of particle attributes
|
||||
- Track specific particles throughout the simulation
|
||||
- Apply different weighing methods when calculating statistics
|
||||
- Perform postprocessing at specific time intervals
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [1. Overview](#1-overview)
|
||||
- [2. Setting Up Postprocessing](#2-setting-up-postprocessing)
|
||||
- [2.1. Basic Configuration](#21-basic-configuration)
|
||||
- [3. Time Control Options](#3-time-control-options)
|
||||
- [4. Processing Methods](#4-processing-methods)
|
||||
- [5. Region Types](#5-region-types)
|
||||
- [6. Processing Operations](#6-processing-operations)
|
||||
- [6.1. Available Functions in average](#61-available-functions-in-average)
|
||||
- [6.2. About fluctuation2 in average function](#62-about-fluctuation2-in-average-function)
|
||||
- [6.3. Derived Functions](#63-derived-functions)
|
||||
- [6.4. Available Fields](#64-available-fields)
|
||||
- [6.5. Optional Parameters](#65-optional-parameters)
|
||||
- [7. Examples](#7-examples)
|
||||
- [7.1. Example 1: Probing Individual Particles](#71-example-1-probing-individual-particles)
|
||||
- [7.2. Example 2: Processing in a Spherical Region](#72-example-2-processing-in-a-spherical-region)
|
||||
- [7.3. Example 3: Processing Along a Line](#73-example-3-processing-along-a-line)
|
||||
- [8. Advanced Features](#8-advanced-features)
|
||||
- [8.1. Special functions applied on fields](#81-special-functions-applied-on-fields)
|
||||
- [8.2. Particle Filtering with includeMask](#82-particle-filtering-with-includemask)
|
||||
- [8.3. Implementation Notes](#83-implementation-notes)
|
||||
- [9. Mathematical Formulations](#9-mathematical-formulations)
|
||||
- [10. A complete dictionary file (postprocessDataDict)](#10-a-complete-dictionary-file-postprocessdatadict)
|
||||
|
||||
## 2. Setting Up Postprocessing
|
||||
|
||||
Postprocessing is configured through a dictionary file named `postprocessDataDict` which should be placed in the `settings` directory. Below is a detailed explanation of the configuration options.
|
||||
|
||||
### 2.1. Basic Configuration
|
||||
|
||||
The input dictionary, **settings/postprocessDataDict**, may look like this:
|
||||
|
||||
```cpp
|
||||
// PostprocessData dictionary
|
||||
|
||||
|
||||
// Enable/disable postprocessing during simulation
|
||||
runTimeActive yes; // Options: yes, no
|
||||
|
||||
// Shape type - only needed when doing post-simulation processing
|
||||
shapeType sphere; // Options depend on the simulation type: sphere, grain, etc.
|
||||
|
||||
// Default time control for postprocessing components
|
||||
defaultTimeControl
|
||||
{
|
||||
timeControl timeStep; // Options: timeStep, simulationTime, settings
|
||||
startTime 0; // Start time for postprocessing
|
||||
endTime 1000; // End time for postprocessing
|
||||
executionInterval 150; // How frequently to run postprocessing
|
||||
}
|
||||
|
||||
// List of postprocessing components
|
||||
components
|
||||
(
|
||||
// Component definitions here...
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
If you want to activate in-simulation postprocessing, you need to add these lines to the `settings/settingsDict` file:
|
||||
|
||||
```cpp
|
||||
libs ("libPostprocessData.so");
|
||||
|
||||
auxFunctions postprocessData;
|
||||
```
|
||||
|
||||
This will link the postprocessing library to your simulation, allowing you to use its features. Note that, anytime you want to deactivate the in-simulation postprocessing, you can simply change the `runTimeActive` option to `no` in `postprocessDataDict` file.
|
||||
|
||||
## 3. Time Control Options
|
||||
|
||||
Each postprocessing component can either use the default time control settings or define its own. There are three main options for time control:
|
||||
|
||||
| Option | Description | Required Parameters |
|
||||
|--------|-------------|---------------------|
|
||||
| `timeStep` | Controls execution based on simulation time steps | `startTime`, `endTime`, `executionInterval` |
|
||||
| `simulationTime` | Controls execution based on simulation time | `startTime`, `endTime`, `executionInterval` |
|
||||
| `settings` | Uses parameters from settingsDict file | None (defined elsewhere) |
|
||||
| `default` | Uses the default time control settings (uses `defaultTimeControl` settings)| None (uses default) |
|
||||
|
||||
If no time control is specified, the `default` option is used automatically.
|
||||
|
||||
## 4. Processing Methods
|
||||
|
||||
The postprocessing module provides several methods for processing particle data. They are categorized into two main groups: bulk and individual methods.
|
||||
|
||||
- **Bulk Methods**: Operate on all particles that are located in a specified locations/regions (cells, spheres, etc.).
|
||||
- **Individual Methods**: Operate on specific particles, allowing for targeted particle property extraction.
|
||||
|
||||
| Method | Property type | Description | Formula |
|
||||
|--------|------------------|-------------|---------|
|
||||
| `arithmetic` | bulk | Simple arithmetic mean/sum with equal weights | Each particle contributes equally |
|
||||
| `uniformDistribution` | bulk | Each particle contributes inversely proportional to the total number of particles | $w_i = 1/n$ where $n$ is the number of particles |
|
||||
| `GaussianDistribution` | bulk | Weight contribution based on distance from center with Gaussian falloff | $w_i = \exp(-\|x_i - c\|^2/(2\sigma^2))/\sqrt{2\pi\sigma^2}$ |
|
||||
| `particleProbe` | individual | Extracts values from specific particles | Direct access to particle properties |
|
||||
|
||||
## 5. Region Types
|
||||
|
||||
Regions define where in the domain the postprocessing operations are applied:
|
||||
|
||||
| Region Type | Description | Required Parameters | Compatible with |
|
||||
|-------------|-------------|---------------------|-----------------|
|
||||
| `sphere` | A spherical region | `radius`, `center` | bulk |
|
||||
| `multipleSpheres` | Multiple spherical regions | `centers`, `radii` | bulk |
|
||||
| `line` | Spheres along a line with specified radius | `p1`, `p2`, `nSpheres`, `radius` | bulk |
|
||||
| `centerPoints` | Specific particles selected by ID | `ids` | individual |
|
||||
|
||||
## 6. Processing Operations
|
||||
|
||||
Within each processing region of type `bulk`, you can define multiple operations to be performed:
|
||||
|
||||
### 6.1. Available Functions in average
|
||||
|
||||
| Function | Property type | Description | Formula | Required Parameters |
|
||||
|----------|---------------|-------------|---------|---------------------|
|
||||
| `average` | bulk | Weighted average of particle field values | see Equation 1 | `field`, `phi` (optional), `threshold` (optional), `includeMask` (optional), `divideByVolume` (optional), `fluctuation2` (optional) |
|
||||
| `sum` | bulk | Weighted sum of particle field values | see Equation 2 | `field`, `phi` (optional),`threshold` (optional), `includeMask` (optional), `divideByVolume` (optional) |
|
||||
|
||||
Equation 1:
|
||||
|
||||
$$\text{mean} = \frac{\sum_j w_j \cdot \phi_j \cdot \text{field}_j}{\sum_i w_i \cdot \phi_i}$$
|
||||
|
||||
Equation 2:
|
||||
|
||||
$$\text{sum} = \sum_j w_j \cdot \phi_j \cdot \text{field}_j$$
|
||||
|
||||
where:
|
||||
|
||||
- $j$ is the index of the particle in the region that also satisfies the `includeMask`
|
||||
- $i$ is the index of the particle in the region
|
||||
- $w_j$ is the weight of particle $j$ based on the selected processing method
|
||||
- $\phi_j$ is the value of the `phi` field for particle $j$ (default is 1)
|
||||
- $field_j$ is the value of the specified field for particle $j$
|
||||
|
||||
### 6.2. About fluctuation2 in average function
|
||||
|
||||
Fluctuation2 is an optional parameter that can be used to account for fluctuations in the particle field values with respect to mean value of the field.
|
||||
It is used in the `average` function to calculate the fluctuation of the field values around the mean. The formula for fluctuation2 is:
|
||||
|
||||
$$\text{fluctuation}^2 = \frac{\sum_j w_j \cdot \phi_j \cdot (\text{field}_j - \text{mean})^2}{\sum_i w_i \cdot \phi_i}$$
|
||||
|
||||
where:
|
||||
|
||||
- `mean`: is the average value of the field in the region.
|
||||
- `field`: The field to be processed (e.g., `velocity`, `mass`, etc.)
|
||||
- `fluctuation2`: Optional parameter to account for fluctuations in the particle field values.
|
||||
|
||||
### 6.3. Derived Functions
|
||||
|
||||
In addition to the above basic functions, some derived functions are available for specific calculations:
|
||||
|
||||
| Function | Property type | Description | Formula | Required Parameters |
|
||||
|----------|---------------|-------------|---------|---------------------|
|
||||
|`avMassVelocity` | bulk | Average velocity weighted by mass | $\frac{\sum_{i \in \text{region}} w_i \cdot m_i \cdot v_i}{\sum_{i \in \text{region}} w_i \cdot m_i}$ | - |
|
||||
|
||||
### 6.4. Available Fields
|
||||
|
||||
All the pointFields in the simulation database (for in-simulation processing), or the ones stored in the time folders (for post-simulation processing) can be referenced in the operations. In addition to them, some extra fields are available for use in the operations. The following fields are available for use in the operations:
|
||||
|
||||
1. Extra fileds to be used in post-processing operations:
|
||||
|
||||
| Field | Field Type | Description | Default Value |
|
||||
|-------|------------|-------------|---------------|
|
||||
| `position` | `realx3` | Particle positions | - |
|
||||
| `one` | `real` | Value 1 for each particle | 1 |
|
||||
| `mass` | `real` | Particle mass | - |
|
||||
| `density` | `real` | Particle density | - |
|
||||
| `volume` | `real` | Particle volume | - |
|
||||
| `diameter` | `real` | Particle diameter | - |
|
||||
| `I` | `real` | Moment of inertia | - |
|
||||
|
||||
2. Common fields which are available in the simulation database/time folders:
|
||||
|
||||
| Field | Field Type | Description |
|
||||
|-------|------------|-------------|
|
||||
| `velocity` | `realx3` | Particle velocity |
|
||||
| `rVelocity` | `realx3` | Particle rotational velocity |
|
||||
| `acceleration` | `realx3` | Particle acceleration |
|
||||
| `rAcceleration` | `realx3` | Particle rotational acceleration |
|
||||
| `contactForce` | `realx3` | Particle contact force |
|
||||
| `contactTorque` | `realx3` | Particle contact torque |
|
||||
| `id` | `integer` | Particle ID |
|
||||
| `shapeIndex` | `integer` | Particle shape index |
|
||||
|
||||
The above fields may vary from one type of simulation to other. Pleas note that this is only a tentative list.
|
||||
|
||||
### 6.5. Optional Parameters
|
||||
|
||||
| Parameter | Description | Default | Options |
|
||||
|-----------|-------------|---------|---------|
|
||||
| `divideByVolume` | Divide result by region volume | `no` | `yes` or `no` |
|
||||
| `threshold` | Exclude regions with fewer particles | 1 | Integer value |
|
||||
| `includeMask` | Filter particles based on a field value | `all` | `all`, `lessThan`, `greaterThan`, `between`, `lessThanOrEq`, `greaterThanOrEq`, `betweenEq` |
|
||||
|`fluctuation2` (in average only)| Calculate fluctuation of field values | `no` | `yes` or `no` |
|
||||
| `phi` | Field to be used for weighted averaging | `one` | Any valid field name |
|
||||
|
||||
## 7. Examples
|
||||
|
||||
### 7.1. Example 1: Probing Individual Particles
|
||||
|
||||
```cpp
|
||||
velocityProb
|
||||
{
|
||||
processMethod particleProbe;
|
||||
processRegion centerPoints;
|
||||
selector id;
|
||||
field component(position,y);
|
||||
ids (0 10 100);
|
||||
timeControl default;
|
||||
}
|
||||
```
|
||||
|
||||
This example extracts the y-component of the position for particles with IDs 0, 10, and 100.
|
||||
|
||||
### 7.2. Example 2: Processing in a Spherical Region
|
||||
|
||||
```cpp
|
||||
on_single_sphere
|
||||
{
|
||||
processMethod arithmetic;
|
||||
processRegion sphere;
|
||||
|
||||
sphereInfo
|
||||
{
|
||||
radius 0.01;
|
||||
center (-0.08 -0.08 0.015);
|
||||
}
|
||||
|
||||
timeControl default;
|
||||
|
||||
operations
|
||||
(
|
||||
averageVel
|
||||
{
|
||||
function average;
|
||||
field mag(velocity);
|
||||
divideByVolume no;
|
||||
fluctuation2 yes;
|
||||
threshold 3;
|
||||
includeMask all;
|
||||
}
|
||||
|
||||
par1Fraction
|
||||
{
|
||||
function average;
|
||||
field one;
|
||||
phi one;
|
||||
divideByVolume no;
|
||||
includeMask lessThan;
|
||||
|
||||
lessThanInfo
|
||||
{
|
||||
field diameter;
|
||||
value 0.0031;
|
||||
}
|
||||
}
|
||||
|
||||
numberDensity
|
||||
{
|
||||
function sum;
|
||||
field one;
|
||||
phi one;
|
||||
divideByVolume yes;
|
||||
}
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
This example defines a sphere region and performs three operations:
|
||||
|
||||
1. Calculate the average of velocity magnitude of particles
|
||||
2. Calculate the fraction of particles with diameter less than 0.0031
|
||||
3. Calculate the number density by summing and dividing by volume
|
||||
|
||||
### 7.3. Example 3: Processing Along a Line
|
||||
|
||||
In this example, a line region is defined. The `lineInfo` section specifies the start and end points of the line, the number of spheres to create along the line, and the radius of each point. Bulk properties are calculated in each sphere, based on the properties of particles contained in each sphere.
|
||||
|
||||
```cpp
|
||||
along_a_line
|
||||
{
|
||||
processMethod arithmetic;
|
||||
processRegion line;
|
||||
|
||||
timeControl simulationTime;
|
||||
startTime 1.0;
|
||||
endTime 3.0;
|
||||
executionInterval 0.1;
|
||||
|
||||
lineInfo
|
||||
{
|
||||
p1 (0 0 0);
|
||||
p2 (0 0.15 0.15);
|
||||
nSpheres 10;
|
||||
radius 0.01;
|
||||
}
|
||||
|
||||
operations
|
||||
(
|
||||
bulkDensity
|
||||
{
|
||||
function sum;
|
||||
field mass;
|
||||
phi one;
|
||||
divideByVolume yes;
|
||||
}
|
||||
|
||||
volumeDensity
|
||||
{
|
||||
function sum;
|
||||
field volume;
|
||||
divideByVolume yes;
|
||||
}
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
This example creates 10 spherical regions along a line from (0,0,0) to (0,0.15,0.15) and calculates the bulk density and volume density in each region.
|
||||
|
||||
## 8. Advanced Features
|
||||
|
||||
### 8.1. Special functions applied on fields
|
||||
|
||||
You can access specific components of vector fields (`realx3`) using the `component` function:
|
||||
|
||||
```cpp
|
||||
field component(position,y); // Access the y-component of position
|
||||
```
|
||||
|
||||
Here is a complete list of these special functions:
|
||||
|
||||
| Function Name | Valid field Type | Example |
|
||||
|-----------------|------------|---------|
|
||||
| `component` | `realx3` | `component(velocity,x)` |
|
||||
| `abs` | `real` | `abs(s)` |
|
||||
| `square` | `real` | `square(I)` |
|
||||
| `cube` | `real` | `cube(diameter)` |
|
||||
| `squre root` | `real` | `sqrt(mass)` |
|
||||
| `magnitude` | `realx3` | `mag(contactForce)` |
|
||||
| `magnitude square` | `realx3` | `magSquare(velocity)` |
|
||||
| `magnitude cube` | `realx3` | `magCube(velocity)` |
|
||||
| `magnitude square root` | `realx3` | `magSqrt(acceleration)` |
|
||||
|
||||
### 8.2. Particle Filtering with includeMask
|
||||
|
||||
The `includeMask` parameter allows you to filter particles based on field values:
|
||||
|
||||
```cpp
|
||||
includeMask lessThan;
|
||||
lessThanInfo
|
||||
{
|
||||
field diameter;
|
||||
value 0.0031;
|
||||
}
|
||||
```
|
||||
|
||||
Supported masks:
|
||||
|
||||
- `all`: Include all particles (default)
|
||||
- `lessThan`: Include particles where field < value
|
||||
- `greaterThan`: Include particles where field > value
|
||||
- `between`: Include particles where value1 < field < value2
|
||||
- `lessThanOrEq`: Include particles where field ≤ value
|
||||
- `greaterThanOrEq`: Include particles where field ≥ value
|
||||
- `betweenEq`: Include particles where value1 ≤ field ≤ value2
|
||||
|
||||
### 8.3. Implementation Notes
|
||||
|
||||
- The postprocessing system can work both during simulation (`runTimeActive yes`) or after simulation completion.
|
||||
- When using post-simulation mode, you must specify the correct `shapeType` to properly initialize the shape objects.
|
||||
- Results are written to output files in the case directory with timestamps.
|
||||
- The `threshold` parameter helps eliminate statistical noise in regions with few particles.
|
||||
- Setting `divideByVolume` to `yes` normalizes results by the volume of the region, useful for calculating densities.
|
||||
|
||||
## 9. Mathematical Formulations
|
||||
|
||||
For weighted `bulk` properties calculation, we have these two general formulations:
|
||||
|
||||
- For weighted averaging:
|
||||
|
||||
$$ \text{average} = \frac{\sum_j w_j \cdot \phi_j \cdot \text{field}_j}{\sum_i w_i \cdot \phi_i} $$
|
||||
|
||||
- For weighted summing:
|
||||
|
||||
$$ \text{sum} = \sum_j w_j \cdot \phi_j \cdot \text{field}_j $$
|
||||
|
||||
If `divideByVolume` is set to `yes`, the result is divided by the volume of the region:
|
||||
|
||||
$$ \text{volumetric result} = \frac{\text{result}}{V_{\text{region}}} $$
|
||||
|
||||
## 10. A complete dictionary file (postprocessDataDict)
|
||||
|
||||
```C++
|
||||
/* -------------------------------*- C++ -*--------------------------------- *\
|
||||
| phasicFlow File |
|
||||
| copyright: www.cemf.ir |
|
||||
\* ------------------------------------------------------------------------- */
|
||||
objectName postprocessDataDict;
|
||||
objectType dictionary;;
|
||||
fileFormat ASCII;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
// Yes: postprocessing is active during the simulation
|
||||
// No: postprocessing is not active during the simulation
|
||||
// and it can be done after simulation
|
||||
runTimeActive yes;
|
||||
|
||||
// shapeType: defines the type of the shape that is used in the simulation
|
||||
// (for example: sphere, grain, etc).
|
||||
// shapeType is only used when postprocessing is done after simulation
|
||||
// to initialize the shape object for post processing operatoins
|
||||
shapeType sphere;
|
||||
|
||||
// default time control to be used in the postprocessing components
|
||||
defaultTimeControl
|
||||
{
|
||||
timeControl timeStep; // timeStep, simulationTime are the options here
|
||||
startTime 0;
|
||||
endTime 1000;
|
||||
executionInterval 150;
|
||||
}
|
||||
|
||||
// list of postprocessing components
|
||||
components
|
||||
(
|
||||
// probing particles for their state variables, like velocity, position, etc
|
||||
velocityProb
|
||||
{
|
||||
processMethod particleProbe;
|
||||
processRegion centerPoints;
|
||||
selector id;
|
||||
field component(position,y);
|
||||
ids (0 10 100);
|
||||
timeControl default; // other options are settings, timeStep, simulationTime
|
||||
// settings: uses parameters from settingsDict file
|
||||
// timeStep: uses the time step of the simulation controlling the execution of postprocessing
|
||||
// simulationTime: uses the simulation time of the simulation controlling the execution of postprocessing
|
||||
// default: uses the default time control (defined in defaultTimeControl).
|
||||
// default behavior: if you do not specify it, parameters in defaultTimeControl is used.
|
||||
}
|
||||
|
||||
on_single_sphere
|
||||
{
|
||||
// method of performing the sum (arithmetic, uniformDistribution, GaussianDistribution)
|
||||
processMethod arithmetic;
|
||||
|
||||
// Postprocessing is done on particles whose centers are inside this spehre
|
||||
processRegion sphere;
|
||||
|
||||
sphereInfo
|
||||
{
|
||||
radius 0.01; // radius of sphere
|
||||
center (-0.08 -0.08 0.015); // center of sphere
|
||||
}
|
||||
|
||||
timeControl default;
|
||||
|
||||
/// all the postprocess operations to be done on sphere region
|
||||
operations
|
||||
(
|
||||
// computes the arithmetic mean of particle velocity
|
||||
averageVel
|
||||
{
|
||||
function average;
|
||||
field velocity;
|
||||
fluctuation2 yes;
|
||||
divideByVolume no; // default is no
|
||||
threshold 3; // default is 1
|
||||
includeMask all; // default is all
|
||||
}
|
||||
// - function: average, sum, and other derived ones from sum and average
|
||||
// - field: names of the fields in the simulation. Some special fields
|
||||
// are: mass, density, volume, position, one, I.
|
||||
// - divideByVolume: whether the result is divided by the volume of the region
|
||||
// - threshold: exclude regions that contains particles less than threshold
|
||||
// - includeMask: all, lessThan, greaterThan, between, lessThanOrEq, greaterThanEq, betweenEq
|
||||
|
||||
|
||||
// computes the fraction of par1 in the region
|
||||
par1Fraction
|
||||
{
|
||||
function average;
|
||||
field one; // default
|
||||
phi one; // default
|
||||
divideByVolume no;
|
||||
includeMask lessThan;
|
||||
|
||||
// diameter of par1 is 0.003, so these settings
|
||||
// will select only particles of type par1
|
||||
lessThanInfo
|
||||
{
|
||||
field diameter;
|
||||
value 0.0031;
|
||||
}
|
||||
}
|
||||
|
||||
numberDensity
|
||||
{
|
||||
function sum;
|
||||
field one;
|
||||
phi one;
|
||||
divideByVolume yes;
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
along_a_line
|
||||
{
|
||||
processMethod arithmetic;
|
||||
|
||||
processRegion line;
|
||||
|
||||
// the time interval for executing the post-processing
|
||||
// other options: timeStep, default, and settings
|
||||
timeControl simulationTime;
|
||||
startTime 1.0;
|
||||
endTime 3.0;
|
||||
executionInterval 0.1;
|
||||
|
||||
// 10 spheres with radius 0.01 along the straight line defined by p1 and p2
|
||||
lineInfo
|
||||
{
|
||||
p1 (0 0 0);
|
||||
p2 (0 0.15 0.15);
|
||||
nSpheres 10;
|
||||
radius 0.01;
|
||||
}
|
||||
|
||||
operations
|
||||
(
|
||||
// computes the arithmetic mean of particle velocity
|
||||
numberDensity
|
||||
{
|
||||
function sum;
|
||||
field one;
|
||||
divideByVolume yes; //default is no
|
||||
}
|
||||
|
||||
volumeDensity
|
||||
{
|
||||
function sum;
|
||||
field volume; //
|
||||
divideByVolume yes; //default is no
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
```
|
@ -25,7 +25,7 @@ Licence:
|
||||
#include "regionPoints.hpp"
|
||||
#include "Field.hpp"
|
||||
|
||||
namespace pFlow
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
@ -119,7 +119,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
} // namespace pFlow
|
||||
} // namespace pFlow::postprocessData
|
||||
|
||||
#include "regionFieldTemplate.cpp"
|
||||
|
||||
|
@ -1,10 +1,14 @@
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
pFlow::regionField<T>::regionField(
|
||||
regionField<T>::regionField(
|
||||
const word& name,
|
||||
const regionPoints& rPoints,
|
||||
const T defaultVal)
|
||||
:
|
||||
field_(name, "regionFieldValue", rPoints.size(), rPoints.size(), defaultVal),
|
||||
regionPoints_(rPoints)
|
||||
{}
|
||||
{}
|
||||
|
||||
} // End namespace pFlow::postprocessData
|
@ -3,7 +3,10 @@
|
||||
#include "Set.hpp"
|
||||
#include "pStructSelector.hpp"
|
||||
|
||||
bool pFlow::centerPointsRegionPoints::selectIds()
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
bool centerPointsRegionPoints::selectIds()
|
||||
{
|
||||
if(!firstTimeUpdate_) return true;
|
||||
firstTimeUpdate_ = false;
|
||||
@ -42,7 +45,7 @@ bool pFlow::centerPointsRegionPoints::selectIds()
|
||||
return true;
|
||||
}
|
||||
|
||||
pFlow::centerPointsRegionPoints::centerPointsRegionPoints(
|
||||
centerPointsRegionPoints::centerPointsRegionPoints(
|
||||
const dictionary &dict,
|
||||
fieldsDataBase &fieldsDataBase)
|
||||
: regionPoints(dict, fieldsDataBase),
|
||||
@ -50,7 +53,7 @@ pFlow::centerPointsRegionPoints::centerPointsRegionPoints(
|
||||
probDict_(dict)
|
||||
{}
|
||||
|
||||
bool pFlow::centerPointsRegionPoints::update()
|
||||
bool centerPointsRegionPoints::update()
|
||||
{
|
||||
if(!selectIds()) return false;
|
||||
|
||||
@ -74,7 +77,7 @@ bool pFlow::centerPointsRegionPoints::update()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pFlow::centerPointsRegionPoints::write(iOstream &os) const
|
||||
bool centerPointsRegionPoints::write(iOstream &os) const
|
||||
{
|
||||
if(firstTimeUpdate_)
|
||||
{
|
||||
@ -95,3 +98,5 @@ bool pFlow::centerPointsRegionPoints::write(iOstream &os) const
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End namespace pFlow::postprocessData
|
||||
|
@ -23,7 +23,7 @@ Licence:
|
||||
|
||||
#include "regionPoints.hpp"
|
||||
|
||||
namespace pFlow
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
/**
|
||||
@ -163,7 +163,7 @@ public:
|
||||
|
||||
}; // class centerPointsRegionPoints
|
||||
|
||||
} // namespace pFlow
|
||||
} // namespace pFlow::postprocessData
|
||||
|
||||
|
||||
|
||||
|
@ -1,7 +1,10 @@
|
||||
#include "lineRegionPoints.hpp"
|
||||
#include "fieldsDataBase.hpp"
|
||||
|
||||
pFlow::lineRegionPoints::lineRegionPoints
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
lineRegionPoints::lineRegionPoints
|
||||
(
|
||||
const dictionary &dict,
|
||||
fieldsDataBase &fieldsDataBase
|
||||
@ -14,7 +17,7 @@ pFlow::lineRegionPoints::lineRegionPoints
|
||||
selectedPoints_("selectedPoints")
|
||||
{
|
||||
const auto& lDict = dict.subDict("lineInfo");
|
||||
uint32 nPoints = lDict.getValMax<uint32>("numPoints",2);
|
||||
uint32 nSpheres = lDict.getValMax<uint32>("nSpheres",2);
|
||||
realList raddi;
|
||||
|
||||
if( lDict.containsDataEntry("radii"))
|
||||
@ -24,24 +27,24 @@ pFlow::lineRegionPoints::lineRegionPoints
|
||||
else
|
||||
{
|
||||
auto r = lDict.getVal<real>("radius");
|
||||
raddi = realList(nPoints, r);
|
||||
raddi = realList(nSpheres, r);
|
||||
}
|
||||
|
||||
if(raddi.size() != nPoints)
|
||||
if(raddi.size() != nSpheres)
|
||||
{
|
||||
fatalErrorInFunction
|
||||
<< "The number elements in of radii list should be equal to the "
|
||||
<< "number of points"<<endl;
|
||||
<< "The number of elements in the radii list should be equal to the "
|
||||
<< "nSpheres"<<endl;
|
||||
fatalExit;
|
||||
}
|
||||
|
||||
sphereRegions_.resize(nPoints, sphere(realx3(0,0,0),1));
|
||||
centerPoints_.resize(nPoints);
|
||||
volumes_.resize(nPoints);
|
||||
diameters_.resize(nPoints);
|
||||
selectedPoints_.resize(nPoints);
|
||||
real dt = 1.0/(nPoints-1);
|
||||
for(uint32 i = 0; i < nPoints; ++i)
|
||||
sphereRegions_.resize(nSpheres, sphere(realx3(0,0,0),1));
|
||||
centerPoints_.resize(nSpheres);
|
||||
volumes_.resize(nSpheres);
|
||||
diameters_.resize(nSpheres);
|
||||
selectedPoints_.resize(nSpheres);
|
||||
real dt = 1.0/(nSpheres-1);
|
||||
for(uint32 i = 0; i < nSpheres; ++i)
|
||||
{
|
||||
centerPoints_[i] = line_.point(i*dt);
|
||||
sphereRegions_[i] = pFlow::sphere(centerPoints_[i], raddi[i]);
|
||||
@ -50,7 +53,7 @@ pFlow::lineRegionPoints::lineRegionPoints
|
||||
}
|
||||
}
|
||||
|
||||
pFlow::span<const pFlow::uint32> pFlow::lineRegionPoints::indices(uint32 elem) const
|
||||
pFlow::span<const pFlow::uint32> lineRegionPoints::indices(uint32 elem) const
|
||||
{
|
||||
if(elem >= size())
|
||||
{
|
||||
@ -65,7 +68,7 @@ pFlow::span<const pFlow::uint32> pFlow::lineRegionPoints::indices(uint32 elem) c
|
||||
selectedPoints_[elem].size());
|
||||
}
|
||||
|
||||
pFlow::span<pFlow::uint32> pFlow::lineRegionPoints::indices(uint32 elem)
|
||||
pFlow::span<pFlow::uint32> lineRegionPoints::indices(uint32 elem)
|
||||
{
|
||||
if(elem >= size())
|
||||
{
|
||||
@ -80,7 +83,7 @@ pFlow::span<pFlow::uint32> pFlow::lineRegionPoints::indices(uint32 elem)
|
||||
selectedPoints_[elem].size());
|
||||
}
|
||||
|
||||
bool pFlow::lineRegionPoints::update()
|
||||
bool lineRegionPoints::update()
|
||||
{
|
||||
const auto points = database().updatePoints();
|
||||
for(auto& elem : selectedPoints_)
|
||||
@ -101,7 +104,7 @@ bool pFlow::lineRegionPoints::update()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pFlow::lineRegionPoints::write(iOstream &os) const
|
||||
bool lineRegionPoints::write(iOstream &os) const
|
||||
{
|
||||
os << "# Spheres along a straight line \n";
|
||||
os << "# No." << tab << "centerPoint" << tab << "diameter" << endl;
|
||||
@ -118,3 +121,5 @@ bool pFlow::lineRegionPoints::write(iOstream &os) const
|
||||
os << endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End namespace pFlow::postprocessData
|
||||
|
@ -54,7 +54,7 @@ Licence:
|
||||
#include "Vectors.hpp"
|
||||
|
||||
|
||||
namespace pFlow
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
class lineRegionPoints
|
||||
|
@ -1,7 +1,10 @@
|
||||
#include "multipleSpheresRegionPoints.hpp"
|
||||
#include "fieldsDataBase.hpp"
|
||||
|
||||
pFlow::multipleSpheresRegionPoints::multipleSpheresRegionPoints
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
multipleSpheresRegionPoints::multipleSpheresRegionPoints
|
||||
(
|
||||
const dictionary &dict,
|
||||
fieldsDataBase &fieldsDataBase
|
||||
@ -46,7 +49,7 @@ pFlow::multipleSpheresRegionPoints::multipleSpheresRegionPoints
|
||||
}
|
||||
}
|
||||
|
||||
pFlow::span<const pFlow::uint32> pFlow::multipleSpheresRegionPoints::indices(uint32 elem) const
|
||||
pFlow::span<const pFlow::uint32> multipleSpheresRegionPoints::indices(uint32 elem) const
|
||||
{
|
||||
if (elem >= size())
|
||||
{
|
||||
@ -59,7 +62,7 @@ pFlow::span<const pFlow::uint32> pFlow::multipleSpheresRegionPoints::indices(uin
|
||||
return span<const uint32>(selectedPoints_[elem].data(), selectedPoints_[elem].size());
|
||||
}
|
||||
|
||||
pFlow::span<pFlow::uint32> pFlow::multipleSpheresRegionPoints::indices(uint32 elem)
|
||||
pFlow::span<pFlow::uint32> multipleSpheresRegionPoints::indices(uint32 elem)
|
||||
{
|
||||
if (elem >= size())
|
||||
{
|
||||
@ -73,7 +76,7 @@ pFlow::span<pFlow::uint32> pFlow::multipleSpheresRegionPoints::indices(uint32 el
|
||||
}
|
||||
|
||||
|
||||
bool pFlow::multipleSpheresRegionPoints::update()
|
||||
bool multipleSpheresRegionPoints::update()
|
||||
{
|
||||
const auto points = database().updatePoints();
|
||||
for (auto& elem : selectedPoints_)
|
||||
@ -94,7 +97,7 @@ bool pFlow::multipleSpheresRegionPoints::update()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pFlow::multipleSpheresRegionPoints::write(iOstream &os) const
|
||||
bool multipleSpheresRegionPoints::write(iOstream &os) const
|
||||
{
|
||||
os << "# Multiple spheres region points\n";
|
||||
os << "# No." << tab << "centerPoint" << tab << "diameter" << endl;
|
||||
@ -110,3 +113,5 @@ bool pFlow::multipleSpheresRegionPoints::write(iOstream &os) const
|
||||
os << endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End namespace pFlow::postprocessData
|
||||
|
@ -51,7 +51,7 @@ Licence:
|
||||
#include "sphere.hpp"
|
||||
#include "Vectors.hpp"
|
||||
|
||||
namespace pFlow
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
class multipleSpheresRegionPoints
|
||||
|
@ -2,7 +2,10 @@
|
||||
#include "fieldsDataBase.hpp"
|
||||
#include "Time.hpp"
|
||||
|
||||
pFlow::regionPoints::regionPoints
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
regionPoints::regionPoints
|
||||
(
|
||||
const dictionary &dict,
|
||||
fieldsDataBase &fieldsDataBase
|
||||
@ -11,18 +14,20 @@ pFlow::regionPoints::regionPoints
|
||||
fieldsDataBase_(fieldsDataBase)
|
||||
{}
|
||||
|
||||
const pFlow::Time& pFlow::regionPoints::time() const
|
||||
const Time& regionPoints::time() const
|
||||
{
|
||||
return fieldsDataBase_.time();
|
||||
}
|
||||
|
||||
const pFlow::fieldsDataBase & pFlow::regionPoints::database() const
|
||||
const fieldsDataBase & regionPoints::database() const
|
||||
{
|
||||
return fieldsDataBase_;
|
||||
}
|
||||
|
||||
pFlow::fieldsDataBase& pFlow::regionPoints::database()
|
||||
fieldsDataBase& regionPoints::database()
|
||||
{
|
||||
return fieldsDataBase_;
|
||||
}
|
||||
|
||||
} // namespace pFlow::postprocessData
|
||||
|
||||
|
@ -25,12 +25,16 @@ Licence:
|
||||
#include "dictionary.hpp"
|
||||
#include "pointStructure.hpp"
|
||||
|
||||
|
||||
namespace pFlow
|
||||
{
|
||||
class Time;
|
||||
}
|
||||
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
class fieldsDataBase;
|
||||
class Time;
|
||||
|
||||
|
||||
/**
|
||||
* @class regionPoints
|
||||
|
@ -1,7 +1,10 @@
|
||||
#include "sphereRegionPoints.hpp"
|
||||
#include "fieldsDataBase.hpp"
|
||||
|
||||
pFlow::sphereRegionPoints::sphereRegionPoints
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
sphereRegionPoints::sphereRegionPoints
|
||||
(
|
||||
const dictionary &dict,
|
||||
fieldsDataBase &fieldsDataBase
|
||||
@ -15,7 +18,7 @@ pFlow::sphereRegionPoints::sphereRegionPoints
|
||||
{
|
||||
}
|
||||
|
||||
bool pFlow::sphereRegionPoints::update()
|
||||
bool sphereRegionPoints::update()
|
||||
{
|
||||
const auto points = database().updatePoints();
|
||||
selectedPoints_.clear();
|
||||
@ -30,7 +33,7 @@ bool pFlow::sphereRegionPoints::update()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pFlow::sphereRegionPoints::write(iOstream &os) const
|
||||
bool sphereRegionPoints::write(iOstream &os) const
|
||||
{
|
||||
os <<"# Single sphere\n";
|
||||
os <<"# center point: "<<sphereRegion_.center()<<endl;
|
||||
@ -39,3 +42,5 @@ bool pFlow::sphereRegionPoints::write(iOstream &os) const
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End namespace pFlow::postprocessData
|
||||
|
@ -38,7 +38,7 @@ Licence:
|
||||
#include "sphere.hpp"
|
||||
#include "Vectors.hpp"
|
||||
|
||||
namespace pFlow
|
||||
namespace pFlow::postprocessData
|
||||
{
|
||||
|
||||
class sphereRegionPoints
|
||||
|
@ -7,123 +7,151 @@ objectType dictionary;;
|
||||
fileFormat ASCII;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
// Yes: postprocessing is active during the simulation
|
||||
// No: postprocessing is not active during the simulation
|
||||
// and it can be done after simulation
|
||||
runTimeActive yes;
|
||||
|
||||
// shapeType: defines the type of the shape that is used in the simulation
|
||||
// (for example: sphere, grain, etc).
|
||||
// shapeType is only used when postprocessing is done after simulation
|
||||
// to initialize the shape object for post processing operatoins
|
||||
shapeType sphere;
|
||||
|
||||
// default time control to be used in the postprocessing components
|
||||
defaultTimeControl
|
||||
{
|
||||
timeControl timeStep;
|
||||
timeControl timeStep; // timeStep, simulationTime are the options here
|
||||
startTime 0;
|
||||
endTime 1000;
|
||||
executionInterval 150;
|
||||
}
|
||||
|
||||
// list of postprocessing components
|
||||
components
|
||||
(
|
||||
velocityProb
|
||||
{
|
||||
processMethod particleProbe;
|
||||
processRegion centerPoints;
|
||||
selector id;
|
||||
field component(position,y);
|
||||
ids (0 10 100);
|
||||
}
|
||||
|
||||
onSingleSphere
|
||||
{
|
||||
// method of performing the sum (arithmetic, uniformDistribution, GaussianDistribution)
|
||||
processMethod arithmetic;
|
||||
processRegion sphere; // type of region on which processing is performed
|
||||
|
||||
sphereInfo
|
||||
{
|
||||
radius 0.01;
|
||||
center (-0.08 -0.08 0.015);
|
||||
}
|
||||
|
||||
timeControl default; // settings, timeStep, simulationTime
|
||||
|
||||
/// all the post process operations to be done
|
||||
operations
|
||||
(
|
||||
// computes the arithmetic mean of particle velocity
|
||||
averageVel
|
||||
{
|
||||
function average;
|
||||
field velocity;
|
||||
divideByVolume no; //default
|
||||
threshold 3; //default is 1;
|
||||
includeMask all;
|
||||
}
|
||||
|
||||
// computes the fraction of par1 in the region
|
||||
par1Fraction
|
||||
{
|
||||
function average;
|
||||
field one;
|
||||
phi one; // default
|
||||
divideByVolume no;
|
||||
includeMask lessThan;
|
||||
|
||||
// diameter of par1 is 0.003, so these settings
|
||||
// will select only particles of type par1
|
||||
lessThanInfo
|
||||
{
|
||||
field diameter;
|
||||
|
||||
value 0.0031;
|
||||
}
|
||||
}
|
||||
|
||||
numberDensity
|
||||
{
|
||||
function sum;
|
||||
field one;
|
||||
phi one; // default
|
||||
divideByVolume yes;
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
alongALine
|
||||
// probing particles for their state variables, like velocity, position, etc
|
||||
velocityProb
|
||||
{
|
||||
processMethod arithmetic;
|
||||
processRegion line;
|
||||
|
||||
// the time interval for executing the post-processing
|
||||
// other options: timeStep, default, and settings
|
||||
timeControl simulationTime;
|
||||
startTime 1.0;
|
||||
endTime 3.0;
|
||||
executionInterval 0.1;
|
||||
|
||||
|
||||
// 10 spheres with radius 0.01 along the straight line defined by p1 and p2
|
||||
lineInfo
|
||||
{
|
||||
p1 (0 0 0);
|
||||
p2 (0 0.15 0.15);
|
||||
numPoints 10;
|
||||
radius 0.01;
|
||||
}
|
||||
|
||||
operations
|
||||
(
|
||||
// computes the arithmetic mean of particle velocity
|
||||
numberDensity
|
||||
{
|
||||
function sum;
|
||||
field one;
|
||||
divideByVolume yes; //default is no
|
||||
}
|
||||
|
||||
volumeDensity
|
||||
{
|
||||
function sum;
|
||||
field cube(diameter); // d^3, although it differs by pi/6
|
||||
divideByVolume yes; //default is no
|
||||
}
|
||||
);
|
||||
processMethod particleProbe;
|
||||
processRegion centerPoints;
|
||||
selector id;
|
||||
field component(position,y);
|
||||
ids (0 10 100);
|
||||
timeControl default; // other options are settings, timeStep, simulationTime
|
||||
// settings: uses parameters from settingsDict file
|
||||
// timeStep: uses the time step of the simulation controlling the execution of postprocessing
|
||||
// simulationTime: uses the simulation time of the simulation controlling the execution of postprocessing
|
||||
// default: uses the default time control (defined in defaultTimeControl).
|
||||
// default behavior: if you do not specify it, parameters in defaultTimeControl is used.
|
||||
}
|
||||
|
||||
);
|
||||
on_single_sphere
|
||||
{
|
||||
// method of performing the sum (arithmetic, uniformDistribution, GaussianDistribution)
|
||||
processMethod arithmetic;
|
||||
|
||||
// Postprocessing is done on particles whose centers are inside this spehre
|
||||
processRegion sphere;
|
||||
|
||||
sphereInfo
|
||||
{
|
||||
radius 0.01; // radius of sphere
|
||||
center (-0.08 -0.08 0.015); // center of sphere
|
||||
}
|
||||
|
||||
timeControl default;
|
||||
|
||||
/// all the postprocess operations to be done on sphere region
|
||||
operations
|
||||
(
|
||||
// computes the arithmetic mean of particle velocity
|
||||
averageVel
|
||||
{
|
||||
function average;
|
||||
field velocity;
|
||||
fluctuation2 yes;
|
||||
divideByVolume no; // default is no
|
||||
threshold 3; // default is 1
|
||||
includeMask all; // default is all
|
||||
}
|
||||
// - function: average, sum, and other derived ones from sum and average
|
||||
// - field: names of the fields in the simulation. Some special fields
|
||||
// are: mass, density, volume, position, one, I.
|
||||
// - divideByVolume: whether the result is divided by the volume of the region
|
||||
// - threshold: exclude regions that contains particles less than threshold
|
||||
// - includeMask: all, lessThan, greaterThan, between, lessThanOrEq, greaterThanEq, betweenEq
|
||||
|
||||
|
||||
// computes the fraction of par1 in the region
|
||||
par1Fraction
|
||||
{
|
||||
function average;
|
||||
field one; // default
|
||||
phi one; // default
|
||||
divideByVolume no;
|
||||
includeMask lessThan;
|
||||
|
||||
// diameter of par1 is 0.003, so these settings
|
||||
// will select only particles of type par1
|
||||
lessThanInfo
|
||||
{
|
||||
field diameter;
|
||||
value 0.0031;
|
||||
}
|
||||
}
|
||||
|
||||
numberDensity
|
||||
{
|
||||
function sum;
|
||||
field one;
|
||||
phi one;
|
||||
divideByVolume yes;
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
along_a_line
|
||||
{
|
||||
processMethod arithmetic;
|
||||
|
||||
processRegion line;
|
||||
|
||||
// the time interval for executing the post-processing
|
||||
// other options: timeStep, default, and settings
|
||||
timeControl simulationTime;
|
||||
startTime 1.0;
|
||||
endTime 3.0;
|
||||
executionInterval 0.1;
|
||||
|
||||
|
||||
// 10 spheres with radius 0.01 along the straight line defined by p1 and p2
|
||||
lineInfo
|
||||
{
|
||||
p1 (0 0 0);
|
||||
p2 (0 0.15 0.15);
|
||||
nSpheres 10;
|
||||
radius 0.01;
|
||||
}
|
||||
|
||||
operations
|
||||
(
|
||||
// computes the arithmetic mean of particle velocity
|
||||
numberDensity
|
||||
{
|
||||
function sum;
|
||||
field one;
|
||||
divideByVolume yes; //default is no
|
||||
}
|
||||
|
||||
volumeDensity
|
||||
{
|
||||
function sum;
|
||||
field volume; //
|
||||
divideByVolume yes; //default is no
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
);
|
||||
|
@ -31,9 +31,9 @@ pFlow::selectorStridedRange::selectAllPointsInRange()
|
||||
|
||||
selectedPoints_.clear();
|
||||
|
||||
for (uint32 i = begin_; i <= end_; i += stride_)
|
||||
for (uint32 i = begin_; i < end_; i += stride_)
|
||||
{
|
||||
selectedPoints_.push_back(i - 1);
|
||||
selectedPoints_.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ pFlow::selectorStridedRange::selectorStridedRange(
|
||||
end_(dict.getValOrSet<uint32>("end", pStruct.size())),
|
||||
stride_(dict.getValOrSet<uint32>("stride", 1u))
|
||||
{
|
||||
begin_ = max(begin_, 1u);
|
||||
begin_ = max(begin_, 0u);
|
||||
end_ = min(end_, static_cast<uint32>(pStruct.size()));
|
||||
stride_ = max(stride_, 1u);
|
||||
|
||||
|
40
tutorials/README.md
Normal file
40
tutorials/README.md
Normal file
@ -0,0 +1,40 @@
|
||||
# phasicFlow Tutorials
|
||||
|
||||
This directory contains various tutorial examples to help you learn how to use phasicFlow for different particle simulation scenarios. Each tutorial provides a complete working example with configuration files and instructions.
|
||||
|
||||
|
||||
## 1. Sphere DEM Simulations (`sphereGranFlow`)
|
||||
|
||||
The most comprehensive collection of tutorials using spherical particles for DEM simulations:
|
||||
|
||||
- [Rotating Drum (Small)](./sphereGranFlow/rotatingDrumSmall/) - Simple rotating drum simulation with 30,000 spherical particles (4 mm diameter)
|
||||
- [Rotating Drum (Medium)](./sphereGranFlow/rotatingDrumMedium/) - Medium-sized rotating drum simulation
|
||||
- [Rotating Drum with Baffles](./sphereGranFlow/RotatingDrumWithBaffles/) - Rotating drum with internal baffles and binary particle mixture
|
||||
- [Rotating Drum with Periodic Boundaries](./sphereGranFlow/drum-PeriodicBoundary/) - Simulates an "infinite length" drum using periodic boundaries
|
||||
- [V-blender](./sphereGranFlow/V-blender/) - V-shaped blender simulation for particle mixing
|
||||
- [Tote Blender](./sphereGranFlow/toteBlender/) - Double pedestal tote blender simulation with 24,000 particles
|
||||
- [Binary System of Particles](./sphereGranFlow/binarySystemOfParticles/) - Demonstrates particle segregation in a rotating drum with two particle sizes
|
||||
- [Screw Conveyor](./sphereGranFlow/screwConveyor/) - Simulates particle transport using a screw conveyor
|
||||
- [Conveyor Belt](./sphereGranFlow/conveyorBelt/) - Simulates particles on a moving conveyor belt
|
||||
- [Rotary Air Lock Valve](./sphereGranFlow/RotaryAirLockValve/) - Simulates a rotary air lock valve with particle insertion
|
||||
- [Layered Silo Filling](./sphereGranFlow/layeredSiloFilling/) - Demonstrates filling a silo with layers of particles
|
||||
- [Homogenization Silo (Periodic Boundaries)](./sphereGranFlow/homogenizationSilo-PeriodicBoundary/) - Simulates homogenization in a silo with periodic boundaries
|
||||
|
||||
## 2. Course-grained (Grain) DEM Simulations (`grainGranFlow`)
|
||||
|
||||
Tutorials for simulations with non-spherical (grain-shaped) particles:
|
||||
|
||||
- [Rotating Drum](./grainGranFlow/rotatingDrum/) - Demonstrates non-spherical grain particles in a rotating drum
|
||||
|
||||
## 3. Geometry Iteration (`iterateGeometry`)
|
||||
|
||||
Tutorials focused on geometry handling and visualization:
|
||||
|
||||
- [Inclined Screw Conveyor](./iterateGeometry/inclinedScrewConveyor/) - Visualizes the geometry of an inclined screw conveyor without particles
|
||||
|
||||
## 4. Post-processing (`postprocessPhasicFlow`)
|
||||
|
||||
Tutorials focused on post-processing and analysis:
|
||||
|
||||
- [Segregation Analysis](./postprocessPhasicFlow/segregation/) - Demonstrates how to analyze particle segregation in simulation results
|
||||
|
@ -44,8 +44,8 @@ positionParticles
|
||||
|
||||
orderedInfo
|
||||
{
|
||||
// minimum space between centers of particles
|
||||
diameter 0.001;
|
||||
// minimum distance between particles centers
|
||||
distance 0.001;
|
||||
|
||||
// number of particles in the simulation
|
||||
numPoints 50000;
|
||||
|
@ -24,7 +24,7 @@ positionParticles
|
||||
|
||||
positionOrderedInfo
|
||||
{
|
||||
diameter 0.005; // minimum space between centers of particles
|
||||
distance 0.005; // minimum distance between particles centers
|
||||
numPoints 30000; // number of particles in the simulation
|
||||
axisOrder (z x y); // axis order for filling the space with particles
|
||||
}
|
||||
@ -41,7 +41,7 @@ setFields
|
||||
{
|
||||
velocity realx3 (0 0 0); // linear velocity (m/s)
|
||||
acceleration realx3 (0 0 0); // linear acceleration (m/s2)
|
||||
r Velocity realx3 (0 0 0); // rotational velocity (rad/s)
|
||||
rVelocity realx3 (0 0 0); // rotational velocity (rad/s)
|
||||
shapeName word smallSphere; // name of the particle shape
|
||||
}
|
||||
|
||||
@ -53,7 +53,8 @@ setFields
|
||||
selectRandomInfo
|
||||
{
|
||||
begin 0; // begin index of points
|
||||
end 29999; // end index of points
|
||||
end 29999; // end index of points
|
||||
number 10000; // number of points to be selected
|
||||
}
|
||||
fieldValue // fields that the selector is applied to
|
||||
{
|
||||
|
@ -6,8 +6,8 @@ objectName particleInsertion;
|
||||
objectType dicrionary;
|
||||
fileFormat ASCII;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
names (sphere); // names of shapes
|
||||
names (sphere); // names of shapes
|
||||
|
||||
diameters (0.005); // diameter of shapes
|
||||
diameters (0.005); // diameter of shapes
|
||||
|
||||
materials (sphereMat); // material names for shapes
|
||||
|
7
tutorials/sphereGranFlow/RotaryAirLockValve/cleanThisCase
Executable file
7
tutorials/sphereGranFlow/RotaryAirLockValve/cleanThisCase
Executable 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
|
||||
|
||||
#------------------------------------------------------------------------------
|
21
tutorials/sphereGranFlow/RotaryAirLockValve/runThisCase
Executable file
21
tutorials/sphereGranFlow/RotaryAirLockValve/runThisCase
Executable 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
|
||||
|
||||
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
@ -2,46 +2,48 @@
|
||||
| phasicFlow File |
|
||||
| copyright: www.cemf.ir |
|
||||
\* ------------------------------------------------------------------------- */
|
||||
objectName domainDict;
|
||||
objectType dictionary;
|
||||
objectName domainDict;
|
||||
objectType dictionary;
|
||||
fileFormat ASCII;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
globalBox // Simulation domain: every particles that goes outside this domain will be deleted
|
||||
|
||||
// Simulation domain: every particles that goes outside this domain will be deleted
|
||||
globalBox
|
||||
{
|
||||
min (0.397538 0.178212 0.00);
|
||||
|
||||
max (0.725537 0.600214 0.06);
|
||||
min (0.397538 0.178212 0.00);
|
||||
|
||||
max (0.725537 0.600214 0.06);
|
||||
}
|
||||
|
||||
boundaries
|
||||
{
|
||||
left
|
||||
{
|
||||
type exit; // other options: periodict, reflective
|
||||
}
|
||||
left
|
||||
{
|
||||
type exit; // other options: periodict, reflective
|
||||
}
|
||||
|
||||
right
|
||||
{
|
||||
type exit; // other options: periodict, reflective
|
||||
}
|
||||
right
|
||||
{
|
||||
type exit; // other options: periodict, reflective
|
||||
}
|
||||
|
||||
bottom
|
||||
{
|
||||
type exit; // other options: periodict, reflective
|
||||
}
|
||||
bottom
|
||||
{
|
||||
type exit; // other options: periodict, reflective
|
||||
}
|
||||
|
||||
top
|
||||
{
|
||||
type exit; // other options: periodict, reflective
|
||||
}
|
||||
top
|
||||
{
|
||||
type exit; // other options: periodict, reflective
|
||||
}
|
||||
|
||||
rear
|
||||
{
|
||||
type exit; // other options: periodict, reflective
|
||||
}
|
||||
rear
|
||||
{
|
||||
type exit; // other options: periodict, reflective
|
||||
}
|
||||
|
||||
front
|
||||
{
|
||||
type exit; // other options: periodict, reflective
|
||||
}
|
||||
front
|
||||
{
|
||||
type exit; // other options: periodict, reflective
|
||||
}
|
||||
}
|
||||
|
@ -2,50 +2,50 @@
|
||||
| phasicFlow File |
|
||||
| copyright: www.cemf.ir |
|
||||
\* ------------------------------------------------------------------------- */
|
||||
objectName geometryDict;
|
||||
objectType dictionary;
|
||||
objectName geometryDict;
|
||||
objectType dictionary;
|
||||
fileFormat ASCII;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
motionModel rotatingAxis; // motion model: rotating object around an axis
|
||||
|
||||
rotatingAxisInfo // information for rotatingAxisMotion motion model
|
||||
{
|
||||
rotAxis
|
||||
{
|
||||
p1 (0.561547 0.372714 0.000); // first point for the axis of rotation
|
||||
|
||||
p2 (0.561547 0.372714 0.010); // second point for the axis of rotation
|
||||
rotAxis
|
||||
{
|
||||
p1 (0.561547 0.372714 0.000); // first point for the axis of rotation
|
||||
|
||||
p2 (0.561547 0.372714 0.010); // second point for the axis of rotation
|
||||
|
||||
omega 2.1; // rotation speed (rad/s)
|
||||
omega 2.1; // rotation speed (rad/s)
|
||||
|
||||
startTime 1.25; // Start time of Geometry Rotating (s)
|
||||
|
||||
endTime 7; // End time of Geometry Rotating (s)
|
||||
}
|
||||
startTime 1.25; // Start time of Geometry Rotating (s)
|
||||
|
||||
endTime 7; // End time of Geometry Rotating (s)
|
||||
}
|
||||
}
|
||||
|
||||
surfaces
|
||||
{
|
||||
gear
|
||||
{
|
||||
type stlWall; // type of the wall
|
||||
gear
|
||||
{
|
||||
type stlWall; // type of the wall
|
||||
|
||||
file gear.stl; // file name in stl folder
|
||||
file gear.stl; // file name in stl folder
|
||||
|
||||
material wallMat; // material name of this wall
|
||||
material wallMat; // material name of this wall
|
||||
|
||||
motion rotAxis; // motion component name
|
||||
}
|
||||
motion rotAxis; // motion component name
|
||||
}
|
||||
|
||||
surfaces
|
||||
{
|
||||
type stlWall; // type of the wall
|
||||
{
|
||||
type stlWall; // type of the wall
|
||||
|
||||
file surfaces.stl; // file name in stl folder
|
||||
file surfaces.stl; // file name in stl folder
|
||||
|
||||
material wallMat; // material name of this wall
|
||||
material wallMat; // material name of this wall
|
||||
|
||||
motion none; // motion component name
|
||||
}
|
||||
motion none; // motion component name
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,8 @@
|
||||
| phasicFlow File |
|
||||
| copyright: www.cemf.ir |
|
||||
\* ------------------------------------------------------------------------- */
|
||||
objectName particlesDict;
|
||||
objectType dictionary;
|
||||
objectName particlesDict;
|
||||
objectType dictionary;
|
||||
fileFormat ASCII;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
|
@ -2,8 +2,8 @@
|
||||
| phasicFlow File |
|
||||
| copyright: www.cemf.ir |
|
||||
\* ------------------------------------------------------------------------- */
|
||||
objectName geometryDict;
|
||||
objectType dictionary;
|
||||
objectName geometryDict;
|
||||
objectType dictionary;
|
||||
fileFormat ASCII;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -25,10 +25,12 @@ g (0 -9.8 0); // gravity vector (m/s2)
|
||||
includeObjects (diameter mass);
|
||||
|
||||
// exclude unnecessary data from saving on disk
|
||||
excludeObjects (rVelocity.dy1 pStructPosition.dy1 pStructVelocity.dy1);
|
||||
excludeObjects ();
|
||||
|
||||
integrationMethod AdamsBashforth2;
|
||||
|
||||
integrationHistory off;
|
||||
|
||||
writeFormat ascii; // data writting format (ascii or binary)
|
||||
|
||||
timersReport Yes; // report timers: Yes or No
|
||||
|
@ -1,4 +1,5 @@
|
||||
# Problem Definition (v-1.0)
|
||||
|
||||
The problem is to simulate a rotating drum with a diameter of 0.24 m, a length of 0.1 m and 6 baffles rotating at 15 rpm. This drum is filled with 20000 particles, the integration time step is 0.00001 s. There are 2 types of particles in this drum, each of which is inserted during the simulation to fill the drum.
|
||||
* **12500** Particles with **4 mm** diameter, at the rate of 12500 particles/s for 1 sec.
|
||||
* **7500** Particles with **5mm** diameter, at the rate of 7500 particles/s for 1 sec.
|
||||
@ -15,10 +16,13 @@ The problem is to simulate a rotating drum with a diameter of 0.24 m, a length o
|
||||
</html>
|
||||
|
||||
# Setting up the Case
|
||||
As it has been explained in the previous cases, the simulation case setup is based on text-based scripts. Here, the simulation case setup are sorted in three folders: `caseSetup`, `setting` and `stl`.
|
||||
|
||||
As it has been explained in the previous cases, the simulation case setup is based on text-based scripts. Here, the simulation case setup are sorted in three folders: `caseSetup`, `setting` and `stl`.
|
||||
|
||||
## Defining small and large particles
|
||||
Then in the `caseSetup/shapes` the diameter and the material name of the particles are defined. Two sizes are defined: 4 and 5 mm.
|
||||
|
||||
Then in the `caseSetup/shapes` the diameter and the material name of the particles are defined. Two sizes are defined: 4 and 5 mm.
|
||||
|
||||
```C++
|
||||
// names of shapes
|
||||
names (smallSphere largeSphere);
|
||||
@ -28,8 +32,8 @@ diameters (0.004 0.005);
|
||||
materials (lightMat heavyMat);
|
||||
```
|
||||
|
||||
|
||||
## Particle Insertion
|
||||
|
||||
In this case we have two regions for inserting the particles. In both regions we define the insertion rate, the start and end time of the insertion, information about the volume of space through which the particles are inserted. The insertion phase in the simulation is performed between times 0 and 1 second.
|
||||
For example, for the insertion region for inserting light particles is shown below.
|
||||
|
||||
@ -39,31 +43,44 @@ in <b>caseSetup/particleInsertion</b> file
|
||||
|
||||
|
||||
```C++
|
||||
// Right Layer Region
|
||||
layerrightregion
|
||||
// Right Region
|
||||
right_region
|
||||
{
|
||||
// type of insertion region
|
||||
timeControl simulationTime;
|
||||
regionType cylinder;
|
||||
// insertion rate (particles/s)
|
||||
// type of insertion region
|
||||
regionType cylinder;
|
||||
// insertion rate (particles/s)
|
||||
rate 12500;
|
||||
// Start time of LightParticles insertion (s)
|
||||
|
||||
timeControl simulationTime;
|
||||
// Start time of insertion (s)
|
||||
startTime 0;
|
||||
// End time of LightParticles insertion (s)
|
||||
// End time of insertion (s)
|
||||
endTime 1;
|
||||
// Time Interval of LightParticles insertion (s)
|
||||
// Time Interval of insertion (s)
|
||||
insertionInterval 0.025;
|
||||
|
||||
cylinderInfo
|
||||
{
|
||||
// Coordinates of cylinderRegion (m,m,m)
|
||||
p2 (-0.15 0.25 0.05);
|
||||
p1 (-0.15 0.24 0.05);
|
||||
// radius of cylinder (m)
|
||||
radius 0.035;
|
||||
// Coordinates of cylinderRegion (m,m,m)
|
||||
p2 (-0.15 0.25 0.05);
|
||||
p1 (-0.15 0.24 0.05);
|
||||
// radius of cylinder (m)
|
||||
radius 0.035;
|
||||
}
|
||||
|
||||
setFields
|
||||
{
|
||||
velocity realx3 (0.0 -0.6 0.0); // initial velocity of inserted particles
|
||||
}
|
||||
|
||||
mixture
|
||||
{
|
||||
smallSphere 1; // mixture composition of inserted particles
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Interaction between particles and walls
|
||||
The `caseSetup/interaction` file defines the material names and properties as well as the interaction parameters: the interaction between the particles and the shell of the rotating drum. Since we define 3 materials for simulation, the interaction matrix is 3x3, while we only need to enter upper triangle elements (interactions are symmetric).
|
||||
|
||||
@ -73,36 +90,37 @@ materials (lightMat heavyMat wallMat);
|
||||
// density of materials [kg/m3]
|
||||
densities (1000 1500 2500);
|
||||
|
||||
/*
|
||||
/*
|
||||
Property (lightMat-lightMat lightMat-heavyMat lightMat-wallMat
|
||||
heavyMat-heavyMat heavyMat-wallMat
|
||||
wallMat-wallMat );
|
||||
*/
|
||||
// Young modulus [Pa]
|
||||
*/
|
||||
// Young modulus [Pa]
|
||||
Yeff (1.0e6 1.0e6 1.0e6
|
||||
1.0e6 1.0e6
|
||||
1.0e6);
|
||||
// Shear modulus [Pa]
|
||||
// Shear modulus [Pa]
|
||||
Geff (0.8e6 0.8e6 0.8e6
|
||||
0.8e6 0.8e6
|
||||
0.8e6);
|
||||
// Poisson's ratio [-]
|
||||
// Poisson's ratio [-]
|
||||
nu (0.25 0.25 0.25
|
||||
0.25 0.25
|
||||
0.25);
|
||||
// coefficient of normal restitution
|
||||
// coefficient of normal restitution
|
||||
en (0.97 0.97 0.85
|
||||
0.97 0.85
|
||||
1.00);
|
||||
// dynamic friction
|
||||
// dynamic friction
|
||||
mu (0.65 0.65 0.35
|
||||
0.65 0.35
|
||||
0.35);
|
||||
// rolling friction
|
||||
// rolling friction
|
||||
mur (0.1 0.1 0.1
|
||||
0.1 0.1
|
||||
0.1);
|
||||
```
|
||||
|
||||
## Settings
|
||||
### Geometry
|
||||
In the `settings/geometryDict` file, the geometry and axis of rotation is defined for the drum. The geometry is composed of a body, front and rear ends.
|
||||
@ -163,28 +181,32 @@ surfaces
|
||||
In this part of `geometryDict` the information of rotating axis and speed of rotation are defined. The start of rotation is at 2 s. The first 2 seconds of simulation is for allowing particles to settle donw in the drum.
|
||||
|
||||
```C++
|
||||
motionModel rotatingAxis;
|
||||
|
||||
motionModel rotatingAxis;
|
||||
|
||||
rotatingAxisInfo
|
||||
{
|
||||
rotAxis
|
||||
{
|
||||
// first point for the axis of rotation
|
||||
p1 (-0.1974 0.2269 0);
|
||||
// second point for the axis of rotation
|
||||
p2 (-0.1974 0.2269 0.1);
|
||||
// rotation speed (rad/s) => 15 rpm
|
||||
omega 2.38733;
|
||||
// Start time of Geometry Rotating
|
||||
startTime 2;
|
||||
// End time of Geometry Rotating
|
||||
endTime 9.5;
|
||||
p1 (-0.1974 0.2269 0);
|
||||
// second point for the axis of rotation
|
||||
p2 (-0.1974 0.2269 0.1);
|
||||
// rotation speed (rad/s) => 15 rpm
|
||||
omega 2.38733;
|
||||
// Start time of Geometry Rotating
|
||||
startTime 2;
|
||||
// End time of Geometry Rotating
|
||||
endTime 9.5;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Performing Simulation
|
||||
|
||||
To run simulations, type the following commands in the terminal one at a time.
|
||||
|
||||
Enter `particlesPhasicFlow` command to create the initial fields for particles.
|
||||
Enter `geometryPhasicFlow` command to create the Geometry.
|
||||
At last, enter `sphereGranFlow` command to start the simulation.
|
||||
After finishing the simulation, you can use `pFlowtoVTK` to convert the results into vtk format stored in ./VTK folder.
|
||||
After finishing the simulation, you can use `pFlowtoVTK` to convert the results into vtk format stored in ./VTK folder.
|
@ -6,6 +6,7 @@ objectName interaction;
|
||||
objectType dicrionary;
|
||||
fileFormat ASCII;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
materials (lightMat heavyMat wallMat); // a list of materials names
|
||||
|
||||
densities (1000 1500 2500); // density of materials [kg/m3]
|
||||
@ -14,7 +15,7 @@ contactListType sortedContactList;
|
||||
|
||||
contactSearch
|
||||
{
|
||||
method NBS; // method for broad search
|
||||
method NBS;
|
||||
|
||||
updateInterval 10;
|
||||
|
||||
|
@ -6,78 +6,78 @@ objectName particleInsertion;
|
||||
objectType dicrionary;
|
||||
fileFormat ASCII;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
active Yes; // is insertion active -> Yes or No
|
||||
|
||||
active Yes; // is insertion active -> Yes or No
|
||||
|
||||
/*
|
||||
Two layers of particles are packed one-by-one using 1 insertion steps
|
||||
*/
|
||||
|
||||
|
||||
layerrightregion // Right Layer Region
|
||||
right_region
|
||||
{
|
||||
timeControl simulationTime;
|
||||
|
||||
regionType cylinder; // type of insertion region
|
||||
regionType cylinder; // type of insertion region
|
||||
|
||||
rate 12500; // Right Region Particles Insertion Rate (particles/s)
|
||||
rate 12500; // Right Region Particles Insertion Rate (particles/s)
|
||||
|
||||
startTime 0; // Start time of LightParticles insertion (s)
|
||||
startTime 0; // Start time of insertion (s)
|
||||
|
||||
endTime 1; // End time of LightParticles insertion (s)
|
||||
endTime 1; // End time of insertion (s)
|
||||
|
||||
insertionInterval 0.025; // Time Interval of LightParticles insertion (s)
|
||||
insertionInterval 0.025; // Time Interval of particles insertion (s)
|
||||
|
||||
cylinderInfo
|
||||
{
|
||||
p2 (-0.15 0.25 0.05); // Top of cylinderRegion (m,m,m)
|
||||
p2 (-0.15 0.25 0.05); // Top of cylinderRegion (m,m,m)
|
||||
|
||||
p1 (-0.15 0.24 0.05); // Bottom of cylinderRegion (m,m,m)
|
||||
p1 (-0.15 0.24 0.05); // Bottom of cylinderRegion (m,m,m)
|
||||
|
||||
radius 0.035; // radius of cylinder (m)
|
||||
radius 0.035; // radius of cylinder (m)
|
||||
}
|
||||
|
||||
setFields
|
||||
{
|
||||
velocity realx3 (0.0 -0.6 0.0); // initial velocity of inserted particles
|
||||
velocity realx3 (0.0 -0.6 0.0); // initial velocity of inserted particles
|
||||
}
|
||||
|
||||
mixture
|
||||
{
|
||||
smallSphere 1; // mixture composition of inserted particles
|
||||
smallSphere 1; // mixture composition of inserted particles
|
||||
}
|
||||
}
|
||||
|
||||
layerleftregion // Left Layer Region
|
||||
left_region
|
||||
{
|
||||
timeControl simulationTime;
|
||||
|
||||
regionType cylinder; // type of insertion region
|
||||
regionType cylinder; // type of insertion region
|
||||
|
||||
rate 7500; // Left Region Particles Insertion Rate (particles/s)
|
||||
rate 7500; // Left Region Particles Insertion Rate (particles/s)
|
||||
|
||||
startTime 0; // Start time of LightParticles insertion (s)
|
||||
startTime 0; // Start time of insertion (s)
|
||||
|
||||
endTime 1; // End time of LightParticles insertion (s)
|
||||
endTime 1; // End time of insertion (s)
|
||||
|
||||
insertionInterval 0.025; // Time Interval of LightParticles insertion (s)
|
||||
insertionInterval 0.025; // Time Interval of insertion (s)
|
||||
|
||||
cylinderInfo
|
||||
{
|
||||
p2 (-0.23 0.25 0.05); // Top of cylinderRegion (m,m,m)
|
||||
p2 (-0.23 0.25 0.05); // Top of cylinderRegion (m,m,m)
|
||||
|
||||
p1 (-0.23 0.24 0.05); // Bottom of cylinderRegion (m,m,m)
|
||||
p1 (-0.23 0.24 0.05); // Bottom of cylinderRegion (m,m,m)
|
||||
|
||||
radius 0.035; // radius of cylinder (m)
|
||||
radius 0.035; // radius of cylinder (m)
|
||||
}
|
||||
|
||||
setFields
|
||||
{
|
||||
velocity realx3 (0.0 -0.6 0.0); // initial velocity of inserted particles
|
||||
velocity realx3 (0.0 -0.6 0.0); // initial velocity of inserted particles
|
||||
}
|
||||
|
||||
mixture
|
||||
{
|
||||
largeSphere 1; // only heavySphere
|
||||
largeSphere 1; // only heavySphere
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,12 +2,13 @@
|
||||
| phasicFlow File |
|
||||
| copyright: www.cemf.ir |
|
||||
\* ------------------------------------------------------------------------- */
|
||||
objectName sphereDict;
|
||||
objectType sphereShape;
|
||||
objectName sphereDict;
|
||||
objectType sphereShape;
|
||||
fileFormat ASCII;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
names (smallSphere largeSphere); // names of shapes
|
||||
|
||||
diameters (0.004 0.005); // diameter of shapes (m)
|
||||
|
||||
materials (lightMat heavyMat); // material names for shapes
|
||||
|
||||
names (smallSphere largeSphere); // names of shapes
|
||||
|
||||
diameters (0.004 0.005); // diameter of shapes (m)
|
||||
|
||||
materials (lightMat heavyMat); // material names for shapes
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user