diff --git a/DEMSystems/DEMSystem/DEMSystem.cpp b/DEMSystems/DEMSystem/DEMSystem.cpp index 7afd8b47..9df8447e 100644 --- a/DEMSystems/DEMSystem/DEMSystem.cpp +++ b/DEMSystems/DEMSystem/DEMSystem.cpp @@ -66,12 +66,13 @@ pFlow::uniquePtr word demSystemName, const std::vector& domains, int argc, - char* argv[] + char* argv[], + bool requireRVel ) { if( wordvCtorSelector_.search(demSystemName) ) { - return wordvCtorSelector_[demSystemName] (demSystemName, domains, argc, argv); + return wordvCtorSelector_[demSystemName] (demSystemName, domains, argc, argv, requireRVel); } else { diff --git a/DEMSystems/DEMSystem/DEMSystem.hpp b/DEMSystems/DEMSystem/DEMSystem.hpp index 677aa847..7b8ed528 100644 --- a/DEMSystems/DEMSystem/DEMSystem.hpp +++ b/DEMSystems/DEMSystem/DEMSystem.hpp @@ -71,13 +71,15 @@ public: word demSystemName, const std::vector& domains, int argc, - char* argv[] + char* argv[], + bool requireRVel ), ( demSystemName, domains, argc, - argv + argv, + requireRVel )); realx3 g()const @@ -119,7 +121,10 @@ public: span parIndexInDomain(int32 domIndx)const = 0; virtual - span diameter() = 0; + span diameter() = 0; + + virtual + span particleId() = 0; virtual span courseGrainFactor() = 0; @@ -176,7 +181,8 @@ public: word demSystemName, const std::vector& domains, int argc, - char* argv[]); + char* argv[], + bool requireRVel=false); }; diff --git a/DEMSystems/grainDEMSystem/grainDEMSystem.cpp b/DEMSystems/grainDEMSystem/grainDEMSystem.cpp index 1f04ece8..d19aed68 100644 --- a/DEMSystems/grainDEMSystem/grainDEMSystem.cpp +++ b/DEMSystems/grainDEMSystem/grainDEMSystem.cpp @@ -163,6 +163,12 @@ pFlow::grainDEMSystem::parIndexInDomain(int32 di)const return particleDistribution_->particlesInDomain(di); } +pFlow::span pFlow::grainDEMSystem::particleId() +{ + return span(particleIdHost_.data(), particleIdHost_.size()); +} + + pFlow::span pFlow::grainDEMSystem::diameter() { return span(diameterHost_.data(), diameterHost_.size()); @@ -233,6 +239,7 @@ bool pFlow::grainDEMSystem::beforeIteration() velocityHost_ = std::as_const(particles_()).velocity().hostView(); positionHost_ = std::as_const(particles_()).pointPosition().hostView(); diameterHost_ = particles_->diameter().hostView(); + particleIdHost_ = particles_->particleId().hostView(); if(requireRVel_) rVelocityHost_ = std::as_const(particles_()).rVelocity().hostView(); diff --git a/DEMSystems/grainDEMSystem/grainDEMSystem.hpp b/DEMSystems/grainDEMSystem/grainDEMSystem.hpp index af849941..a80994f0 100644 --- a/DEMSystems/grainDEMSystem/grainDEMSystem.hpp +++ b/DEMSystems/grainDEMSystem/grainDEMSystem.hpp @@ -63,6 +63,8 @@ protected: ViewType1D diameterHost_; + ViewType1D particleIdHost_; + bool requireRVel_ = false; ViewType1D rVelocityHost_; @@ -122,6 +124,8 @@ public: span parIndexInDomain(int32 di)const override; + span particleId() override; + span diameter() override; span courseGrainFactor() override; diff --git a/DEMSystems/sphereDEMSystem/sphereDEMSystem.cpp b/DEMSystems/sphereDEMSystem/sphereDEMSystem.cpp index 9a87d8db..135b68b2 100644 --- a/DEMSystems/sphereDEMSystem/sphereDEMSystem.cpp +++ b/DEMSystems/sphereDEMSystem/sphereDEMSystem.cpp @@ -165,6 +165,11 @@ pFlow::sphereDEMSystem::parIndexInDomain(int32 di)const return particleDistribution_->particlesInDomain(di); } +pFlow::span pFlow::sphereDEMSystem::particleId() +{ + return span(); +} + pFlow::span pFlow::sphereDEMSystem::diameter() { return span(diameterHost_.data(), diameterHost_.size()); @@ -235,6 +240,7 @@ bool pFlow::sphereDEMSystem::beforeIteration() velocityHost_ = std::as_const(particles_()).velocity().hostView(); positionHost_ = std::as_const(particles_()).pointPosition().hostView(); diameterHost_ = particles_->diameter().hostView(); + particleIdHost_ = particles_->particleId().hostView(); if(requireRVel_) rVelocityHost_ = std::as_const(particles_()).rVelocity().hostView(); diff --git a/DEMSystems/sphereDEMSystem/sphereDEMSystem.hpp b/DEMSystems/sphereDEMSystem/sphereDEMSystem.hpp index 1b6ab072..41fb90d9 100644 --- a/DEMSystems/sphereDEMSystem/sphereDEMSystem.hpp +++ b/DEMSystems/sphereDEMSystem/sphereDEMSystem.hpp @@ -63,6 +63,8 @@ protected: ViewType1D diameterHost_; + ViewType1D particleIdHost_; + bool requireRVel_ = false; ViewType1D rVelocityHost_; @@ -122,6 +124,8 @@ public: span parIndexInDomain(int32 di)const override; + span particleId() override; + span diameter() override; span courseGrainFactor() override; diff --git a/src/Particles/particles/particles.hpp b/src/Particles/particles/particles.hpp index b098f167..7779d7b6 100644 --- a/src/Particles/particles/particles.hpp +++ b/src/Particles/particles/particles.hpp @@ -185,6 +185,18 @@ public: return contactTorque_; } + inline + uint32PointField_D& particleId() + { + return idHandler_(); + } + + inline + const uint32PointField_D& particleId() const + { + return idHandler_(); + } + inline uint32 maxId()const { diff --git a/src/PostprocessData/readme.md b/src/PostprocessData/readme.md index ee1431ca..3f613766 100644 --- a/src/PostprocessData/readme.md +++ b/src/PostprocessData/readme.md @@ -5,6 +5,14 @@ The `PostprocessData` module in phasicFlow provides powerful tools for analyzing - 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. +
+ +**IMPORTANT NOTE** + +in-simulation postprocessing is not implemented for MPI execution. For post-simulation postprocessing, you can use the `postprocessPhasicFlow` utility without MPI, even though the actual simulation has been done using MPI. + +
+ ## 1. Overview Postprocessing in phasicFlow allows you to: @@ -118,12 +126,17 @@ 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 | +| `sphere` | A spherical region | `radius`, `center` defined in `sphereInfo` dict| bulk | +| `multipleSpheres` | Multiple spherical regions | `centers`, `radii` defined in `multiplSpheresInfo` dict | bulk | +| `line` | Spheres along a line with specified radius | `p1`, `p2`, `nSpheres`, `radius` defined in `lineInfo` dict| bulk | +| `box`| A cuboid region | `min`, `max` defined in `boxInfo` dict | bulk | +| `centerPoints`* | Specific particles selected by ID | `ids` | individual | +| `centerPoints`* | Specific particles selected by center points located in a box | `boxInfo` | individual | +| `centerPoints`* | Specific particles selected by center points located in a sphere | `sphereInfo` | individual | +| `centerPoints`* | Specific particles selected by center points located in a cylinder | `cylinderInfo` | individual | +| \* Particles selection is done when simulation reaches the time that is specified by `startTime` of the post-process component and this selection remains intact up to the end of simulation. This is very good for particle tracking purposes or when you want to analyze specific particles behavior over time. | -## 6. Processing Operations +## 6. Processing Operations for Bulk Properties Within each processing region of type `bulk`, you can define multiple operations to be performed: @@ -565,5 +578,4 @@ components } ); - ``` diff --git a/src/PostprocessData/region/regionPoints/boxRegionPoints/boxRegionPoints.cpp b/src/PostprocessData/region/regionPoints/boxRegionPoints/boxRegionPoints.cpp index 577f9705..64b7e4b6 100644 --- a/src/PostprocessData/region/regionPoints/boxRegionPoints/boxRegionPoints.cpp +++ b/src/PostprocessData/region/regionPoints/boxRegionPoints/boxRegionPoints.cpp @@ -19,7 +19,7 @@ boxRegionPoints::boxRegionPoints (boxRegion_.maxPoint().y() - boxRegion_.minPoint().y()) * (boxRegion_.maxPoint().z() - boxRegion_.minPoint().z()) ), - diameter_(pow(3 * volume_ / 4.0 / Pi, 1.0 / 3.0)), + diameter_(2 * pow(3 * volume_ / 4.0 / Pi, 1.0 / 3.0)), selectedPoints_("selectedPoints") { } diff --git a/src/PostprocessData/region/regionPoints/centerPointsRegionPoints/centerPointsRegionPoints.cpp b/src/PostprocessData/region/regionPoints/centerPointsRegionPoints/centerPointsRegionPoints.cpp index 73aaf7f2..729c5134 100644 --- a/src/PostprocessData/region/regionPoints/centerPointsRegionPoints/centerPointsRegionPoints.cpp +++ b/src/PostprocessData/region/regionPoints/centerPointsRegionPoints/centerPointsRegionPoints.cpp @@ -8,6 +8,8 @@ namespace pFlow::postprocessData bool centerPointsRegionPoints::selectIds() { + // check if it is already found the ids of particles + // if not, then find the ids of particles if(!firstTimeUpdate_) return true; firstTimeUpdate_ = false; @@ -26,16 +28,20 @@ bool centerPointsRegionPoints::selectIds() } } else - // TODO: this should be corrected to select ids of particles - // that are selected based on the selector (this is visa versa) { auto selectorPtr = pStructSelector::create( selector, database().pStruct(), probDict_.subDict(selector+"Info")); auto selectedPoints = selectorPtr->selectedPoints(); - ids_.resize(selectedPoints.size()); - ids_.assign(selectedPoints.begin(), selectedPoints.end()); + const auto& idField = database().updateFieldUint32(idName_); + + ids_.clear(); + ids_.reserve(selectedPoints.size()); + for( auto& pntIndex: selectedPoints) + { + ids_.push_back(idField[pntIndex]); + } } volume_.resize(ids_.size(),1.0); @@ -62,11 +68,12 @@ bool centerPointsRegionPoints::update() const auto& idField = database().updateFieldUint32(idName_); selectedPoints_.fill(-1); - for(uint32 i = 0; i < idField.size(); ++i) + for( uint32 j=0; j< ids_.size(); ++j) { - for( uint32 j=0; j< ids_.size(); ++j) + auto id = ids_[j]; + for( uint32 i=0; i< idField.size(); i++) { - if(idField[i] == ids_[j]) + if(idField[i] == id) { selectedPoints_[j] = i; break;