From ab7f700ead22a04a38b8421895b9b91caf985682 Mon Sep 17 00:00:00 2001 From: Hamidreza Date: Wed, 9 Apr 2025 19:47:57 +0330 Subject: [PATCH 1/9] first commit for post-processing - the whole structure is ready. - next step whould be execute methods and then write methods - post-processing after simulation is not started yet. --- src/PostProcessData/CMakeLists.txt | 35 + .../fieldsDataBase/fieldFunctions.hpp | 165 +++++ .../fieldsDataBase/fieldsDataBase.cpp | 664 ++++++++++++++++++ .../fieldsDataBase/fieldsDataBase.hpp | 389 ++++++++++ .../fieldsDataBaseTemplates.cpp | 80 +++ .../method/GaussianDistribution.hpp | 107 +++ .../method/uniformDistribution.hpp | 86 +++ .../operation/PostprocessOperationSum.cpp | 69 ++ .../operation/PostprocessOperationSum.hpp | 76 ++ .../operation/fieldFunctions.hpp | 117 +++ .../operation/includeMask/IncludeMask.hpp | 192 +++++ .../operation/includeMask/IncludeMasks.cpp | 50 ++ .../operation/includeMask/includeMask.cpp | 91 +++ .../operation/includeMask/includeMask.hpp | 115 +++ .../operation/includeMask/maskOperations.hpp | 162 +++++ .../operation/postprocessOperation.cpp | 101 +++ .../operation/postprocessOperation.hpp | 167 +++++ .../PostprocessComponent.cpp | 109 +++ .../PostprocessComponent.hpp | 117 +++ .../PostprocessComponentGaussian.hpp | 73 ++ .../PostprocessComponents.cpp | 34 + .../particleProbePostprocessComponent.cpp | 26 + .../particleProbePostprocessComponent.hpp | 94 +++ .../postprocessComponent.cpp | 55 ++ .../postprocessComponent.hpp | 114 +++ src/PostProcessData/postprocessData.cpp | 99 +++ src/PostProcessData/postprocessData.hpp | 103 +++ src/PostProcessData/postprocessDataDict | 108 +++ .../postprocessTimeControl.hpp | 65 ++ .../region/regionFields.hpp/regionField.hpp | 95 +++ .../regionFields.hpp/regionFieldTemplate.cpp | 10 + .../regionPoints/centerPointsRegionPoints.cpp | 86 +++ .../regionPoints/centerPointsRegionPoints.hpp | 116 +++ .../region/regionPoints/lineRegionPoints.cpp | 83 +++ .../region/regionPoints/lineRegionPoints.hpp | 100 +++ .../region/regionPoints/regionPoints.cpp | 28 + .../region/regionPoints/regionPoints.hpp | 103 +++ .../regionPoints/sphereRegionPoints.cpp | 31 + .../regionPoints/sphereRegionPoints.hpp | 98 +++ 39 files changed, 4413 insertions(+) create mode 100644 src/PostProcessData/CMakeLists.txt create mode 100644 src/PostProcessData/fieldsDataBase/fieldFunctions.hpp create mode 100644 src/PostProcessData/fieldsDataBase/fieldsDataBase.cpp create mode 100644 src/PostProcessData/fieldsDataBase/fieldsDataBase.hpp create mode 100644 src/PostProcessData/fieldsDataBase/fieldsDataBaseTemplates.cpp create mode 100644 src/PostProcessData/method/GaussianDistribution.hpp create mode 100644 src/PostProcessData/method/uniformDistribution.hpp create mode 100644 src/PostProcessData/operation/PostprocessOperationSum.cpp create mode 100644 src/PostProcessData/operation/PostprocessOperationSum.hpp create mode 100644 src/PostProcessData/operation/fieldFunctions.hpp create mode 100644 src/PostProcessData/operation/includeMask/IncludeMask.hpp create mode 100644 src/PostProcessData/operation/includeMask/IncludeMasks.cpp create mode 100644 src/PostProcessData/operation/includeMask/includeMask.cpp create mode 100644 src/PostProcessData/operation/includeMask/includeMask.hpp create mode 100644 src/PostProcessData/operation/includeMask/maskOperations.hpp create mode 100644 src/PostProcessData/operation/postprocessOperation.cpp create mode 100644 src/PostProcessData/operation/postprocessOperation.hpp create mode 100644 src/PostProcessData/postprocessComponent/PostprocessComponent.cpp create mode 100644 src/PostProcessData/postprocessComponent/PostprocessComponent.hpp create mode 100644 src/PostProcessData/postprocessComponent/PostprocessComponentGaussian.hpp create mode 100644 src/PostProcessData/postprocessComponent/PostprocessComponents.cpp create mode 100644 src/PostProcessData/postprocessComponent/particleProbePostprocessComponent.cpp create mode 100644 src/PostProcessData/postprocessComponent/particleProbePostprocessComponent.hpp create mode 100644 src/PostProcessData/postprocessComponent/postprocessComponent.cpp create mode 100644 src/PostProcessData/postprocessComponent/postprocessComponent.hpp create mode 100644 src/PostProcessData/postprocessData.cpp create mode 100644 src/PostProcessData/postprocessData.hpp create mode 100755 src/PostProcessData/postprocessDataDict create mode 100644 src/PostProcessData/postprocessTimeControl.hpp create mode 100644 src/PostProcessData/region/regionFields.hpp/regionField.hpp create mode 100644 src/PostProcessData/region/regionFields.hpp/regionFieldTemplate.cpp create mode 100644 src/PostProcessData/region/regionPoints/centerPointsRegionPoints.cpp create mode 100644 src/PostProcessData/region/regionPoints/centerPointsRegionPoints.hpp create mode 100644 src/PostProcessData/region/regionPoints/lineRegionPoints.cpp create mode 100644 src/PostProcessData/region/regionPoints/lineRegionPoints.hpp create mode 100644 src/PostProcessData/region/regionPoints/regionPoints.cpp create mode 100644 src/PostProcessData/region/regionPoints/regionPoints.hpp create mode 100644 src/PostProcessData/region/regionPoints/sphereRegionPoints.cpp create mode 100644 src/PostProcessData/region/regionPoints/sphereRegionPoints.hpp diff --git a/src/PostProcessData/CMakeLists.txt b/src/PostProcessData/CMakeLists.txt new file mode 100644 index 00000000..e5a624a8 --- /dev/null +++ b/src/PostProcessData/CMakeLists.txt @@ -0,0 +1,35 @@ + +set(SourceFiles +fieldsDataBase/fieldsDataBase.cpp + +postprocessComponent/postprocessComponent.cpp +postprocessComponent/PostprocessComponents.cpp + +operation/postprocessOperation.cpp +operation/PostprocessOperationSum.cpp + + +postprocessData.cpp + +postprocessComponent/postprocessComponent.cpp +postprocessComponent/PostprocessComponents.cpp +postprocessComponent/particleProbePostprocessComponent.cpp + +operation/includeMask/includeMask.cpp +operation/includeMask/IncludeMasks.cpp +operation/postprocessOperation.cpp +operation/PostprocessOperationSum.cpp + +region/regionPoints/sphereRegionPoints.cpp +region/regionPoints/regionPoints.cpp +region/regionPoints/lineRegionPoints.cpp +region/regionPoints/centerPointsRegionPoints.cpp + +) + +set(link_libs Kokkos::kokkos phasicFlow Particles) + +pFlow_add_library_install(PostProcessData SourceFiles link_libs) + +add_subdirectory(testPostprocess) + diff --git a/src/PostProcessData/fieldsDataBase/fieldFunctions.hpp b/src/PostProcessData/fieldsDataBase/fieldFunctions.hpp new file mode 100644 index 00000000..ea5b7110 --- /dev/null +++ b/src/PostProcessData/fieldsDataBase/fieldFunctions.hpp @@ -0,0 +1,165 @@ +/*------------------------------- phasicFlow --------------------------------- + O C enter of + O O E ngineering and + O O M ultiscale modeling of + OOOOOOO F luid flow +------------------------------------------------------------------------------ + Copyright (C): www.cemf.ir + email: hamid.r.norouzi AT gmail.com +------------------------------------------------------------------------------ +Licence: + This file is part of phasicFlow code. It is a free software for simulating + granular and multiphase flows. You can redistribute it and/or modify it under + the terms of GNU General Public License v3 or any other later versions. + + phasicFlow is distributed to help others in their research in the field of + granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +-----------------------------------------------------------------------------*/ + +#ifndef __fieldFunctions_hpp__ +#define __fieldFunctions_hpp__ + +#include "types.hpp" +#include "span.hpp" + +namespace pFlow +{ + +template +inline +void funcCast(span src, span dst) +{ + for(uint32 i=0; i(src[i]); + } +} + +template +inline +void funcAbs(span src, span dst) +{ + for(uint32 i=0; i +inline +void funcSquare(span src, span dst) +{ + for( uint32 i=0; i(src[i]),2); + } +} + +template +inline +void funcCube(span src, span dst) +{ + for( uint32 i=0; i(src[i]),3); + } +} + +template +inline +void funcSquareRoot(span src, span dst) +{ + for( uint32 i=0; i(src[i])); + } +} + +template +inline +void funcMagnitude(span src, span dst) +{ + for( uint32 i=0; i +inline +void funcMagnitudeSquare(span src, span dst) +{ + for( uint32 i=0; i +inline +void funcMagnitudeCube(span src, span dst) +{ + for( uint32 i=0; i +inline +void funcMagnitudeSquareRoot(span src, span dst) +{ + for( uint32 i=0; i src, span dst, char component) +{ + for( uint32 i=0; i src, span dst, char component) +{ + for( uint32 i=0; i + +#include "vocabs.hpp" +#include "Time.hpp" +#include "fieldsDataBase.hpp" +#include "fieldFunctions.hpp" +#include "dynamicPointStructure.hpp" + +bool pFlow::fieldsDataBase::checkForUpdate(const word &name, bool forceUpdate) +{ + auto t = currentTime(); + bool shouldUpdate = false; + + if(auto [iter, found]= captureTime_.findIf(name); found) + { + shouldUpdate = iter->second < t; + iter->second = t; + } + else + { + shouldUpdate = true; + captureTime_.insertIf(name, t); + } + + return shouldUpdate; +} + +pFlow::span pFlow::fieldsDataBase::createOrGetRealField(const word &name) +{ + + bool shouldUpdate = checkForUpdate(name); + + if(shouldUpdate) + { + allFields_.emplaceBackOrReplace> + ( + name, + FieldTypeHost + ( + name, + "value", + pointFieldSize() + ) + ); + } + + auto& field = allFields_.getObject>(name); + return span( + field.data(), + field.size()); +} + +bool pFlow::fieldsDataBase::findFunction( + const word &compoundFieldName, + word &fieldName, + fieldsDataBase::Functions &func) +{ + + std::regex pattern(R"((\w+)?\((\w+)(?:,([xyzw]))?\)|(\w+))"); + std::smatch match; + + if (std::regex_match(compoundFieldName, match, pattern)) + { + if (match[1].matched) // Function is present + { + word functionName = match[1].str(); + fieldName = match[2].str(); + + // Map the function name to the enum value + if(functionName=="component") + { + if (!match[3].matched) // Component is not present + { + fatalErrorInFunction << + "Component (x, y, z, or w) is not specified in the function component: " << compoundFieldName << + " the format is component(u,x), where u is the vector field name and x is the compoenent." << endl; + return false; + } + + switch (match[3].str()[0]) + { + case 'x': func = fieldsDataBase::Functions::ComponentX; break; + case 'y': func = fieldsDataBase::Functions::ComponentY; break; + case 'z': func = fieldsDataBase::Functions::ComponentZ; break; + case 'w': func = fieldsDataBase::Functions::ComponentW; break; + default: + fatalErrorInFunction << + "Invalid component specified: " << match[3].str() << endl; + return false; + } + return true; + } + else if (functionName == "abs") + { + func = fieldsDataBase::Functions::Abs; + } + else if (functionName == "square") + { + func = fieldsDataBase::Functions::Square; + } + else if (functionName == "cube") + { + func = fieldsDataBase::Functions::Cube; + } + else if (functionName == "sqrt") + { + func = fieldsDataBase::Functions::SqureRoot; + } + else if (functionName == "mag") + { + func = fieldsDataBase::Functions::Magnitude; + } + else if (functionName == "magSquare") + { + func = fieldsDataBase::Functions::MagnitudeSquare; + } + else if (functionName == "magCube") + { + func = fieldsDataBase::Functions::MagnitudeCube; + } + else if (functionName == "magSqrt") + { + func = fieldsDataBase::Functions::MagnitudeSquareRoot; + } + else + { + fatalErrorInFunction << + "Unknown function specified: " << functionName<< + " in: "<() || + inputType == getTypeName() ) + { + outputType = getTypeName(); + return true; + } + else + { + fatalErrorInFunction<<"Wrong function: component(u,comp), for input field type: "<() ) + { + outputType = getTypeName(); + return true; + } + else + { + fatalErrorInFunction<<"Wrong function: component(u,w), for input field type: "<() || + inputType == getTypeName() || + inputType == getTypeName() || + inputType == getTypeName() ) + { + outputType = getTypeName(); + return true; + } + else + { + fatalErrorInFunction<<"Wrong input field type for functions abs, squqre, cube, and sqrt."<< + " field type is "<< inputType<() || + inputType == getTypeName() ) + { + outputType = getTypeName(); + return true; + } + else + { + fatalErrorInFunction<<"Wroing input field type for functions mag, magSquare, magCube, magSqrt. "<< + " Input field type is "<< inputType<() || + inputType == getTypeName() || + inputType == getTypeName()) + { + outputType = inputType; + return true; + } + else if( inputType == getTypeName() || + inputType == getTypeName() ) + { + outputType = getTypeName(); + return true; + } + else + { + fatalErrorInFunction<< "Wroing input field type "<< inputType<second; + } + else + { + word fieldTypeName = time_.lookupObjectTypeName(fieldName); + word space; + if(!pointFieldGetType(fieldTypeName, originalType, space)) + { + fatalErrorInFunction<<"Cannot extract type name from "<< fieldTypeName< pFlow::fieldsDataBase::updatePoints(bool forceUpdate) +{ + + bool shouldUpdate = checkForUpdate("position", forceUpdate); + + if(shouldUpdate) + { + const auto& pstruct = pStruct(); + allFields_.emplaceBackOrReplace( + "position", + pstruct.activePointsHost()); + } + + auto& points = allFields_.getObject("position"); + + return span( + points.data(), + points.size()); + +} + +pFlow::span pFlow::fieldsDataBase::updateFieldRealx3 +( + const word &compoundName, + bool forceUpdate +) +{ + word originalType, typeAfterFunction, fieldName; + Functions func; + + if( !getPointFieldType(compoundName, fieldName, originalType, typeAfterFunction, func)) + { + fatalErrorInFunction<< "Error in getting the type name of field: "<< + compoundName<<", with type name: "<< originalType <(nullptr, 0); + } + + if( originalType == getTypeName() && func == Functions::None ) + { + return updateField(fieldName, forceUpdate); + } + else + { + fatalErrorInFunction<< "Error in getting the type name of field: "<< + compoundName<<", with type name: "<< originalType <(nullptr, 0); + } + +} + +pFlow::span pFlow::fieldsDataBase::updateFieldRealx4 +( + const word &compoundName, + bool forceUpdate +) +{ + word originalType, typeAfterFunction, fieldName; + Functions func; + + if( !getPointFieldType(compoundName, fieldName, originalType, typeAfterFunction, func)) + { + fatalErrorInFunction<< "Error in getting the type name of field: "<< + compoundName<<", with type name: "<< originalType <(nullptr, 0); + } + + if( originalType == getTypeName() && func == Functions::None ) + { + return updateField(fieldName, forceUpdate); + } + else + { + fatalErrorInFunction<< "Error in getting the type name of field: "<< + compoundName<<", with type name: "<< originalType <(nullptr, 0); + } + +} + +pFlow::span pFlow::fieldsDataBase::updateFieldReal +( + const word &compoundName, + bool forceUpdate +) +{ + word originalType, typeAfterFunction, fieldName; + Functions func; + + if( !getPointFieldType(compoundName, fieldName, originalType, typeAfterFunction, func)) + { + fatalErrorInFunction<< "Error in getting the type name of field: "<< + compoundName<<", with type name: "<< originalType <(nullptr, 0); + } + + // if the output type is not real, then it is not supported yet + if(typeAfterFunction != getTypeName()) + { + fatalErrorInFunction<< "The output type of field "<< compoundName<< + " is not real, it is: "<< typeAfterFunction<(nullptr, 0); + } + + // if the orginal type is real and no function, then it is a normal field + if( originalType == getTypeName() && func == Functions::None ) + { + return updateField(fieldName, forceUpdate); + } + + // if the original type is uint32, and no funciton, cast to real + if( originalType == getTypeName() && func == Functions::None ) + { + auto sp = updateField(fieldName, forceUpdate); + auto spReal = createOrGetRealField(fieldName+".real"); + funcCast(sp, spReal); + return spReal; + } + else + { + fatalErrorInFunction<<"No function can be applied to field of type uint32. "<< + " The field is: "<< compoundName<(nullptr, 0); + fatalExit; + } + + if( originalType == getTypeName() ) + { + switch(func) + { + case Functions::Abs: + { + auto sp = updateField(fieldName, forceUpdate); + auto spReal = createOrGetRealField(compoundName); + funcAbs(sp, spReal); + return spReal; + } + case Functions::Square: + { + auto sp = updateField(fieldName, forceUpdate); + auto spReal = createOrGetRealField(compoundName); + funcSquare(sp, spReal); + return spReal; + } + case Functions::Cube: + { + auto sp = updateField(fieldName, forceUpdate); + auto spReal = createOrGetRealField(compoundName); + funcCube(sp, spReal); + return spReal; + } + case Functions::SqureRoot: + { + auto sp = updateField(fieldName, forceUpdate); + auto spReal = createOrGetRealField(compoundName+".sqrt"); + funcSquareRoot(sp, spReal); + return spReal; + } + default: + { + fatalErrorInFunction<< "Wrong function for field type real in :"<< + compoundName<(nullptr, 0); + } + } + } + + if( originalType == getTypeName()) + { + switch(func) + { + case Functions::Magnitude: + { + auto sp = updateField(fieldName, forceUpdate); + auto spReal = createOrGetRealField(compoundName); + funcMagnitude(sp, spReal); + return spReal; + } + case Functions::MagnitudeSquare: + { + auto sp = updateField(fieldName, forceUpdate); + auto spReal = createOrGetRealField(compoundName); + funcMagnitudeSquare(sp, spReal); + return spReal; + } + case Functions::MagnitudeCube: + { + auto sp = updateField(fieldName, forceUpdate); + auto spReal = createOrGetRealField(compoundName); + funcMagnitudeCube(sp, spReal); + return spReal; + } + case Functions::MagnitudeSquareRoot: + { + auto sp = updateField(fieldName, forceUpdate); + auto spReal = createOrGetRealField(compoundName); + funcMagnitudeSquareRoot(sp, spReal); + return spReal; + } + case Functions::ComponentX: + { + auto sp = updateField(fieldName, forceUpdate); + auto spReal = createOrGetRealField(compoundName); + funcComponent(sp, spReal, 'x'); + return spReal; + } + case Functions::ComponentY: + { + auto sp = updateField(fieldName, forceUpdate); + auto spReal = createOrGetRealField(compoundName); + funcComponent(sp, spReal, 'y'); + return spReal; + } + case Functions::ComponentZ: + { + auto sp = updateField(fieldName, forceUpdate); + auto spReal = createOrGetRealField(compoundName); + funcComponent(sp, spReal, 'z'); + return spReal; + } + default: + { + fatalErrorInFunction<< "Wrong function for field type realx3 in :"<< + compoundName<(nullptr, 0); + } + } + } + + fatalErrorInFunction<<"NOT SUPPORTED "<(nullptr, 0); +} + +pFlow::span pFlow::fieldsDataBase::updateFieldUint32 +( + const word& name, + bool forceUpdate +) +{ + return updateField(name, forceUpdate); +} + +pFlow::allPointFieldTypes pFlow::fieldsDataBase::updateFieldAll +( + const word &compoundName, + bool forceUpdate +) +{ + word originalType, typeAfterFunction; + + if( !getPointFieldType(compoundName, originalType, typeAfterFunction)) + { + fatalErrorInFunction<< "Error in getting the type name of field: "<< + compoundName<<", with type name: "<< originalType <(nullptr,0); + } + + if( typeAfterFunction== getTypeName() ) + { + return updateField(compoundName, forceUpdate); + } + else if( typeAfterFunction == getTypeName() ) + { + return updateField(compoundName, forceUpdate); + } + else if( typeAfterFunction == getTypeName() ) + { + return updateField(compoundName, forceUpdate); + } + else + { + fatalErrorInFunction<< "Invalid feild "<< compoundName<(nullptr, 0); + } +} + +const pFlow::pointStructure &pFlow::fieldsDataBase::pStruct() const +{ + if(inSimulation_) + { + return + static_cast( + time_.lookupObject(pointStructureFile__) + ); + } + else + { + return time_.lookupObject(pointStructureFile__); + } +} + +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; +} + diff --git a/src/PostProcessData/fieldsDataBase/fieldsDataBase.hpp b/src/PostProcessData/fieldsDataBase/fieldsDataBase.hpp new file mode 100644 index 00000000..13a71f31 --- /dev/null +++ b/src/PostProcessData/fieldsDataBase/fieldsDataBase.hpp @@ -0,0 +1,389 @@ +/*------------------------------- phasicFlow --------------------------------- + O C enter of + O O E ngineering and + O O M ultiscale modeling of + OOOOOOO F luid flow +------------------------------------------------------------------------------ + Copyright (C): www.cemf.ir + email: hamid.r.norouzi AT gmail.com +------------------------------------------------------------------------------ +Licence: + This file is part of phasicFlow code. It is a free software for simulating + granular and multiphase flows. You can redistribute it and/or modify it under + the terms of GNU General Public License v3 or any other later versions. + + phasicFlow is distributed to help others in their research in the field of + granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +-----------------------------------------------------------------------------*/ + +#ifndef __fieldsDataBase_hpp__ +#define __fieldsDataBase_hpp__ + +#include +#include + + +#include "pointStructure.hpp" +#include "pointFields.hpp" +#include "anyList.hpp" +#include "Map.hpp" +#include "span.hpp" + +namespace pFlow +{ + +class Time; + +bool pointFieldGetType(const word& TYPENAME, word& fieldType, word& fieldSpace); + +template +concept ValidFieldType = + std::same_as || + std::same_as || + std::same_as || + std::same_as; + +template +concept VectorType = + std::same_as || + std::same_as; + +template +concept ScalarType = + std::same_as; + + +template +concept ValidRegionFieldType = + std::same_as || + std::same_as || + std::same_as ; + + +using allPointFieldTypes = std::variant, span, span>; + + +class fieldsDataBase + +{ +private: + + // - Typedefs + + /// Point position data type + using PointsTypeHost = typename pointStructure::PointsTypeHost; + + /// Point field data type + template + using FieldTypeHost = typename internalField::FieldTypeHost; + + /// @brief Enumeration of functions that can be applied to point fields. + enum class Functions + { + None, /// no function + ComponentX, /// component(u,x) + ComponentY, /// component(u,y) + ComponentZ, /// component(u,z) + ComponentW, /// component(u,w) + Abs, /// abs(s) + Square, /// square(s) + Cube, /// cube(s) + SqureRoot, /// sqrt(s) + Magnitude, /// mag(u) + MagnitudeSquare, /// magSquare(u) + MagnitudeCube, /// magCube(u) + MagnitudeSquareRoot /// magSqrt(u) + }; + + + // - Member variables + + /// const reference to the Time object + const Time& time_; + + /// List to store all the point fields + anyList allFields_; + + /// Map to store the last capture time of each field + wordMap captureTime_; + + /// + bool inSimulation_ = false; + + static const inline std::map reservedFieldNames_ + { + {"position", "realx3"}, + {"one", "real"} + }; + + // - Private member functions + + uint32 pointFieldSize() + { + auto s = updatePoints(); + return s.size(); + } + + /// @brief Checks if a field needs to be updated. + /// @param name The name of the field to check. + /// @param forceUpdate Forces an update if true. Defaults to `false`. + /// @return `true` if the field needs updating or `forceUpdate` is true, `false` otherwise. + bool checkForUpdate(const word& name, bool forceUpdate = false); + + /** + * @brief Updates and retrieves a point field of a specified type from the database. + * + * This is a template function that updates and retrieves a point field of type `T` + * from the database. It checks if the field needs to be updated based on the last + * capture time or if a forced update is requested. If an update is necessary, it + * retrieves the latest data for the field. + * + * @tparam T The type of the point field to update and retrieve. Must be a ValidFieldType. + * @param name The name of the field to update. + * @param forceUpdate A boolean flag indicating whether to force an update of the field + * regardless of its current state. Defaults to `false`. + * + * @return A span of `T` representing the updated field data. + * + * @throws message If the field cannot be found in the database or if there is a type mismatch. + */ + template + span updateField(const word& name, bool forceUpdate = false); + + /// @brief Creates a new real field or retrieves an existing one. + /// + /// If a field with the given name already exists, it returns a span to that field. + /// If the field does not exist, it creates a new real field with the given name + /// and returns a span to the newly created field. + /// + /// @param name The name of the field to create or retrieve. + /// @return span of the field + span createOrGetRealField(const word& name); + + /** + * @brief Parses a compound field name to extract the base field name and function. + * + * This function takes a compound field name, which may include a function applied + * to a base field (e.g., "mag(velocity)"), and parses it to extract the base field + * name (e.g., "velocity") and the function to be applied (e.g., `Functions::Magnitude`). + * + * The function supports the following syntax for compound field names: + * - `fieldName` (no function applied) + * - `functionName(fieldName)` + * + * Supported function names are defined in the `Functions` enum. + * + * @param compoundFieldName The compound field name to parse. + * @param fieldName A reference to a `word` where the extracted base field name + * will be stored. + * @param func A reference to a `Functions` enum where the identified function + * will be stored. If no function is applied, this will be set to + * `Functions::None`. + * + * @return `true` if the compound field name was successfully parsed and the base + * field name and function were extracted, `false` otherwise. + * + * @note The function modifies the `fieldName` and `func` parameters to return the + * extracted information. + */ + static + bool findFunction( + const word& compoundFieldName, + word& fieldName, + fieldsDataBase::Functions& func ); + + /** + * @brief Determines the input and output types for a given function. + * + * This function takes a `Functions` enum value and an input type as a string + * and determines the corresponding output type based on the function being applied. + * + * @param func The function for which to determine the input and output types. + * @param inputType The input type as a string. + * @param outputType A reference to a string where the determined output type will be stored. + * + * @return `true` if the input and output types were successfully determined, `false` otherwise. + */ + static + bool inputOutputType( + fieldsDataBase::Functions func, + const word& inputType, + word& outputType); + +public: + + // - constructors + + fieldsDataBase(const Time& time, bool inSimulation); + + /// no copy constructor + fieldsDataBase(const fieldsDataBase&) = delete; + + /// no move constructor + fieldsDataBase(fieldsDataBase&&) = delete; + + /// no copy assignment + fieldsDataBase& operator=(const fieldsDataBase&) = delete; + + /// no move assignment + fieldsDataBase& operator=(fieldsDataBase&&) = delete; + + /// destructor + ~fieldsDataBase() = default; + + // - Public Access Functions + /// returns the current time + timeValue currentTime()const; + + /// const ref to object Time + const Time& time()const + { + return time_; + } + + // - Public Member Functions + + /** + * @brief Retrieves the type of a point field based on its compound name. + * + * This function attempts to extract the type of a point field from its compound name. + * The compound name may include additional information such as a function or operation + * applied to the field, ie. mag(velcoty). If the type is successfully determined, it + * is stored in the provided `typeName` parameter. + * + * @param compoundName The compound name of the field, which may include additional + * information about operations or functions applied to the field. + * @param originalType A reference to a `word` where the original type name is obtained. + * This will be set to the type of the field before any function is applied. + * @param typeAfterFunction A reference to a `word` where the type name after applying + * the function is obtained. + * @param func the applied function to the field. + * + * @return `true` if the type was successfully determined and stored in `typeName`, + * `false` otherwise. + */ + bool getPointFieldType( + const word& compoundName, + word& fieldName, + word& originalType, + word& typeAfterFunction, + Functions& func); + + /// overload for the function getPointFieldType without `func` argument + bool getPointFieldType( + const word& compoundName, + word& originalType, + word& typeAfterFunction); + + /// overload for function getPointFieldType without `originalType` argument + bool getPointFieldType( + const word& compoundName, + word& typeAfterFunction); + + /** + * @brief Updates the points data and returns a span to the updated points. + * + * This function ensures that the points data is up-to-date by checking if an update + * is necessary. If the data is outdated or if a forced update is requested, it retrieves + * the latest points data and stores it in the internal fields database. The function + * then returns a span to the updated points data for further use. + * + * @param forceUpdate A boolean flag indicating whether to force an update of the points + * data regardless of its current state. Defaults to `false`. + * + * @return A span of `realx3` representing the updated points data. + */ + span updatePoints(bool forceUpdate = false); + + /** + * @brief Updates and retrieves a realx3 point field from the database. + * + * This function retrieves or updates a realx3 field based on its compound name. + * The compound name cannot include any function operation. + * If the field needs to be updated or if forceUpdate is true, the method will + * fetch the latest data from the database. + * + * @param compoundName The name of the field, possibly including a function operation + * @param forceUpdate If true, forces an update of the field regardless of its current state. + * Defaults to false. + * + * @return A span containing the updated realx3 field data + * + * @throws message If the field type is not compatible with realx3 or if the field + * cannot be found in the database + */ + span updateFieldRealx3( + const word& compoundName, + bool forceUpdate = false); + + /** + * @brief Updates and retrieves a realx4 point field from the database. + * + * This function retrieves or updates a realx4 field based on its compound name. + * The compound name cannot include any function operation. + * If the field needs to be updated or if forceUpdate is true, the method will + * fetch the latest data from the database. + * + * @param compoundName The name of the field, possibly including a function operation + * @param forceUpdate If true, forces an update of the field regardless of its current state. + * Defaults to false. + * + * @return A span containing the updated realx3 field data + * + * @throws message If the field type is not compatible with realx4 or if the field + * cannot be found in the database + */ + span updateFieldRealx4( + const word& compoundName, + bool forceUpdate = false); + + /** + * @brief Updates and retrieves a real point field from the database. + * + * This function retrieves or updates a real field based on its compound name. + * The compound name may include a function operation (e.g., abs, square, etc.). + * If the field needs to be updated or if forceUpdate is true, the method will + * fetch the latest data from the database and apply the specified function. + * + * Supported functions include: + * - None: Retrieves the field as is. + * - abs: Computes the absolute value of the field. + * - square: Computes the square of the field. + * - cube: Computes the cube of the field. + * - sqrt: Computes the square root of the field. + * - mag, magSquare, magCube, magSqrt: Compute magnitude-related operations for vector fields. + * - component(x, y, z): Extracts a specific component from a vector field. + * + * @param compoundName The name of the field, possibly including a function operation. + * @param forceUpdate If true, forces an update of the field regardless of its current state. + * Defaults to false. + * + * @return A span containing the updated real field data. + * + * @throws message If the field type is not compatible with real or if the field + * cannot be found in the database. + */ + span updateFieldReal( + const word& compoundName, + bool forceUpdate = false); + + span updateFieldUint32( + const word& name, + bool forceUpdate = false); + + /// Updates and retrieves a point field of any type from the database. + /// It returns types real, realx3 and realx4 only. + allPointFieldTypes updateFieldAll( + const word& compoundName, + bool forceUpdate = false); + + const pointStructure& pStruct()const; +}; + +} // nampespace pFlow + +#include "fieldsDataBaseTemplates.cpp" + +#endif //__fieldsDataBased_hpp__ diff --git a/src/PostProcessData/fieldsDataBase/fieldsDataBaseTemplates.cpp b/src/PostProcessData/fieldsDataBase/fieldsDataBaseTemplates.cpp new file mode 100644 index 00000000..888a6136 --- /dev/null +++ b/src/PostProcessData/fieldsDataBase/fieldsDataBaseTemplates.cpp @@ -0,0 +1,80 @@ +/*------------------------------- phasicFlow --------------------------------- + O C enter of + O O E ngineering and + O O M ultiscale modeling of + OOOOOOO F luid flow +------------------------------------------------------------------------------ + Copyright (C): www.cemf.ir + email: hamid.r.norouzi AT gmail.com +------------------------------------------------------------------------------ +Licence: + This file is part of phasicFlow code. It is a free software for simulating + granular and multiphase flows. You can redistribute it and/or modify it under + the terms of GNU General Public License v3 or any other later versions. + + phasicFlow is distributed to help others in their research in the field of + granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +-----------------------------------------------------------------------------*/ + +#ifndef __fieldsDataBaseTemplates_hpp__ +#define __fieldsDataBaseTemplates_hpp__ + +#include "fieldsDataBase.hpp" + +template +inline +pFlow::span pFlow::fieldsDataBase::updateField(const word& name, bool forceUpdate) +{ + + bool shouldUpdate = checkForUpdate(name, forceUpdate); + + if(shouldUpdate) + { + if(name == "one") + { + allFields_.emplaceBackOrReplace> + ( + "one", + FieldTypeHost + ( + "one", + "value", + pointFieldSize(), + T{1} + ) + ); + } + else if( name == "position") + { + if constexpr( std::same_as) + { + return updatePoints(forceUpdate); + } + else + { + fatalErrorInFunction<< "Error in getting the type name of field: "<< + name<<", with type name: "<< getTypeName() <(nullptr, 0); + } + } + else + { + const auto& pField = time_.lookupObject>(name); + allFields_.emplaceBackOrReplace>( + name, + pField.activeValuesHost()); + } + } + + auto& field = allFields_.getObject>(name); + + return span( + field.data(), + field.size()); + +} + +#endif //__fieldsDataBaseTemplates_hpp__ \ No newline at end of file diff --git a/src/PostProcessData/method/GaussianDistribution.hpp b/src/PostProcessData/method/GaussianDistribution.hpp new file mode 100644 index 00000000..53889b76 --- /dev/null +++ b/src/PostProcessData/method/GaussianDistribution.hpp @@ -0,0 +1,107 @@ +/*------------------------------- 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 __GaussianDistribution_hpp__ +#define __GaussianDistribution_hpp__ + +#include + +#include "typeInfo.hpp" +#include "types.hpp" +#include "span.hpp" + + +namespace pFlow +{ + +class GaussianDistribution +{ +private: + + std::vector weight_; + + real variance_ = 1.0; + + realx3 mean_ = {0,0,0}; + +public: + + TypeInfoNV("GaussianDistribution"); + + + GaussianDistribution() = default; + + GaussianDistribution(realx3 mean, real variance) + : + weight_(), + variance_(variance), + mean_(mean) + {} + + GaussianDistribution(const GaussianDistribution&) = default; + + GaussianDistribution(GaussianDistribution&&) = default; + + GaussianDistribution& operator =(const GaussianDistribution&) = default; + + GaussianDistribution& operator = (GaussianDistribution&&) = default; + + ~GaussianDistribution()=default; + + bool updateWeights(const realx3& center, const span& indices, const span& points) + { + weight_.clear(); + weight_.resize(indices.size()); + + real sum = 0.0; + for(uint32 i=0; i getWeights() + { + return span(weight_.data(), weight_.size()); + } + +}; +} // namespace pFlow + +#endif // __GaussianDistribution_hpp__ \ No newline at end of file diff --git a/src/PostProcessData/method/uniformDistribution.hpp b/src/PostProcessData/method/uniformDistribution.hpp new file mode 100644 index 00000000..736d9d2f --- /dev/null +++ b/src/PostProcessData/method/uniformDistribution.hpp @@ -0,0 +1,86 @@ +/*------------------------------- 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 __uniformDistribution_hpp__ +#define __uniformDistribution_hpp__ + +#include "types.hpp" +#include "typeInfo.hpp" +#include "span.hpp" + +namespace pFlow +{ + +class dictionary; + +class uniformDistribution +{ +private: + + std::vector weight_; + +public: + + // type info + TypeInfoNV("uniformDistribution"); + + uniformDistribution() + {} + + uniformDistribution(const uniformDistribution&) = default; + + uniformDistribution(uniformDistribution&&) = default; + + uniformDistribution& operator=(const uniformDistribution&) = default; + + uniformDistribution& operator=(uniformDistribution&&) = default; + + ~uniformDistribution()=default; + + + bool updateWeights(const realx3& center, const span& points) + { + uint32 n = max(points.size(), 1u); + weight_.assign(n, 1.0/n); + return true; + } + + bool updateWeights(uint32 n) + { + n = max(n, 1u); + weight_.assign(n, 1.0/n); + return true; + } + + real getWeight(uint32 i)const + { + return weight_[i]; + } + + span getWeights() + { + return span(weight_.data(), weight_.size()); + } + +}; + +} + +#endif //__uniformDistribution_hpp__ \ No newline at end of file diff --git a/src/PostProcessData/operation/PostprocessOperationSum.cpp b/src/PostProcessData/operation/PostprocessOperationSum.cpp new file mode 100644 index 00000000..259ff951 --- /dev/null +++ b/src/PostProcessData/operation/PostprocessOperationSum.cpp @@ -0,0 +1,69 @@ +#include "PostprocessOperationSum.hpp" +#include "dictionary.hpp" +#include "fieldsDataBase.hpp" +#include "fieldFunctions.hpp" + +pFlow::PostprocessOperationSum::PostprocessOperationSum +( + const dictionary &opDict, + const regionPoints ®Points, + fieldsDataBase &fieldsDB +) +: + postprocessOperation(opDict, regPoints, fieldsDB) +{ + if( fieldType() == getTypeName() ) + { + processedRegField_ = makeUnique( + regionField(processedFieldName(), regPoints, real(0))); + } + else if( fieldType() == getTypeName() ) + { + processedRegField_ = makeUnique( + regionField(processedFieldName(), regPoints, realx3(0))); + } + else if( fieldType() == getTypeName() ) + { + processedRegField_ = makeUnique( + regionField(processedFieldName(), regPoints, realx4(0))); + } + else + { + fatalErrorInFunction<<" in dictionary "<< opDict.globalName() + << " field type is not supported for sum operation" + << " field type is "<< fieldType() + << endl; + fatalExit; + } +} + +bool pFlow::PostprocessOperationSum::execute +( + const std::vector>& weights +) +{ + auto allField = database().updateFieldAll(fieldName()); + auto phi = database().updateFieldReal( + phiFieldName()); + + auto mask = getMask(); + word procName = processedFieldName(); + const auto& regP = regPoints(); + bool dbVol = divideByVolume(); + + + std::visit([&](auto&& field)->processedRegFieldType + { + return executeSumOperation( + procName, + field, + regP, + dbVol, + weights, + phi, + mask); + }, + allField); + + return true; +} diff --git a/src/PostProcessData/operation/PostprocessOperationSum.hpp b/src/PostProcessData/operation/PostprocessOperationSum.hpp new file mode 100644 index 00000000..5e9cb314 --- /dev/null +++ b/src/PostProcessData/operation/PostprocessOperationSum.hpp @@ -0,0 +1,76 @@ +/*------------------------------- 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 __PostprocessOperationSum_hpp__ +#define __PostprocessOperationSum_hpp__ + +#include +#include + +#include "postprocessOperation.hpp" +#include "regionField.hpp" +#include "includeMask.hpp" + +namespace pFlow +{ + + +class PostprocessOperationSum +: + public postprocessOperation +{ +private: + + using processedRegFieldType = std::variant + < + regionField, + regionField, + regionField + >; + + /// Pointer to the include mask used for masking operations. + uniquePtr processedRegField_ = nullptr; + +public: + + TypeInfo("PostprocessOperation"); + + PostprocessOperationSum( + const dictionary& opDict, + const regionPoints& regPoints, + fieldsDataBase& fieldsDB); + + ~PostprocessOperationSum() override = default; + + add_vCtor + ( + postprocessOperation, + PostprocessOperationSum, + dictionary + ); + + bool execute(const std::vector>& weights) override; + +}; + + +} + +#endif //__PostprocessOperation_hpp__ \ No newline at end of file diff --git a/src/PostProcessData/operation/fieldFunctions.hpp b/src/PostProcessData/operation/fieldFunctions.hpp new file mode 100644 index 00000000..8e9d6427 --- /dev/null +++ b/src/PostProcessData/operation/fieldFunctions.hpp @@ -0,0 +1,117 @@ +/*------------------------------- phasicFlow --------------------------------- + O C enter of + O O E ngineering and + O O M ultiscale modeling of + OOOOOOO F luid flow +------------------------------------------------------------------------------ + Copyright (C): www.cemf.ir + email: hamid.r.norouzi AT gmail.com +------------------------------------------------------------------------------ +Licence: + This file is part of phasicFlow code. It is a free software for simulating + granular and multiphase flows. You can redistribute it and/or modify it under + the terms of GNU General Public License v3 or any other later versions. + + phasicFlow is distributed to help others in their research in the field of + granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +-----------------------------------------------------------------------------*/ + +#ifndef __fieldFunctions_hpp__ +#define __fieldFunctions_hpp__ + +#include + +#include "span.hpp" +#include "regionPoints.hpp" +#include "regionField.hpp" +#include "includeMask.hpp" + +namespace pFlow +{ + +template +regionField executeSumOperation +( + const word& regFieldName, + const span& field, + const regionPoints& regPoints, + const bool devideByVol, + const std::vector>& weights, + const span& phi, + const includeMask::Mask& mask +) +{ + regionField processedField(regFieldName, regPoints, T{}); + + for(uint32 reg =0; reg +regionField executeAverageOperation +( + const word& regFieldName, + const span& field, + const regionPoints& regPoints, + const std::vector>& weights, + const span& phi, + const includeMask::Mask& mask +) +{ + regionField processedField(regFieldName, regPoints, T{}); + + for(uint32 reg =0; reg +class IncludeMask +: + public includeMask +{ +public: + + using Mask = typename includeMask::Mask; + +private: + + std::vector mask_; + + Operator operator_; + + word fieldName_; + + timeValue lastUpdated_ = -1; + + bool updateMask() + { + timeValue t = database().currentTime(); + + if( equal( t, lastUpdated_)) return true; + + span s; + if constexpr (std::is_same_v) + { + s = database().updateFieldReal(fieldName_); + } + else if constexpr ( std::is_same_v) + { + s = database().updateFieldRealx3(fieldName_); + } + else if constexpr( std::is_same_v) + { + s = database().updateFieldRealx4(fieldName_); + } + else + { + fatalErrorInFunction<<"Type "<< getTypeName() + <<" is not supported for IncludeMask for field " + << fieldName_ << endl; + return false; + } + + + mask_.resize(s.size()); + + for(uint32 i=0; i("field")) + {} + + add_vCtor( + includeMask, + IncludeMask, + dictionary); + + Mask getMask() override + { + updateMask(); + return Mask(mask_); + } + +}; + + +template +class IncludeMask> +: + public includeMask +{ +public: + + using Mask = typename includeMask::Mask; + +private: + + std::vector mask_; + + timeValue lastUpdated_ = -1; + + bool updateMask() + { + timeValue t = database().currentTime(); + + if( equal( t, lastUpdated_)) return true; + + span s = database().updatePoints(); + mask_.resize(s.size(), true); + + lastUpdated_ = t ; + + return true; + } + +public: + + TypeInfoTemplate12("IncludeMask", T, allOp); + + IncludeMask( + const dictionary& opDict, + fieldsDataBase& feildsDB) + : + includeMask(opDict, feildsDB) + { + span s = database().updatePoints(); + mask_.resize(s.size(), true); + } + + add_vCtor( + includeMask, + IncludeMask, + dictionary); + + Mask getMask()override + { + updateMask(); + return Mask(mask_); + } + +}; + + +} // pFlow + +#endif //__IncludeMask_hpp__ + + diff --git a/src/PostProcessData/operation/includeMask/IncludeMasks.cpp b/src/PostProcessData/operation/includeMask/IncludeMasks.cpp new file mode 100644 index 00000000..8fd6cd3e --- /dev/null +++ b/src/PostProcessData/operation/includeMask/IncludeMasks.cpp @@ -0,0 +1,50 @@ +/*------------------------------- 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 "IncludeMask.hpp" + +// real +template class pFlow::IncludeMask >; +template class pFlow::IncludeMask >; + +template class pFlow::IncludeMask >; +template class pFlow::IncludeMask >; + +template class pFlow::IncludeMask >; + +template class pFlow::IncludeMask >; +template class pFlow::IncludeMask >; + +template class pFlow::IncludeMask>; + +// realx3 +template class pFlow::IncludeMask >; +template class pFlow::IncludeMask >; + +template class pFlow::IncludeMask >; +template class pFlow::IncludeMask >; + +template class pFlow::IncludeMask >; + +template class pFlow::IncludeMask >; +template class pFlow::IncludeMask >; + + +// realx4 diff --git a/src/PostProcessData/operation/includeMask/includeMask.cpp b/src/PostProcessData/operation/includeMask/includeMask.cpp new file mode 100644 index 00000000..a2703b1f --- /dev/null +++ b/src/PostProcessData/operation/includeMask/includeMask.cpp @@ -0,0 +1,91 @@ +/*------------------------------- 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 "includeMask.hpp" +#include "dictionary.hpp" +#include "fieldsDataBase.hpp" + + +pFlow::includeMask::includeMask +( + const dictionary& dict, + fieldsDataBase& fieldDB +) +: + database_(fieldDB) +{} + + +pFlow::uniquePtr pFlow::includeMask::create +( + const dictionary& opDict, + fieldsDataBase& feildsDB +) +{ + word mask = opDict.getValOrSet("includeMask", "all"); + word fieldType; + if( mask != "all") + { + auto& maskDict = opDict.subDict(mask+"Info"); + word maskField = maskDict.getVal("field"); + + if( !feildsDB.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, mask); + + if( dictionaryvCtorSelector_.search(method) ) + { + auto objPtr = + dictionaryvCtorSelector_[method] + (opDict, feildsDB); + 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 new file mode 100644 index 00000000..f277ec7b --- /dev/null +++ b/src/PostProcessData/operation/includeMask/includeMask.hpp @@ -0,0 +1,115 @@ +/*------------------------------- 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 __includeMask_hpp__ +#define __includeMask_hpp__ + +#include + +#include "virtualConstructor.hpp" + +namespace pFlow +{ + + +class fieldsDataBase; +class dictionary; + +class includeMask +{ +public: + + class Mask + { + const std::vector& mask_; + + public: + + Mask(const std::vector& msk) + : + mask_(msk) + {} + + Mask(const Mask&) = default; + + Mask(Mask&&) = default; + + ~Mask()=default; + + auto size()const + { + return mask_.size(); + } + + bool operator()(uint32 i)const + { + return mask_[i]; + } + }; + +private: + + fieldsDataBase& database_; + +public: + + TypeInfo("includeMask"); + + includeMask(const dictionary& opDict, fieldsDataBase& feildsDB); + + virtual ~includeMask() = default; + + create_vCtor + ( + includeMask, + dictionary, + ( + const dictionary& opDict, fieldsDataBase& feildsDB + ), + (opDict, feildsDB) + ); + + const fieldsDataBase& database()const + { + return database_; + } + + fieldsDataBase& database() + { + return database_; + } + + virtual + Mask getMask()= 0; + + static + uniquePtr create( + const dictionary& opDict, + fieldsDataBase& feildsDB); + +}; + + + +} // pFlow + +#endif //__IncludeMask_hpp__ + + diff --git a/src/PostProcessData/operation/includeMask/maskOperations.hpp b/src/PostProcessData/operation/includeMask/maskOperations.hpp new file mode 100644 index 00000000..13fec7d3 --- /dev/null +++ b/src/PostProcessData/operation/includeMask/maskOperations.hpp @@ -0,0 +1,162 @@ + +#ifndef __maskOperation_hpp__ +#define __maskOperation_hpp__ + +#include "types.hpp" +#include "dictionary.hpp" + +namespace pFlow +{ + +template +struct greaterThanOp +{ + TypeInfoNV("greaterThan"); + + inline + bool operator()(const T &compVal, const T &val) const { + return val > compVal; } +}; + +template +struct greaterThanEqOp +{ + TypeInfoNV("greaterThanEq"); + + inline + bool operator()(const T &compVal, const T &val) const { + return val >= compVal; } +}; + +template +struct lessThanOp +{ + TypeInfoNV("lessThan"); + + inline + bool operator()(const T &compVal, const T &val) const { + return val < compVal; } +}; + +template +struct lessThanEqOp +{ + TypeInfoNV("lessThanEq"); + + inline + bool operator()(const T &compVal, const T &val) const { + return val <= compVal; } +}; + +template +struct equalOp +{ + TypeInfoNV("equal"); + + inline + bool operator()(const T &compVal, const T &val) const { + return equal(val , compVal); } +}; + + +template +struct betweenOp +{ + TypeInfoNV("between"); + + inline + bool operator()(const T &compVal1, const T &compVal2 ,const T &val) const { + return val>compVal1 && val +struct betweenEqOp +{ + TypeInfoNV("betweenEq"); + + inline + bool operator()(const T &compVal1, const T &compVal2 ,const T &val) const { + return val>=compVal1 && val<=compVal2; } +}; + +template +struct allOp +{ + TypeInfoNV("all"); + + inline + bool operator()() const {return true; } +}; + + + +template class Operator> +class compareOne +{ +public: + + using opertorType = Operator; + +protected: + T compValue_{}; + opertorType operator_{}; +public: + + TypeInfoNV(Operator::TYPENAME()); + + compareOne(const dictionary& dict) + : + compValue_(dict.getVal("value")) + {} + + bool operator()(const T& value)const + { + return operator_(compValue_, value); + } +}; + +template class Operator> +class compareTwo +{ +public: + using opertorType = Operator; +protected: + T compValue1_; + T compValue2_; + opertorType operator_{}; +public: + + TypeInfoNV(opertorType::TYPENAME()); + + compareTwo(const dictionary& dict) + : + compValue1_(dict.getVal("value1")), + compValue2_(dict.getVal("value2")) + {} + + bool operator()(const T& value)const + { + return operator_(compValue1_, compValue2_, value); + } +}; + +template +class compareZero +{ +protected: + Operator operator_{}; +public: + + TypeInfoNV(Operator::TYPENAME()); + compareZero(const dictionary& dict); + + bool operator()(const T& value) const + { + return operator_(); + } +}; + +} + +#endif //__maskOperation_hpp__ \ No newline at end of file diff --git a/src/PostProcessData/operation/postprocessOperation.cpp b/src/PostProcessData/operation/postprocessOperation.cpp new file mode 100644 index 00000000..c37961c1 --- /dev/null +++ b/src/PostProcessData/operation/postprocessOperation.cpp @@ -0,0 +1,101 @@ +/*------------------------------- 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 "postprocessOperation.hpp" +#include "regionPoints.hpp" +#include "fieldsDataBase.hpp" + +pFlow::postprocessOperation::postprocessOperation +( + const dictionary &opDict, + const regionPoints& regPoints, + fieldsDataBase &fieldsDB +) +: + operationDict_(opDict), + threshold_ + ( + opDict.getValOrSet("threshold", 1) + ), + divideByVolume_ + ( + opDict.getValOrSet("dividedByVolume", Logical(false)) + ), + regionPoints_ + ( + regPoints + ), + database_ + ( + fieldsDB + ), + fieldName_ + ( + opDict.getValOrSet("field", "one") + ), + phiFieldName_ + ( + opDict.getValOrSet("phi", "one") + ), + includeMask_ + ( + includeMask::create(opDict, fieldsDB) + ) +{ + + if(!fieldsDB.getPointFieldType(fieldName_, fieldType_)) + { + fatalErrorInFunction; + fatalExit; + } +} + +pFlow::uniquePtr + pFlow::postprocessOperation::create + ( + const dictionary &opDict, + const regionPoints& regPoints, + fieldsDataBase &fieldsDB + ) +{ + word func = opDict.getVal("function"); + word method = angleBracketsNames("PostprocessOperation", func); + if( dictionaryvCtorSelector_.search(method) ) + { + REPORT(3)<<"Operation "<< Green_Text(opDict.name())<<" with function "<< Green_Text(func)< includeMask_ = nullptr; + +public: + + + TypeInfo("postprocessOperation"); + + postprocessOperation( + const dictionary& opDict, + const regionPoints& regPoints, + fieldsDataBase& fieldsDB ); + + virtual ~postprocessOperation()=default; + + create_vCtor( + postprocessOperation, + dictionary, + ( + const dictionary& opDict, + const regionPoints& regPoints, + fieldsDataBase& fieldsDB + ), + (opDict, regPoints, fieldsDB)); + + const regionPoints& regPoints()const + { + return regionPoints_; + } + + const fieldsDataBase& database()const + { + return database_; + } + + fieldsDataBase& database() + { + return database_; + } + + word processedFieldName()const + { + return operationDict_.name(); + } + + const word& fieldName()const + { + return fieldName_; + } + + const word& fieldType()const + { + return fieldType_; + } + + const word& phiFieldName()const + { + return phiFieldName_; + } + + const dictionary& operationDict()const + { + return operationDict_; + } + const uint32 threshold()const + { + return threshold_; + } + + bool divideByVolume()const + { + return divideByVolume_(); + } + + Mask getMask() + { + return includeMask_().getMask(); + } + + + virtual + bool execute(const std::vector>& weights) = 0; + + static + uniquePtr create( + const dictionary& opDict, + const regionPoints& regPoints, + fieldsDataBase& fieldsDB); + +}; + +} + +#endif //__postprocessOperation_hpp__ \ No newline at end of file diff --git a/src/PostProcessData/postprocessComponent/PostprocessComponent.cpp b/src/PostProcessData/postprocessComponent/PostprocessComponent.cpp new file mode 100644 index 00000000..5720bdaa --- /dev/null +++ b/src/PostProcessData/postprocessComponent/PostprocessComponent.cpp @@ -0,0 +1,109 @@ +#include "PostprocessComponent.hpp" +/*------------------------------- 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. + +-----------------------------------------------------------------------------*/ + +template +pFlow::PostprocessComponent::PostprocessComponent +( + const dictionary& dict, + fieldsDataBase& fieldsDB, + const baseTimeControl& defaultTimeControl +) +: + postprocessComponent(dict, fieldsDB, defaultTimeControl), + regionPointsPtr_ + ( + makeUnique(dict, fieldsDB) + ), + regionsProcessMethod_ + ( + regionPointsPtr_().size() + ), + operationDicts_(readDictList("operations", dict)) +{ + + for(auto& opDict:operationDicts_) + { + operatios_.push_back + ( + postprocessOperation::create + ( + opDict, + regionPointsPtr_(), + this->database() + ) + ); + } +} + + +template +bool pFlow::PostprocessComponent::execute +( + const timeInfo &ti, + bool forceUpdate +) +{ + + if( !timeControl().eventTime(ti)) + { + executed_ = false; + return true; + } + + // update processing methods + + auto centers = this->regPoints().centers(); + const uint32 n = centers.size(); + auto points = this->database().updatePoints(); + + for(uint32 i=0; iregPoints().indices(i); + regionsProcessMethod_[i].updateWeights( + centers[i], + indices, + points); + } + + std::vector> weights(n); + + for(uint32 i=0; iexecute(weights) ) + { + fatalErrorInFunction + <<"error occured in executing operatoin defined in dict " + << op->operationDict() + < + +#include "ListPtr.hpp" +#include "List.hpp" +#include "postprocessComponent.hpp" +#include "postprocessOperation.hpp" +#include "dictionaryList.hpp" +#include "fieldsDataBase.hpp" +#include "regionPoints.hpp" +#include "regionField.hpp" + +namespace pFlow +{ + +template +class PostprocessComponent +: + public postprocessComponent +{ +private: + + + ListPtr operatios_; + + /// Region type for selecting a subset of particles for processing + uniquePtr regionPointsPtr_; + + /// Method for processing the selected particles data + std::vector regionsProcessMethod_; + + bool executed_{false}; + + dictionaryList operationDicts_; + +protected: + + std::vector& regionProecessMethod() + { + return regionsProcessMethod_; + } + +public: + + // type info + TypeInfoTemplate12( + "PostprocessComponent", + RegionType, + ProcessMethodType); + + PostprocessComponent( + const dictionary& dict, + fieldsDataBase& fieldsDB, + const baseTimeControl& defaultTimeControl); + + ~PostprocessComponent() override = default; + + // add the virtual constructor + add_vCtor( + postprocessComponent, + PostprocessComponent, + dictionary + ); + + word name()const override + { + return operationDicts_.parrent().name(); + } + + regionPoints& regPoints() override + { + return static_cast(regionPointsPtr_()); + } + + const regionPoints& regPoints()const override + { + return static_cast(regionPointsPtr_()); + } + + bool execute(const timeInfo& ti, bool forceUpdate = false) override; + + bool executed()const override + { + return executed_; + } + + + +}; + +} + +#include "PostprocessComponent.cpp" + +#endif \ No newline at end of file diff --git a/src/PostProcessData/postprocessComponent/PostprocessComponentGaussian.hpp b/src/PostProcessData/postprocessComponent/PostprocessComponentGaussian.hpp new file mode 100644 index 00000000..d846ddcc --- /dev/null +++ b/src/PostProcessData/postprocessComponent/PostprocessComponentGaussian.hpp @@ -0,0 +1,73 @@ +/*------------------------------- 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 __PostprocessComponentGaussian_hpp__ +#define __PostprocessComponentGaussian_hpp__ + +#include "PostprocessComponent.hpp" +#include "GaussianDistribution.hpp" + +namespace pFlow +{ + +template +class PostprocessComponentGaussian +: + public PostprocessComponent +{ +public: + + /// type info + TypeInfoTemplate12("PostprocessComponent", RegionType, GaussianDistribution); + + PostprocessComponentGaussian + ( + const dictionary& dict, + fieldsDataBase& fieldsDB, + const baseTimeControl& defaultTimeControl + ) + : + PostprocessComponent(dict, fieldsDB, defaultTimeControl) + { + /// initializes the Gaussian distribution for all elements of region + //const uint32 n = this->regPoints().size(); + auto d = this->regPoints().eqDiameters(); + auto c = this->regPoints().centers(); + auto& regs = this->regionProecessMethod(); + const uint32 n = d.size(); + for(uint32 i=0; i; + + diff --git a/src/PostProcessData/postprocessComponent/particleProbePostprocessComponent.cpp b/src/PostProcessData/postprocessComponent/particleProbePostprocessComponent.cpp new file mode 100644 index 00000000..33105c41 --- /dev/null +++ b/src/PostProcessData/postprocessComponent/particleProbePostprocessComponent.cpp @@ -0,0 +1,26 @@ +#include "particleProbePostprocessComponent.hpp" + +pFlow::particleProbePostprocessComponent::particleProbePostprocessComponent +( + const dictionary &dict, + fieldsDataBase &fieldsDB, + const baseTimeControl &defaultTimeControl +) +: + postprocessComponent(dict, fieldsDB, defaultTimeControl), + regionPointsPtr_ + ( + makeUnique(dict, fieldsDB) + ), + name_(dict.name()) +{} + +bool pFlow::particleProbePostprocessComponent::execute +( + const timeInfo &ti, + bool forceExecute +) +{ + + return false; +} diff --git a/src/PostProcessData/postprocessComponent/particleProbePostprocessComponent.hpp b/src/PostProcessData/postprocessComponent/particleProbePostprocessComponent.hpp new file mode 100644 index 00000000..7ceaf893 --- /dev/null +++ b/src/PostProcessData/postprocessComponent/particleProbePostprocessComponent.hpp @@ -0,0 +1,94 @@ +/*------------------------------- 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 __particleProbePostprocessComponent_hpp__ +#define __particleProbePostprocessComponent_hpp__ + +#include "postprocessComponent.hpp" +#include "fieldsDataBase.hpp" +#include "centerPointsRegionPoints.hpp" +#include "regionField.hpp" + +namespace pFlow +{ + +class particleProbePostprocessComponent +: + public postprocessComponent +{ +private: + + using processedRegFieldType = std::variant + < + regionField, + regionField, + regionField + >; + + bool executed_{false}; + + uniquePtr regionPointsPtr_; + + uniquePtr processedField_ = nullptr; + + word name_; + +public: + + TypeInfo("PostprocessComponent"); + + particleProbePostprocessComponent + ( + const dictionary& dict, + fieldsDataBase& fieldsDB, + const baseTimeControl& defaultTimeControl + ); + + ~particleProbePostprocessComponent()override = default; + + + word name()const override + { + return name_; + } + + regionPoints& regPoints() override + { + return regionPointsPtr_(); + } + + + const regionPoints& regPoints() const override + { + return regionPointsPtr_(); + } + + bool execute(const timeInfo& ti, bool forceExecute = false) override; + + bool executed() const override + { + return executed_; + } + +}; + +} + +#endif //__particleProbePostprocessComponent_hpp__ \ No newline at end of file diff --git a/src/PostProcessData/postprocessComponent/postprocessComponent.cpp b/src/PostProcessData/postprocessComponent/postprocessComponent.cpp new file mode 100644 index 00000000..ed2e3b6c --- /dev/null +++ b/src/PostProcessData/postprocessComponent/postprocessComponent.cpp @@ -0,0 +1,55 @@ +#include "postprocessComponent.hpp" +#include "fieldsDataBase.hpp" +#include "Time.hpp" + + +pFlow::postprocessComponent::postprocessComponent +( + const dictionary &dict, + fieldsDataBase &fieldsDB, + const baseTimeControl &defaultTimeControl +) +: + timeControl_( + dict, + defaultTimeControl, + baseTimeControl( + fieldsDB.time().startTime(), + fieldsDB.time().endTime(), + fieldsDB.time().saveInterval()) + ), + fieldsDataBase_(fieldsDB) +{ +} + + +pFlow::uniquePtr pFlow::postprocessComponent::create +( + const dictionary& dict, + fieldsDataBase& fieldsDB, + const baseTimeControl& defaultTimeControl +) +{ + word method = dict.getVal("processMethod"); + word region = dict.getVal("processRegion"); + + auto compModel = angleBracketsNames2("PostprocessComponent", region, method); + + if( dictionaryvCtorSelector_.search(compModel) ) + { + REPORT(2)<<"Creating postprocess component "<< Green_Text(compModel)<<" ..."< create( + const dictionary& dict, + fieldsDataBase& fieldsDB, + const baseTimeControl& defaultTimeControl); + +}; + +} // namespace pFlow + +#endif // __postprocessComponent_hpp__ \ No newline at end of file diff --git a/src/PostProcessData/postprocessData.cpp b/src/PostProcessData/postprocessData.cpp new file mode 100644 index 00000000..359fa893 --- /dev/null +++ b/src/PostProcessData/postprocessData.cpp @@ -0,0 +1,99 @@ + +/*------------------------------- 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 "List.hpp" +#include "systemControl.hpp" +#include "postprocessData.hpp" +#include "fileDictionary.hpp" +#include "postprocessComponent.hpp" + +pFlow::postprocessData::postprocessData(const systemControl &control) +: + auxFunctions(control), + time_(control.time()), + fieldsDataBase_(control.time(), true), + dict_ + ( + objectFile + ( + "postprocessDataDict", + control.settings().path(), + objectFile::READ_IF_PRESENT, + objectFile::WRITE_NEVER + ) + ), + componentsDicts_(readDictList("components", dict_)) +{ + // if dictionary is not provided, no extra action is required. + if( !dict_.fileExist() ) + { + return; + } + + activeInSimulation_ = dict_.getValOrSet( + "activeInSimulation", + Logical{true}); + + if(dict_.containsDictionay("defaultTimeControl")) + { + defaultTimeControlPtr_ = + makeUnique( + dict_.subDict("defaultTimeControl"), + "execution"); + } + else + { + // default time control from settings + defaultTimeControlPtr_ = makeUnique( + control.time().startTime(), + control.time().endTime(), + control.time().saveInterval(), + "execution"); + } + + for(auto& compDict:componentsDicts_) + { + postprocesses_.push_back( postprocessComponent::create( + compDict, + fieldsDataBase_, + defaultTimeControlPtr_() )); + } + +} + +bool pFlow::postprocessData::execute() +{ + + const auto& ti = time_.TimeInfo(); + + for(auto& component:postprocesses_) + { + if(!component->execute(ti)) + { + fatalErrorInFunction + <<"Error occured in executing postprocess component: " + <name()< postprocesses_; + + /// const ref to Time + const Time& time_; + + /// Database for all the points fields on the host + fieldsDataBase fieldsDataBase_; + + /// file dictionary that is constructed from the file (postProcessDataDict) + fileDictionary dict_; + + /// list of dictionaries for postprocess components + dictionaryList componentsDicts_; + + /// @brief default time control that can be used for all post-process components + uniquePtr defaultTimeControlPtr_= nullptr; + +public: + + TypeInfo("postprocessData"); + + /// @brief Construct from systemControl and a boolean flag + /// this constructor is used when postprocesing is active + /// during simulation. + /// @param control const reference to systemControl + postprocessData(const systemControl& control); + + ~postprocessData()override = default; + + add_vCtor + ( + auxFunctions, + postprocessData, + systemControl + ); + + bool execute() override; + + + + bool wirte()const override + { + return false; + } + +}; + +} // namespace pFlow + +#endif // __postprocessData_hpp__ \ No newline at end of file diff --git a/src/PostProcessData/postprocessDataDict b/src/PostProcessData/postprocessDataDict new file mode 100755 index 00000000..8fed2b42 --- /dev/null +++ b/src/PostProcessData/postprocessDataDict @@ -0,0 +1,108 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ +objectName processDataDict; +objectType dictionary;; +fileFormat ASCII; +/*---------------------------------------------------------------------------*/ + +runTimeActive yes; + +defaultTimeControl +{ + timeControl; + startTime; + endTime; + actionInterval 0.05; +} + +components +( + velocityProb + { + method particleProbe; + region idSelecttion; + field velocity; + ids (0 10 100); + timeControl timeStep; + startTime 0; + endTime infinity; + probInterval 1; + } + + 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; + } + } + ); + } + + comp3 + { + + region line; + lineInfo + { + p1 (); + p2 (); + numPoints 10; + radius 0.01; + } + timeControl settingsDict; //default; + type numberBased; + operations(); + } + + 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; + + } + ); + } +); diff --git a/src/PostProcessData/postprocessTimeControl.hpp b/src/PostProcessData/postprocessTimeControl.hpp new file mode 100644 index 00000000..f70cfd2a --- /dev/null +++ b/src/PostProcessData/postprocessTimeControl.hpp @@ -0,0 +1,65 @@ +/*------------------------------- 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 __postprocessTimeControl_hpp__ +#define __postprocessTimeControl_hpp__ + +#include "baseTimeControl.hpp" + +namespace pFlow +{ +class postprocessTimeControl +: + public baseTimeControl +{ +public: +postprocessTimeControl( + const dictionary& dict, + const baseTimeControl& defaultTimeControl, + const baseTimeControl& settingTimeControl + ) + : + baseTimeControl(0, 1, 1) + { + auto tControl = dict.getValOrSet("timeControl", "default"); + if(tControl == "default") + { + baseTimeControl::operator=( + defaultTimeControl + ); + } + else if(tControl == "settingsDict") + { + baseTimeControl::operator=( + settingTimeControl + ); + } + else + { + baseTimeControl::operator=( baseTimeControl(dict, "execution") ); + } + } + + // Additional methods and members can be added here +}; + +} // namespace pFlow + +#endif // __postprocessTimeControl_hpp__ \ No newline at end of file diff --git a/src/PostProcessData/region/regionFields.hpp/regionField.hpp b/src/PostProcessData/region/regionFields.hpp/regionField.hpp new file mode 100644 index 00000000..559f854f --- /dev/null +++ b/src/PostProcessData/region/regionFields.hpp/regionField.hpp @@ -0,0 +1,95 @@ +/*------------------------------- 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 __regionField_hpp__ +#define __regionField_hpp__ + +#include "types.hpp" +#include "regionPoints.hpp" +#include "Field.hpp" + +namespace pFlow +{ + +template +class regionField +{ +private: + + /// the field value + Field field_; + + /// the region points + const regionPoints& regionPoints_; +public: + + TypeInfoTemplateNV11("regionField", T); + + regionField( + const word& name, + const regionPoints& rPoints, + const T defaultVal); + + regionField(const regionField&) = default; + + regionField(regionField&&) = default; + + regionField& operator=(const regionField&) = default; + + regionField& operator=(regionField&&) = default; + + ~regionField() = default; + + /// get the field value + T& operator[] (const uint32 i) + { + return field_[i]; + } + + /// get the field value + const T& operator[] (const uint32 i)const + { + return field_[i]; + } + + /// get field name + word name()const + { + return field_.name(); + } + + /// @brief write the field to a file + /// @param os output file stream + /// @return true if successful and false if fails + bool writeFieldToFile(iOstream& os)const; + + /// @brief write the field to vtk format (cell based) + /// @param os output file stream + /// @return true if successful and false if fails + bool writeFieldToVtk(iOstream& os)const; + +}; + + +} // namespace pFlow + +#include "regionFieldTemplate.cpp" + +#endif // __regionField_hpp__ \ No newline at end of file diff --git a/src/PostProcessData/region/regionFields.hpp/regionFieldTemplate.cpp b/src/PostProcessData/region/regionFields.hpp/regionFieldTemplate.cpp new file mode 100644 index 00000000..65112474 --- /dev/null +++ b/src/PostProcessData/region/regionFields.hpp/regionFieldTemplate.cpp @@ -0,0 +1,10 @@ + +template +pFlow::regionField::regionField( + const word& name, + const regionPoints& rPoints, + const T defaultVal) +: + field_(name, "regionFieldValue", rPoints.size(), rPoints.size(), defaultVal), + regionPoints_(rPoints) +{} \ No newline at end of file diff --git a/src/PostProcessData/region/regionPoints/centerPointsRegionPoints.cpp b/src/PostProcessData/region/regionPoints/centerPointsRegionPoints.cpp new file mode 100644 index 00000000..2595ca14 --- /dev/null +++ b/src/PostProcessData/region/regionPoints/centerPointsRegionPoints.cpp @@ -0,0 +1,86 @@ +#include "centerPointsRegionPoints.hpp" +#include "fieldsDataBase.hpp" +#include "Set.hpp" +#include "pStructSelector.hpp" + +bool pFlow::centerPointsRegionPoints::selectIds() +{ + if(!firstTimeUpdate_) return true; + firstTimeUpdate_ = false; + + word selector = probDict_.getVal("selector"); + + if(selector == "id") + { + auto idList = probDict_.getVal("ids"); + Set uniqueIds; + + uniqueIds.insert(idList.begin(), idList.end()); + + for(auto& id:uniqueIds) + { + ids_.push_back(id); + } + } + else + { + auto selectorPtr = pStructSelector::create( + selector, + database().pStruct(), + probDict_); + auto selectedPoints = selectorPtr->selectedPoints(); + ids_.resize(selectedPoints.size()); + ids_.assign(selectedPoints.begin(), selectedPoints.end()); + } + + volume_.resize(ids_.size(),1.0); + diameter_.resize(ids_.size(),1.0); + center_.resize(ids_.size(), realx3(0,0,0)); + selectedPoints_.resize(ids_.size(), -1); + return false; +} + +pFlow::centerPointsRegionPoints::centerPointsRegionPoints( + const dictionary &dict, + fieldsDataBase &fieldsDataBase) + : regionPoints(dict, fieldsDataBase), + idName_(dict.getValOrSet("idName", "id")), + probDict_(dict) +{ + auto idList = dict.getVal("ids"); + Set uniqueIds; + + uniqueIds.insert(idList.begin(), idList.end()); + + for(auto& id:uniqueIds) + { + ids_.push_back(id); + } + + selectedPoints_.resize(ids_.size()); +} + +bool pFlow::centerPointsRegionPoints::update() +{ + if(!selectIds()) return false; + + if(ids_.empty()) return true; + + 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) + { + if(idField[i] == ids_[j]) + { + selectedPoints_[j] = i; + break; + } + } + } + + return false; +} + diff --git a/src/PostProcessData/region/regionPoints/centerPointsRegionPoints.hpp b/src/PostProcessData/region/regionPoints/centerPointsRegionPoints.hpp new file mode 100644 index 00000000..b80a3442 --- /dev/null +++ b/src/PostProcessData/region/regionPoints/centerPointsRegionPoints.hpp @@ -0,0 +1,116 @@ +/*------------------------------- 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 __centerPointsRegionPoints_hpp__ +#define __centerPointsRegionPoints_hpp__ + +#include "regionPoints.hpp" + +namespace pFlow +{ + +class centerPointsRegionPoints +: + public regionPoints +{ +private: + + bool firstTimeUpdate_ = true; + + /// the ids provided in the dictionary + uint32Vector ids_; + + /// the volume of region + realVector volume_ {"volume"}; + + realVector diameter_{"diameter"}; + /// center point of the region + /// this is not used in the idSelection region + realx3Vector center_ {"center"}; + + /// the point indices that are selected by this region + uint32Vector selectedPoints_{"selectedPoints"}; + + /// the name of the id field + word idName_= "id"; + + /// keeps the dictionary for first update use + dictionary probDict_; + + + bool selectIds(); + +public: + + TypeInfo("centerPoints"); + + centerPointsRegionPoints( + const dictionary& dict, + fieldsDataBase& fieldsDataBase); + + ~centerPointsRegionPoints() override = default; + + uint32 size()const override + { + return selectedPoints_.size(); + } + + bool empty()const override + { + return selectedPoints_.empty(); + } + + span volumes()const override + { + return span(volume_.data(), volume_.size()); + } + + span eqDiameters()const override + { + return span(diameter_.data(), diameter_.size()); + } + + span centers()const override + { + return span(center_.data(), center_.size()); + } + + span indices(uint32 elem)const override + { + return span(selectedPoints_.data(), selectedPoints_.size()); + } + + 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 + bool update() override; + + +}; // class centerPointsRegionPoints + +} // namespace pFlow + + + +#endif // __centerPointsRegionPoints_hpp__ \ No newline at end of file diff --git a/src/PostProcessData/region/regionPoints/lineRegionPoints.cpp b/src/PostProcessData/region/regionPoints/lineRegionPoints.cpp new file mode 100644 index 00000000..955e74bf --- /dev/null +++ b/src/PostProcessData/region/regionPoints/lineRegionPoints.cpp @@ -0,0 +1,83 @@ +#include "lineRegionPoints.hpp" +#include "fieldsDataBase.hpp" + +pFlow::lineRegionPoints::lineRegionPoints +( + const dictionary &dict, + fieldsDataBase &fieldsDataBase +) +: + regionPoints(dict, fieldsDataBase), + line_(dict.subDict("lineInfo")), + centerPoints_("centerPoints"), + volumes_("volumes"), + selectedPoints_("selectedPoints") +{ + const auto& lDict = dict.subDict("lineInfo"); + uint32 nPoints = lDict.getValMax("numPoints",2); + realList raddi; + + if( lDict.containsDataEntry("radii")) + { + raddi = lDict.getVal("radii"); + } + else + { + auto r = lDict.getVal("radius"); + raddi = realList(nPoints, r); + } + + 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()) + { + fatalErrorInFunction + << "The element index is out of range. elem: " << elem + << " size: " << size() << endl; + fatalExit; + } + + return span(selectedPoints_[elem].data(), selectedPoints_[elem].size()); +} + +bool pFlow::lineRegionPoints::update() +{ + const auto points = database().updatePoints(); + for(auto& elem:selectedPoints_) + { + elem.clear(); + } + + for(uint32 i = 0; i < points.size(); ++i) + { + for(uint32 j = 0; j < sphereRegions_.size(); ++j) + { + if( sphereRegions_[j].isInside(points[i])) + { + selectedPoints_[j].push_back(i); + } + } + } + return true; +} diff --git a/src/PostProcessData/region/regionPoints/lineRegionPoints.hpp b/src/PostProcessData/region/regionPoints/lineRegionPoints.hpp new file mode 100644 index 00000000..045eab39 --- /dev/null +++ b/src/PostProcessData/region/regionPoints/lineRegionPoints.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 __lineRegionPoints_hpp__ +#define __lineRegionPoints_hpp__ + +#include "regionPoints.hpp" +#include "line.hpp" +#include "sphere.hpp" +#include "Vectors.hpp" + +namespace pFlow +{ + +class lineRegionPoints +: + public regionPoints +{ +private: + + /// line region for selecting points + line line_; + + /// all sphere regions + Vector sphereRegions_; + + /// center poitns of regions/elements + realx3Vector centerPoints_; + + /// volumes of all elements/regions + realVector volumes_; + + realVector diameters_; + + /// the point indices that are selected by this region + Vector selectedPoints_; + +public: + + TypeInfo(line::TYPENAME()); + + lineRegionPoints( + const dictionary& dict, + fieldsDataBase& fieldsDataBase); + + ~lineRegionPoints() override = default; + + uint32 size()const override + { + return sphereRegions_.size(); + } + + bool empty()const override + { + return sphereRegions_.empty(); + } + + span volumes()const override + { + return span(volumes_.data(), volumes_.size()); + } + + span eqDiameters()const override + { + return span(diameters_.data(), diameters_.size()); + } + + span centers()const override + { + return span(centerPoints_.data(), centerPoints_.size()); + } + + span indices(uint32 elem)const override; + + + bool update() override; + +}; + +} + + +#endif // __lineRegionPoints_hpp__ \ No newline at end of file diff --git a/src/PostProcessData/region/regionPoints/regionPoints.cpp b/src/PostProcessData/region/regionPoints/regionPoints.cpp new file mode 100644 index 00000000..20599503 --- /dev/null +++ b/src/PostProcessData/region/regionPoints/regionPoints.cpp @@ -0,0 +1,28 @@ +#include "regionPoints.hpp" +#include "fieldsDataBase.hpp" +#include "Time.hpp" + +pFlow::regionPoints::regionPoints +( + const dictionary &dict, + fieldsDataBase &fieldsDataBase +) +: + fieldsDataBase_(fieldsDataBase) +{} + +const pFlow::Time& pFlow::regionPoints::time() const +{ + return fieldsDataBase_.time(); +} + +const pFlow::fieldsDataBase & pFlow::regionPoints::database() const +{ + return fieldsDataBase_; +} + +pFlow::fieldsDataBase& pFlow::regionPoints::database() +{ + return fieldsDataBase_; +} + diff --git a/src/PostProcessData/region/regionPoints/regionPoints.hpp b/src/PostProcessData/region/regionPoints/regionPoints.hpp new file mode 100644 index 00000000..353f73cb --- /dev/null +++ b/src/PostProcessData/region/regionPoints/regionPoints.hpp @@ -0,0 +1,103 @@ +/*------------------------------- 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 __regionPoints_hpp__ +#define __regionPoints_hpp__ + +#include "dictionary.hpp" +#include "pointStructure.hpp" + + +namespace pFlow +{ + +class fieldsDataBase; +class Time; + +class regionPoints +{ + using PointsTypeHost = typename pointStructure::PointsTypeHost; + + fieldsDataBase& fieldsDataBase_; + +public: + + TypeInfo("regionPoints"); + + + regionPoints( + const dictionary& dict, + fieldsDataBase& fieldsDataBase); + + virtual ~regionPoints() = default; + + const Time& time()const; + + const fieldsDataBase& database()const; + + fieldsDataBase& database(); + + /// @brief size of elements + virtual + uint32 size()const = 0; + + /// @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;*/ + + + /// @brief volume of elements + /// @return sapn for accessing the volume of elements + virtual + span volumes()const =0; + + virtual + span eqDiameters()const = 0; + + /// center points of elements + virtual + span centers()const = 0; + + /// indices of particles inside the element @var elem + virtual + span indices(uint32 elem)const = 0; + + virtual + span indices(uint32 elem) = 0; + + virtual + bool update() = 0; + + /*virtual + bool write()const=0;*/ + + /*static + uniquePtr create( + const dictionary& dict, + fieldsDataBase& fieldsDataBase);*/ + +}; + +} + +#endif // __regionPoints_hpp__ \ No newline at end of file diff --git a/src/PostProcessData/region/regionPoints/sphereRegionPoints.cpp b/src/PostProcessData/region/regionPoints/sphereRegionPoints.cpp new file mode 100644 index 00000000..566fd688 --- /dev/null +++ b/src/PostProcessData/region/regionPoints/sphereRegionPoints.cpp @@ -0,0 +1,31 @@ +#include "sphereRegionPoints.hpp" +#include "fieldsDataBase.hpp" + +pFlow::sphereRegionPoints::sphereRegionPoints +( + const dictionary &dict, + fieldsDataBase &fieldsDataBase +) +: + regionPoints(dict, fieldsDataBase), + sphereRegion_(dict.subDict("sphereInfo")), + volume_(sphereRegion_.volume()), + diameter_(2*sphereRegion_.radius()), + selectedPoints_("selectedPoints") +{ +} + +bool pFlow::sphereRegionPoints::update() +{ + const auto points = database().updatePoints(); + selectedPoints_.clear(); + for(uint32 i = 0; i < points.size(); ++i) + { + if( sphereRegion_.isInside(points[i])) + { + selectedPoints_.push_back(i); + } + } + + return false; +} diff --git a/src/PostProcessData/region/regionPoints/sphereRegionPoints.hpp b/src/PostProcessData/region/regionPoints/sphereRegionPoints.hpp new file mode 100644 index 00000000..a8ec481f --- /dev/null +++ b/src/PostProcessData/region/regionPoints/sphereRegionPoints.hpp @@ -0,0 +1,98 @@ +/*------------------------------- 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 __sphereRegionPoints_hpp__ +#define __sphereRegionPoints_hpp__ + +#include "regionPoints.hpp" +#include "sphere.hpp" +#include "Vectors.hpp" + +namespace pFlow +{ +class sphereRegionPoints +: + public regionPoints +{ +private: + + /// spehre region for selecting points + sphere sphereRegion_; + + /// the volume of region + real volume_; + + real diameter_; + + /// the point indices that are selected by this region + uint32Vector selectedPoints_; + +public: + + TypeInfo(sphere::TYPENAME()); + + sphereRegionPoints( + const dictionary& dict, + fieldsDataBase& fieldsDataBase); + + ~sphereRegionPoints() override = default; + + uint32 size()const override + { + return 1; + } + + bool empty()const override + { + return false; + } + + span volumes()const override + { + return span(&volume_, 1); + } + + span eqDiameters()const override + { + return span(&diameter_, 1); + } + + span centers()const override + { + return span(&sphereRegion_.center(), 1); + } + + span indices(uint32 elem)const override + { + return span(selectedPoints_.data(), selectedPoints_.size()); + } + + span indices(uint32 elem) override + { + return span(selectedPoints_.data(), selectedPoints_.size()); + } + + bool update()override; + +}; + +} + +#endif // __sphereRegionPoints_hpp__ \ No newline at end of file From 162cfd3b6ab7093940e729e5a50a400d9c7097bb Mon Sep 17 00:00:00 2001 From: Hamidreza Date: Thu, 10 Apr 2025 21:16:31 +0330 Subject: [PATCH 2/9] The main structure is tested. functons like execute and write are added and tested. other components are left --- src/PostProcessData/CMakeLists.txt | 35 ----- .../particleProbePostprocessComponent.cpp | 26 ---- src/PostprocessData/CMakeLists.txt | 30 ++++ .../fieldsDataBase/fieldFunctions.hpp | 0 .../fieldsDataBase/fieldsDataBase.cpp | 42 ++--- .../fieldsDataBase/fieldsDataBase.hpp | 0 .../fieldsDataBaseTemplates.cpp | 0 .../PostprocessOperationSum.cpp | 28 ++-- .../PostprocessOperationSum.hpp | 14 +- .../PostprocessOperation}/fieldFunctions.hpp | 7 +- .../operation/includeMask/IncludeMask.hpp | 0 .../operation/includeMask/IncludeMasks.cpp | 0 .../operation/includeMask/includeMask.cpp | 0 .../operation/includeMask/includeMask.hpp | 0 .../operation/includeMask/maskOperations.hpp | 0 .../postprocessOperation.cpp | 104 ++++++++++++- .../postprocessOperation.hpp | 28 +++- .../PostprocessComponent.cpp | 57 ++++++- .../PostprocessComponent.hpp | 4 +- .../PostprocessComponentArithmetic.hpp | 73 +++++++++ .../PostprocessComponentGaussian.hpp | 0 .../PostprocessComponentUniform.hpp | 73 +++++++++ .../PostprocessComponents.cpp | 9 +- .../particleProbePostprocessComponent.cpp | 147 ++++++++++++++++++ .../particleProbePostprocessComponent.hpp | 15 +- .../postprocessComponent.cpp | 0 .../postprocessComponent.hpp | 3 + .../postprocessData}/postprocessData.cpp | 25 ++- .../postprocessData}/postprocessData.hpp | 6 +- .../postprocessData/postprocessGlobals.hpp | 35 +++++ .../postprocessTimeControl.hpp | 0 .../processMethod}/GaussianDistribution.hpp | 0 .../processMethod/arithmetic.hpp | 91 +++++++++++ .../processMethod}/uniformDistribution.hpp | 13 +- .../region/regionFields}/regionField.hpp | 15 ++ .../regionFields}/regionFieldTemplate.cpp | 0 .../centerPointsRegionPoints.cpp | 39 +++-- .../centerPointsRegionPoints.hpp | 6 + .../lineRegionPoints}/lineRegionPoints.cpp | 17 ++ .../lineRegionPoints}/lineRegionPoints.hpp | 6 + .../regionPoints/regionPoints.cpp | 0 .../regionPoints/regionPoints.hpp | 8 +- .../sphereRegionPoints.cpp | 12 +- .../sphereRegionPoints.hpp | 7 + .../sampleDictionary}/postprocessDataDict | 0 45 files changed, 821 insertions(+), 154 deletions(-) delete mode 100644 src/PostProcessData/CMakeLists.txt delete mode 100644 src/PostProcessData/postprocessComponent/particleProbePostprocessComponent.cpp create mode 100644 src/PostprocessData/CMakeLists.txt rename src/{PostProcessData => PostprocessData}/fieldsDataBase/fieldFunctions.hpp (100%) rename src/{PostProcessData => PostprocessData}/fieldsDataBase/fieldsDataBase.cpp (95%) rename src/{PostProcessData => PostprocessData}/fieldsDataBase/fieldsDataBase.hpp (100%) rename src/{PostProcessData => PostprocessData}/fieldsDataBase/fieldsDataBaseTemplates.cpp (100%) rename src/{PostProcessData/operation => PostprocessData/operation/PostprocessOperation}/PostprocessOperationSum.cpp (79%) rename src/{PostProcessData/operation => PostprocessData/operation/PostprocessOperation}/PostprocessOperationSum.hpp (92%) rename src/{PostProcessData/operation => PostprocessData/operation/PostprocessOperation}/fieldFunctions.hpp (96%) rename src/{PostProcessData => PostprocessData}/operation/includeMask/IncludeMask.hpp (100%) rename src/{PostProcessData => PostprocessData}/operation/includeMask/IncludeMasks.cpp (100%) rename src/{PostProcessData => PostprocessData}/operation/includeMask/includeMask.cpp (100%) rename src/{PostProcessData => PostprocessData}/operation/includeMask/includeMask.hpp (100%) rename src/{PostProcessData => PostprocessData}/operation/includeMask/maskOperations.hpp (100%) rename src/{PostProcessData/operation => PostprocessData/operation/postprocessOperation}/postprocessOperation.cpp (53%) rename src/{PostProcessData/operation => PostprocessData/operation/postprocessOperation}/postprocessOperation.hpp (88%) rename src/{PostProcessData/postprocessComponent => PostprocessData/postprocessComponent/PostprocessComponent}/PostprocessComponent.cpp (68%) rename src/{PostProcessData/postprocessComponent => PostprocessData/postprocessComponent/PostprocessComponent}/PostprocessComponent.hpp (98%) create mode 100644 src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponentArithmetic.hpp rename src/{PostProcessData/postprocessComponent => PostprocessData/postprocessComponent/PostprocessComponent}/PostprocessComponentGaussian.hpp (100%) create mode 100644 src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponentUniform.hpp rename src/{PostProcessData/postprocessComponent => PostprocessData/postprocessComponent/PostprocessComponent}/PostprocessComponents.cpp (82%) create mode 100644 src/PostprocessData/postprocessComponent/particleProbePostprocessComponent/particleProbePostprocessComponent.cpp rename src/{PostProcessData/postprocessComponent => PostprocessData/postprocessComponent/particleProbePostprocessComponent}/particleProbePostprocessComponent.hpp (88%) rename src/{PostProcessData => PostprocessData/postprocessComponent}/postprocessComponent/postprocessComponent.cpp (100%) rename src/{PostProcessData => PostprocessData/postprocessComponent}/postprocessComponent/postprocessComponent.hpp (97%) rename src/{PostProcessData => PostprocessData/postprocessData}/postprocessData.cpp (83%) rename src/{PostProcessData => PostprocessData/postprocessData}/postprocessData.hpp (97%) create mode 100644 src/PostprocessData/postprocessData/postprocessGlobals.hpp rename src/{PostProcessData => PostprocessData/postprocessData}/postprocessTimeControl.hpp (100%) rename src/{PostProcessData/method => PostprocessData/processMethod}/GaussianDistribution.hpp (100%) create mode 100644 src/PostprocessData/processMethod/arithmetic.hpp rename src/{PostProcessData/method => PostprocessData/processMethod}/uniformDistribution.hpp (90%) rename src/{PostProcessData/region/regionFields.hpp => PostprocessData/region/regionFields}/regionField.hpp (92%) rename src/{PostProcessData/region/regionFields.hpp => PostprocessData/region/regionFields}/regionFieldTemplate.cpp (100%) rename src/{PostProcessData/region/regionPoints => PostprocessData/region/regionPoints/centerPointsRegionPoints}/centerPointsRegionPoints.cpp (79%) rename src/{PostProcessData/region/regionPoints => PostprocessData/region/regionPoints/centerPointsRegionPoints}/centerPointsRegionPoints.hpp (96%) rename src/{PostProcessData/region/regionPoints => PostprocessData/region/regionPoints/lineRegionPoints}/lineRegionPoints.cpp (82%) rename src/{PostProcessData/region/regionPoints => PostprocessData/region/regionPoints/lineRegionPoints}/lineRegionPoints.hpp (95%) rename src/{PostProcessData/region => PostprocessData/region/regionPoints}/regionPoints/regionPoints.cpp (100%) rename src/{PostProcessData/region => PostprocessData/region/regionPoints}/regionPoints/regionPoints.hpp (95%) rename src/{PostProcessData/region/regionPoints => PostprocessData/region/regionPoints/sphereRegionPoints}/sphereRegionPoints.cpp (71%) rename src/{PostProcessData/region/regionPoints => PostprocessData/region/regionPoints/sphereRegionPoints}/sphereRegionPoints.hpp (95%) rename src/{PostProcessData => PostprocessData/sampleDictionary}/postprocessDataDict (100%) diff --git a/src/PostProcessData/CMakeLists.txt b/src/PostProcessData/CMakeLists.txt deleted file mode 100644 index e5a624a8..00000000 --- a/src/PostProcessData/CMakeLists.txt +++ /dev/null @@ -1,35 +0,0 @@ - -set(SourceFiles -fieldsDataBase/fieldsDataBase.cpp - -postprocessComponent/postprocessComponent.cpp -postprocessComponent/PostprocessComponents.cpp - -operation/postprocessOperation.cpp -operation/PostprocessOperationSum.cpp - - -postprocessData.cpp - -postprocessComponent/postprocessComponent.cpp -postprocessComponent/PostprocessComponents.cpp -postprocessComponent/particleProbePostprocessComponent.cpp - -operation/includeMask/includeMask.cpp -operation/includeMask/IncludeMasks.cpp -operation/postprocessOperation.cpp -operation/PostprocessOperationSum.cpp - -region/regionPoints/sphereRegionPoints.cpp -region/regionPoints/regionPoints.cpp -region/regionPoints/lineRegionPoints.cpp -region/regionPoints/centerPointsRegionPoints.cpp - -) - -set(link_libs Kokkos::kokkos phasicFlow Particles) - -pFlow_add_library_install(PostProcessData SourceFiles link_libs) - -add_subdirectory(testPostprocess) - diff --git a/src/PostProcessData/postprocessComponent/particleProbePostprocessComponent.cpp b/src/PostProcessData/postprocessComponent/particleProbePostprocessComponent.cpp deleted file mode 100644 index 33105c41..00000000 --- a/src/PostProcessData/postprocessComponent/particleProbePostprocessComponent.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "particleProbePostprocessComponent.hpp" - -pFlow::particleProbePostprocessComponent::particleProbePostprocessComponent -( - const dictionary &dict, - fieldsDataBase &fieldsDB, - const baseTimeControl &defaultTimeControl -) -: - postprocessComponent(dict, fieldsDB, defaultTimeControl), - regionPointsPtr_ - ( - makeUnique(dict, fieldsDB) - ), - name_(dict.name()) -{} - -bool pFlow::particleProbePostprocessComponent::execute -( - const timeInfo &ti, - bool forceExecute -) -{ - - return false; -} diff --git a/src/PostprocessData/CMakeLists.txt b/src/PostprocessData/CMakeLists.txt new file mode 100644 index 00000000..2c15a7c4 --- /dev/null +++ b/src/PostprocessData/CMakeLists.txt @@ -0,0 +1,30 @@ +set(SourceFiles + # Main postprocess data + postprocessData/postprocessData.cpp + + # Fields database + fieldsDataBase/fieldsDataBase.cpp + + # Regions + region/regionPoints/regionPoints/regionPoints.cpp + region/regionPoints/sphereRegionPoints/sphereRegionPoints.cpp + region/regionPoints/lineRegionPoints/lineRegionPoints.cpp + region/regionPoints/centerPointsRegionPoints/centerPointsRegionPoints.cpp + + # Postprocess components + postprocessComponent/postprocessComponent/postprocessComponent.cpp + postprocessComponent/particleProbePostprocessComponent/particleProbePostprocessComponent.cpp + postprocessComponent/PostprocessComponent/PostprocessComponents.cpp + + # Operations + operation/postprocessOperation/postprocessOperation.cpp + operation/PostprocessOperation/PostprocessOperationSum.cpp + operation/includeMask/includeMask.cpp + operation/includeMask/IncludeMasks.cpp + + +) + +set(link_libs Kokkos::kokkos phasicFlow Particles) + +pFlow_add_library_install(PostprocessData SourceFiles link_libs) \ No newline at end of file diff --git a/src/PostProcessData/fieldsDataBase/fieldFunctions.hpp b/src/PostprocessData/fieldsDataBase/fieldFunctions.hpp similarity index 100% rename from src/PostProcessData/fieldsDataBase/fieldFunctions.hpp rename to src/PostprocessData/fieldsDataBase/fieldFunctions.hpp diff --git a/src/PostProcessData/fieldsDataBase/fieldsDataBase.cpp b/src/PostprocessData/fieldsDataBase/fieldsDataBase.cpp similarity index 95% rename from src/PostProcessData/fieldsDataBase/fieldsDataBase.cpp rename to src/PostprocessData/fieldsDataBase/fieldsDataBase.cpp index 46efefa5..cbd47c98 100644 --- a/src/PostProcessData/fieldsDataBase/fieldsDataBase.cpp +++ b/src/PostprocessData/fieldsDataBase/fieldsDataBase.cpp @@ -465,19 +465,22 @@ pFlow::span pFlow::fieldsDataBase::updateFieldReal } // if the original type is uint32, and no funciton, cast to real - if( originalType == getTypeName() && func == Functions::None ) + if( originalType == getTypeName()) { - auto sp = updateField(fieldName, forceUpdate); - auto spReal = createOrGetRealField(fieldName+".real"); - funcCast(sp, spReal); - return spReal; - } - else - { - fatalErrorInFunction<<"No function can be applied to field of type uint32. "<< - " The field is: "<< compoundName<(nullptr, 0); - fatalExit; + if(func == Functions::None) + { + auto sp = updateField(fieldName, forceUpdate); + auto spReal = createOrGetRealField(fieldName+".real"); + funcCast(sp, spReal); + return spReal; + } + else + { + fatalErrorInFunction<<"No function can be applied to field of type uint32. "<< + " The field is: "<< compoundName<(nullptr, 0); + fatalExit; + } } if( originalType == getTypeName() ) @@ -606,27 +609,30 @@ pFlow::allPointFieldTypes pFlow::fieldsDataBase::updateFieldAll bool forceUpdate ) { - word originalType, typeAfterFunction; + + word originalType, typeAfterFunction, fieldName; + Functions func; - if( !getPointFieldType(compoundName, originalType, typeAfterFunction)) + if( !getPointFieldType(compoundName, fieldName, originalType, typeAfterFunction, func)) { fatalErrorInFunction<< "Error in getting the type name of field: "<< compoundName<<", with type name: "<< originalType <(nullptr,0); + return span(nullptr, 0); } + if( typeAfterFunction== getTypeName() ) { - return updateField(compoundName, forceUpdate); + return updateFieldRealx3(compoundName, forceUpdate); } else if( typeAfterFunction == getTypeName() ) { - return updateField(compoundName, forceUpdate); + return updateFieldRealx4(compoundName, forceUpdate); } else if( typeAfterFunction == getTypeName() ) { - return updateField(compoundName, forceUpdate); + return updateFieldReal(compoundName, forceUpdate); } else { diff --git a/src/PostProcessData/fieldsDataBase/fieldsDataBase.hpp b/src/PostprocessData/fieldsDataBase/fieldsDataBase.hpp similarity index 100% rename from src/PostProcessData/fieldsDataBase/fieldsDataBase.hpp rename to src/PostprocessData/fieldsDataBase/fieldsDataBase.hpp diff --git a/src/PostProcessData/fieldsDataBase/fieldsDataBaseTemplates.cpp b/src/PostprocessData/fieldsDataBase/fieldsDataBaseTemplates.cpp similarity index 100% rename from src/PostProcessData/fieldsDataBase/fieldsDataBaseTemplates.cpp rename to src/PostprocessData/fieldsDataBase/fieldsDataBaseTemplates.cpp diff --git a/src/PostProcessData/operation/PostprocessOperationSum.cpp b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.cpp similarity index 79% rename from src/PostProcessData/operation/PostprocessOperationSum.cpp rename to src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.cpp index 259ff951..bae7af3f 100644 --- a/src/PostProcessData/operation/PostprocessOperationSum.cpp +++ b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.cpp @@ -51,19 +51,21 @@ bool pFlow::PostprocessOperationSum::execute const auto& regP = regPoints(); bool dbVol = divideByVolume(); - - std::visit([&](auto&& field)->processedRegFieldType - { - return executeSumOperation( - procName, - field, - regP, - dbVol, - weights, - phi, - mask); - }, - allField); + processedRegField_ = makeUnique + ( + std::visit([&](auto&& field)->processedRegFieldType + { + return executeSumOperation( + procName, + field, + regP, + dbVol, + weights, + phi, + mask); + }, + allField) + ); return true; } diff --git a/src/PostProcessData/operation/PostprocessOperationSum.hpp b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.hpp similarity index 92% rename from src/PostProcessData/operation/PostprocessOperationSum.hpp rename to src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.hpp index 5e9cb314..94134602 100644 --- a/src/PostProcessData/operation/PostprocessOperationSum.hpp +++ b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.hpp @@ -37,14 +37,7 @@ class PostprocessOperationSum public postprocessOperation { private: - - using processedRegFieldType = std::variant - < - regionField, - regionField, - regionField - >; - + /// Pointer to the include mask used for masking operations. uniquePtr processedRegField_ = nullptr; @@ -66,6 +59,11 @@ public: dictionary ); + const processedRegFieldType& processedField()const override + { + return processedRegField_(); + } + bool execute(const std::vector>& weights) override; }; diff --git a/src/PostProcessData/operation/fieldFunctions.hpp b/src/PostprocessData/operation/PostprocessOperation/fieldFunctions.hpp similarity index 96% rename from src/PostProcessData/operation/fieldFunctions.hpp rename to src/PostprocessData/operation/PostprocessOperation/fieldFunctions.hpp index 8e9d6427..e1494459 100644 --- a/src/PostProcessData/operation/fieldFunctions.hpp +++ b/src/PostprocessData/operation/PostprocessOperation/fieldFunctions.hpp @@ -31,6 +31,7 @@ Licence: namespace pFlow { + template regionField executeSumOperation ( @@ -54,7 +55,7 @@ regionField executeSumOperation uint n = 0; for(auto index:partIndices) { - if( mask( index )) + if( index!= -1 && mask( index )) { sum += w[n] * field[index]* phi[index]; } @@ -96,7 +97,7 @@ regionField executeAverageOperation uint n = 0; for(auto index:partIndices) { - if( mask( index )) + if( index!= -1 && mask( index )) { sumNum += w[n] * field[index]* phi[index]; } @@ -114,4 +115,4 @@ regionField executeAverageOperation } // namespace pFlow -#endif //__fieldFunctions_hpp__ \ No newline at end of file +#endif //__fieldFunctions_hpp__ diff --git a/src/PostProcessData/operation/includeMask/IncludeMask.hpp b/src/PostprocessData/operation/includeMask/IncludeMask.hpp similarity index 100% rename from src/PostProcessData/operation/includeMask/IncludeMask.hpp rename to src/PostprocessData/operation/includeMask/IncludeMask.hpp diff --git a/src/PostProcessData/operation/includeMask/IncludeMasks.cpp b/src/PostprocessData/operation/includeMask/IncludeMasks.cpp similarity index 100% rename from src/PostProcessData/operation/includeMask/IncludeMasks.cpp rename to src/PostprocessData/operation/includeMask/IncludeMasks.cpp diff --git a/src/PostProcessData/operation/includeMask/includeMask.cpp b/src/PostprocessData/operation/includeMask/includeMask.cpp similarity index 100% rename from src/PostProcessData/operation/includeMask/includeMask.cpp rename to src/PostprocessData/operation/includeMask/includeMask.cpp diff --git a/src/PostProcessData/operation/includeMask/includeMask.hpp b/src/PostprocessData/operation/includeMask/includeMask.hpp similarity index 100% rename from src/PostProcessData/operation/includeMask/includeMask.hpp rename to src/PostprocessData/operation/includeMask/includeMask.hpp diff --git a/src/PostProcessData/operation/includeMask/maskOperations.hpp b/src/PostprocessData/operation/includeMask/maskOperations.hpp similarity index 100% rename from src/PostProcessData/operation/includeMask/maskOperations.hpp rename to src/PostprocessData/operation/includeMask/maskOperations.hpp diff --git a/src/PostProcessData/operation/postprocessOperation.cpp b/src/PostprocessData/operation/postprocessOperation/postprocessOperation.cpp similarity index 53% rename from src/PostProcessData/operation/postprocessOperation.cpp rename to src/PostprocessData/operation/postprocessOperation/postprocessOperation.cpp index c37961c1..8c42daa3 100644 --- a/src/PostProcessData/operation/postprocessOperation.cpp +++ b/src/PostprocessData/operation/postprocessOperation/postprocessOperation.cpp @@ -18,10 +18,72 @@ Licence: -----------------------------------------------------------------------------*/ +#include "Time.hpp" #include "postprocessOperation.hpp" #include "regionPoints.hpp" #include "fieldsDataBase.hpp" +namespace pFlow +{ + +template +inline +bool writeField +( + iOstream& os, + timeValue t, + const regionField field, + uint32 threshold, + const T& defValue=T{} +) +{ + const auto& regPoints = field.regPoints(); + const uint32 n = field.size(); + os<= threshold) + { + if constexpr(std::is_same_v) + { + os<) + { + os << field[i].x() << ' ' << field[i].y() << ' ' << field[i].z() << ' ' << field[i].w() << tab; + } + else + { + os<) + { + os<) + { + os << defValue.x() << ' ' << defValue.y() << ' ' << defValue.z() << ' ' << defValue.w() << tab; + } + else + { + os< - pFlow::postprocessOperation::create +const pFlow::Time& pFlow::postprocessOperation::time() const +{ + return database_.time(); +} + +bool pFlow::postprocessOperation::write(const fileSystem &parDir) const +{ + auto ti = time().TimeInfo(); + + if(!osPtr_) + { + fileSystem path = parDir+( + processedFieldName() + ".Start_" + ti.prevTimeName()); + osPtr_ = makeUnique(path); + + regPoints().write(osPtr_()); + } + + const auto& field = processedField(); + + std::visit ( - const dictionary &opDict, - const regionPoints& regPoints, - fieldsDataBase &fieldsDB - ) + [&](auto&& arg)->bool + { + return writeField(osPtr_(), ti.t(), arg, threshold_); + }, + field + ); + + return true; +} + +pFlow::uniquePtr +pFlow::postprocessOperation::create( + const dictionary &opDict, + const regionPoints ®Points, + fieldsDataBase &fieldsDB) { word func = opDict.getVal("function"); word method = angleBracketsNames("PostprocessOperation", func); diff --git a/src/PostProcessData/operation/postprocessOperation.hpp b/src/PostprocessData/operation/postprocessOperation/postprocessOperation.hpp similarity index 88% rename from src/PostProcessData/operation/postprocessOperation.hpp rename to src/PostprocessData/operation/postprocessOperation/postprocessOperation.hpp index 01cd853b..fa847bdd 100644 --- a/src/PostProcessData/operation/postprocessOperation.hpp +++ b/src/PostprocessData/operation/postprocessOperation/postprocessOperation.hpp @@ -20,18 +20,28 @@ Licence: #ifndef __postprocessOperation_hpp__ #define __postprocessOperation_hpp__ +#include + #include "virtualConstructor.hpp" #include "Logical.hpp" #include "dictionary.hpp" #include "span.hpp" +#include "oFstream.hpp" +#include "regionField.hpp" #include "includeMask.hpp" - namespace pFlow { +using processedRegFieldType = std::variant + < + regionField, + regionField, + regionField + >; + class fieldsDataBase; -class regionPoints; +class Time; /*! * @brief Base class for post-processing operations. @@ -69,10 +79,12 @@ private: word fieldType_; /// Name of the phi field to be processed. - word phiFieldName_; + word phiFieldName_; /// Pointer to the include mask used for masking operations. uniquePtr includeMask_ = nullptr; + + mutable uniquePtr osPtr_ = nullptr; public: @@ -111,6 +123,8 @@ public: return database_; } + const Time& time()const; + word processedFieldName()const { return operationDict_.name(); @@ -150,10 +164,18 @@ public: return includeMask_().getMask(); } + virtual + const processedRegFieldType& processedField()const=0; virtual bool execute(const std::vector>& weights) = 0; + virtual + bool write(const fileSystem &parDir)const; + + virtual + bool write(iOstream& os)const {return true;} + static uniquePtr create( const dictionary& opDict, diff --git a/src/PostProcessData/postprocessComponent/PostprocessComponent.cpp b/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponent.cpp similarity index 68% rename from src/PostProcessData/postprocessComponent/PostprocessComponent.cpp rename to src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponent.cpp index 5720bdaa..c815d255 100644 --- a/src/PostProcessData/postprocessComponent/PostprocessComponent.cpp +++ b/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponent.cpp @@ -61,22 +61,31 @@ bool pFlow::PostprocessComponent::execute bool forceUpdate ) { - - if( !timeControl().eventTime(ti)) + if( !forceUpdate && !timeControl().eventTime(ti)) { executed_ = false; return true; } // update processing methods + auto& regPoints = this->regPoints(); - auto centers = this->regPoints().centers(); - const uint32 n = centers.size(); - auto points = this->database().updatePoints(); + if(!regPoints.update()) + { + fatalErrorInFunction + << "regionPoints update failed for " + << operationDicts_.globalName() + << endl; + return false; + } + + auto centers = regPoints.centers(); + const uint32 n = centers.size(); + auto points = this->database().updatePoints(); for(uint32 i=0; iregPoints().indices(i); + auto indices = regPoints.indices(i); regionsProcessMethod_[i].updateWeights( centers[i], indices, @@ -93,7 +102,7 @@ bool pFlow::PostprocessComponent::execute for(auto& op:operatios_) { - if( op->execute(weights) ) + if( !op->execute(weights) ) { fatalErrorInFunction <<"error occured in executing operatoin defined in dict " @@ -105,5 +114,39 @@ bool pFlow::PostprocessComponent::execute executed_ = true; + return true; +} + +template +inline +bool pFlow::PostprocessComponent::write +( + const fileSystem &parDir +) const +{ + if(!executed_) return true; + + if(regionPointsPtr_().writeToSameTimeFile()) + { + for(auto& operation:operatios_) + { + if(!operation->write(parDir)) + { + fatalErrorInFunction + <<"Error occurred in writing operation defined in dict " + << operation->operationDict() + < +class PostprocessComponentArithmetic +: + public PostprocessComponent +{ +public: + + /// type info + TypeInfoTemplate12("PostprocessComponent", RegionType, arithmetic); + + PostprocessComponentArithmetic + ( + const dictionary& dict, + fieldsDataBase& fieldsDB, + const baseTimeControl& defaultTimeControl + ) + : + PostprocessComponent(dict, fieldsDB, defaultTimeControl) + { + /// initializes the arithmetic distribution for all elements of region + //const uint32 n = this->regPoints().size(); + auto d = this->regPoints().eqDiameters(); + auto c = this->regPoints().centers(); + auto& regs = this->regionProecessMethod(); + const uint32 n = d.size(); + for(uint32 i=0; i +class PostprocessComponentUniform +: + public PostprocessComponent +{ +public: + + /// type info + TypeInfoTemplate12("PostprocessComponent", RegionType, uniformDistribution); + + PostprocessComponentUniform + ( + const dictionary& dict, + fieldsDataBase& fieldsDB, + const baseTimeControl& defaultTimeControl + ) + : + PostprocessComponent(dict, fieldsDB, defaultTimeControl) + { + /// initializes the Uniform distribution for all elements of region + //const uint32 n = this->regPoints().size(); + auto d = this->regPoints().eqDiameters(); + auto c = this->regPoints().centers(); + auto& regs = this->regionProecessMethod(); + const uint32 n = d.size(); + for(uint32 i=0; i; - +template class pFlow::PostprocessComponentUniform; +template class pFlow::PostprocessComponentArithmetic; diff --git a/src/PostprocessData/postprocessComponent/particleProbePostprocessComponent/particleProbePostprocessComponent.cpp b/src/PostprocessData/postprocessComponent/particleProbePostprocessComponent/particleProbePostprocessComponent.cpp new file mode 100644 index 00000000..3aad17a4 --- /dev/null +++ b/src/PostprocessData/postprocessComponent/particleProbePostprocessComponent/particleProbePostprocessComponent.cpp @@ -0,0 +1,147 @@ +#include "particleProbePostprocessComponent.hpp" +#include "Time.hpp" + +namespace pFlow +{ + +template +inline +regionField porbeExecute +( + const word& regFieldName, + const span& field, + const regionPoints& regPoints +) +{ + regionField processedField(regFieldName, regPoints, T{}); + auto partIndices = regPoints.indices(0); + + uint n = 0; + for(auto index:partIndices) + { + if(index != -1) + { + processedField[n] = field[index]; + } + n++; + } + return processedField; +} + +template +inline bool writeField +( + iOstream& os, + timeValue t, + const regionField& field, + const regionPoints& regPoints, + const T& invalidVal = T{} +) +{ + auto indices = regPoints.indices(0); + const uint32 s= field.size(); + os<< t <) + { + os< ) + { + os<(dict, fieldsDB) + ), + fieldName_ + ( + dict.getVal("field") + ), + name_(dict.name()) +{} + +bool pFlow::particleProbePostprocessComponent::execute +( + const timeInfo &ti, + bool forceExecute +) +{ + if( !forceExecute && !timeControl().eventTime(ti)) + { + executed_ = false; + return true; + } + + if(!regionPointsPtr_().update()) + { + fatalErrorInFunction + << "regionPoints update for "<< name_ << " failed. \n"; + return false; + } + + auto field = database().updateFieldAll(fieldName_); + auto pFieldName = name_; + + processedField_ = makeUnique + ( + std::visit( + [&](auto&& f) -> processedRegFieldType + { + return porbeExecute( + pFieldName, + f, + regionPointsPtr_()); + }, + field) + ); + + executed_ = true; + return true; +} + + +bool pFlow::particleProbePostprocessComponent::write(const fileSystem& parDir)const +{ + if(! executed_ ) return true; + + const auto ti = database().time().TimeInfo(); + + if( !osPtr_) + { + // file is not open yet + fileSystem path = parDir + (name_+".Start_"+ti.prevTimeName()); + osPtr_ = makeUnique(path); + regionPointsPtr_().write(osPtr_()); + } + + std::visit + ([&](auto&& arg)->bool + { + return writeField(osPtr_(), ti.t(), arg, regionPointsPtr_()); + }, + processedField_() + ); + + return true; +} \ No newline at end of file diff --git a/src/PostProcessData/postprocessComponent/particleProbePostprocessComponent.hpp b/src/PostprocessData/postprocessComponent/particleProbePostprocessComponent/particleProbePostprocessComponent.hpp similarity index 88% rename from src/PostProcessData/postprocessComponent/particleProbePostprocessComponent.hpp rename to src/PostprocessData/postprocessComponent/particleProbePostprocessComponent/particleProbePostprocessComponent.hpp index 7ceaf893..5069e291 100644 --- a/src/PostProcessData/postprocessComponent/particleProbePostprocessComponent.hpp +++ b/src/PostprocessData/postprocessComponent/particleProbePostprocessComponent/particleProbePostprocessComponent.hpp @@ -25,10 +25,12 @@ Licence: #include "fieldsDataBase.hpp" #include "centerPointsRegionPoints.hpp" #include "regionField.hpp" +#include "oFstream.hpp" namespace pFlow { + class particleProbePostprocessComponent : public postprocessComponent @@ -48,8 +50,12 @@ private: uniquePtr processedField_ = nullptr; + word fieldName_; + word name_; + mutable uniquePtr osPtr_ = nullptr; + public: TypeInfo("PostprocessComponent"); @@ -63,6 +69,12 @@ public: ~particleProbePostprocessComponent()override = default; + add_vCtor + ( + postprocessComponent, + particleProbePostprocessComponent, + dictionary + ); word name()const override { @@ -74,7 +86,6 @@ public: return regionPointsPtr_(); } - const regionPoints& regPoints() const override { return regionPointsPtr_(); @@ -87,6 +98,8 @@ public: return executed_; } + bool write(const fileSystem& parDir)const override; + }; } diff --git a/src/PostProcessData/postprocessComponent/postprocessComponent.cpp b/src/PostprocessData/postprocessComponent/postprocessComponent/postprocessComponent.cpp similarity index 100% rename from src/PostProcessData/postprocessComponent/postprocessComponent.cpp rename to src/PostprocessData/postprocessComponent/postprocessComponent/postprocessComponent.cpp diff --git a/src/PostProcessData/postprocessComponent/postprocessComponent.hpp b/src/PostprocessData/postprocessComponent/postprocessComponent/postprocessComponent.hpp similarity index 97% rename from src/PostProcessData/postprocessComponent/postprocessComponent.hpp rename to src/PostprocessData/postprocessComponent/postprocessComponent/postprocessComponent.hpp index e409068b..70db2153 100644 --- a/src/PostProcessData/postprocessComponent/postprocessComponent.hpp +++ b/src/PostprocessData/postprocessComponent/postprocessComponent/postprocessComponent.hpp @@ -101,6 +101,9 @@ public: virtual bool executed()const = 0; + virtual + bool write(const fileSystem& parDir)const = 0; + static uniquePtr create( const dictionary& dict, diff --git a/src/PostProcessData/postprocessData.cpp b/src/PostprocessData/postprocessData/postprocessData.cpp similarity index 83% rename from src/PostProcessData/postprocessData.cpp rename to src/PostprocessData/postprocessData/postprocessData.cpp index 359fa893..064b5ad1 100644 --- a/src/PostProcessData/postprocessData.cpp +++ b/src/PostprocessData/postprocessData/postprocessData.cpp @@ -23,6 +23,7 @@ Licence: #include "systemControl.hpp" #include "postprocessData.hpp" #include "fileDictionary.hpp" +#include "postprocessGlobals.hpp" #include "postprocessComponent.hpp" pFlow::postprocessData::postprocessData(const systemControl &control) @@ -42,6 +43,8 @@ pFlow::postprocessData::postprocessData(const systemControl &control) ), componentsDicts_(readDictList("components", dict_)) { + postProcessGlobals::defaultDir__ = CWD()/pFlow::postProcessGlobals::defaultRelDir__; + // if dictionary is not provided, no extra action is required. if( !dict_.fileExist() ) { @@ -81,7 +84,6 @@ pFlow::postprocessData::postprocessData(const systemControl &control) bool pFlow::postprocessData::execute() { - const auto& ti = time_.TimeInfo(); for(auto& component:postprocesses_) @@ -96,4 +98,23 @@ bool pFlow::postprocessData::execute() } return true; -} \ No newline at end of file +} + +bool pFlow::postprocessData::write() const +{ + for(auto& component:postprocesses_) + { + if(!component->executed()) + { + continue; + } + if(!component->write(postProcessGlobals::defaultDir__/component->name())) + { + fatalErrorInFunction + <<"Error occured in writing postprocess component: " + <name()< + +#include "types.hpp" +#include "typeInfo.hpp" +#include "span.hpp" + +namespace pFlow +{ + +class dictionary; + +class arithmetic +{ +private: + + std::vector weight_; + +public: + + // type info + TypeInfoNV("arithmetic"); + + arithmetic() + {} + + arithmetic(const arithmetic&) = default; + + arithmetic(arithmetic&&) = default; + + arithmetic& operator=(const arithmetic&) = default; + + arithmetic& operator=(arithmetic&&) = default; + + ~arithmetic()=default; + + + bool updateWeights + ( + const realx3& center, + const span& indices, + const span& points + ) + { + return updateWeights(indices.size()); + } + + bool updateWeights(uint32 n) + { + n = max(n, 1u); + weight_.assign(n, 1); + return true; + } + + real getWeight(uint32 i)const + { + return weight_[i]; + } + + span getWeights() + { + return span(weight_.data(), weight_.size()); + } + +}; + +} + +#endif //__arithmetic_hpp__ \ No newline at end of file diff --git a/src/PostProcessData/method/uniformDistribution.hpp b/src/PostprocessData/processMethod/uniformDistribution.hpp similarity index 90% rename from src/PostProcessData/method/uniformDistribution.hpp rename to src/PostprocessData/processMethod/uniformDistribution.hpp index 736d9d2f..d0445615 100644 --- a/src/PostProcessData/method/uniformDistribution.hpp +++ b/src/PostprocessData/processMethod/uniformDistribution.hpp @@ -21,6 +21,8 @@ Licence: #ifndef __uniformDistribution_hpp__ #define __uniformDistribution_hpp__ +#include + #include "types.hpp" #include "typeInfo.hpp" #include "span.hpp" @@ -55,11 +57,14 @@ public: ~uniformDistribution()=default; - bool updateWeights(const realx3& center, const span& points) + bool updateWeights + ( + const realx3& center, + const span& indices, + const span& points + ) { - uint32 n = max(points.size(), 1u); - weight_.assign(n, 1.0/n); - return true; + return updateWeights(indices.size()); } bool updateWeights(uint32 n) diff --git a/src/PostProcessData/region/regionFields.hpp/regionField.hpp b/src/PostprocessData/region/regionFields/regionField.hpp similarity index 92% rename from src/PostProcessData/region/regionFields.hpp/regionField.hpp rename to src/PostprocessData/region/regionFields/regionField.hpp index 559f854f..8d47a281 100644 --- a/src/PostProcessData/region/regionFields.hpp/regionField.hpp +++ b/src/PostprocessData/region/regionFields/regionField.hpp @@ -57,6 +57,11 @@ public: ~regionField() = default; + const regionPoints& regPoints() const + { + return regionPoints_; + } + /// get the field value T& operator[] (const uint32 i) { @@ -75,6 +80,16 @@ public: return field_.name(); } + auto size()const + { + return field_.size(); + } + + bool empty()const + { + return field_.empty(); + } + /// @brief write the field to a file /// @param os output file stream /// @return true if successful and false if fails diff --git a/src/PostProcessData/region/regionFields.hpp/regionFieldTemplate.cpp b/src/PostprocessData/region/regionFields/regionFieldTemplate.cpp similarity index 100% rename from src/PostProcessData/region/regionFields.hpp/regionFieldTemplate.cpp rename to src/PostprocessData/region/regionFields/regionFieldTemplate.cpp diff --git a/src/PostProcessData/region/regionPoints/centerPointsRegionPoints.cpp b/src/PostprocessData/region/regionPoints/centerPointsRegionPoints/centerPointsRegionPoints.cpp similarity index 79% rename from src/PostProcessData/region/regionPoints/centerPointsRegionPoints.cpp rename to src/PostprocessData/region/regionPoints/centerPointsRegionPoints/centerPointsRegionPoints.cpp index 2595ca14..e16ef774 100644 --- a/src/PostProcessData/region/regionPoints/centerPointsRegionPoints.cpp +++ b/src/PostprocessData/region/regionPoints/centerPointsRegionPoints/centerPointsRegionPoints.cpp @@ -37,7 +37,7 @@ bool pFlow::centerPointsRegionPoints::selectIds() diameter_.resize(ids_.size(),1.0); center_.resize(ids_.size(), realx3(0,0,0)); selectedPoints_.resize(ids_.size(), -1); - return false; + return true; } pFlow::centerPointsRegionPoints::centerPointsRegionPoints( @@ -46,19 +46,7 @@ pFlow::centerPointsRegionPoints::centerPointsRegionPoints( : regionPoints(dict, fieldsDataBase), idName_(dict.getValOrSet("idName", "id")), probDict_(dict) -{ - auto idList = dict.getVal("ids"); - Set uniqueIds; - - uniqueIds.insert(idList.begin(), idList.end()); - - for(auto& id:uniqueIds) - { - ids_.push_back(id); - } - - selectedPoints_.resize(ids_.size()); -} +{} bool pFlow::centerPointsRegionPoints::update() { @@ -81,6 +69,27 @@ bool pFlow::centerPointsRegionPoints::update() } } - return false; + return true; } + +bool pFlow::centerPointsRegionPoints::write(iOstream &os) const +{ + if(firstTimeUpdate_) + { + fatalErrorInFunction + <<"Write operation should be done before executing the update. \n"; + return false; + } + os <<"# Probing particles for selected ids\n"; + os << "# SelectedId: "; + + for(auto& id: ids_) + { + os << id << tab; + } + os << endl; + os << "time"< create( diff --git a/src/PostProcessData/region/regionPoints/sphereRegionPoints.cpp b/src/PostprocessData/region/regionPoints/sphereRegionPoints/sphereRegionPoints.cpp similarity index 71% rename from src/PostProcessData/region/regionPoints/sphereRegionPoints.cpp rename to src/PostprocessData/region/regionPoints/sphereRegionPoints/sphereRegionPoints.cpp index 566fd688..4022c00e 100644 --- a/src/PostProcessData/region/regionPoints/sphereRegionPoints.cpp +++ b/src/PostprocessData/region/regionPoints/sphereRegionPoints/sphereRegionPoints.cpp @@ -27,5 +27,15 @@ bool pFlow::sphereRegionPoints::update() } } - return false; + return true; +} + +bool pFlow::sphereRegionPoints::write(iOstream &os) const +{ + os <<"# Single sphere\n"; + os <<"# center point: "< Date: Thu, 10 Apr 2025 21:22:35 +0330 Subject: [PATCH 3/9] Push after adding PostptocessData lib --- src/CMakeLists.txt | 2 + src/phasicFlow/CMakeLists.txt | 1 + .../containers/List/anyList/anyList.hpp | 21 ++++ src/phasicFlow/dictionary/dictionaryList.hpp | 114 ++++++++++++++++++ src/phasicFlow/globals/vocabs.hpp | 1 + .../repository/Time/baseTimeControl.cpp | 40 +++++- .../repository/Time/baseTimeControl.hpp | 41 ++++++- .../repository/Time/timeControl.hpp | 10 ++ src/phasicFlow/repository/Time/timeInfo.hpp | 6 + .../auxFunctions/auxFunctions.cpp | 56 +++++++++ .../auxFunctions/auxFunctions.hpp | 65 ++++++++++ .../systemControl/systemControl.cpp | 16 +++ .../systemControl/systemControl.hpp | 4 + src/phasicFlow/smartPointers/uniquePtr.hpp | 7 +- .../structuredData/sphere/sphere.hpp | 6 + 15 files changed, 377 insertions(+), 13 deletions(-) create mode 100644 src/phasicFlow/dictionary/dictionaryList.hpp create mode 100644 src/phasicFlow/repository/systemControl/auxFunctions/auxFunctions.cpp create mode 100644 src/phasicFlow/repository/systemControl/auxFunctions/auxFunctions.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7b403304..e912cc93 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,3 +13,5 @@ add_subdirectory(Interaction) add_subdirectory(MotionModel) +add_subdirectory(PostprocessData) + diff --git a/src/phasicFlow/CMakeLists.txt b/src/phasicFlow/CMakeLists.txt index eb50c1a7..c8a697ea 100644 --- a/src/phasicFlow/CMakeLists.txt +++ b/src/phasicFlow/CMakeLists.txt @@ -47,6 +47,7 @@ repository/Time/Time.cpp repository/Time/timeControl.cpp repository/Time/baseTimeControl.cpp repository/systemControl/systemControl.cpp +repository/systemControl/auxFunctions/auxFunctions.cpp repository/systemControl/dynamicLinkLibs.cpp commandLine/commandLine.cpp diff --git a/src/phasicFlow/containers/List/anyList/anyList.hpp b/src/phasicFlow/containers/List/anyList/anyList.hpp index 91a93360..b720a783 100644 --- a/src/phasicFlow/containers/List/anyList/anyList.hpp +++ b/src/phasicFlow/containers/List/anyList/anyList.hpp @@ -79,6 +79,27 @@ public: /// List of varibales names const wordList& names()const; + template + void emplaceBackOrReplace(const word& name, Args&&... args) + { + if( contains(name)) + { + int32 i = names_.findi(name); + types_[i] = getTypeName(); + anyList_.pos(i)->reset(); + anyList_.pos(i)-> emplace(std::forward(args)...); + } + else + { + names_.push_back(name); + types_.push_back(getTypeName()); + anyList_.emplace_back( + std::in_place_type, + std::forward(args)...); + } + + } + /// Create variable using constructor in-place template reference emplaceBack(const word& name, Args&&... args) diff --git a/src/phasicFlow/dictionary/dictionaryList.hpp b/src/phasicFlow/dictionary/dictionaryList.hpp new file mode 100644 index 00000000..d47e891e --- /dev/null +++ b/src/phasicFlow/dictionary/dictionaryList.hpp @@ -0,0 +1,114 @@ +/*------------------------------- 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 __dictionaryList_hpp__ +#define __dictionaryList_hpp__ + +#include "List.hpp" +#include "dictionary.hpp" + + +namespace pFlow +{ + +class dictionaryList +: + public List +{ +private: + + const dictionary& parrent_; + + word name_; + + +public: + + TypeInfoNV("dictionaryList"); + + dictionaryList(const word& name, const dictionary& parrent) + : + List(), + parrent_(parrent), + name_(name) + {} + + dictionaryList(const dictionaryList&) = default; + + dictionaryList(dictionaryList&&) = default; + + dictionaryList& operator = (const dictionaryList&) = default; + + dictionaryList& operator = (dictionaryList&&) = default; + + ~dictionaryList() = default; + + const word& name()const + { + return name_; + } + + const word globalName()const + { + return parrent_.globalName(); + } + + List& dicts() + { + return *this; + } + + const List& dicts()const + { + return *this; + } + + const dictionary& parrent()const + { + return parrent_; + } + +}; + +inline +dictionaryList readDictList(const word& name, const dictionary& dict) +{ + if(!dict.containsDataEntry(name)) + { + fatalErrorInFunction + <<"data entry: "<< name + <<" does not exist in dictionary "<< dict.globalName()<>(name); + for(auto& d:dicts) + { + allDicts.emplace_back(d.name(), dict, d); + } + + return allDicts; +} + +} + + + +#endif \ No newline at end of file diff --git a/src/phasicFlow/globals/vocabs.hpp b/src/phasicFlow/globals/vocabs.hpp index 9cb2c5bd..33844862 100755 --- a/src/phasicFlow/globals/vocabs.hpp +++ b/src/phasicFlow/globals/vocabs.hpp @@ -47,6 +47,7 @@ const inline char* const contactSearchFile__ = "contactSearch"; const inline char* const propertyFile__ = "interaction"; const inline char* const interactionFile__ = "interaction"; const inline char* const postprocessFile__ = "postprocessDict"; +const inline char* const postprocessDataFiel__ = "postprocessDataDict"; const inline char* const uniform__ = "uniform"; const inline char* const nonUniform__ = "nonUniform"; diff --git a/src/phasicFlow/repository/Time/baseTimeControl.cpp b/src/phasicFlow/repository/Time/baseTimeControl.cpp index b3bba368..c4a83327 100644 --- a/src/phasicFlow/repository/Time/baseTimeControl.cpp +++ b/src/phasicFlow/repository/Time/baseTimeControl.cpp @@ -21,14 +21,24 @@ Licence: #include "baseTimeControl.hpp" #include "timeInfo.hpp" -pFlow::baseTimeControl::baseTimeControl +void pFlow::baseTimeControl::setTimeControl ( - const dictionary &dict, - const word& intervalPrefix, - timeValue defStartTime + timeValue startTime, + timeValue endTime, + timeValue interval, + const word &intervalPrefix ) -: - intervalPrefix_(intervalPrefix) +{ + isTimeStep_ = false; + intervalPrefix_ = intervalPrefix; + rRange_ = stridedRange(startTime, endTime, interval); +} + +pFlow::baseTimeControl::baseTimeControl( + const dictionary &dict, + const word &intervalPrefix, + timeValue defStartTime) + : intervalPrefix_(intervalPrefix) { auto tControl = dict.getVal("timeControl"); if(tControl == "timeStep") @@ -119,6 +129,24 @@ pFlow::baseTimeControl::baseTimeControl(int32 start, int32 end, int32 stride, co { } +pFlow::baseTimeControl::baseTimeControl +( + timeValue start, + timeValue end, + timeValue stride, + const word &intervalPrefix +) +: + isTimeStep_(false), + rRange_( + start, end, stride + ), + intervalPrefix_( + intervalPrefix.size()==0uL? word("interval"): intervalPrefix+"Interval" + ) +{ +} + bool pFlow::baseTimeControl::eventTime(uint32 iter, timeValue t, timeValue dt) const { if(isTimeStep_) diff --git a/src/phasicFlow/repository/Time/baseTimeControl.hpp b/src/phasicFlow/repository/Time/baseTimeControl.hpp index f49d97be..8e9dd62f 100644 --- a/src/phasicFlow/repository/Time/baseTimeControl.hpp +++ b/src/phasicFlow/repository/Time/baseTimeControl.hpp @@ -32,13 +32,21 @@ class baseTimeControl { private: - bool isTimeStep_; + bool isTimeStep_; - int32StridedRagne iRange_; + int32StridedRagne iRange_; - stridedRange rRange_; + stridedRange rRange_; - const word intervalPrefix_; + word intervalPrefix_; + +protected: + + void setTimeControl( + timeValue startTime, + timeValue endTime, + timeValue interval, + const word& intervalPrefix); public: @@ -59,8 +67,33 @@ public: int32 end, int32 stride, const word& intervalPrefix = "" + ); + + baseTimeControl( + timeValue start, + timeValue end, + timeValue stride, + const word& intervalPrefix = "" ); + baseTimeControl( + const baseTimeControl& other + ) = default; + + baseTimeControl( + baseTimeControl&& other + ) = default; + + baseTimeControl& operator=( + const baseTimeControl& other + ) = default; + + baseTimeControl& operator=( + baseTimeControl&& other + ) = default; + + ~baseTimeControl() = default; + inline bool isTimeStep() const { return isTimeStep_; diff --git a/src/phasicFlow/repository/Time/timeControl.hpp b/src/phasicFlow/repository/Time/timeControl.hpp index 065b3777..dc2bb80b 100644 --- a/src/phasicFlow/repository/Time/timeControl.hpp +++ b/src/phasicFlow/repository/Time/timeControl.hpp @@ -120,6 +120,16 @@ public: return startTime_; } + timeValue endTime()const + { + return endTime_; + } + + timeValue saveInterval()const + { + return saveInterval_; + } + word timeName()const; timeValue currentTime() const diff --git a/src/phasicFlow/repository/Time/timeInfo.hpp b/src/phasicFlow/repository/Time/timeInfo.hpp index fc759614..ee0cff61 100644 --- a/src/phasicFlow/repository/Time/timeInfo.hpp +++ b/src/phasicFlow/repository/Time/timeInfo.hpp @@ -106,6 +106,12 @@ public: return real2FixedStripZeros(currentTime_, presicion_); } + inline + word prevTimeName()const + { + return real2FixedStripZeros( max(currentTime_-dt_, timeValue(0)), presicion_); + } + static uint32 precision() { diff --git a/src/phasicFlow/repository/systemControl/auxFunctions/auxFunctions.cpp b/src/phasicFlow/repository/systemControl/auxFunctions/auxFunctions.cpp new file mode 100644 index 00000000..8214a3c2 --- /dev/null +++ b/src/phasicFlow/repository/systemControl/auxFunctions/auxFunctions.cpp @@ -0,0 +1,56 @@ +/*------------------------------- 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 "auxFunctions.hpp" +#include "systemControl.hpp" + + +pFlow::uniquePtr + pFlow::auxFunctions::create(const systemControl& control) +{ + const auto& setDict = control.settingsDict(); + + if( !setDict.containsDataEntry("auxFunctions")) + { + return nullptr; + } + + word func = setDict.getVal("auxFunctions"); + + if( systemControlvCtorSelector_.search(func) ) + { + REPORT(1)<<"Creating auxiliary function "<< Green_Text(func)<< " ..."< create(const systemControl& control); + +}; + +} // namespace pFlow + +#endif \ No newline at end of file diff --git a/src/phasicFlow/repository/systemControl/systemControl.cpp b/src/phasicFlow/repository/systemControl/systemControl.cpp index 75109c71..4c9ae2f0 100644 --- a/src/phasicFlow/repository/systemControl/systemControl.cpp +++ b/src/phasicFlow/repository/systemControl/systemControl.cpp @@ -25,6 +25,8 @@ Licence: #include "types.hpp" #include "vocabs.hpp" +inline static bool axuFunctionsInitialized__ = false; + bool pFlow::systemControl::readIncludeExclue(const dictionary& dict) { if (dict.containsDataEntry("includeObjects")) @@ -187,6 +189,18 @@ bool pFlow::systemControl::operator++(int) { auto toContinue = time()++; + if(!axuFunctionsInitialized__) + { + auxFunctions_ = auxFunctions::create(*this); + axuFunctionsInitialized__ = true; + } + + if(auxFunctions_) + { + auxFunctions_().execute(); + auxFunctions_().write(); + } + if (toContinue) { writeToFileTimer_.start(); @@ -221,3 +235,5 @@ bool pFlow::systemControl::operator++(int) return toContinue; } + + diff --git a/src/phasicFlow/repository/systemControl/systemControl.hpp b/src/phasicFlow/repository/systemControl/systemControl.hpp index 94d3b939..0e9f8988 100644 --- a/src/phasicFlow/repository/systemControl/systemControl.hpp +++ b/src/phasicFlow/repository/systemControl/systemControl.hpp @@ -34,10 +34,13 @@ Licence: #include "Timers.hpp" #include "dynamicLinkLibs.hpp" #include "Set.hpp" +#include "auxFunctions.hpp" + namespace pFlow { + class systemControl : public repository @@ -83,6 +86,7 @@ protected: wordSet excludeList_; + uniquePtr auxFunctions_ = nullptr; bool readIncludeExclue(const dictionary& dict); diff --git a/src/phasicFlow/smartPointers/uniquePtr.hpp b/src/phasicFlow/smartPointers/uniquePtr.hpp index c28490c7..23e7f3a6 100644 --- a/src/phasicFlow/smartPointers/uniquePtr.hpp +++ b/src/phasicFlow/smartPointers/uniquePtr.hpp @@ -38,15 +38,16 @@ namespace pFlow template< - typename T + typename T, + typename Deleter = std::default_delete > class uniquePtr : - public std::unique_ptr + public std::unique_ptr { public: - using uniquePtrType = std::unique_ptr; + using uniquePtrType = std::unique_ptr; // using base constructors using uniquePtrType::unique_ptr; diff --git a/src/phasicFlow/structuredData/sphere/sphere.hpp b/src/phasicFlow/structuredData/sphere/sphere.hpp index 21b20d1c..2586723c 100644 --- a/src/phasicFlow/structuredData/sphere/sphere.hpp +++ b/src/phasicFlow/structuredData/sphere/sphere.hpp @@ -105,6 +105,12 @@ public: return sqrt(radius2_); } + INLINE_FUNCTION_HD + real volume()const + { + return 4.0/3.0* Pi * pow(radius(),3.0); + } + //// - IO operation FUNCTION_H bool read(iIstream & is); From d136ac02627bd73d019e4b2f9e0ce971730a3f55 Mon Sep 17 00:00:00 2001 From: Hamidreza Date: Fri, 11 Apr 2025 10:13:53 +0330 Subject: [PATCH 4/9] autoComplete improved for better time folder filtering and fields improved for better field filtering --- cmake/autoComplete | 107 +++++++++++++++++++++++++++++++-------------- 1 file changed, 74 insertions(+), 33 deletions(-) diff --git a/cmake/autoComplete b/cmake/autoComplete index 6c289ce5..babf3843 100644 --- a/cmake/autoComplete +++ b/cmake/autoComplete @@ -1,48 +1,89 @@ PF_cFlags="--description --help --version" AllTimeFolders= __getAllTime(){ - files=( $(ls) ) - deleteFiles=(settings caseSetup cleanThisCase VTK runThisCase stl postprocess postProcess) - declare -A delk - for del in "${deleteFiles[@]}" ; do delk[$del]=1 ; done - # Tag items to remove, based on - for k in "${!files[@]}" ; do - [ "${delk[${files[$k]}]-}" ] && unset 'files[k]' - done - # Compaction - COMPREPLY=("${files[@]}") - AllTimeFolders="${files[@]}" + # Initialize empty array for time folders + local time_folders=() + + # Loop through all directories in current folder + for dir in */; do + # Remove trailing slash + dir=${dir%/} + + # Check if directory name is a valid floating point number + # This pattern matches integers and floating point numbers + if [[ $dir =~ ^[0-9]+(\.[0-9]+)?$ ]]; then + time_folders+=("$dir") + fi + done + + # Set completion reply to the time folders + COMPREPLY=("${time_folders[@]}") + AllTimeFolders="${time_folders[@]}" } __getFields(){ - __getAllTime - local -A unique_files=() + __getAllTime + local -A unique_files=() + # Files to exclude from suggestions + local exclude_files=("shapeHash" "pStructure" "particleInsertion" "p" "alpha" "U" "Sp" "Su" "phi") + declare -A exclude_dict + + # Build exclude dictionary for faster lookups + for file in "${exclude_files[@]}"; do + exclude_dict["$file"]=1 + done - for dir in $AllTimeFolders; do - # Check if the directory exists - if [ ! -d "$dir" ]; then - continue # Skip to the next directory - fi - - files_in_dir=$(find "$dir" -maxdepth 1 -type f -printf '%f\n' | sort -u) - - # Add filenames to the associative array (duplicates will be overwritten) - while IFS= read -r filename; do - unique_files["$filename"]=1 # Just the key is important, value can be anything - done <<< "$files_in_dir" - - done - COMPREPLY=("${!unique_files[@]}") - AllTimeFolders= + for dir in $AllTimeFolders; do + # Skip if not a directory + [ ! -d "$dir" ] && continue + + # Find all files in this time directory + while IFS= read -r filename; do + # Skip empty lines and excluded files + [ -z "$filename" ] || [ "${exclude_dict[$filename]+exists}" ] && continue + + # Add to unique files + unique_files["$filename"]=1 + done < <(find "$dir" -maxdepth 1 -type f -printf '%f\n') + done + + # Set completion reply to the unique filenames + COMPREPLY=(${!unique_files[@]}) + + # Clear global variable + AllTimeFolders= } _pFlowToVTK(){ - if [ "$3" == "--time" ] ; then + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + + # Check if we're completing a field + local is_field=0 + for ((i=1; i Date: Tue, 15 Apr 2025 21:27:49 +0330 Subject: [PATCH 5/9] 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 From 35f10e5a94d93bf02355ce0abb50deead1d3e6d0 Mon Sep 17 00:00:00 2001 From: Hamidreza Date: Tue, 15 Apr 2025 21:30:54 +0330 Subject: [PATCH 6/9] Operations averge, mass velocity and region multisphereRegion are added --- .../PostprocessOperationAvMassVelocity.cpp | 20 ++ .../PostprocessOperationAvMassVelocity.hpp | 173 +++++++++++++++ .../PostprocessOperationAverage.cpp | 138 ++++++++++++ .../PostprocessOperationAverage.hpp | 203 ++++++++++++++++++ .../multipleSpheresRegionPoints.cpp | 98 +++++++++ .../multipleSpheresRegionPoints.hpp | 161 ++++++++++++++ 6 files changed, 793 insertions(+) create mode 100644 src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAvMassVelocity.cpp create mode 100644 src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAvMassVelocity.hpp create mode 100644 src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAverage.cpp create mode 100644 src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAverage.hpp create mode 100644 src/PostprocessData/region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.cpp create mode 100644 src/PostprocessData/region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.hpp diff --git a/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAvMassVelocity.cpp b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAvMassVelocity.cpp new file mode 100644 index 00000000..580d5ae0 --- /dev/null +++ b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAvMassVelocity.cpp @@ -0,0 +1,20 @@ +#include "PostprocessOperationAvMassVelocity.hpp" + +pFlow::PostprocessOperationAvMassVelocity::PostprocessOperationAvMassVelocity +( + const dictionary &opDict, + const regionPoints ®Points, + fieldsDataBase &fieldsDB +) +: + PostprocessOperationAverage + ( + opDict, + opDict.getValOrSet("velocityName", "velocity"), + opDict.getValOrSet("massName", "mass"), + "all", + regPoints, + fieldsDB + ) +{ +} \ No newline at end of file diff --git a/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAvMassVelocity.hpp b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAvMassVelocity.hpp new file mode 100644 index 00000000..16b029f1 --- /dev/null +++ b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAvMassVelocity.hpp @@ -0,0 +1,173 @@ +/*------------------------------- 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 __PostprocessOperationAvMassVelocity_hpp__ +#define __PostprocessOperationAvMassVelocity_hpp__ + +/*! + * @class PostprocessOperationAvMassVelocity + * @brief A class for averaging field values within specified regions during post-processing. + * + * @details + * The PostprocessOperationAvMassVelocity class is a specialized post-processing operation that + * calculates the average of field values within specified regions. It inherits from the + * postprocessOperation base class and implements a weighted averaging operation that + * can be applied to scalar (real), vector (realx3), and tensor (realx4) fields. + * + * The average operation follows the mathematical formula: + * \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$ represents all particles within the specified processing region + * - \f$ j \f$ belongs to a subset of \f$ i \f$ based on an includeMask + * - \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}_j \f$ is the value from the target field for particle \f$ j \f$ + * + * The calculation can optionally be divided by the region volume (when divideByVolume is set to yes), + * which allows calculating normalized averages: + * \f[ + * \text{result} = \frac{1}{V_{\text{region}}} \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] + * + * The averaging 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 Example + * Below is a sample dictionary showing how to configure and use this class: + * + * ``` + * processMethod arithmetic; // method of performing the sum (arithmetic, uniformDistribution, GaussianDistribution) + * processRegion sphere; // type of region on which processing is performed + * + * sphereInfo + * { + * radius 0.01; + * center (-0.08 -0.08 0.015); + * } + * + * timeControl default; + * + * /// all the post process operations to be done + * operations + * ( + * // computes the arithmetic mean of particle velocity + * averageVel + * { + * function average; + * field velocity; + * dividedByVolume no; // default is no + * threshold 3; // default is 1 + * includeMask all; // include all particles in the calculation + * } + * + * // computes the fraction of par1 in the region + * par1Fraction + * { + * function average; + * field one; // the "one" field is special - all members have value 1.0 + * phi one; // default is "one" + * 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; + * } + * } + * ); + * ``` + * + * @section defaults Default Behavior + * - By default, `phi` is set to the field named "one" which contains value 1.0 for all entries + * - `dividedByVolume` is set to "no" by default + * - `threshold` is set to 1 by default + * - `includeMask` can be set to various filters, with "all" being the default to include all particles + * + * @section special Special Fields + * The field named "one" is a special field where all members have the value 1.0. This makes it + * particularly useful for calculating: + * + * 1. Volume or number fractions (as shown in the par1Fraction example) + * 2. Simple counts when used with an appropriate mask + * 3. Normalizing values by particle count + * + * @see postprocessOperation + * @see executeAverageOperation + */ + +#include +#include + +#include "postprocessOperation.hpp" +#include "regionField.hpp" +#include "includeMask.hpp" + +namespace pFlow +{ + + +class PostprocessOperationAvMassVelocity +: + public postprocessOperation +{ + +public: + + TypeInfo("PostprocessOperation"); + + /// @brief Constructs average operation processor + /// @param opDict Operation parameters dictionary + /// @param regPoints Region points data + /// @param fieldsDB Fields database + PostprocessOperationAvMassVelocity( + const dictionary& opDict, + const regionPoints& regPoints, + fieldsDataBase& fieldsDB); + + /// destructor + ~PostprocessOperationAvMassVelocity() override = default; + + /// add this virtual constructor to the base class + add_vCtor + ( + postprocessOperation, + PostprocessOperationAvMassVelocity, + dictionary + ); + +}; + + +} + +#endif //__PostprocessOperationAvMassVelocity_hpp__ \ No newline at end of file diff --git a/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAverage.cpp b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAverage.cpp new file mode 100644 index 00000000..a0de2384 --- /dev/null +++ b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAverage.cpp @@ -0,0 +1,138 @@ +#include "PostprocessOperationAverage.hpp" +#include "dictionary.hpp" +#include "fieldsDataBase.hpp" +#include "fieldFunctions.hpp" + +/// Constructs average processor and initializes result field based on input field type +pFlow::PostprocessOperationAverage::PostprocessOperationAverage +( + const dictionary &opDict, + const regionPoints ®Points, + fieldsDataBase &fieldsDB +) +: + postprocessOperation(opDict, regPoints, fieldsDB), + calculateFluctuation2_(opDict.getValOrSet("fluctuation2", Logical(false))) +{ + if( fieldType() == getTypeName() ) + { + processedRegFieldPtr_ = makeUnique( + regionField(processedFieldName(), regPoints, real(0))); + } + else if( fieldType() == getTypeName() ) + { + processedRegFieldPtr_ = makeUnique( + regionField(processedFieldName(), regPoints, realx3(0))); + } + else if( fieldType() == getTypeName() ) + { + processedRegFieldPtr_ = makeUnique( + regionField(processedFieldName(), regPoints, realx4(0))); + } + else + { + fatalErrorInFunction<<" in dictionary "<< opDict.globalName() + << " field type is not supported for average operation" + << " field type is "<< fieldType() + << endl; + fatalExit; + } +} + +pFlow::PostprocessOperationAverage::PostprocessOperationAverage +( + const dictionary &opDict, + const word &fieldName, + const word &phiName, + const word &includeName, + const regionPoints ®Points, + fieldsDataBase &fieldsDB +) +: + postprocessOperation(opDict, fieldName, phiName, includeName, regPoints, fieldsDB), + calculateFluctuation2_(opDict.getValOrSet("fluctuation2", Logical(false))) +{ + if( fieldType() == getTypeName() ) + { + processedRegFieldPtr_ = makeUnique( + regionField(processedFieldName(), regPoints, real(0))); + } + else if( fieldType() == getTypeName() ) + { + processedRegFieldPtr_ = makeUnique( + regionField(processedFieldName(), regPoints, realx3(0))); + } + else if( fieldType() == getTypeName() ) + { + processedRegFieldPtr_ = makeUnique( + regionField(processedFieldName(), regPoints, realx4(0))); + } + else + { + fatalErrorInFunction<<" in dictionary "<< opDict.globalName() + << " field type is not supported for average operation" + << " field type is "<< fieldType() + << endl; + fatalExit; + } +} + +/// Performs weighted average of field values within each region +bool pFlow::PostprocessOperationAverage::execute +( + const std::vector>& weights +) +{ + auto allField = database().updateFieldAll(fieldName()); + auto phi = database().updateFieldReal( + phiFieldName()); + + auto mask = getMask(); + word procName = processedFieldName(); + const auto& regP = regPoints(); + bool dbVol = divideByVolume(); + + processedRegFieldPtr_ = makeUnique + ( + std::visit([&](auto&& field)->processedRegFieldType + { + return executeAverageOperation( + procName, + field, + regP, + dbVol, + weights, + phi, + mask); + }, + allField) + ); + + if(calculateFluctuation2_) + { + auto& processedRegField = processedRegFieldPtr_(); + fluctuation2FieldPtr_ = makeUnique + ( + std::visit([&](auto& field)->processedRegFieldType + { + using T = typename std::decay_t>::valueType; + if constexpr( std::is_same_v || + std::is_same_v|| + std::is_same_v) + { + return executeFluctuation2Operation( + procName, + field, + std::get>(processedRegField), + dbVol, + weights, + mask); + } + }, + allField) + ); + } + + + return true; +} \ No newline at end of file diff --git a/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAverage.hpp b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAverage.hpp new file mode 100644 index 00000000..93181c1e --- /dev/null +++ b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAverage.hpp @@ -0,0 +1,203 @@ +/*------------------------------- 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 __PostprocessOperationAverage_hpp__ +#define __PostprocessOperationAverage_hpp__ + +/*! + * @class PostprocessOperationAverage + * @brief A class for averaging field values within specified regions during post-processing. + * + * @details + * The PostprocessOperationAverage class is a specialized post-processing operation that + * calculates the average of field values within specified regions. It inherits from the + * postprocessOperation base class and implements a weighted averaging operation that + * can be applied to scalar (real), vector (realx3), and tensor (realx4) fields. + * + * The average operation follows the mathematical formula: + * \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$ represents all particles within the specified processing region + * - \f$ j \f$ belongs to a subset of \f$ i \f$ based on an includeMask + * - \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}_j \f$ is the value from the target field for particle \f$ j \f$ + * + * The calculation can optionally be divided by the region volume (when divideByVolume is set to yes), + * which allows calculating normalized averages: + * \f[ + * \text{result} = \frac{1}{V_{\text{region}}} \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] + * + * The averaging 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 Example + * Below is a sample dictionary showing how to configure and use this class: + * + * ``` + * processMethod arithmetic; // method of performing the sum (arithmetic, uniformDistribution, GaussianDistribution) + * processRegion sphere; // type of region on which processing is performed + * + * sphereInfo + * { + * radius 0.01; + * center (-0.08 -0.08 0.015); + * } + * + * timeControl default; + * + * /// all the post process operations to be done + * operations + * ( + * // computes the arithmetic mean of particle velocity + * averageVel + * { + * function average; + * field velocity; + * dividedByVolume no; // default is no + * threshold 3; // default is 1 + * includeMask all; // include all particles in the calculation + * } + * + * // computes the fraction of par1 in the region + * par1Fraction + * { + * function average; + * field one; // the "one" field is special - all members have value 1.0 + * phi one; // default is "one" + * 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; + * } + * } + * ); + * ``` + * + * @section defaults Default Behavior + * - By default, `phi` is set to the field named "one" which contains value 1.0 for all entries + * - `dividedByVolume` is set to "no" by default + * - `threshold` is set to 1 by default + * - `includeMask` can be set to various filters, with "all" being the default to include all particles + * + * @section special Special Fields + * The field named "one" is a special field where all members have the value 1.0. This makes it + * particularly useful for calculating: + * + * 1. Volume or number fractions (as shown in the par1Fraction example) + * 2. Simple counts when used with an appropriate mask + * 3. Normalizing values by particle count + * + * @see postprocessOperation + * @see executeAverageOperation + */ + +#include +#include + +#include "postprocessOperation.hpp" +#include "regionField.hpp" +#include "includeMask.hpp" + +namespace pFlow +{ + + +class PostprocessOperationAverage +: + public postprocessOperation +{ +private: + + ///< Flag to calculate fluctuation powered by 2 + Logical calculateFluctuation2_; + + /// Result field containing averages for each region (real, realx3, or realx4) + uniquePtr processedRegFieldPtr_ = nullptr; + + uniquePtr fluctuation2FieldPtr_ = nullptr; + +public: + + TypeInfo("PostprocessOperation"); + + /// @brief Constructs average operation processor + /// @param opDict Operation parameters dictionary + /// @param regPoints Region points data + /// @param fieldsDB Fields database + PostprocessOperationAverage( + const dictionary& opDict, + const regionPoints& regPoints, + fieldsDataBase& fieldsDB); + + PostprocessOperationAverage( + const dictionary& opDict, + const word& fieldName, + const word& phiName, + const word& includeName, + const regionPoints& regPoints, + fieldsDataBase& fieldsDB); + + + /// destructor + ~PostprocessOperationAverage() override = default; + + /// add this virtual constructor to the base class + add_vCtor + ( + postprocessOperation, + PostprocessOperationAverage, + dictionary + ); + + /// @brief Get the processed field containing regional averages + /// @return Const reference to average results + const processedRegFieldType& processedField()const override + { + return processedRegFieldPtr_(); + } + + /// @brief Execute average operation on field values + /// @param weights Weight factors for particles + /// @return True if successful + bool execute(const std::vector>& weights) override; + +}; + + +} + +#endif //__PostprocessOperationAverage_hpp__ \ No newline at end of file diff --git a/src/PostprocessData/region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.cpp b/src/PostprocessData/region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.cpp new file mode 100644 index 00000000..8665f72e --- /dev/null +++ b/src/PostprocessData/region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.cpp @@ -0,0 +1,98 @@ +#include "multipleSpheresRegionPoints.hpp" +#include "fieldsDataBase.hpp" + +pFlow::multipleSpheresRegionPoints::multipleSpheresRegionPoints +( + const dictionary &dict, + fieldsDataBase &fieldsDataBase +) +: + regionPoints(dict, fieldsDataBase) +{ + const auto& multiSphereInfo = dict.subDict("multipleSphereInfo"); + + // Read centers and radii lists + auto centers = multiSphereInfo.getVal>("centers"); + auto radii = multiSphereInfo.getVal>("radii"); + + // Check if lists have the same length + if(centers.size() != radii.size()) + { + fatalErrorInFunction + << "The number of centers (" << centers.size() + << ") does not match the number of radii (" << radii.size() << ")" + << endl; + fatalExit; + } + + uint32 nSpheres = centers.size(); + + // Initialize data structures + sphereRegions_.resize(nSpheres, sphere(realx3(0.0, 0.0, 0.0), 1.0)); + centerPoints_.resize(nSpheres); + diameters_.resize(nSpheres); + volumes_.resize(nSpheres); + selectedPoints_.resize(nSpheres); + + // Setup each sphere + for (uint32 i = 0; i < nSpheres; ++i) + { + real diameter = 2.0 * radii[i]; // Convert radius to diameter + + sphereRegions_[i] = pFlow::sphere(centers[i], radii[i]); + centerPoints_[i] = centers[i]; + diameters_[i] = diameter; + volumes_[i] = sphereRegions_[i].volume(); + } +} + +pFlow::span pFlow::multipleSpheresRegionPoints::indices(uint32 elem) const +{ + if (elem >= size()) + { + fatalErrorInFunction + << "The element index is out of range. elem: " << elem + << " size: " << size() << endl; + fatalExit; + } + + return span(selectedPoints_[elem].data(), selectedPoints_[elem].size()); +} + +bool pFlow::multipleSpheresRegionPoints::update() +{ + const auto points = database().updatePoints(); + for (auto& elem : selectedPoints_) + { + elem.clear(); + } + + for (uint32 i = 0; i < points.size(); ++i) + { + for (uint32 j = 0; j < sphereRegions_.size(); ++j) + { + if (sphereRegions_[j].isInside(points[i])) + { + selectedPoints_[j].push_back(i); + } + } + } + return true; +} + +bool pFlow::multipleSpheresRegionPoints::write(iOstream &os) const +{ + os << "# Multiple spheres region points\n"; + os << "# No." << tab << "centerPoint" << tab << "diameter" << endl; + for (uint32 i = 0; i < sphereRegions_.size(); ++i) + { + os << "# " << i << tab << sphereRegions_[i].center() << tab << diameters_[i] << '\n'; + } + os << "time/No. "; + for (uint32 i = 0; i < sphereRegions_.size(); ++i) + { + os << i << " "; + } + os << endl; + return true; +} diff --git a/src/PostprocessData/region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.hpp b/src/PostprocessData/region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.hpp new file mode 100644 index 00000000..f250d216 --- /dev/null +++ b/src/PostprocessData/region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.hpp @@ -0,0 +1,161 @@ +/*------------------------------- 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. + +-----------------------------------------------------------------------------*/ + +/** + * @class multipleSpheresRegionPoints + * @brief A class to select and track particles contained within multiple + * spherical regions + * @details This class defines multiple spherical regions in the simulation + * domain and identifies which particles are contained within each + * sphere at each time step. It inherits from the regionPoints base + * class and specializes it for handling multiple spherical regions + * simultaneously. + * + * The class reads a list of center points and radii from a dictionary, + * creates sphere objects for each, and provides methods to: + * - Track which particles are inside each spherical region + * - Return volumetric information about the regions + * - Access center points and size information for each sphere + * + * + * @note Used in post-processing workflows to analyze particle behavior + * in specific regions of interest within the simulation domain. + * + * @see regionPoints Base class for all region-based point selection + * @see sphere Geometric primitive used to define spherical regions + * @see postprocessPhasicFlow Utility for post-processing simulation data + * @see fieldsDataBase Database containing simulation field data + */ + +#ifndef __multipleSpheresRegionPoints_hpp__ +#define __multipleSpheresRegionPoints_hpp__ + +#include "regionPoints.hpp" +#include "sphere.hpp" +#include "Vectors.hpp" + +namespace pFlow +{ + +class multipleSpheresRegionPoints +: + public regionPoints +{ +private: + + /// Vector containing all spherical regions used for particle selection + Vector sphereRegions_; + + /// Center coordinates of all spherical regions + realx3Vector centerPoints_; + + /// Diameters of all spherical regions + realVector diameters_; + + /// Volumes of all spherical regions + realVector volumes_; + + /// Vectors of point indices for particles contained in each spherical region + /// Each element corresponds to a particular sphere region + Vector selectedPoints_; + +public: + + /// Type identification for run-time type information + TypeInfo("multipleSpheres"); + + /// Constructor + /// @param dict Dictionary containing multipleSpheresInfo for the regions + /// @param fieldsDataBase Reference to the database containing field data + multipleSpheresRegionPoints( + const dictionary& dict, + fieldsDataBase& fieldsDataBase); + + /// Virtual destructor for proper inheritance cleanup + ~multipleSpheresRegionPoints() override = default; + + /// Returns the number of spherical regions + /// @return Number of spherical regions + uint32 size()const override + { + return sphereRegions_.size(); + } + + /// Checks if there are any spherical regions defined + /// @return True if no regions exist, false otherwise + bool empty()const override + { + return sphereRegions_.empty(); + } + + /// Returns the volumes of all spherical regions + /// @return Span containing the volumes of all regions + span volumes()const override + { + return span(volumes_.data(), volumes_.size()); + } + + /// Returns the diameters of all spherical regions + /// @return Span containing the diameters of all regions + span diameters()const + { + return span(diameters_.data(), diameters_.size()); + } + + /// Returns the equivalent diameters of all spherical regions + /// @return Span containing the equivalent diameters (same as diameters) + span eqDiameters()const + { + return diameters(); + } + + /// Returns the center coordinates of all spherical regions + /// @return Span containing the center points of all regions + span centers()const override + { + return span(centerPoints_.data(), centerPoints_.size()); + } + + /// Returns the indices of particles contained in a specific spherical region + /// @param elem Index of the spherical region to query + /// @return Span containing indices of particles within the specified region + span indices(uint32 elem)const override; + + /// Updates the selection of particles within each spherical region + /// @return True if update was successful, false otherwise + bool update() override; + + /// Determines if data should be written to the same time file + /// @return True to indicate regions should be written to the same time file + bool writeToSameTimeFile()const override + { + return true; + } + + /// Writes region data to the output stream + /// @param os Output stream to write data to + /// @return True if write operation was successful, false otherwise + bool write(iOstream& os) const override; +}; + +} + + +#endif // __multipleSpheresRegionPoints_hpp__ \ No newline at end of file From 7c9a72417496bf7e8cd6f28f3646aa38b1c75628 Mon Sep 17 00:00:00 2001 From: Hamidreza Date: Tue, 15 Apr 2025 22:20:00 +0330 Subject: [PATCH 7/9] Postprocessing: IncludeMask documentation --- .../operation/includeMask/IncludeMask.hpp | 46 +++++++++++++- .../operation/includeMask/includeMask.hpp | 62 ++++++++++++++++++- .../operation/includeMask/maskOperations.hpp | 19 ++++++ 3 files changed, 124 insertions(+), 3 deletions(-) diff --git a/src/PostprocessData/operation/includeMask/IncludeMask.hpp b/src/PostprocessData/operation/includeMask/IncludeMask.hpp index bff0449a..6a4a24f7 100644 --- a/src/PostprocessData/operation/includeMask/IncludeMask.hpp +++ b/src/PostprocessData/operation/includeMask/IncludeMask.hpp @@ -18,6 +18,39 @@ Licence: -----------------------------------------------------------------------------*/ +/** + * @brief A template class implementing includeMask for filtering data based on field values + * + * The IncludeMask class creates boolean masks that identify which elements from a field + * satisfy a given condition. It applies an operator to each element of a field and + * generates a mask (vector of booleans) where true means the element satisfies the + * condition and should be included. + * + * @tparam T The data type of the field (real, realx3, realx4) + * @tparam Operator The operation class that defines the condition (e.g., greaterThanOp) + * + * The class has a specialized implementation for allOp operator which includes all elements. + * + * Usage example in postprocessDataDict: + * ``` + * // Create a dictionary with the required configuration for filtering + * + * { + * includeMask lessThan; + * + * // Diameter of par1 is 0.003, so these settings + * // will select only particles of type par1 + * lessThanInfo + * { + * field diameter; + * value 0.0031; + * } + * + * } + * + * ``` + */ + #ifndef __IncludeMask_hpp__ #define __IncludeMask_hpp__ @@ -31,7 +64,6 @@ Licence: namespace pFlow { - template class IncludeMask : @@ -39,18 +71,24 @@ class IncludeMask { public: + /// Type alias for the mask container returned by getMask() using Mask = typename includeMask::Mask; private: + /// Boolean vector the filtering status of each element (true = include) std::vector mask_; + /// Comparison operator instance that evaluates the filtering condition Operator operator_; + /// Name of the field to apply filtering on word fieldName_; + /// Timestamp when mask was last updated (-1 indicates never updated) timeValue lastUpdated_ = -1; + /// Updates the mask based on current field values if needed, returns true if successful bool updateMask() { timeValue t = database().currentTime(); @@ -91,6 +129,7 @@ private: return true; } + /// Returns the name of the operator as a string (from operator's TYPENAME) static word operatorName() { @@ -101,6 +140,7 @@ public: TypeInfoTemplate12("IncludeMask", T, Operator); + /// Constructs an IncludeMask using settings from dictionary and field database IncludeMask( const dictionary& dict, fieldsDataBase& feildsDB) @@ -113,12 +153,14 @@ public: operatorName()+"Info" ).getVal("field")) {} - + + /// Add virtual constructor pattern for creating instances add_vCtor( includeMask, IncludeMask, dictionary); + /// Returns the mask for filtering elements (updates the mask if necessary) Mask getMask() override { updateMask(); diff --git a/src/PostprocessData/operation/includeMask/includeMask.hpp b/src/PostprocessData/operation/includeMask/includeMask.hpp index 522e1641..928822b8 100644 --- a/src/PostprocessData/operation/includeMask/includeMask.hpp +++ b/src/PostprocessData/operation/includeMask/includeMask.hpp @@ -18,6 +18,27 @@ Licence: -----------------------------------------------------------------------------*/ +/** + * @class includeMask +* @brief Base class for creating inclusion masks for data filtering +* + * includeMask is an abstract base class for creating masks that filter data + * from a fieldsDataBase. Derived classes implement specific filtering criteria + * through the getMask() method which returns a Mask object - a wrapper around + * a vector of booleans that indicates which elements to include/exclude. + * + * This class follows a factory pattern with create() methods that instantiate + * the appropriate derived mask type based on dictionary settings. + * + * Derived classes can implement various filtering strategies such as: + * - Filtering by field values + * - Filtering by spatial regions + * - Filtering by predefined criteria + * + * The Mask objects returned by getMask() can be used in postprocessing operations + * to include only the data points that match the specified criteria. + */ + #ifndef __includeMask_hpp__ #define __includeMask_hpp__ @@ -28,36 +49,49 @@ Licence: namespace pFlow { - +// forward declaration class fieldsDataBase; class dictionary; + class includeMask { public: + /// @brief Wrapper around a boolean vector that represents elements to include/exclude + /// Provides a functional interface to access the underlying mask vector + /// where true indicates inclusion and false indicates exclusion. class Mask { + /// @brief Reference to the underlying boolean vector const std::vector& mask_; public: + /// @brief Constructor from a boolean vector + /// @param msk Boolean vector where true means include, false means exclude Mask(const std::vector& msk) : mask_(msk) {} + /// @brief Copy constructor Mask(const Mask&) = default; + /// @brief Move constructor Mask(Mask&&) = default; + /// @brief Destructor ~Mask()=default; + /// @brief Get the size of the mask auto size()const { return mask_.size(); } + /// @brief Check if element at index i should be included + /// @param i Index to check bool operator()(uint32 i)const { return mask_[i]; @@ -66,18 +100,28 @@ public: private: + /// @brief Reference to the database containing fields to be filtered fieldsDataBase& database_; public: TypeInfo("includeMask"); + /// @brief Constructor + /// @param opDict Dictionary containing operation settings + /// @param feildsDB Database of fields includeMask(const dictionary& opDict, fieldsDataBase& feildsDB); + /// @brief Constructor with explicit type + /// @param type Type of mask to create + /// @param opDict Dictionary containing operation settings + /// @param feildsDB Database of fields includeMask(const word& type, const dictionary& opDict, fieldsDataBase& feildsDB); + /// @brief Virtual destructor virtual ~includeMask() = default; + /// @brief Virtual constructor pattern implementation using dictionary create_vCtor ( includeMask, @@ -88,6 +132,7 @@ public: (opDict, feildsDB) ); + /// @brief Virtual constructor pattern implementation using type and dictionary create_vCtor ( includeMask, @@ -100,24 +145,39 @@ public: (type, opDict, feildsDB) ); + /// @brief Get const access to the database + /// @return Const reference to the fields database const fieldsDataBase& database()const { return database_; } + /// @brief Get non-const access to the database + /// @return Reference to the fields database fieldsDataBase& database() { return database_; } + /// @brief Get the mask for filtering elements + /// @return Mask object indicating which elements to include virtual Mask getMask()= 0; + /// @brief Factory method to create appropriate mask type from dictionary + /// @param opDict Dictionary with mask settings including type + /// @param feildsDB Database of fields to filter + /// @return Unique pointer to created mask instance static uniquePtr create( const dictionary& opDict, fieldsDataBase& feildsDB); + /// @brief Factory method to create mask with explicit type + /// @param type Type of mask to create + /// @param opDict Dictionary with mask settings + /// @param feildsDB Database of fields to filter + /// @return Unique pointer to created mask instance static uniquePtr create( const word& type, diff --git a/src/PostprocessData/operation/includeMask/maskOperations.hpp b/src/PostprocessData/operation/includeMask/maskOperations.hpp index 13fec7d3..63bb5665 100644 --- a/src/PostprocessData/operation/includeMask/maskOperations.hpp +++ b/src/PostprocessData/operation/includeMask/maskOperations.hpp @@ -1,3 +1,22 @@ +/*------------------------------- 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 __maskOperation_hpp__ #define __maskOperation_hpp__ From 98a30bc98c96ad931887f6d3cdda10ff602ed5a9 Mon Sep 17 00:00:00 2001 From: Hamidreza Date: Thu, 17 Apr 2025 02:41:36 +0330 Subject: [PATCH 8/9] keepHistory for integration to automatically remove the fields related to integration. The default is no save on the disk --- .../AdamsBashforth2/AdamsBashforth2.cpp | 7 ++++--- .../AdamsBashforth2/AdamsBashforth2.hpp | 3 ++- .../AdamsBashforth3/AdamsBashforth3.cpp | 7 ++++--- .../AdamsBashforth3/AdamsBashforth3.hpp | 3 ++- .../AdamsBashforth4/AdamsBashforth4.cpp | 7 ++++--- .../AdamsBashforth4/AdamsBashforth4.hpp | 3 ++- .../AdamsBashforth5/AdamsBashforth5.cpp | 7 ++++--- .../AdamsBashforth5/AdamsBashforth5.hpp | 3 ++- src/Integration/integration/integration.cpp | 11 +++++++---- src/Integration/integration/integration.hpp | 19 +++++++++++++++---- .../grainParticles/grainParticles.cpp | 3 ++- .../sphereParticles/sphereParticles.cpp | 3 ++- .../dynamicPointStructure.cpp | 8 +++++--- .../systemControl/systemControl.cpp | 15 ++++++++++++--- .../systemControl/systemControl.hpp | 1 + src/phasicFlow/types/quadruple/quadruple.hpp | 2 +- 16 files changed, 69 insertions(+), 33 deletions(-) diff --git a/src/Integration/AdamsBashforth2/AdamsBashforth2.cpp b/src/Integration/AdamsBashforth2/AdamsBashforth2.cpp index 0eaa4bdb..9f457fe8 100644 --- a/src/Integration/AdamsBashforth2/AdamsBashforth2.cpp +++ b/src/Integration/AdamsBashforth2/AdamsBashforth2.cpp @@ -97,10 +97,11 @@ pFlow::AdamsBashforth2::AdamsBashforth2 const word& baseName, pointStructure& pStruct, const word& method, - const realx3Field_D& initialValField + const realx3Field_D& initialValField, + bool keepHistory ) : - integration(baseName, pStruct, method, initialValField), + integration(baseName, pStruct, method, initialValField, keepHistory), realx3PointField_D ( objectFile @@ -108,7 +109,7 @@ pFlow::AdamsBashforth2::AdamsBashforth2 groupNames(baseName,"dy1"), pStruct.time().integrationFolder(), objectFile::READ_IF_PRESENT, - objectFile::WRITE_ALWAYS + keepHistory?objectFile::WRITE_ALWAYS:objectFile::WRITE_NEVER ), pStruct, zero3, diff --git a/src/Integration/AdamsBashforth2/AdamsBashforth2.hpp b/src/Integration/AdamsBashforth2/AdamsBashforth2.hpp index a8218465..0241bb8e 100644 --- a/src/Integration/AdamsBashforth2/AdamsBashforth2.hpp +++ b/src/Integration/AdamsBashforth2/AdamsBashforth2.hpp @@ -81,7 +81,8 @@ public: const word& baseName, pointStructure& pStruct, const word& method, - const realx3Field_D& initialValField); + const realx3Field_D& initialValField, + bool keepHistory); /// Destructor ~AdamsBashforth2()override = default; diff --git a/src/Integration/AdamsBashforth3/AdamsBashforth3.cpp b/src/Integration/AdamsBashforth3/AdamsBashforth3.cpp index e728e533..c15b5ff2 100644 --- a/src/Integration/AdamsBashforth3/AdamsBashforth3.cpp +++ b/src/Integration/AdamsBashforth3/AdamsBashforth3.cpp @@ -109,10 +109,11 @@ pFlow::AdamsBashforth3::AdamsBashforth3 const word& baseName, pointStructure& pStruct, const word& method, - const realx3Field_D& initialValField + const realx3Field_D& initialValField, + bool keepHistory ) : - AdamsBashforth2(baseName, pStruct, method, initialValField), + AdamsBashforth2(baseName, pStruct, method, initialValField, keepHistory), dy2_ ( objectFile @@ -120,7 +121,7 @@ pFlow::AdamsBashforth3::AdamsBashforth3 groupNames(baseName,"dy2"), pStruct.time().integrationFolder(), objectFile::READ_IF_PRESENT, - objectFile::WRITE_ALWAYS + keepHistory ? objectFile::WRITE_ALWAYS : objectFile::WRITE_NEVER ), pStruct, zero3, diff --git a/src/Integration/AdamsBashforth3/AdamsBashforth3.hpp b/src/Integration/AdamsBashforth3/AdamsBashforth3.hpp index e71166ae..50a23c39 100644 --- a/src/Integration/AdamsBashforth3/AdamsBashforth3.hpp +++ b/src/Integration/AdamsBashforth3/AdamsBashforth3.hpp @@ -71,7 +71,8 @@ public: const word& baseName, pointStructure& pStruct, const word& method, - const realx3Field_D& initialValField); + const realx3Field_D& initialValField, + bool keepHistory); /// Destructor diff --git a/src/Integration/AdamsBashforth4/AdamsBashforth4.cpp b/src/Integration/AdamsBashforth4/AdamsBashforth4.cpp index a0d5c4a1..24461282 100644 --- a/src/Integration/AdamsBashforth4/AdamsBashforth4.cpp +++ b/src/Integration/AdamsBashforth4/AdamsBashforth4.cpp @@ -115,10 +115,11 @@ pFlow::AdamsBashforth4::AdamsBashforth4 const word& baseName, pointStructure& pStruct, const word& method, - const realx3Field_D& initialValField + const realx3Field_D& initialValField, + bool keepHistory ) : - AdamsBashforth3(baseName, pStruct, method, initialValField), + AdamsBashforth3(baseName, pStruct, method, initialValField, keepHistory), dy3_ ( objectFile @@ -126,7 +127,7 @@ pFlow::AdamsBashforth4::AdamsBashforth4 groupNames(baseName,"dy3"), pStruct.time().integrationFolder(), objectFile::READ_IF_PRESENT, - objectFile::WRITE_ALWAYS + keepHistory?objectFile::WRITE_ALWAYS:objectFile::WRITE_NEVER ), pStruct, zero3, diff --git a/src/Integration/AdamsBashforth4/AdamsBashforth4.hpp b/src/Integration/AdamsBashforth4/AdamsBashforth4.hpp index fc2b913b..a9bb9a43 100644 --- a/src/Integration/AdamsBashforth4/AdamsBashforth4.hpp +++ b/src/Integration/AdamsBashforth4/AdamsBashforth4.hpp @@ -69,7 +69,8 @@ public: const word& baseName, pointStructure& pStruct, const word& method, - const realx3Field_D& initialValField); + const realx3Field_D& initialValField, + bool keepHistory); diff --git a/src/Integration/AdamsBashforth5/AdamsBashforth5.cpp b/src/Integration/AdamsBashforth5/AdamsBashforth5.cpp index 3fde7276..dd1503e2 100644 --- a/src/Integration/AdamsBashforth5/AdamsBashforth5.cpp +++ b/src/Integration/AdamsBashforth5/AdamsBashforth5.cpp @@ -123,10 +123,11 @@ pFlow::AdamsBashforth5::AdamsBashforth5 const word &baseName, pointStructure &pStruct, const word &method, - const realx3Field_D &initialValField + const realx3Field_D &initialValField, + bool keepHistory ) : - AdamsBashforth4(baseName, pStruct, method, initialValField), + AdamsBashforth4(baseName, pStruct, method, initialValField, keepHistory), dy4_ ( objectFile @@ -134,7 +135,7 @@ pFlow::AdamsBashforth5::AdamsBashforth5 groupNames(baseName,"dy4"), pStruct.time().integrationFolder(), objectFile::READ_IF_PRESENT, - objectFile::WRITE_ALWAYS + keepHistory?objectFile::WRITE_ALWAYS:objectFile::WRITE_NEVER ), pStruct, zero3, diff --git a/src/Integration/AdamsBashforth5/AdamsBashforth5.hpp b/src/Integration/AdamsBashforth5/AdamsBashforth5.hpp index ed16d99c..939f96a3 100644 --- a/src/Integration/AdamsBashforth5/AdamsBashforth5.hpp +++ b/src/Integration/AdamsBashforth5/AdamsBashforth5.hpp @@ -68,7 +68,8 @@ public: const word& baseName, pointStructure& pStruct, const word& method, - const realx3Field_D& initialValField); + const realx3Field_D& initialValField, + bool keepHistory); diff --git a/src/Integration/integration/integration.cpp b/src/Integration/integration/integration.cpp index d9fc8ba8..710df9ad 100644 --- a/src/Integration/integration/integration.cpp +++ b/src/Integration/integration/integration.cpp @@ -51,10 +51,12 @@ pFlow::integration::integration( const word &baseName, pointStructure &pStruct, const word &, - const realx3Field_D &) + const realx3Field_D &, + bool keepHistory) : owner_(*pStruct.owner()), pStruct_(pStruct), - baseName_(baseName) + baseName_(baseName), + keepHistory_(keepHistory) {} @@ -64,12 +66,13 @@ pFlow::uniquePtr const word& baseName, pointStructure& pStruct, const word& method, - const realx3Field_D& initialValField + const realx3Field_D& initialValField, + bool keepHistory ) { if( wordvCtorSelector_.search(method) ) { - return wordvCtorSelector_[method] (baseName, pStruct, method, initialValField); + return wordvCtorSelector_[method] (baseName, pStruct, method, initialValField, keepHistory); } else { diff --git a/src/Integration/integration/integration.hpp b/src/Integration/integration/integration.hpp index fb0d84df..1161bd1e 100644 --- a/src/Integration/integration/integration.hpp +++ b/src/Integration/integration/integration.hpp @@ -24,6 +24,7 @@ Licence: #include "virtualConstructor.hpp" #include "pointFields.hpp" +#include "Logical.hpp" namespace pFlow @@ -63,6 +64,8 @@ private: /// The base name for integration const word baseName_; + bool keepHistory_; + protected: bool insertValues( @@ -83,7 +86,8 @@ public: const word& baseName, pointStructure& pStruct, const word& method, - const realx3Field_D& initialValField); + const realx3Field_D& initialValField, + bool keepHistory); /// Copy constructor integration(const integration&) = default; @@ -109,9 +113,10 @@ public: const word& baseName, pointStructure& pStruct, const word& method, - const realx3Field_D& initialValField + const realx3Field_D& initialValField, + bool keepHistory ), - (baseName, pStruct, method, initialValField) + (baseName, pStruct, method, initialValField, keepHistory) ); @@ -138,6 +143,11 @@ public: return owner_; } + bool keepHistory()const + { + return keepHistory_; + } + virtual void updateBoundariesSlaveToMasterIfRequested() = 0; /// return integration method @@ -164,7 +174,8 @@ public: const word& baseName, pointStructure& pStruct, const word& method, - const realx3Field_D& initialValField); + const realx3Field_D& initialValField, + bool keepHistory); }; // integration diff --git a/src/Particles/GrainParticles/grainParticles/grainParticles.cpp b/src/Particles/GrainParticles/grainParticles/grainParticles.cpp index 1e6cc065..d4d5bf05 100644 --- a/src/Particles/GrainParticles/grainParticles/grainParticles.cpp +++ b/src/Particles/GrainParticles/grainParticles/grainParticles.cpp @@ -248,7 +248,8 @@ pFlow::grainParticles::grainParticles( "rVelocity", dynPointStruct(), intMethod, - rAcceleration_.field() + rAcceleration_.field(), + control.keepIntegrationHistory() ); if( !rVelIntegration_ ) diff --git a/src/Particles/SphereParticles/sphereParticles/sphereParticles.cpp b/src/Particles/SphereParticles/sphereParticles/sphereParticles.cpp index f63177b1..ffb73e3c 100644 --- a/src/Particles/SphereParticles/sphereParticles/sphereParticles.cpp +++ b/src/Particles/SphereParticles/sphereParticles/sphereParticles.cpp @@ -229,7 +229,8 @@ pFlow::sphereParticles::sphereParticles( "rVelocity", dynPointStruct(), intMethod, - rAcceleration_.field() + rAcceleration_.field(), + control.keepIntegrationHistory() ); if( !rVelIntegration_ ) diff --git a/src/Particles/dynamicPointStructure/dynamicPointStructure.cpp b/src/Particles/dynamicPointStructure/dynamicPointStructure.cpp index fb465bcb..cdc8472a 100644 --- a/src/Particles/dynamicPointStructure/dynamicPointStructure.cpp +++ b/src/Particles/dynamicPointStructure/dynamicPointStructure.cpp @@ -58,13 +58,14 @@ pFlow::dynamicPointStructure::dynamicPointStructure { REPORT(1)<< "Creating integration method "<< Green_Text(integrationMethod_)<<" for dynamicPointStructure."< Date: Fri, 18 Apr 2025 15:32:53 +0330 Subject: [PATCH 9/9] PostprocessData update Modifications on fieldsDataBase to work both during simulation and post-simulation Some bug fixes and changes to the code based Correction for region volume --- .../GrainParticles/grainShape/grainShape.cpp | 27 +- .../GrainParticles/grainShape/grainShape.hpp | 26 +- .../sphereShape/sphereShape.cpp | 17 + .../sphereShape/sphereShape.hpp | 15 + src/Particles/particles/particles.hpp | 2 +- src/Particles/particles/shape/shape.cpp | 68 +++- src/Particles/particles/shape/shape.hpp | 29 ++ src/PostprocessData/CMakeLists.txt | 3 + .../fieldsDataBase/fieldsDataBase.cpp | 297 ++++++++++++--- .../fieldsDataBase/fieldsDataBase.hpp | 342 ++++++------------ .../fieldsDataBase/fieldsDataBaseDclr.hpp | 45 +++ .../fieldsDataBaseTemplates.cpp | 115 ++++-- .../simulationFieldsDataBase.cpp | 62 ++++ .../simulationFieldsDataBase.hpp | 79 ++++ .../PostprocessOperationAvMassVelocity.hpp | 4 +- .../PostprocessOperationAverage.cpp | 8 +- .../PostprocessOperationAverage.hpp | 4 +- .../PostprocessOperationSum.cpp | 7 +- .../PostprocessOperationSum.hpp | 4 +- ...ldFunctions.hpp => operationFunctions.hpp} | 24 +- .../operation/includeMask/IncludeMask.hpp | 67 +++- .../operation/includeMask/includeMask.cpp | 6 +- .../postprocessOperation.cpp | 6 +- .../postprocessOperation.hpp | 5 +- .../PostprocessComponent.cpp | 8 +- .../PostprocessComponent.hpp | 12 + .../PostprocessComponentArithmetic.hpp | 2 + .../PostprocessComponentGaussian.hpp | 10 +- .../PostprocessComponentUniform.hpp | 2 + .../PostprocessComponents.cpp | 11 +- .../particleProbePostprocessComponent.cpp | 2 +- .../postprocessData/postprocessData.cpp | 17 +- .../postprocessData/postprocessData.hpp | 5 +- .../postprocessData/postprocessGlobals.hpp | 2 +- .../processMethod/GaussianDistribution.hpp | 8 +- .../centerPointsRegionPoints.cpp | 4 +- .../lineRegionPoints/lineRegionPoints.cpp | 16 + .../lineRegionPoints/lineRegionPoints.hpp | 2 + .../multipleSpheresRegionPoints.cpp | 14 + .../multipleSpheresRegionPoints.hpp | 5 + .../sampleDictionary/postprocessDataDict | 10 +- .../repository/repository/repository.cpp | 37 +- .../repository/repository/repository.hpp | 4 + .../selectorRandomPoints.cpp | 15 +- 44 files changed, 1065 insertions(+), 383 deletions(-) create mode 100644 src/PostprocessData/fieldsDataBase/fieldsDataBaseDclr.hpp create mode 100644 src/PostprocessData/fieldsDataBase/simulationFieldsDataBase.cpp create mode 100644 src/PostprocessData/fieldsDataBase/simulationFieldsDataBase.hpp rename src/PostprocessData/operation/PostprocessOperation/{fieldFunctions.hpp => operationFunctions.hpp} (88%) diff --git a/src/Particles/GrainParticles/grainShape/grainShape.cpp b/src/Particles/GrainParticles/grainShape/grainShape.cpp index 4558940b..246b5be8 100644 --- a/src/Particles/GrainParticles/grainShape/grainShape.cpp +++ b/src/Particles/GrainParticles/grainShape/grainShape.cpp @@ -73,6 +73,18 @@ pFlow::grainShape::grainShape } } +pFlow::grainShape::grainShape +( + const word &shapeType, + const word &fileName, + repository *owner, + const property &prop +) +: + grainShape(fileName, owner, prop) +{ +} + pFlow::real pFlow::grainShape::maxBoundingSphere() const { return max(grainDiameters_); @@ -99,9 +111,12 @@ pFlow::real pFlow::grainShape::boundingDiameter(uint32 index) const { return grainDiameters_[index]; } - fatalErrorInFunction<<"Invalid index for diameter "<< - index< pFlow::shape::create +( + const word &shapeType, + const word &fileName, + repository *owner, + const property &prop +) +{ + word type = angleBracketsNames("shape", shapeType); + + if( wordvCtorSelector_.search(type) ) + { + auto objPtr = + wordvCtorSelector_[type] + (shapeType, fileName, owner, prop); + return objPtr; + } + else + { + printKeys + ( + fatalError << "Ctor Selector "<< + type << " dose not exist. \n" + <<"Avaiable ones are: \n\n" + , + wordvCtorSelector_ + ); + fatalExit; + return nullptr; + } + +} diff --git a/src/Particles/particles/shape/shape.hpp b/src/Particles/particles/shape/shape.hpp index 5a4007aa..4c7d74e9 100644 --- a/src/Particles/particles/shape/shape.hpp +++ b/src/Particles/particles/shape/shape.hpp @@ -60,9 +60,28 @@ public: const word& fileName, repository* owner, const property& prop); + + shape( + const word& shapeType, + const word& fileName, + repository* owner, + const property& prop); ~shape() override=default; + create_vCtor + ( + shape, + word, + ( + const word& shapeType, + const word& fileName, + repository* owner, + const property& prop + ), + (shapeType, fileName, owner, prop) + ); + inline const auto& properties()const { @@ -148,6 +167,9 @@ public: virtual realVector boundingDiameter()const = 0; + virtual + realVector volume()const = 0; + virtual bool mass(uint32 index, real& m)const = 0; @@ -187,6 +209,13 @@ public: virtual real Inertial_zz(uint32 index)const = 0; + static + uniquePtr create( + const word& shapeType, + const word& fileName, + repository* owner, + const property& prop); + }; } diff --git a/src/PostprocessData/CMakeLists.txt b/src/PostprocessData/CMakeLists.txt index bb3999d4..a68a6d75 100644 --- a/src/PostprocessData/CMakeLists.txt +++ b/src/PostprocessData/CMakeLists.txt @@ -4,6 +4,7 @@ set(SourceFiles # Fields database fieldsDataBase/fieldsDataBase.cpp + fieldsDataBase/simulationFieldsDataBase.cpp # Regions region/regionPoints/regionPoints/regionPoints.cpp @@ -21,6 +22,8 @@ set(SourceFiles operation/postprocessOperation/postprocessOperation.cpp operation/PostprocessOperation/PostprocessOperationSum.cpp operation/PostprocessOperation/PostprocessOperationAverage.cpp + operation/PostprocessOperation/PostprocessOperationAvMassVelocity.cpp + operation/includeMask/includeMask.cpp operation/includeMask/IncludeMasks.cpp diff --git a/src/PostprocessData/fieldsDataBase/fieldsDataBase.cpp b/src/PostprocessData/fieldsDataBase/fieldsDataBase.cpp index 508c572c..2ea4e81b 100644 --- a/src/PostprocessData/fieldsDataBase/fieldsDataBase.cpp +++ b/src/PostprocessData/fieldsDataBase/fieldsDataBase.cpp @@ -21,17 +21,43 @@ Licence: #include #include "vocabs.hpp" -#include "Time.hpp" +#include "systemControl.hpp" #include "fieldsDataBase.hpp" #include "fieldFunctions.hpp" -#include "dynamicPointStructure.hpp" -bool pFlow::fieldsDataBase::checkForUpdate(const word &name, bool forceUpdate) + +namespace pFlow +{ + +bool pointFieldGetType(const word& TYPENAME, word& fieldType, word& fieldSpace); + +} + +bool pFlow::fieldsDataBase::loadPointStructureToTime() +{ + return false; +} + +pFlow::word pFlow::fieldsDataBase::getPointFieldType(const word &name) const +{ + word pfType = time_.lookupObjectTypeName(name); + word type, space; + if(!pointFieldGetType(pfType, type, space)) + { + fatalErrorInFunction + <<"Error in retriving the type of pointField " + << pfType<second < t || forceUpdate; iter->second = t; @@ -39,7 +65,7 @@ bool pFlow::fieldsDataBase::checkForUpdate(const word &name, bool forceUpdate) else { shouldUpdate = true; - captureTime_.insertIf(name, t); + captureTime_.insertIf(compoundName, t); } return shouldUpdate; @@ -70,6 +96,105 @@ pFlow::span pFlow::fieldsDataBase::createOrGetRealField(const word field.size()); } +pFlow::span pFlow::fieldsDataBase::createOrGetVolume(bool forceUpdate) +{ + const word fName = "volume"; + bool shouldUpdate = checkForUpdate(fName, forceUpdate); + + if(shouldUpdate) + { + const auto index = updateFieldUint32("shapeIndex", true); + auto vols = getShape().volume(); + + FieldTypeHost volField + ( + fName, + "value", + pointFieldSize() + ); + + for(uint32 i=0; i< volField.size(); i++) + { + volField[i] = vols[index[i]]; + } + + allFields_.emplaceBackOrReplace> + ( + fName, + std::move(volField) + ); + } + + auto& field = allFields_.getObject>(fName); + return span( + field.data(), + field.size()); + +} + +pFlow::span pFlow::fieldsDataBase::createOrGetDensity(bool forceUpdate) +{ + const word fName = "density"; + + bool shouldUpdate = checkForUpdate(fName, forceUpdate); + + if(shouldUpdate) + { + const auto index = updateFieldUint32("shapeIndex", true); + const auto dens = getShape().density(); + + FieldTypeHost denFeild + ( + fName, + "value", + pointFieldSize() + ); + + for(uint32 i=0; i< denFeild.size(); i++) + { + denFeild[i] = dens[index[i]]; + } + + allFields_.emplaceBackOrReplace> + ( + fName, + std::move(denFeild) + ); + } + + auto& field = allFields_.getObject>(fName); + return span( + field.data(), + field.size()); +} + +pFlow::span pFlow::fieldsDataBase::createOrGetOne(bool forceUpdate) +{ + const word fName = "one"; + + bool shouldUpdate = checkForUpdate(fName, forceUpdate); + + if(shouldUpdate) + { + allFields_.emplaceBackOrReplace> + ( + fName, + FieldTypeHost + ( + fName, + "value", + pointFieldSize(), + 1.0 + ) + ); + } + + auto& field = allFields_.getObject>(fName); + return span( + field.data(), + field.size()); +} + bool pFlow::fieldsDataBase::findFunction( const word &compoundFieldName, word &fieldName, @@ -274,9 +399,9 @@ bool pFlow::fieldsDataBase::inputOutputType return false; } -pFlow::fieldsDataBase::fieldsDataBase(const Time &time, bool inSimulation) -: - time_(time), +pFlow::fieldsDataBase::fieldsDataBase(systemControl& control, bool inSimulation) +: + time_(control.time()), inSimulation_(inSimulation) {} @@ -285,84 +410,110 @@ pFlow::timeValue pFlow::fieldsDataBase::currentTime() const return time_.currentTime(); } -bool pFlow::fieldsDataBase::getPointFieldType +bool pFlow::fieldsDataBase::getFieldTypeNameFunction ( - const word& compoundName, - word& fieldName, + const word& compoundName, + word& pointFieldName, word& originalType, word& typeAfterFunction, Functions& func -) +)const { - if( !findFunction(compoundName, fieldName, func)) + if( !findFunction(compoundName, pointFieldName, func)) { - fatalErrorInFunction; + fatalErrorInFunction + <<"Error in processing function for field: " + <second; + // The name is in the reserved fields + originalType = reservedFieldNames_.find(pointFieldName)->second; } else { - word fieldTypeName = time_.lookupObjectTypeName(fieldName); - word space; - if(!pointFieldGetType(fieldTypeName, originalType, space)) + // the name is in the Time object + if(pointFieldNameExists(pointFieldName)) { - fatalErrorInFunction<<"Cannot extract type name from "<< fieldTypeName< pFlow::fieldsDataBase::updatePoints(bool forceUpdate) { - - bool shouldUpdate = checkForUpdate("position", forceUpdate); + const word fName = "position"; + bool shouldUpdate = checkForUpdate(fName, forceUpdate); if(shouldUpdate) { + // load pointStructure + if(!loadPointStructureToTime()) + { + fatalErrorInFunction<< "Error in loading pointStructure to Time object."<( - "position", - pstruct.activePointsHost()); + allFields_.emplaceBackOrReplace + ( + fName, + pstruct.activePointsHost() + ); } - auto& points = allFields_.getObject("position"); + auto& points = allFields_.getObject(fName); return span( points.data(), @@ -379,7 +530,12 @@ pFlow::span pFlow::fieldsDataBase::updateFieldRealx3 word originalType, typeAfterFunction, fieldName; Functions func; - if( !getPointFieldType(compoundName, fieldName, originalType, typeAfterFunction, func)) + if( !getFieldTypeNameFunction( + compoundName, + fieldName, + originalType, + typeAfterFunction, + func) ) { fatalErrorInFunction<< "Error in getting the type name of field: "<< compoundName<<", with type name: "<< originalType < pFlow::fieldsDataBase::updateFieldRealx4 word originalType, typeAfterFunction, fieldName; Functions func; - if( !getPointFieldType(compoundName, fieldName, originalType, typeAfterFunction, func)) + if( !getFieldTypeNameFunction( + compoundName, + fieldName, + originalType, + typeAfterFunction, + func)) { fatalErrorInFunction<< "Error in getting the type name of field: "<< compoundName<<", with type name: "<< originalType < pFlow::fieldsDataBase::updateFieldReal word originalType, typeAfterFunction, fieldName; Functions func; - if( !getPointFieldType(compoundName, fieldName, originalType, typeAfterFunction, func)) + if( !getFieldTypeNameFunction( + compoundName, + fieldName, + originalType, + typeAfterFunction, + func) ) { fatalErrorInFunction<< "Error in getting the type name of field: "<< compoundName<<", with type name: "<< originalType <(nullptr, 0); } - - if( typeAfterFunction== getTypeName() ) + if( typeAfterFunction == getTypeName() ) { return updateFieldRealx3(compoundName, forceUpdate); } @@ -642,19 +805,41 @@ pFlow::allPointFieldTypes pFlow::fieldsDataBase::updateFieldAll } } -const pFlow::pointStructure &pFlow::fieldsDataBase::pStruct() const + + +pFlow::uniquePtr + pFlow::fieldsDataBase::create(systemControl& control, bool inSimulation) { - if(inSimulation_) + word dbType; + if(inSimulation) { - return - static_cast( - time_.lookupObject(pointStructureFile__) - ); + dbType = "fieldsDataBase"; } else { - return time_.lookupObject(pointStructureFile__); + dbType = "fieldsDataBase"; } + + if( boolvCtorSelector_.search(dbType) ) + { + auto objPtr = + boolvCtorSelector_[dbType](control, inSimulation); + return objPtr; + } + else + { + printKeys + ( + fatalError << "Ctor Selector "<< + dbType << " does not exist. \n" + <<"Available ones are: \n\n" + , + boolvCtorSelector_ + ); + fatalExit; + } + + return nullptr; } bool pFlow::pointFieldGetType(const word& TYPENAME, word& fieldType, word& fieldSpace) diff --git a/src/PostprocessData/fieldsDataBase/fieldsDataBase.hpp b/src/PostprocessData/fieldsDataBase/fieldsDataBase.hpp index 13a71f31..ec8c577e 100644 --- a/src/PostprocessData/fieldsDataBase/fieldsDataBase.hpp +++ b/src/PostprocessData/fieldsDataBase/fieldsDataBase.hpp @@ -21,52 +21,23 @@ Licence: #ifndef __fieldsDataBase_hpp__ #define __fieldsDataBase_hpp__ -#include -#include - +#include "fieldsDataBaseDclr.hpp" #include "pointStructure.hpp" #include "pointFields.hpp" #include "anyList.hpp" #include "Map.hpp" -#include "span.hpp" +#include "shape.hpp" + namespace pFlow { +class systemControl; class Time; -bool pointFieldGetType(const word& TYPENAME, word& fieldType, word& fieldSpace); - -template -concept ValidFieldType = - std::same_as || - std::same_as || - std::same_as || - std::same_as; - -template -concept VectorType = - std::same_as || - std::same_as; - -template -concept ScalarType = - std::same_as; - - -template -concept ValidRegionFieldType = - std::same_as || - std::same_as || - std::same_as ; - - -using allPointFieldTypes = std::variant, span, span>; - class fieldsDataBase - { private: @@ -99,9 +70,6 @@ private: // - Member variables - - /// const reference to the Time object - const Time& time_; /// List to store all the point fields anyList allFields_; @@ -109,114 +77,95 @@ private: /// Map to store the last capture time of each field wordMap captureTime_; - /// + /// Reference to the Time object + Time& time_; + + /// Flag indicating if we're in simulation mode bool inSimulation_ = false; - + +protected: + + /// Map of reserved field names with their corresponding types static const inline std::map reservedFieldNames_ { {"position", "realx3"}, - {"one", "real"} + {"one", "real"}, + {"volume", "real"}, + {"density", "real"} }; - - // - Private member functions - uint32 pointFieldSize() - { - auto s = updatePoints(); - return s.size(); - } + /// check if pointField name exists in Time or time folder + virtual + bool pointFieldNameExists(const word& name)const = 0; - /// @brief Checks if a field needs to be updated. - /// @param name The name of the field to check. - /// @param forceUpdate Forces an update if true. Defaults to `false`. - /// @return `true` if the field needs updating or `forceUpdate` is true, `false` otherwise. - bool checkForUpdate(const word& name, bool forceUpdate = false); + /// Loads a pointField with a given name to the Time object + virtual + bool loadPointFieldToTime(const word& name)= 0; + + virtual + bool loadPointStructureToTime()=0; + + /// get the type name of the pointField in the Time object + word getPointFieldType(const word& name)const; + + /// Checks if a field needs to be updated based on capture time + bool checkForUpdate(const word& compoundName, bool forceUpdate = false); - /** - * @brief Updates and retrieves a point field of a specified type from the database. - * - * This is a template function that updates and retrieves a point field of type `T` - * from the database. It checks if the field needs to be updated based on the last - * capture time or if a forced update is requested. If an update is necessary, it - * retrieves the latest data for the field. - * - * @tparam T The type of the point field to update and retrieve. Must be a ValidFieldType. - * @param name The name of the field to update. - * @param forceUpdate A boolean flag indicating whether to force an update of the field - * regardless of its current state. Defaults to `false`. - * - * @return A span of `T` representing the updated field data. - * - * @throws message If the field cannot be found in the database or if there is a type mismatch. - */ template span updateField(const word& name, bool forceUpdate = false); + + template + span updateReservedField(const word& name, bool forceUpdate = false); - /// @brief Creates a new real field or retrieves an existing one. - /// - /// If a field with the given name already exists, it returns a span to that field. - /// If the field does not exist, it creates a new real field with the given name - /// and returns a span to the newly created field. - /// - /// @param name The name of the field to create or retrieve. - /// @return span of the field span createOrGetRealField(const word& name); - /** - * @brief Parses a compound field name to extract the base field name and function. - * - * This function takes a compound field name, which may include a function applied - * to a base field (e.g., "mag(velocity)"), and parses it to extract the base field - * name (e.g., "velocity") and the function to be applied (e.g., `Functions::Magnitude`). - * - * The function supports the following syntax for compound field names: - * - `fieldName` (no function applied) - * - `functionName(fieldName)` - * - * Supported function names are defined in the `Functions` enum. - * - * @param compoundFieldName The compound field name to parse. - * @param fieldName A reference to a `word` where the extracted base field name - * will be stored. - * @param func A reference to a `Functions` enum where the identified function - * will be stored. If no function is applied, this will be set to - * `Functions::None`. - * - * @return `true` if the compound field name was successfully parsed and the base - * field name and function were extracted, `false` otherwise. - * - * @note The function modifies the `fieldName` and `func` parameters to return the - * extracted information. - */ + span createOrGetVolume(bool forceUpdate=false); + + span createOrGetDensity(bool forceUpdate=false); + + span createOrGetOne(bool forceUpdate=false); + static bool findFunction( const word& compoundFieldName, word& fieldName, fieldsDataBase::Functions& func ); - /** - * @brief Determines the input and output types for a given function. - * - * This function takes a `Functions` enum value and an input type as a string - * and determines the corresponding output type based on the function being applied. - * - * @param func The function for which to determine the input and output types. - * @param inputType The input type as a string. - * @param outputType A reference to a string where the determined output type will be stored. - * - * @return `true` if the input and output types were successfully determined, `false` otherwise. - */ static bool inputOutputType( fieldsDataBase::Functions func, const word& inputType, word& outputType); + +protected: + + // - protected member functions + + + virtual + bool checkTimeFolder(const word& fieldName) const = 0; + + virtual + const shape& getShape() const= 0; + + + /// @brief return the size of pointStructure + uint32 pointFieldSize() + { + auto s = updatePoints(); + return s.size(); + } + public: + // - Type info + + TypeInfo("fieldsDataBase"); + // - constructors - fieldsDataBase(const Time& time, bool inSimulation); + fieldsDataBase(systemControl& control, bool inSimulation); /// no copy constructor fieldsDataBase(const fieldsDataBase&) = delete; @@ -231,140 +180,70 @@ public: fieldsDataBase& operator=(fieldsDataBase&&) = delete; /// destructor - ~fieldsDataBase() = default; + virtual ~fieldsDataBase() = default; + + create_vCtor + ( + fieldsDataBase, + bool, + (systemControl& control, bool inSimulation), + (control, inSimulation) + ); + // - Public Access Functions /// returns the current time timeValue currentTime()const; - /// const ref to object Time - const Time& time()const + /// const ref to object Time + const Time& time()const { return time_; } - + + Time& time() + { + return time_; + } + // - Public Member Functions - /** - * @brief Retrieves the type of a point field based on its compound name. - * - * This function attempts to extract the type of a point field from its compound name. - * The compound name may include additional information such as a function or operation - * applied to the field, ie. mag(velcoty). If the type is successfully determined, it - * is stored in the provided `typeName` parameter. - * - * @param compoundName The compound name of the field, which may include additional - * information about operations or functions applied to the field. - * @param originalType A reference to a `word` where the original type name is obtained. - * This will be set to the type of the field before any function is applied. - * @param typeAfterFunction A reference to a `word` where the type name after applying - * the function is obtained. - * @param func the applied function to the field. - * - * @return `true` if the type was successfully determined and stored in `typeName`, - * `false` otherwise. - */ - bool getPointFieldType( + bool getFieldTypeNameFunction + ( const word& compoundName, - word& fieldName, + word& pointFieldName, word& originalType, word& typeAfterFunction, - Functions& func); - - /// overload for the function getPointFieldType without `func` argument - bool getPointFieldType( - const word& compoundName, - word& originalType, - word& typeAfterFunction); - - /// overload for function getPointFieldType without `originalType` argument - bool getPointFieldType( - const word& compoundName, - word& typeAfterFunction); + Functions& func + )const; - /** - * @brief Updates the points data and returns a span to the updated points. - * - * This function ensures that the points data is up-to-date by checking if an update - * is necessary. If the data is outdated or if a forced update is requested, it retrieves - * the latest points data and stores it in the internal fields database. The function - * then returns a span to the updated points data for further use. - * - * @param forceUpdate A boolean flag indicating whether to force an update of the points - * data regardless of its current state. Defaults to `false`. - * - * @return A span of `realx3` representing the updated points data. - */ + + bool getFieldType + ( + const word& compoundName, + word& originalType, + word& typeAfterFunction + ) const; + + bool getFieldType + ( + const word& compoundName, + word& typeAfterFunction + ) const; + + + /// update pointStructure if necessary span updatePoints(bool forceUpdate = false); - /** - * @brief Updates and retrieves a realx3 point field from the database. - * - * This function retrieves or updates a realx3 field based on its compound name. - * The compound name cannot include any function operation. - * If the field needs to be updated or if forceUpdate is true, the method will - * fetch the latest data from the database. - * - * @param compoundName The name of the field, possibly including a function operation - * @param forceUpdate If true, forces an update of the field regardless of its current state. - * Defaults to false. - * - * @return A span containing the updated realx3 field data - * - * @throws message If the field type is not compatible with realx3 or if the field - * cannot be found in the database - */ + /// update a field with realx3 type span updateFieldRealx3( const word& compoundName, bool forceUpdate = false); - /** - * @brief Updates and retrieves a realx4 point field from the database. - * - * This function retrieves or updates a realx4 field based on its compound name. - * The compound name cannot include any function operation. - * If the field needs to be updated or if forceUpdate is true, the method will - * fetch the latest data from the database. - * - * @param compoundName The name of the field, possibly including a function operation - * @param forceUpdate If true, forces an update of the field regardless of its current state. - * Defaults to false. - * - * @return A span containing the updated realx3 field data - * - * @throws message If the field type is not compatible with realx4 or if the field - * cannot be found in the database - */ span updateFieldRealx4( const word& compoundName, bool forceUpdate = false); - /** - * @brief Updates and retrieves a real point field from the database. - * - * This function retrieves or updates a real field based on its compound name. - * The compound name may include a function operation (e.g., abs, square, etc.). - * If the field needs to be updated or if forceUpdate is true, the method will - * fetch the latest data from the database and apply the specified function. - * - * Supported functions include: - * - None: Retrieves the field as is. - * - abs: Computes the absolute value of the field. - * - square: Computes the square of the field. - * - cube: Computes the cube of the field. - * - sqrt: Computes the square root of the field. - * - mag, magSquare, magCube, magSqrt: Compute magnitude-related operations for vector fields. - * - component(x, y, z): Extracts a specific component from a vector field. - * - * @param compoundName The name of the field, possibly including a function operation. - * @param forceUpdate If true, forces an update of the field regardless of its current state. - * Defaults to false. - * - * @return A span containing the updated real field data. - * - * @throws message If the field type is not compatible with real or if the field - * cannot be found in the database. - */ span updateFieldReal( const word& compoundName, bool forceUpdate = false); @@ -378,11 +257,20 @@ public: allPointFieldTypes updateFieldAll( const word& compoundName, bool forceUpdate = false); + + virtual + const pointStructure& pStruct()const = 0; - const pointStructure& pStruct()const; + virtual + void resetTimeFolder() = 0; + + static + uniquePtr create( + systemControl& control, + bool inSimulation); }; -} // nampespace pFlow +} // namespace pFlow #include "fieldsDataBaseTemplates.cpp" diff --git a/src/PostprocessData/fieldsDataBase/fieldsDataBaseDclr.hpp b/src/PostprocessData/fieldsDataBase/fieldsDataBaseDclr.hpp new file mode 100644 index 00000000..283b5e7b --- /dev/null +++ b/src/PostprocessData/fieldsDataBase/fieldsDataBaseDclr.hpp @@ -0,0 +1,45 @@ + +#ifndef __fieldsDataBaseDclr_hpp__ +#define __fieldsDataBaseDclr_hpp__ + +#include +#include +#include + +#include "types.hpp" +#include "span.hpp" + +namespace pFlow +{ + + +template +concept ValidFieldType = + std::same_as || + std::same_as || + std::same_as || + std::same_as; + +template +concept VectorType = + std::same_as || + std::same_as; + +template +concept ScalarType = + std::same_as; + + +template +concept ValidRegionFieldType = + std::same_as || + std::same_as || + std::same_as ; + + +using allPointFieldTypes = std::variant, span, span>; + + +} // namespace pFlow + +#endif //__fieldsDataBaseDclr_hpp__ \ No newline at end of file diff --git a/src/PostprocessData/fieldsDataBase/fieldsDataBaseTemplates.cpp b/src/PostprocessData/fieldsDataBase/fieldsDataBaseTemplates.cpp index 9466a8d6..a36eb95c 100644 --- a/src/PostprocessData/fieldsDataBase/fieldsDataBaseTemplates.cpp +++ b/src/PostprocessData/fieldsDataBase/fieldsDataBaseTemplates.cpp @@ -32,40 +32,25 @@ pFlow::span pFlow::fieldsDataBase::updateField(const word& name, bool forceUp if(shouldUpdate) { - if(name == "one") - { - allFields_.emplaceBackOrReplace> - ( - "one", - FieldTypeHost - ( - "one", - "value", - pointFieldSize(), - T{1} - ) - ); - } - else if( name == "position") + if(reservedFieldNames_.contains(name)) { - if constexpr( std::same_as) + return updateReservedField(name, true); + } + else + { + if( loadPointFieldToTime(name) ) { - return updatePoints(true); + const auto& pField = time_.lookupObject>(name); + allFields_.emplaceBackOrReplace>( + name, + pField.activeValuesHost()); } else { - fatalErrorInFunction<< "Error in getting the type name of field: "<< - name<<", with type name: "<< getTypeName() <(nullptr, 0); } - } - else - { - const auto& pField = time_.lookupObject>(name); - allFields_.emplaceBackOrReplace>( - name, - pField.activeValuesHost()); + } } @@ -77,4 +62,80 @@ pFlow::span pFlow::fieldsDataBase::updateField(const word& name, bool forceUp } + +template +inline +pFlow::span pFlow::fieldsDataBase::updateReservedField +( + const word& name, + bool forceUpdate +) +{ + if(name == "one") + { + if constexpr( std::same_as) + { + return createOrGetOne(forceUpdate); + } + else + { + fatalErrorInFunction + << "This type: " + << getTypeName() + <<" is not supported for field one."<) + { + return createOrGetVolume(forceUpdate); + } + else + { + fatalErrorInFunction + << "This type: " + << getTypeName() + <<" is not supported for field volume."<) + { + return createOrGetDensity(forceUpdate); + } + else + { + fatalErrorInFunction + << "This type: " + << getTypeName() + <<" is not supported for field density."<) + { + return updatePoints(forceUpdate); + } + else + { + fatalErrorInFunction + << "This type: " + << getTypeName() + <<" is not supported for field position."<(nullptr, 0); + +} + #endif //__fieldsDataBaseTemplates_hpp__ \ No newline at end of file diff --git a/src/PostprocessData/fieldsDataBase/simulationFieldsDataBase.cpp b/src/PostprocessData/fieldsDataBase/simulationFieldsDataBase.cpp new file mode 100644 index 00000000..312f8e51 --- /dev/null +++ b/src/PostprocessData/fieldsDataBase/simulationFieldsDataBase.cpp @@ -0,0 +1,62 @@ +#include "Time.hpp" +#include "simulationFieldsDataBase.hpp" +#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 +{ + return time().lookupObjectName(name); +} + +bool pFlow::simulationFieldsDataBase::loadPointFieldToTime(const word &name) +{ + return time().lookupObjectName(name); +} + +bool pFlow::simulationFieldsDataBase::loadPointStructureToTime() +{ + // it is already in the Time object + return time().lookupObjectName(pointStructureFile__); +} + +bool pFlow::simulationFieldsDataBase::checkTimeFolder(const word &fieldName) const +{ + return true; +} + +const pFlow::shape& pFlow::simulationFieldsDataBase::getShape() const +{ + return shape_; +} + +pFlow::simulationFieldsDataBase::simulationFieldsDataBase +( + systemControl &control, + bool inSimulation +) +: + fieldsDataBase(control, inSimulation), + shape_ + ( + dynamic_cast(*control.caseSetup().lookupObjectPtr(shapeFile__)) + ) +{ +} + +const pFlow::pointStructure &pFlow::simulationFieldsDataBase::pStruct() const +{ + return + static_cast + ( + time().lookupObject(pointStructureFile__) + ); +} + +void pFlow::simulationFieldsDataBase::resetTimeFolder() +{ +} diff --git a/src/PostprocessData/fieldsDataBase/simulationFieldsDataBase.hpp b/src/PostprocessData/fieldsDataBase/simulationFieldsDataBase.hpp new file mode 100644 index 00000000..d7ea7f50 --- /dev/null +++ b/src/PostprocessData/fieldsDataBase/simulationFieldsDataBase.hpp @@ -0,0 +1,79 @@ +/*------------------------------- phasicFlow --------------------------------- + O C enter of + O O E ngineering and + O O M ultiscale modeling of + OOOOOOO F luid flow +------------------------------------------------------------------------------ + Copyright (C): www.cemf.ir + email: hamid.r.norouzi AT gmail.com +------------------------------------------------------------------------------ +Licence: + This file is part of phasicFlow code. It is a free software for simulating + granular and multiphase flows. You can redistribute it and/or modify it under + the terms of GNU General Public License v3 or any other later versions. + + phasicFlow is distributed to help others in their research in the field of + granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +-----------------------------------------------------------------------------*/ + +#ifndef __simulationFieldsDataBase_hpp__ +#define __simulationFieldsDataBase_hpp__ + +#include "fieldsDataBase.hpp" + +namespace pFlow +{ + +class simulationFieldsDataBase +: + public fieldsDataBase +{ +private: + + const shape& shape_; + +protected: + + /// check if pointField name exists in Time or time folder + bool pointFieldNameExists(const word& name)const override; + + /// Loads a pointField with a given name to the Time object. + /// For simulation, it just checks if the name exists + bool loadPointFieldToTime(const word& name) override; + + /// Loads pointStructure to the Time object + /// For simulation, it just checks if the name exists + bool loadPointStructureToTime() override; + + bool checkTimeFolder(const word& fieldName) const override; + + const shape& getShape() const override; + +public: + + TypeInfo("fieldsDataBase"); + + simulationFieldsDataBase(systemControl& control, bool inSimulation); + + ~simulationFieldsDataBase() override = default; + + add_vCtor + ( + fieldsDataBase, + simulationFieldsDataBase, + bool + ); + + const pointStructure& pStruct()const override; + + void resetTimeFolder() override; + +}; + + +} + + +#endif //__simulationFieldsDataBase_hpp__ \ No newline at end of file diff --git a/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAvMassVelocity.hpp b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAvMassVelocity.hpp index 16b029f1..5c0f164e 100644 --- a/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAvMassVelocity.hpp +++ b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAvMassVelocity.hpp @@ -128,7 +128,7 @@ Licence: #include #include -#include "postprocessOperation.hpp" +#include "PostprocessOperationAverage.hpp" #include "regionField.hpp" #include "includeMask.hpp" @@ -138,7 +138,7 @@ namespace pFlow class PostprocessOperationAvMassVelocity : - public postprocessOperation + public PostprocessOperationAverage { public: diff --git a/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAverage.cpp b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAverage.cpp index a0de2384..3ffbd5b8 100644 --- a/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAverage.cpp +++ b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAverage.cpp @@ -1,7 +1,7 @@ #include "PostprocessOperationAverage.hpp" #include "dictionary.hpp" #include "fieldsDataBase.hpp" -#include "fieldFunctions.hpp" +#include "operationFunctions.hpp" /// Constructs average processor and initializes result field based on input field type pFlow::PostprocessOperationAverage::PostprocessOperationAverage @@ -80,7 +80,8 @@ pFlow::PostprocessOperationAverage::PostprocessOperationAverage /// Performs weighted average of field values within each region bool pFlow::PostprocessOperationAverage::execute ( - const std::vector>& weights + const std::vector>& weights, + const regionField& volFactor ) { auto allField = database().updateFieldAll(fieldName()); @@ -99,7 +100,7 @@ bool pFlow::PostprocessOperationAverage::execute return executeAverageOperation( procName, field, - regP, + volFactor, dbVol, weights, phi, @@ -124,6 +125,7 @@ bool pFlow::PostprocessOperationAverage::execute procName, field, std::get>(processedRegField), + volFactor, dbVol, weights, mask); diff --git a/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAverage.hpp b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAverage.hpp index 93181c1e..6620d588 100644 --- a/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAverage.hpp +++ b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAverage.hpp @@ -193,7 +193,9 @@ public: /// @brief Execute average operation on field values /// @param weights Weight factors for particles /// @return True if successful - bool execute(const std::vector>& weights) override; + bool execute( + const std::vector>& weights, + const regionField& volFactor) override; }; diff --git a/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.cpp b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.cpp index 922bc1d4..c10315d7 100644 --- a/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.cpp +++ b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.cpp @@ -1,7 +1,7 @@ #include "PostprocessOperationSum.hpp" #include "dictionary.hpp" #include "fieldsDataBase.hpp" -#include "fieldFunctions.hpp" +#include "operationFunctions.hpp" /// Constructs sum processor and initializes result field based on input field type pFlow::PostprocessOperationSum::PostprocessOperationSum @@ -41,7 +41,8 @@ pFlow::PostprocessOperationSum::PostprocessOperationSum /// Performs weighted sum of field values within each region bool pFlow::PostprocessOperationSum::execute ( - const std::vector>& weights + const std::vector>& weights, + const regionField& volFactor ) { auto allField = database().updateFieldAll(fieldName()); @@ -60,7 +61,7 @@ bool pFlow::PostprocessOperationSum::execute return executeSumOperation( procName, field, - regP, + volFactor, dbVol, weights, phi, diff --git a/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.hpp b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.hpp index c8e910ff..b811e89b 100644 --- a/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.hpp +++ b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.hpp @@ -175,7 +175,9 @@ public: /// @brief Execute sum operation on field values /// @param weights Weight factors for particles /// @return True if successful - bool execute(const std::vector>& weights) override; + bool execute( + const std::vector>& weights, + const regionField& volFactor) override; }; diff --git a/src/PostprocessData/operation/PostprocessOperation/fieldFunctions.hpp b/src/PostprocessData/operation/PostprocessOperation/operationFunctions.hpp similarity index 88% rename from src/PostprocessData/operation/PostprocessOperation/fieldFunctions.hpp rename to src/PostprocessData/operation/PostprocessOperation/operationFunctions.hpp index 3e278858..8dbe643b 100644 --- a/src/PostprocessData/operation/PostprocessOperation/fieldFunctions.hpp +++ b/src/PostprocessData/operation/PostprocessOperation/operationFunctions.hpp @@ -18,8 +18,8 @@ Licence: -----------------------------------------------------------------------------*/ -#ifndef __fieldFunctions_hpp__ -#define __fieldFunctions_hpp__ +#ifndef __operationFunctions_hpp__ +#define __operationFunctions_hpp__ #include @@ -36,13 +36,14 @@ regionField executeSumOperation ( const word& regFieldName, const span& field, - const regionPoints& regPoints, + const regionField& volFactor, const bool devideByVol, const std::vector>& weights, const span& phi, const includeMask::Mask& mask ) { + const auto& regPoints = volFactor.regPoints(); regionField processedField(regFieldName, regPoints, T{}); auto vols = regPoints.volumes(); @@ -63,7 +64,7 @@ regionField executeSumOperation } if(devideByVol) { - processedField[reg] = sum/vols[reg]; + processedField[reg] = sum/(volFactor[reg] * vols[reg]); } else { @@ -80,13 +81,15 @@ regionField executeAverageOperation ( const word& regFieldName, const span& field, - const regionPoints& regPoints, - const bool devideByVol, + const regionField& volFactor, + const bool devideByVol, const std::vector>& weights, const span& phi, const includeMask::Mask& mask ) { + + const auto& regPoints = volFactor.regPoints(); regionField processedField(regFieldName, regPoints, T{}); auto vols = regPoints.volumes(); @@ -113,7 +116,7 @@ regionField executeAverageOperation if(devideByVol) { - processedField[reg] = sumNum / max(sumDen, smallValue) / vols[reg]; + processedField[reg] = sumNum / max(sumDen, smallValue) / (volFactor[reg] * vols[reg]); } else { @@ -131,7 +134,8 @@ regionField executeFluctuation2Operation ( const word& regFieldName, const span& field, - const regionField& fieldAvg, + const regionField& fieldAvg, + const regionField& volFactor, const bool devideByVol, const std::vector>& weights, const includeMask::Mask& mask @@ -145,7 +149,7 @@ regionField executeFluctuation2Operation { auto partIndices = regPoints.indices(reg); auto w = weights[reg]; - auto vol = vols[reg]; + auto vol = volFactor[reg] * vols[reg]; T avField{}; if(devideByVol) { @@ -188,4 +192,4 @@ regionField executeFluctuation2Operation } // namespace pFlow -#endif //__fieldFunctions_hpp__ +#endif //__operationFunctions_hpp__ diff --git a/src/PostprocessData/operation/includeMask/IncludeMask.hpp b/src/PostprocessData/operation/includeMask/IncludeMask.hpp index 6a4a24f7..34ae4dfb 100644 --- a/src/PostprocessData/operation/includeMask/IncludeMask.hpp +++ b/src/PostprocessData/operation/includeMask/IncludeMask.hpp @@ -154,11 +154,34 @@ public: ).getVal("field")) {} + IncludeMask( + const word& type, + const dictionary& dict, + fieldsDataBase& feildsDB) + : + includeMask(type, dict, feildsDB), + operator_(dict.subDict(operatorName()+"Info")), + fieldName_( + dict.subDict + ( + operatorName()+"Info" + ).getVal("field")) + {} + /// Add virtual constructor pattern for creating instances - add_vCtor( + add_vCtor + ( includeMask, IncludeMask, - dictionary); + dictionary + ); + + add_vCtor + ( + includeMask, + IncludeMask, + word + ); /// Returns the mask for filtering elements (updates the mask if necessary) Mask getMask() override @@ -203,20 +226,40 @@ public: TypeInfoTemplate12("IncludeMask", T, allOp); - IncludeMask( - const dictionary& opDict, + IncludeMask( + const dictionary& opDict, fieldsDataBase& feildsDB) - : - includeMask(opDict, feildsDB) - { + : + includeMask(opDict, feildsDB) + { span s = database().updatePoints(); mask_.resize(s.size(), true); - } + } - add_vCtor( - includeMask, - IncludeMask, - dictionary); + IncludeMask( + const word& type, + const dictionary& opDict, + fieldsDataBase& feildsDB) + : + includeMask(type, opDict, feildsDB) + { + span s = database().updatePoints(); + mask_.resize(s.size(), true); + } + + add_vCtor + ( + includeMask, + IncludeMask, + dictionary + ); + + add_vCtor + ( + includeMask, + IncludeMask, + word + ); Mask getMask()override { diff --git a/src/PostprocessData/operation/includeMask/includeMask.cpp b/src/PostprocessData/operation/includeMask/includeMask.cpp index 95c85fb8..209391be 100644 --- a/src/PostprocessData/operation/includeMask/includeMask.cpp +++ b/src/PostprocessData/operation/includeMask/includeMask.cpp @@ -57,7 +57,7 @@ pFlow::uniquePtr pFlow::includeMask::create auto& maskDict = opDict.subDict(mask+"Info"); word maskField = maskDict.getVal("field"); - if( !fieldsDB.getPointFieldType(maskField, fieldType) ) + if( !fieldsDB.getFieldType(maskField, fieldType) ) { fatalErrorInFunction<<"Error in retriving the type of field" << maskField <<" from dictionary " @@ -111,7 +111,7 @@ pFlow::uniquePtr auto& maskDict = opDict.subDict(type+"Info"); word maskField = maskDict.getVal("field"); - if( !fieldsDB.getPointFieldType(maskField, fieldType) ) + if( !fieldsDB.getFieldType(maskField, fieldType) ) { fatalErrorInFunction<<"Error in retriving the type of field" << maskField <<" from dictionary " @@ -143,7 +143,7 @@ pFlow::uniquePtr method << " dose not exist. \n" <<"Avaiable ones are: \n\n" , - dictionaryvCtorSelector_ + wordvCtorSelector_ ); fatalExit; return nullptr; diff --git a/src/PostprocessData/operation/postprocessOperation/postprocessOperation.cpp b/src/PostprocessData/operation/postprocessOperation/postprocessOperation.cpp index 53473a09..e752f359 100644 --- a/src/PostprocessData/operation/postprocessOperation/postprocessOperation.cpp +++ b/src/PostprocessData/operation/postprocessOperation/postprocessOperation.cpp @@ -117,7 +117,7 @@ pFlow::postprocessOperation::postprocessOperation ), divideByVolume_ ( - opDict.getValOrSet("dividedByVolume", Logical(false)) + opDict.getValOrSet("divideByVolume", Logical(false)) ), regionPoints_ ( @@ -141,7 +141,7 @@ pFlow::postprocessOperation::postprocessOperation ) { - if(!fieldsDB.getPointFieldType(fieldName_, fieldType_)) + if(!fieldsDB.getFieldType(fieldName_, fieldType_)) { fatalErrorInFunction; fatalExit; @@ -159,7 +159,7 @@ bool pFlow::postprocessOperation::write(const fileSystem &parDir) const if(!osPtr_) { fileSystem path = parDir+( - processedFieldName() + ".Start_" + ti.prevTimeName()); + processedFieldName() + ".Start_" + ti.timeName()); osPtr_ = makeUnique(path); regPoints().write(osPtr_()); diff --git a/src/PostprocessData/operation/postprocessOperation/postprocessOperation.hpp b/src/PostprocessData/operation/postprocessOperation/postprocessOperation.hpp index 86e776d3..285a7b7e 100644 --- a/src/PostprocessData/operation/postprocessOperation/postprocessOperation.hpp +++ b/src/PostprocessData/operation/postprocessOperation/postprocessOperation.hpp @@ -246,7 +246,10 @@ public: /// execute the operation /// @param weights Vector of weights for the operation. - virtual bool execute(const std::vector>& weights) = 0; + /// @param volFactor a factor to be multiplied by the volume of the region + virtual bool execute( + const std::vector>& weights, + const regionField& volFactor) = 0; /// write the result to a file /// @param parDir Parent directory for the output file. diff --git a/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponent.cpp b/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponent.cpp index 759395f5..10590f7c 100644 --- a/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponent.cpp +++ b/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponent.cpp @@ -36,6 +36,12 @@ pFlow::PostprocessComponent::PostprocessComponent ( regionPointsPtr_().size() ), + volumeFactor_ + ( + "volumeFactor", + regionPointsPtr_(), + 1.0 + ), operationDicts_(readDictList("operations", dict)) { @@ -106,7 +112,7 @@ bool pFlow::PostprocessComponent::execute for(auto& op:operatios_) { - if( !op->execute(weights) ) + if( !op->execute(weights, volumeFactor_) ) { fatalErrorInFunction <<"error occured in executing operatoin defined in dict " diff --git a/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponent.hpp b/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponent.hpp index 51c46490..996467a1 100644 --- a/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponent.hpp +++ b/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponent.hpp @@ -51,6 +51,8 @@ private: /// Method for processing the selected particles data std::vector regionsProcessMethod_; + regionField volumeFactor_; + bool executed_{false}; dictionaryList operationDicts_; @@ -62,6 +64,16 @@ protected: return regionsProcessMethod_; } + regionField& volumeFactor() + { + return volumeFactor_; + } + + const regionField& volumeFactor()const + { + return volumeFactor_; + } + public: // type info diff --git a/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponentArithmetic.hpp b/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponentArithmetic.hpp index d801c9d4..7b9a37c3 100644 --- a/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponentArithmetic.hpp +++ b/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponentArithmetic.hpp @@ -51,10 +51,12 @@ public: auto d = this->regPoints().eqDiameters(); auto c = this->regPoints().centers(); auto& regs = this->regionProecessMethod(); + auto& volFactor = this->volumeFactor(); const uint32 n = d.size(); for(uint32 i=0; iregPoints().eqDiameters(); auto c = this->regPoints().centers(); auto& regs = this->regionProecessMethod(); + auto& volFactor = this->volumeFactor(); + const uint32 n = d.size(); for(uint32 i=0; iregPoints().eqDiameters(); auto c = this->regPoints().centers(); auto& regs = this->regionProecessMethod(); + auto& volFactor = this->volumeFactor(); const uint32 n = d.size(); for(uint32 i=0; i; template class pFlow::PostprocessComponentUniform; template class pFlow::PostprocessComponentArithmetic; +template class pFlow::PostprocessComponentGaussian; +template class pFlow::PostprocessComponentUniform; +template class pFlow::PostprocessComponentArithmetic; + +template class pFlow::PostprocessComponentGaussian; +template class pFlow::PostprocessComponentUniform; +template class pFlow::PostprocessComponentArithmetic; + diff --git a/src/PostprocessData/postprocessComponent/particleProbePostprocessComponent/particleProbePostprocessComponent.cpp b/src/PostprocessData/postprocessComponent/particleProbePostprocessComponent/particleProbePostprocessComponent.cpp index f388c939..7588e602 100644 --- a/src/PostprocessData/postprocessComponent/particleProbePostprocessComponent/particleProbePostprocessComponent.cpp +++ b/src/PostprocessData/postprocessComponent/particleProbePostprocessComponent/particleProbePostprocessComponent.cpp @@ -135,7 +135,7 @@ bool pFlow::particleProbePostprocessComponent::write(const fileSystem& parDir)co if( !osPtr_) { // file is not open yet - fileSystem path = parDir + (name_+".Start_"+ti.prevTimeName()); + fileSystem path = parDir + (name_+".Start_"+ti.timeName()); osPtr_ = makeUnique(path); regionPointsPtr_().write(osPtr_()); } diff --git a/src/PostprocessData/postprocessData/postprocessData.cpp b/src/PostprocessData/postprocessData/postprocessData.cpp index 15a7709b..dc1dc479 100644 --- a/src/PostprocessData/postprocessData/postprocessData.cpp +++ b/src/PostprocessData/postprocessData/postprocessData.cpp @@ -30,7 +30,14 @@ pFlow::postprocessData::postprocessData(const systemControl &control) : auxFunctions(control), time_(control.time()), - fieldsDataBase_(control.time(), true), + fieldsDataBasePtr_ + ( + fieldsDataBase::create + ( + const_cast(control), + true + ) + ), dict_ ( objectFile @@ -73,6 +80,12 @@ pFlow::postprocessData::postprocessData(const systemControl &control) control.time().saveInterval(), "execution"); } + + shapeType_ = dict_.getValOrSet + ( + "shapeType", + word("sphere") + ); componentsDictsPtr_ = makeUnique(readDictList("components", dict_)); @@ -80,7 +93,7 @@ pFlow::postprocessData::postprocessData(const systemControl &control) { postprocesses_.push_back( postprocessComponent::create( compDict, - fieldsDataBase_, + fieldsDataBasePtr_(), defaultTimeControlPtr_() )); } diff --git a/src/PostprocessData/postprocessData/postprocessData.hpp b/src/PostprocessData/postprocessData/postprocessData.hpp index 4e5a95f2..e2223116 100644 --- a/src/PostprocessData/postprocessData/postprocessData.hpp +++ b/src/PostprocessData/postprocessData/postprocessData.hpp @@ -57,11 +57,14 @@ class postprocessData const Time& time_; /// Database for all the points fields on the host - fieldsDataBase fieldsDataBase_; + uniquePtr fieldsDataBasePtr_; /// file dictionary that is constructed from the file (postProcessDataDict) fileDictionary dict_; + /// name of the shape for use in the time of postprocess after simulation + word shapeType_; + /// list of dictionaries for postprocess components uniquePtr componentsDictsPtr_ = nullptr; diff --git a/src/PostprocessData/postprocessData/postprocessGlobals.hpp b/src/PostprocessData/postprocessData/postprocessGlobals.hpp index 99d04038..335bc267 100644 --- a/src/PostprocessData/postprocessData/postprocessGlobals.hpp +++ b/src/PostprocessData/postprocessData/postprocessGlobals.hpp @@ -27,7 +27,7 @@ namespace pFlow::postProcessGlobals { static fileSystem defaultDir__; -inline const word defaultRelDir__ = "VTK/postprocessData"; +inline const word defaultRelDir__ = "postprocessData"; } diff --git a/src/PostprocessData/processMethod/GaussianDistribution.hpp b/src/PostprocessData/processMethod/GaussianDistribution.hpp index 53889b76..6248bfa0 100644 --- a/src/PostprocessData/processMethod/GaussianDistribution.hpp +++ b/src/PostprocessData/processMethod/GaussianDistribution.hpp @@ -26,7 +26,7 @@ Licence: #include "typeInfo.hpp" #include "types.hpp" #include "span.hpp" - +#include "numericConstants.hpp" namespace pFlow { @@ -74,15 +74,15 @@ public: for(uint32 i=0; iselectedPoints(); ids_.resize(selectedPoints.size()); ids_.assign(selectedPoints.begin(), selectedPoints.end()); diff --git a/src/PostprocessData/region/regionPoints/lineRegionPoints/lineRegionPoints.cpp b/src/PostprocessData/region/regionPoints/lineRegionPoints/lineRegionPoints.cpp index 5e41ddf3..979a51a6 100644 --- a/src/PostprocessData/region/regionPoints/lineRegionPoints/lineRegionPoints.cpp +++ b/src/PostprocessData/region/regionPoints/lineRegionPoints/lineRegionPoints.cpp @@ -38,6 +38,7 @@ pFlow::lineRegionPoints::lineRegionPoints 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) @@ -64,6 +65,21 @@ pFlow::span pFlow::lineRegionPoints::indices(uint32 elem) c selectedPoints_[elem].size()); } +pFlow::span pFlow::lineRegionPoints::indices(uint32 elem) +{ + if(elem >= size()) + { + fatalErrorInFunction + << "The element index is out of range. elem: " << elem + << " size: " << size() << endl; + fatalExit; + } + + return span( + selectedPoints_[elem].data(), + selectedPoints_[elem].size()); +} + bool pFlow::lineRegionPoints::update() { const auto points = database().updatePoints(); diff --git a/src/PostprocessData/region/regionPoints/lineRegionPoints/lineRegionPoints.hpp b/src/PostprocessData/region/regionPoints/lineRegionPoints/lineRegionPoints.hpp index bdffd094..58989aab 100644 --- a/src/PostprocessData/region/regionPoints/lineRegionPoints/lineRegionPoints.hpp +++ b/src/PostprocessData/region/regionPoints/lineRegionPoints/lineRegionPoints.hpp @@ -126,6 +126,8 @@ public: /// Return indices of points in the specified element/region span indices(uint32 elem)const override; + + span indices(uint32 elem) override; /// Update regions based on current particle positions bool update() override; diff --git a/src/PostprocessData/region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.cpp b/src/PostprocessData/region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.cpp index 8665f72e..e983c602 100644 --- a/src/PostprocessData/region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.cpp +++ b/src/PostprocessData/region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.cpp @@ -59,6 +59,20 @@ pFlow::span pFlow::multipleSpheresRegionPoints::indices(uin return span(selectedPoints_[elem].data(), selectedPoints_[elem].size()); } +pFlow::span pFlow::multipleSpheresRegionPoints::indices(uint32 elem) +{ + if (elem >= size()) + { + fatalErrorInFunction + << "The element index is out of range. elem: " << elem + << " size: " << size() << endl; + fatalExit; + } + + return span(selectedPoints_[elem].data(), selectedPoints_[elem].size()); +} + + bool pFlow::multipleSpheresRegionPoints::update() { const auto points = database().updatePoints(); diff --git a/src/PostprocessData/region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.hpp b/src/PostprocessData/region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.hpp index f250d216..e01da658 100644 --- a/src/PostprocessData/region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.hpp +++ b/src/PostprocessData/region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.hpp @@ -138,6 +138,11 @@ public: /// @return Span containing indices of particles within the specified region span indices(uint32 elem)const override; + /// Returns the indices of particles contained in a specific spherical region + /// @param elem Index of the spherical region to query + /// @return Span containing indices of particles within the specified region + span indices(uint32 elem) override; + /// Updates the selection of particles within each spherical region /// @return True if update was successful, false otherwise bool update() override; diff --git a/src/PostprocessData/sampleDictionary/postprocessDataDict b/src/PostprocessData/sampleDictionary/postprocessDataDict index 3cf582a1..92e7d8a5 100755 --- a/src/PostprocessData/sampleDictionary/postprocessDataDict +++ b/src/PostprocessData/sampleDictionary/postprocessDataDict @@ -50,7 +50,7 @@ components { function average; field velocity; - dividedByVolume no; //default + divideByVolume no; //default threshold 3; //default is 1; includeMask all; } @@ -61,7 +61,7 @@ components function average; field one; phi one; // default - dividedByVolume no; + divideByVolume no; includeMask lessThan; // diameter of par1 is 0.003, so these settings @@ -79,7 +79,7 @@ components function sum; field one; phi one; // default - dividedByVolume yes; + divideByVolume yes; } ); @@ -114,14 +114,14 @@ components { function sum; field one; - dividedByVolume yes; //default is no + divideByVolume yes; //default is no } volumeDensity { function sum; field cube(diameter); // d^3, although it differs by pi/6 - dividedByVolume yes; //default is no + divideByVolume yes; //default is no } ); } diff --git a/src/phasicFlow/repository/repository/repository.cpp b/src/phasicFlow/repository/repository/repository.cpp index 648b912f..2815956f 100644 --- a/src/phasicFlow/repository/repository/repository.cpp +++ b/src/phasicFlow/repository/repository/repository.cpp @@ -236,7 +236,42 @@ size_t pFlow::repository::numRepositories()const return repositories_.size(); } -pFlow::repository& pFlow::repository::lookupRepository(const word& name) +const pFlow::IOobject *pFlow::repository::lookupObjectPtr +( + const word &name +) const +{ + if( auto [iter, success] = objects_.findIf(name); success ) + { + return iter->second; + } + else + { + fatalErrorInFunction << + "Object with name " << name << " is not found in repository " << this->name()<second; + } + else + { + fatalErrorInFunction << + "Object with name " << name << " is not found in repository " << this->name()< T& lookupObject(const word& name); diff --git a/src/phasicFlow/structuredData/pointStructure/selectors/selectorRandomPoints/selectorRandomPoints.cpp b/src/phasicFlow/structuredData/pointStructure/selectors/selectorRandomPoints/selectorRandomPoints.cpp index 3a4a28f0..2e1591de 100644 --- a/src/phasicFlow/structuredData/pointStructure/selectors/selectorRandomPoints/selectorRandomPoints.cpp +++ b/src/phasicFlow/structuredData/pointStructure/selectors/selectorRandomPoints/selectorRandomPoints.cpp @@ -93,9 +93,18 @@ pFlow::selectorRandomPoints::selectorRandomPoints( const dictionary& dict ) : pStructSelector(type, pStruct, dict), - begin_(dict.getVal("begin")), - end_(dict.getValOrSet("end", pStruct.size())), - number_(dict.getValOrSet("number", 1)) + begin_ + ( + dict.getValOrSet("begin",0u) + ), + end_ + ( + dict.getValOrSetMax("end", pStruct.size()) + ), + number_ + ( + dict.getValOrSetMax("number", 0u) + ) { begin_ = max(begin_, 1u); end_ = min(end_, static_cast(pStruct.size()));