From 093160ba32eb9b0de5cf848d5e86629d4c7921ad Mon Sep 17 00:00:00 2001 From: Hamidreza Date: Tue, 15 Apr 2025 21:27:49 +0330 Subject: [PATCH] Postprocess framework - Executed has been completed and testd. - regions multipleSpheres are compelete - Docs for regions is comelete. --- src/PostprocessData/CMakeLists.txt | 2 + .../fieldsDataBase/fieldsDataBase.cpp | 2 +- .../fieldsDataBaseTemplates.cpp | 2 +- .../PostprocessOperationSum.cpp | 2 + .../PostprocessOperationSum.hpp | 117 +++++++++- .../PostprocessOperation/fieldFunctions.hpp | 95 ++++++++- .../operation/includeMask/includeMask.cpp | 69 +++++- .../operation/includeMask/includeMask.hpp | 20 ++ .../postprocessOperation.cpp | 30 ++- .../postprocessOperation.hpp | 106 ++++++++- .../PostprocessComponent.cpp | 4 + .../particleProbePostprocessComponent.cpp | 7 +- .../postprocessData/postprocessData.cpp | 12 +- .../postprocessData/postprocessData.hpp | 2 +- .../region/regionFields/regionField.hpp | 16 ++ .../centerPointsRegionPoints.hpp | 54 ++++- .../lineRegionPoints/lineRegionPoints.cpp | 28 +-- .../lineRegionPoints/lineRegionPoints.hpp | 52 ++++- .../regionPoints/regionPoints.hpp | 39 ++-- .../sphereRegionPoints/sphereRegionPoints.hpp | 73 ++++++- .../sampleDictionary/postprocessDataDict | 201 ++++++++++-------- 21 files changed, 762 insertions(+), 171 deletions(-) diff --git a/src/PostprocessData/CMakeLists.txt b/src/PostprocessData/CMakeLists.txt index 2c15a7c4..bb3999d4 100644 --- a/src/PostprocessData/CMakeLists.txt +++ b/src/PostprocessData/CMakeLists.txt @@ -10,6 +10,7 @@ set(SourceFiles region/regionPoints/sphereRegionPoints/sphereRegionPoints.cpp region/regionPoints/lineRegionPoints/lineRegionPoints.cpp region/regionPoints/centerPointsRegionPoints/centerPointsRegionPoints.cpp + region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.cpp # Postprocess components postprocessComponent/postprocessComponent/postprocessComponent.cpp @@ -19,6 +20,7 @@ set(SourceFiles # Operations operation/postprocessOperation/postprocessOperation.cpp operation/PostprocessOperation/PostprocessOperationSum.cpp + operation/PostprocessOperation/PostprocessOperationAverage.cpp operation/includeMask/includeMask.cpp operation/includeMask/IncludeMasks.cpp diff --git a/src/PostprocessData/fieldsDataBase/fieldsDataBase.cpp b/src/PostprocessData/fieldsDataBase/fieldsDataBase.cpp index cbd47c98..508c572c 100644 --- a/src/PostprocessData/fieldsDataBase/fieldsDataBase.cpp +++ b/src/PostprocessData/fieldsDataBase/fieldsDataBase.cpp @@ -33,7 +33,7 @@ bool pFlow::fieldsDataBase::checkForUpdate(const word &name, bool forceUpdate) if(auto [iter, found]= captureTime_.findIf(name); found) { - shouldUpdate = iter->second < t; + shouldUpdate = iter->second < t || forceUpdate; iter->second = t; } else diff --git a/src/PostprocessData/fieldsDataBase/fieldsDataBaseTemplates.cpp b/src/PostprocessData/fieldsDataBase/fieldsDataBaseTemplates.cpp index 888a6136..9466a8d6 100644 --- a/src/PostprocessData/fieldsDataBase/fieldsDataBaseTemplates.cpp +++ b/src/PostprocessData/fieldsDataBase/fieldsDataBaseTemplates.cpp @@ -50,7 +50,7 @@ pFlow::span pFlow::fieldsDataBase::updateField(const word& name, bool forceUp { if constexpr( std::same_as) { - return updatePoints(forceUpdate); + return updatePoints(true); } else { diff --git a/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.cpp b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.cpp index bae7af3f..922bc1d4 100644 --- a/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.cpp +++ b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.cpp @@ -3,6 +3,7 @@ #include "fieldsDataBase.hpp" #include "fieldFunctions.hpp" +/// Constructs sum processor and initializes result field based on input field type pFlow::PostprocessOperationSum::PostprocessOperationSum ( const dictionary &opDict, @@ -37,6 +38,7 @@ pFlow::PostprocessOperationSum::PostprocessOperationSum } } +/// Performs weighted sum of field values within each region bool pFlow::PostprocessOperationSum::execute ( const std::vector>& weights diff --git a/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.hpp b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.hpp index 94134602..c8e910ff 100644 --- a/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.hpp +++ b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.hpp @@ -21,6 +21,107 @@ Licence: #ifndef __PostprocessOperationSum_hpp__ #define __PostprocessOperationSum_hpp__ +/*! + * @class PostprocessOperationSum + * @brief A class for summing field values within specified regions during post-processing. + * + * @details + * The PostprocessOperationSum class is a specialized post-processing operation that + * calculates the sum of field values within specified regions. It inherits from the + * postprocessOperation base class and implements a weighted summation operation that + * can be applied to scalar (real), vector (realx3), and tensor (realx4) fields. + * + * The sum operation follows the mathematical formula: + * \f[ + * \text{result} = \sum_{i \in \text{processRegion}} w_i \cdot \phi_i \cdot \text{field}_i + * \f] + * + * Where: + * - \f$ i \f$ represents particles within the specified processing region + * - \f$ w_i \f$ is the weight factor for particle \f$ i \f$ + * - \f$ \phi_i \f$ is the value from the phi field for particle \f$ i \f$ + * - \f$ \text{field}_i \f$ is the value from the target field for particle \f$ i \f$ + * + * The calculation can optionally be divided by the region volume (when divideByVolume is set to yes), + * which allows calculating density-like quantities: + * \f[ + * \text{result} = \frac{1}{V_{\text{region}}} \sum_{i \in \text{processRegion}} w_i \cdot \phi_i \cdot \text{field}_i + * \f] + * + * The summation can be further filtered using an includeMask to selectively include only + * specific particles that satisfy certain criteria. + * + * This class supports the following field types: + * - real (scalar values) + * - realx3 (vector values) + * - realx4 (tensor values) + * + * @section usage Usage + * + * To use the PostprocessOperationSum class in a postprocessDataDict file, the following + * parameters can be specified: + * + * - function: Must be set to "sum" to use this operation + * - field: The name of the field to process (e.g., "velocity", "diameter", "one") + * - Special fields like "one" (constant value 1) are also supported + * - Expressions like "cube(diameter)" can be used for mathematical operations + * - dividedByVolume: Whether to divide the sum by the region volume (yes/no, default: no) + * - includeMask: Optional mask to filter which particles to include in the calculation + * + * @section example Example Configuration + * + * Here is an example configuration in the postprocessDataDict file: + * + * @code + * { + * 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 number density (particles per unit volume) + * numberDensity + * { + * function sum; + * field one; // constant field with value 1.0 + * dividedByVolume yes; // divide by region volume + * } + * + * // computes an approximation of volume fraction + * volumeDensity + * { + * function sum; + * field cube(diameter); // d^3, although it differs by pi/6 + * dividedByVolume yes; + * } + * ); + * } + * @endcode + * + * In this example: + * - numberDensity: Calculates the number of particles per unit volume + * - volumeDensity: Calculates an approximation of the volume fraction using d³ + * + * @see postprocessOperation + * @see executeSumOperation + */ + #include #include @@ -37,21 +138,26 @@ class PostprocessOperationSum public postprocessOperation { private: - - /// Pointer to the include mask used for masking operations. + /// Result field containing sums for each region (real, realx3, or realx4) uniquePtr processedRegField_ = nullptr; public: TypeInfo("PostprocessOperation"); + /// @brief Constructs sum operation processor + /// @param opDict Operation parameters dictionary + /// @param regPoints Region points data + /// @param fieldsDB Fields database PostprocessOperationSum( const dictionary& opDict, const regionPoints& regPoints, fieldsDataBase& fieldsDB); + /// destructor ~PostprocessOperationSum() override = default; + /// add this virtual constructor to the base class add_vCtor ( postprocessOperation, @@ -59,11 +165,16 @@ public: dictionary ); + /// @brief Get the processed field containing regional sums + /// @return Const reference to sum results const processedRegFieldType& processedField()const override { return processedRegField_(); } + /// @brief Execute sum operation on field values + /// @param weights Weight factors for particles + /// @return True if successful bool execute(const std::vector>& weights) override; }; @@ -71,4 +182,4 @@ public: } -#endif //__PostprocessOperation_hpp__ \ No newline at end of file +#endif //__PostprocessOperationSum_hpp__ \ No newline at end of file diff --git a/src/PostprocessData/operation/PostprocessOperation/fieldFunctions.hpp b/src/PostprocessData/operation/PostprocessOperation/fieldFunctions.hpp index e1494459..3e278858 100644 --- a/src/PostprocessData/operation/PostprocessOperation/fieldFunctions.hpp +++ b/src/PostprocessData/operation/PostprocessOperation/fieldFunctions.hpp @@ -31,7 +31,6 @@ Licence: namespace pFlow { - template regionField executeSumOperation ( @@ -45,13 +44,14 @@ regionField executeSumOperation ) { regionField processedField(regFieldName, regPoints, T{}); + auto vols = regPoints.volumes(); for(uint32 reg =0; reg executeAverageOperation ( const word& regFieldName, const span& field, - const regionPoints& regPoints, + const regionPoints& regPoints, + const bool devideByVol, const std::vector>& weights, const span& phi, const includeMask::Mask& mask ) { regionField processedField(regFieldName, regPoints, T{}); + auto vols = regPoints.volumes(); for(uint32 reg =0; reg +regionField executeFluctuation2Operation +( + const word& regFieldName, + const span& field, + const regionField& fieldAvg, + const bool devideByVol, + const std::vector>& weights, + const includeMask::Mask& mask +) +{ + const auto& regPoints = fieldAvg.regPoints(); + regionField processedField(regFieldName, regPoints, T{}); + auto vols = regPoints.volumes(); + + for(uint32 reg =0; reg(2)); + } + sumDen += w[n]; + } + n++; + } + + if(devideByVol) + { + processedField[reg] = sumNum / max(sumDen, smallValue) / vol; + } + else + { + processedField[reg] = sumNum / max(sumDen, smallValue); + } } diff --git a/src/PostprocessData/operation/includeMask/includeMask.cpp b/src/PostprocessData/operation/includeMask/includeMask.cpp index a2703b1f..95c85fb8 100644 --- a/src/PostprocessData/operation/includeMask/includeMask.cpp +++ b/src/PostprocessData/operation/includeMask/includeMask.cpp @@ -33,11 +33,21 @@ pFlow::includeMask::includeMask database_(fieldDB) {} +pFlow::includeMask::includeMask +( + const word &type, + const dictionary &opDict, + fieldsDataBase &fieldsDB +) +: + database_(fieldsDB) +{ +} pFlow::uniquePtr pFlow::includeMask::create ( const dictionary& opDict, - fieldsDataBase& feildsDB + fieldsDataBase& fieldsDB ) { word mask = opDict.getValOrSet("includeMask", "all"); @@ -47,7 +57,7 @@ pFlow::uniquePtr pFlow::includeMask::create auto& maskDict = opDict.subDict(mask+"Info"); word maskField = maskDict.getVal("field"); - if( !feildsDB.getPointFieldType(maskField, fieldType) ) + if( !fieldsDB.getPointFieldType(maskField, fieldType) ) { fatalErrorInFunction<<"Error in retriving the type of field" << maskField <<" from dictionary " @@ -68,7 +78,7 @@ pFlow::uniquePtr pFlow::includeMask::create { auto objPtr = dictionaryvCtorSelector_[method] - (opDict, feildsDB); + (opDict, fieldsDB); return objPtr; } else @@ -87,5 +97,56 @@ pFlow::uniquePtr pFlow::includeMask::create return nullptr; } - +pFlow::uniquePtr + pFlow::includeMask::create +( + const word &type, + const dictionary &opDict, + fieldsDataBase &fieldsDB +) +{ + word fieldType; + if( type != "all") + { + auto& maskDict = opDict.subDict(type+"Info"); + word maskField = maskDict.getVal("field"); + + if( !fieldsDB.getPointFieldType(maskField, fieldType) ) + { + fatalErrorInFunction<<"Error in retriving the type of field" + << maskField <<" from dictionary " + << maskDict.globalName() + << endl; + fatalExit; + return nullptr; + } + } + else + { + fieldType = getTypeName(); + } + word method = angleBracketsNames2("IncludeMask", fieldType, type); + + if( wordvCtorSelector_.search(method) ) + { + auto objPtr = + wordvCtorSelector_[method] + (type, opDict, fieldsDB); + return objPtr; + } + else + { + printKeys + ( + fatalError << "Ctor Selector "<< + method << " dose not exist. \n" + <<"Avaiable ones are: \n\n" + , + dictionaryvCtorSelector_ + ); + fatalExit; + return nullptr; + } + return nullptr; +} diff --git a/src/PostprocessData/operation/includeMask/includeMask.hpp b/src/PostprocessData/operation/includeMask/includeMask.hpp index f277ec7b..522e1641 100644 --- a/src/PostprocessData/operation/includeMask/includeMask.hpp +++ b/src/PostprocessData/operation/includeMask/includeMask.hpp @@ -74,6 +74,8 @@ public: includeMask(const dictionary& opDict, fieldsDataBase& feildsDB); + includeMask(const word& type, const dictionary& opDict, fieldsDataBase& feildsDB); + virtual ~includeMask() = default; create_vCtor @@ -85,6 +87,18 @@ public: ), (opDict, feildsDB) ); + + create_vCtor + ( + includeMask, + word, + ( + const word& type, + const dictionary& opDict, + fieldsDataBase& feildsDB + ), + (type, opDict, feildsDB) + ); const fieldsDataBase& database()const { @@ -103,6 +117,12 @@ public: uniquePtr create( const dictionary& opDict, fieldsDataBase& feildsDB); + + static + uniquePtr create( + const word& type, + const dictionary& opDict, + fieldsDataBase& feildsDB); }; diff --git a/src/PostprocessData/operation/postprocessOperation/postprocessOperation.cpp b/src/PostprocessData/operation/postprocessOperation/postprocessOperation.cpp index 8c42daa3..53473a09 100644 --- a/src/PostprocessData/operation/postprocessOperation/postprocessOperation.cpp +++ b/src/PostprocessData/operation/postprocessOperation/postprocessOperation.cpp @@ -82,14 +82,33 @@ bool writeField } - - pFlow::postprocessOperation::postprocessOperation ( const dictionary &opDict, const regionPoints& regPoints, fieldsDataBase &fieldsDB ) +: + postprocessOperation + ( + opDict, + opDict.getVal("field"), + opDict.getValOrSet("phi", "one"), + opDict.getValOrSet("includeMask", "all"), + regPoints, + fieldsDB + ) +{} + +pFlow::postprocessOperation::postprocessOperation +( + const dictionary &opDict, + const word &fieldName, + const word &phiName, + const word& includeName, + const regionPoints ®Points, + fieldsDataBase &fieldsDB +) : operationDict_(opDict), threshold_ @@ -110,15 +129,15 @@ pFlow::postprocessOperation::postprocessOperation ), fieldName_ ( - opDict.getValOrSet("field", "one") + fieldName ), phiFieldName_ ( - opDict.getValOrSet("phi", "one") + phiName ), includeMask_ ( - includeMask::create(opDict, fieldsDB) + includeMask::create(includeName, opDict, fieldsDB) ) { @@ -128,7 +147,6 @@ pFlow::postprocessOperation::postprocessOperation fatalExit; } } - const pFlow::Time& pFlow::postprocessOperation::time() const { return database_.time(); diff --git a/src/PostprocessData/operation/postprocessOperation/postprocessOperation.hpp b/src/PostprocessData/operation/postprocessOperation/postprocessOperation.hpp index fa847bdd..86e776d3 100644 --- a/src/PostprocessData/operation/postprocessOperation/postprocessOperation.hpp +++ b/src/PostprocessData/operation/postprocessOperation/postprocessOperation.hpp @@ -20,6 +20,53 @@ Licence: #ifndef __postprocessOperation_hpp__ #define __postprocessOperation_hpp__ +/*! + * @class postprocessOperation + * @file postprocessOperation.hpp + * @brief Base class for post-processing operations on particle data. + * This class provides the foundational structure and functionality + * for performing various post-processing operations on simulation data. + * + * @details + * The postprocessOperation class operates on field data (specified in the input dictionary) + * and performs specific operations on that field within defined regions. It serves as + * part of the post-processing framework in phasicFlow to analyze particle simulation results. + * + * Operations are performed on specific subsets of particles defined by region points and + * can be filtered using include masks. The class supports different field types (real, + * realx3, realx4) through the processedRegFieldType variant. + * + * The main operations supported include: + * + * 1. Sum operation: + * - Calculates: + * \f[ + * \text{result} = \sum_{i \in \text{processRegion}} w_i \cdot \phi_i \cdot \text{field}_i + * \f] + * - Where \f$ i \f$ belongs to the particles in the specified processRegion + * - \f$ w_i \f$ is the weight factor for particle \f$ i \f$ + * - \f$ \phi_i \f$ is the value from the phi field for particle \f$ i \f$ + * - \f$ \text{field}_i \f$ is the value from the target field for particle \f$ i \f$ + * - Implemented in the derived class PostprocessOperationSum + * + * 2. Average operation: + * - Calculates: + * \f[ + * \text{result} = \frac{\sum_{j \in \text{includeMask}} w_j \cdot \phi_j \cdot \text{field}_j} + * {\sum_{i \in \text{processRegion}} w_i \cdot \phi_i} + * \f] + * - Where \f$ i \f$ belongs to all particles in the specified processRegion + * - \f$ j \f$ belongs to a subset of \f$ i \f$ based on an includeMask defined in the input dictionary + * - This allows calculating regional averages on specific subsets of particles + * + * The class uses threshold values to exclude regions with insufficient particles + * and supports optional division by volume for density-like calculations. Results are written + * to files for later analysis or visualization. + * + * @note The actual processing is performed by derived classes that implement + * the execute() method for specific operation types. + */ + #include #include "virtualConstructor.hpp" @@ -33,6 +80,9 @@ Licence: namespace pFlow { +/// Type alias for processed region field types. +/// Only regionField, regionField, and regionField are supported +/// in the postprocessOperation class. using processedRegFieldType = std::variant < regionField, @@ -40,14 +90,10 @@ using processedRegFieldType = std::variant regionField >; +/// - forward declaration class fieldsDataBase; class Time; -/*! - * @brief Base class for post-processing operations. - * This class provides the basic structure and functionality - * for performing post-processing operations on simulation data. - */ class postprocessOperation { public: @@ -88,16 +134,31 @@ private: public: - + /// Type info TypeInfo("postprocessOperation"); + /// Constructor + /// @param opDict Dictionary containing operation-specific parameters. + /// @param regPoints Reference to the region points used in the operation. + /// @param fieldsDB Reference to the fields database containing field data. postprocessOperation( const dictionary& opDict, const regionPoints& regPoints, fieldsDataBase& fieldsDB ); - + + postprocessOperation( + const dictionary& opDict, + const word& fieldName, + const word& phiName, + const word& includeName, + const regionPoints& regPoints, + fieldsDataBase& fieldsDB + ); + + /// destructor virtual ~postprocessOperation()=default; - + + /// Active the virtual constructor for creating derived classes. create_vCtor( postprocessOperation, dictionary, @@ -108,74 +169,99 @@ public: ), (opDict, regPoints, fieldsDB)); + /// Access to regionPoints instance const regionPoints& regPoints()const { return regionPoints_; } + /// Access to fields database instance const fieldsDataBase& database()const { return database_; } + /// Access to fields database instance fieldsDataBase& database() { return database_; } + /// Access to the time instance const Time& time()const; + /// Return the name of the processed field. word processedFieldName()const { return operationDict_.name(); } + /// return the name of the field to be processed. const word& fieldName()const { return fieldName_; } + /// return the type name of the field to be processed. const word& fieldType()const { return fieldType_; } + /// return the name of the phi field to be processed. const word& phiFieldName()const { return phiFieldName_; } + /// Access to the operation dictionary const dictionary& operationDict()const { return operationDict_; } + + /// return threshold value + /// which is used to exclude the regions which contain + /// particles fewer than this value. const uint32 threshold()const { return threshold_; } + /// whether the result is divided by volume of the region bool divideByVolume()const { return divideByVolume_(); } + /// return the include mask Mask getMask() { return includeMask_().getMask(); } + /// return the processed field virtual const processedRegFieldType& processedField()const=0; - virtual - bool execute(const std::vector>& weights) = 0; + /// execute the operation + /// @param weights Vector of weights for the operation. + virtual bool execute(const std::vector>& weights) = 0; + /// write the result to a file + /// @param parDir Parent directory for the output file. virtual bool write(const fileSystem &parDir)const; + /// write the result to output stream (possibly a file) + /// @param os Output stream to write the result. virtual bool write(iOstream& os)const {return true;} + /// Create the polymorphic object using the virtual constructor. + /// @param opDict Dictionary containing operation-specific parameters. + /// @param regPoints Reference to the region points used in the operation. + /// @param fieldsDB Reference to the fields database containing field data. static uniquePtr create( const dictionary& opDict, diff --git a/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponent.cpp b/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponent.cpp index c815d255..759395f5 100644 --- a/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponent.cpp +++ b/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponent.cpp @@ -67,6 +67,10 @@ bool pFlow::PostprocessComponent::execute return true; } + REPORT(1)<<"Executing postprocess component (" + <regPoints(); diff --git a/src/PostprocessData/postprocessComponent/particleProbePostprocessComponent/particleProbePostprocessComponent.cpp b/src/PostprocessData/postprocessComponent/particleProbePostprocessComponent/particleProbePostprocessComponent.cpp index 3aad17a4..f388c939 100644 --- a/src/PostprocessData/postprocessComponent/particleProbePostprocessComponent/particleProbePostprocessComponent.cpp +++ b/src/PostprocessData/postprocessComponent/particleProbePostprocessComponent/particleProbePostprocessComponent.cpp @@ -92,7 +92,12 @@ bool pFlow::particleProbePostprocessComponent::execute executed_ = false; return true; } - + + REPORT(1)<<"Executing postprocess component (" + <(readDictList("components", dict_)); + + for(auto& compDict:*componentsDictsPtr_) { postprocesses_.push_back( postprocessComponent::create( compDict, diff --git a/src/PostprocessData/postprocessData/postprocessData.hpp b/src/PostprocessData/postprocessData/postprocessData.hpp index 82ba3281..4e5a95f2 100644 --- a/src/PostprocessData/postprocessData/postprocessData.hpp +++ b/src/PostprocessData/postprocessData/postprocessData.hpp @@ -63,7 +63,7 @@ class postprocessData fileDictionary dict_; /// list of dictionaries for postprocess components - dictionaryList componentsDicts_; + uniquePtr componentsDictsPtr_ = nullptr; /// @brief default time control that can be used for all post-process components uniquePtr defaultTimeControlPtr_= nullptr; diff --git a/src/PostprocessData/region/regionFields/regionField.hpp b/src/PostprocessData/region/regionFields/regionField.hpp index 8d47a281..1996fed1 100644 --- a/src/PostprocessData/region/regionFields/regionField.hpp +++ b/src/PostprocessData/region/regionFields/regionField.hpp @@ -31,6 +31,22 @@ namespace pFlow template class regionField { +public: + using FieldType = Field; + + using iterator = typename FieldType::iterator; + + using const_iterator = typename FieldType::const_iterator; + + using reference = typename FieldType::reference; + + using const_reference = typename FieldType::const_reference; + + using value_type = typename FieldType::value_type; + + using pointer = typename FieldType::pointer; + + using const_pointer = typename FieldType::const_pointer; private: /// the field value diff --git a/src/PostprocessData/region/regionPoints/centerPointsRegionPoints/centerPointsRegionPoints.hpp b/src/PostprocessData/region/regionPoints/centerPointsRegionPoints/centerPointsRegionPoints.hpp index ed8d7e87..1da7cc4f 100644 --- a/src/PostprocessData/region/regionPoints/centerPointsRegionPoints/centerPointsRegionPoints.hpp +++ b/src/PostprocessData/region/regionPoints/centerPointsRegionPoints/centerPointsRegionPoints.hpp @@ -26,6 +26,34 @@ Licence: namespace pFlow { +/** + * @class centerPointsRegionPoints + * @brief A region points implementation that selects particles based on their IDs + * + * This class is responsible for selecting points (particles) by their IDs from + * a simulation database and tracking their properties. It maintains information + * about the selected particles including their positions, volumes, and diameters. + * + * The selection is performed based on IDs provided in the input dictionary. + * Once selected, the particles' properties can be accessed through various + * methods. The update method allows refreshing the selection when particle data + * changes. The selection occurs at startTime defined in the time control, and + * there are some methods for selecting ids: + * - specifying ids + * - using selectors specified in pStructSelector class, which includes: + * - box: selects particles within a box region + * - sphere: selects particles within a spherical region + * - cylinder: selects particles within a cylindrical region + * - random: randomly selects a specified number of particles + * - strided: selects particles with a specified stride pattern + * + * This class is useful for tracking specific particles of interest throughout + * a simulation and analyzing their behavior. + * + * @see regionPoints Base class providing the interface for different region + * point selections + * @see pStructSelector Class providing different particle selection methods + */ class centerPointsRegionPoints : public regionPoints @@ -59,6 +87,7 @@ private: public: + /// Type info TypeInfo("centerPoints"); centerPointsRegionPoints( @@ -67,50 +96,69 @@ public: ~centerPointsRegionPoints() override = default; + /// @brief Returns the number of selected points/particles + /// @return Number of selected points/particles uint32 size()const override { return selectedPoints_.size(); } + /// @brief Checks if there are no selected points + /// @return True if no points are selected, false otherwise bool empty()const override { return selectedPoints_.empty(); } + /// @brief Returns the volumes of the selected points (this is normally not used) span volumes()const override { return span(volume_.data(), volume_.size()); } - span eqDiameters()const override + /// @brief Returns the equivalent diameters of the regions (this is normally not used ) + span eqDiameters()const override { return span(diameter_.data(), diameter_.size()); } + /// @brief Returns the center positions of the selected points + /// @return Span containing the center positions of all selected points span centers()const override { return span(center_.data(), center_.size()); } + /// @brief Returns the indices of the selected points (const version) + /// @param elem Element index (not used in this implementation) + /// @return Span containing the indices of all selected points span indices(uint32 elem)const override { return span(selectedPoints_.data(), selectedPoints_.size()); } + /// @brief Returns the indices of the selected points (non-const version) + /// @param elem Element index (not used in this implementation) + /// @return Span containing the indices of all selected points span indices(uint32 elem) override { return span(selectedPoints_.data(), selectedPoints_.size()); } - /// @brief update the selected points based on the ids - /// @return true if the operation is successful + /// @brief Updates the selected points based on the particle IDs + /// @return True if the operation is successful, false otherwise bool update() override; + /// @brief Checks if the data should be written to the same time file + /// @return True if data should be written to the same time file, false otherwise bool writeToSameTimeFile()const override { return true; } + /// @brief Writes the data to the output stream + /// @param os Output stream + /// @return True if the operation is successful, false otherwise bool write(iOstream& os)const override; }; // class centerPointsRegionPoints diff --git a/src/PostprocessData/region/regionPoints/lineRegionPoints/lineRegionPoints.cpp b/src/PostprocessData/region/regionPoints/lineRegionPoints/lineRegionPoints.cpp index c8adfca8..5e41ddf3 100644 --- a/src/PostprocessData/region/regionPoints/lineRegionPoints/lineRegionPoints.cpp +++ b/src/PostprocessData/region/regionPoints/lineRegionPoints/lineRegionPoints.cpp @@ -30,7 +30,8 @@ pFlow::lineRegionPoints::lineRegionPoints if(raddi.size() != nPoints) { fatalErrorInFunction - << "The number elements in of radii list should be equal to the number of points"< pFlow::lineRegionPoints::indices(uint32 elem) const { - if(elem>=size()) + if(elem >= size()) { fatalErrorInFunction << "The element index is out of range. elem: " << elem @@ -58,13 +59,15 @@ pFlow::span pFlow::lineRegionPoints::indices(uint32 elem) c fatalExit; } - return span(selectedPoints_[elem].data(), selectedPoints_[elem].size()); + return span( + selectedPoints_[elem].data(), + selectedPoints_[elem].size()); } bool pFlow::lineRegionPoints::update() { const auto points = database().updatePoints(); - for(auto& elem:selectedPoints_) + for(auto& elem : selectedPoints_) { elem.clear(); } @@ -84,17 +87,18 @@ bool pFlow::lineRegionPoints::update() bool pFlow::lineRegionPoints::write(iOstream &os) const { - os <<"# Spheres along a straight line \n"; - os <<"# No."< sphereRegions_; - /// center poitns of regions/elements + /// Center points of all spherical regions realx3Vector centerPoints_; - /// volumes of all elements/regions + /// Volumes of all spherical regions realVector volumes_; + /// Diameters of all spherical regions realVector diameters_; - /// the point indices that are selected by this region + /// Point/particles indices selected by each region Vector selectedPoints_; public: + /// Type information for runtime type identification TypeInfo(line::TYPENAME()); + /// Construct from dictionary that contains lineInfo and fields database lineRegionPoints( const dictionary& dict, fieldsDataBase& fieldsDataBase); + /// Default destructor ~lineRegionPoints() override = default; + /// Return number of regions uint32 size()const override { return sphereRegions_.size(); } + /// Check if regions list is empty bool empty()const override { return sphereRegions_.empty(); } + /// Return volumes of all regions span volumes()const override { return span(volumes_.data(), volumes_.size()); } + /// Return equivalent diameters of all regions span eqDiameters()const override { return span(diameters_.data(), diameters_.size()); } + /// Return center points of all regions span centers()const override { return span(centerPoints_.data(), centerPoints_.size()); } + /// Return indices of points in the specified element/region span indices(uint32 elem)const override; - + /// Update regions based on current particle positions bool update() override; + /// Whether to write all data to the same time file bool writeToSameTimeFile()const override { return true; } + /// Write data to output stream bool write(iOstream& os) const override; }; diff --git a/src/PostprocessData/region/regionPoints/regionPoints/regionPoints.hpp b/src/PostprocessData/region/regionPoints/regionPoints/regionPoints.hpp index b6a9df66..0931175f 100644 --- a/src/PostprocessData/region/regionPoints/regionPoints/regionPoints.hpp +++ b/src/PostprocessData/region/regionPoints/regionPoints/regionPoints.hpp @@ -32,27 +32,43 @@ namespace pFlow class fieldsDataBase; class Time; +/** + * @class regionPoints + * @brief Abstract base class for managing and processing volumetric regions + * in the simulation. Particles are selected based on their positions within + * these defined regions. + * + * This class provides an interface for accessing and manipulating data + * related to regions of points (particles), including their volumes, equivalent + * diameters, center points, and particle indices that they contain. It interacts with the + * fieldsDataBase and Time classes to retrieve simulation data. + */ class regionPoints { - using PointsTypeHost = typename pointStructure::PointsTypeHost; + using PointsTypeHost = typename pointStructure::PointsTypeHost; + /// Reference to the fields database containing simulation data fieldsDataBase& fieldsDataBase_; public: TypeInfo("regionPoints"); - + /// Constructor with dictionary and fields database reference regionPoints( const dictionary& dict, fieldsDataBase& fieldsDataBase); + /// Default virtual destructor virtual ~regionPoints() = default; + /// Returns reference to the time object from the database const Time& time()const; + /// Returns const reference to the fields database const fieldsDataBase& database()const; + /// Returns non-const reference to the fields database fieldsDataBase& database(); /// @brief size of elements @@ -61,11 +77,7 @@ public: /// @brief check if the region is empty virtual - bool empty()const = 0; - - /*/// @brief return the type of the region - virtual const word& type()const = 0;*/ - + bool empty()const = 0; /// @brief volume of elements /// @return sapn for accessing the volume of elements @@ -75,30 +87,29 @@ public: virtual span eqDiameters()const = 0; - /// center points of elements + /// center points of elements virtual span centers()const = 0; - /// indices of particles inside the element @var elem + /// Returns const span of particle indices inside the specified element region virtual span indices(uint32 elem)const = 0; + /// Returns non-const span of particle indices inside the specified element region virtual span indices(uint32 elem) = 0; + /// Updates the points (particles) inside regions based on current particle positions virtual bool update() = 0; + /// Returns true if the region should be written to the same time file virtual bool writeToSameTimeFile()const = 0; + /// Writes region data to the output stream virtual bool write(iOstream& os)const=0; - - /*static - uniquePtr create( - const dictionary& dict, - fieldsDataBase& fieldsDataBase);*/ }; diff --git a/src/PostprocessData/region/regionPoints/sphereRegionPoints/sphereRegionPoints.hpp b/src/PostprocessData/region/regionPoints/sphereRegionPoints/sphereRegionPoints.hpp index a6e11ef4..ad7f9296 100644 --- a/src/PostprocessData/region/regionPoints/sphereRegionPoints/sphereRegionPoints.hpp +++ b/src/PostprocessData/region/regionPoints/sphereRegionPoints/sphereRegionPoints.hpp @@ -18,6 +18,19 @@ Licence: -----------------------------------------------------------------------------*/ +/** + * @file sphereRegionPoints.hpp + * @brief A class representing a spherical region for point selection + * + * This class provides functionality to select points within a spherical region + * and to compute related properties such as volume and equivalent diameter. + * It inherits from regionPoints and implements all required virtual methods. + * + * @see regionPoints + * @see sphere + * @see fieldsDataBase + */ + #ifndef __sphereRegionPoints_hpp__ #define __sphereRegionPoints_hpp__ @@ -27,75 +40,127 @@ Licence: namespace pFlow { + class sphereRegionPoints : public regionPoints { private: - /// spehre region for selecting points + /// Sphere object defining the region for point selection sphere sphereRegion_; - /// the volume of region + /// Volume of the spherical region real volume_; + /// Diameter of the spherical region real diameter_; - /// the point indices that are selected by this region + /// Indices of points that are selected by this region uint32Vector selectedPoints_; public: TypeInfo(sphere::TYPENAME()); + /** + * @brief Construct a spherical region for point selection + * + * @param dict Dictionary containing sphereInfo dictionary + * @param fieldsDataBase Database containing fields data + */ sphereRegionPoints( const dictionary& dict, fieldsDataBase& fieldsDataBase); + /// Destructor ~sphereRegionPoints() override = default; + /** + * @brief Get the number of regions (always 1 for sphere) + * @return Always returns 1 + */ uint32 size()const override { return 1; } + /** + * @brief Check if the region is empty + * @return Always returns false + */ bool empty()const override { return false; } + /** + * @brief Get the volume of the spherical region + * @return A span containing the volume of the region + */ span volumes()const override { return span(&volume_, 1); } + /** + * @brief Get the equivalent diameter of the spherical region + * @return A span containing the diameter of the region + */ span eqDiameters()const override { return span(&diameter_, 1); } + /** + * @brief Get the center of the spherical region + * @return A span containing the center point of the region + */ span centers()const override { return span(&sphereRegion_.center(), 1); } - + + /** + * @brief Get the indices of points within the region (const version) + * @param elem Element index (ignored as there's only one sphere) + * @return A span containing indices of points within the region + */ span indices(uint32 elem)const override { return span(selectedPoints_.data(), selectedPoints_.size()); } + /** + * @brief Get the indices of points within the region (non-const version) + * @param elem Element index (ignored as there's only one sphere) + * @return A span containing indices of points within the region + */ span indices(uint32 elem) override { return span(selectedPoints_.data(), selectedPoints_.size()); } + /** + * @brief Update the points selected by this region + * @return True if update was successful + */ bool update()override; + /** + * @brief Determine if data should be written to the same time file + * @return Always returns true + */ bool writeToSameTimeFile()const override { return true; } + /** + * @brief Write region data to output stream + * @param os Output stream to write to + * @return True if write was successful + */ bool write(iOstream& os)const override; }; diff --git a/src/PostprocessData/sampleDictionary/postprocessDataDict b/src/PostprocessData/sampleDictionary/postprocessDataDict index 8fed2b42..3cf582a1 100755 --- a/src/PostprocessData/sampleDictionary/postprocessDataDict +++ b/src/PostprocessData/sampleDictionary/postprocessDataDict @@ -2,107 +2,128 @@ | phasicFlow File | | copyright: www.cemf.ir | \* ------------------------------------------------------------------------- */ -objectName processDataDict; -objectType dictionary;; -fileFormat ASCII; +objectName postprocessDataDict; +objectType dictionary;; +fileFormat ASCII; /*---------------------------------------------------------------------------*/ -runTimeActive yes; +runTimeActive yes; defaultTimeControl { - timeControl; - startTime; - endTime; - actionInterval 0.05; + timeControl timeStep; + startTime 0; + endTime 1000; + executionInterval 150; } components ( - velocityProb - { - method particleProbe; - region idSelecttion; - field velocity; - ids (0 10 100); - timeControl timeStep; - startTime 0; - endTime infinity; - probInterval 1; - } + 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; + dividedByVolume 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 + dividedByVolume 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; + } + } - comp2 - { - method uniformDistribution; - region spehre; - - sphereInfo - { - radius 0.01; - center (); - } - timeControl default; //default; - operations - ( - numParticle - { - function sum; - field compoenent(velocity,x); - phi square(mass); - divideByVol no; //default - threshold 1; //default; - defaultVal NaN; - //includeMask all; //default; - includeMask lessThan; - lessThanInfo - { - field diameter; - value 0.003; - } - } - ); + numberDensity + { + function sum; + field one; + phi one; // default + dividedByVolume yes; + + } + ); } - - comp3 + + alongALine { - - region line; - lineInfo - { - p1 (); - p2 (); + 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; - } - timeControl settingsDict; //default; - type numberBased; - operations(); + radius 0.01; + } + + operations + ( + // computes the arithmetic mean of particle velocity + numberDensity + { + function sum; + field one; + dividedByVolume yes; //default is no + } + + volumeDensity + { + function sum; + field cube(diameter); // d^3, although it differs by pi/6 + dividedByVolume yes; //default is no + } + ); } - - comp4 - { - type GaussianDistribution; - region hexMesh; // unstructuredMehs; - hexMeshInfo - { - min (-0.3 -1.4 -0.01); - max ( 0.3 2 0.48 ); - nx 30; // number of divisions in x direction - ny 160; // number of divisions in y direction - nz 24; // number of divisions in z direction - } - timeControl settingsDict; // read from settingsDict - operations - ( - avVelocity - { - type average; - field realx3 velocity; // default to real 1.0 - divideByVol no; // default - threshold 1; //default; - includeMask all; //default; - - } - ); - } -); + +); \ No newline at end of file