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 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()) + { + 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() ) + { + 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, 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( typeAfterFunction== getTypeName() ) + { + return updateFieldRealx3(compoundName, forceUpdate); + } + else if( typeAfterFunction == getTypeName() ) + { + return updateFieldRealx4(compoundName, forceUpdate); + } + else if( typeAfterFunction == getTypeName() ) + { + return updateFieldReal(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/operation/PostprocessOperation/PostprocessOperationSum.cpp b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.cpp new file mode 100644 index 00000000..bae7af3f --- /dev/null +++ b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.cpp @@ -0,0 +1,71 @@ +#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(); + + 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/PostprocessOperation/PostprocessOperationSum.hpp b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.hpp new file mode 100644 index 00000000..94134602 --- /dev/null +++ b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.hpp @@ -0,0 +1,74 @@ +/*------------------------------- 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: + + /// 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 + ); + + const processedRegFieldType& processedField()const override + { + return processedRegField_(); + } + + bool execute(const std::vector>& weights) override; + +}; + + +} + +#endif //__PostprocessOperation_hpp__ \ No newline at end of file diff --git a/src/PostprocessData/operation/PostprocessOperation/fieldFunctions.hpp b/src/PostprocessData/operation/PostprocessOperation/fieldFunctions.hpp new file mode 100644 index 00000000..e1494459 --- /dev/null +++ b/src/PostprocessData/operation/PostprocessOperation/fieldFunctions.hpp @@ -0,0 +1,118 @@ +/*------------------------------- 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/postprocessOperation.cpp b/src/PostprocessData/operation/postprocessOperation/postprocessOperation.cpp new file mode 100644 index 00000000..8c42daa3 --- /dev/null +++ b/src/PostprocessData/operation/postprocessOperation/postprocessOperation.cpp @@ -0,0 +1,193 @@ +/*------------------------------- 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 "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<("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; + } +} + +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 + ( + [&](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); + if( dictionaryvCtorSelector_.search(method) ) + { + REPORT(3)<<"Operation "<< Green_Text(opDict.name())<<" with function "<< Green_Text(func)< + +#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 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: + + using Mask = typename includeMask::Mask; + +private: + + /// Dictionary containing operation-specific parameters. + dictionary operationDict_; + + /// This Threshold is used to exclude the regions which contain + /// fewer than this value. + uint32 threshold_; + + /// Logical flag to determine if the result is divided by volume. + Logical divideByVolume_; + + /// Reference to the region points used in the operation. + const regionPoints& regionPoints_; + + /// Reference to the fields database containing field data. + fieldsDataBase& database_; + + /// Name of the field to be processed. + word fieldName_; + + /// Type of the field to be processed. + word fieldType_; + + /// Name of the phi field to be processed. + word phiFieldName_; + + /// Pointer to the include mask used for masking operations. + uniquePtr includeMask_ = nullptr; + + mutable uniquePtr osPtr_ = 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_; + } + + const Time& time()const; + + 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 + 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, + const regionPoints& regPoints, + fieldsDataBase& fieldsDB); + +}; + +} + +#endif //__postprocessOperation_hpp__ \ No newline at end of file diff --git a/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponent.cpp b/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponent.cpp new file mode 100644 index 00000000..c815d255 --- /dev/null +++ b/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponent.cpp @@ -0,0 +1,152 @@ +#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( !forceUpdate && !timeControl().eventTime(ti)) + { + executed_ = false; + return true; + } + + // update processing methods + auto& regPoints = this->regPoints(); + + 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; i> weights(n); + + for(uint32 i=0; iexecute(weights) ) + { + fatalErrorInFunction + <<"error occured in executing operatoin defined in dict " + << op->operationDict() + < +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() + < + +#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_; + } + + bool write(const fileSystem& parDir)const override; + +}; + + + +} + +#include "PostprocessComponent.cpp" + +#endif \ No newline at end of file diff --git a/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponentArithmetic.hpp b/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponentArithmetic.hpp new file mode 100644 index 00000000..d801c9d4 --- /dev/null +++ b/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponentArithmetic.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 __PostprocessComponentArithmetic_hpp__ +#define __PostprocessComponentArithmetic_hpp__ + +#include "PostprocessComponent.hpp" +#include "arithmetic.hpp" + +namespace pFlow +{ + +template +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 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 +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/particleProbePostprocessComponent.hpp b/src/PostprocessData/postprocessComponent/particleProbePostprocessComponent/particleProbePostprocessComponent.hpp new file mode 100644 index 00000000..5069e291 --- /dev/null +++ b/src/PostprocessData/postprocessComponent/particleProbePostprocessComponent/particleProbePostprocessComponent.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 __particleProbePostprocessComponent_hpp__ +#define __particleProbePostprocessComponent_hpp__ + +#include "postprocessComponent.hpp" +#include "fieldsDataBase.hpp" +#include "centerPointsRegionPoints.hpp" +#include "regionField.hpp" +#include "oFstream.hpp" + +namespace pFlow +{ + + +class particleProbePostprocessComponent +: + public postprocessComponent +{ +private: + + using processedRegFieldType = std::variant + < + regionField, + regionField, + regionField + >; + + bool executed_{false}; + + uniquePtr regionPointsPtr_; + + uniquePtr processedField_ = nullptr; + + word fieldName_; + + word name_; + + mutable uniquePtr osPtr_ = nullptr; + +public: + + TypeInfo("PostprocessComponent"); + + particleProbePostprocessComponent + ( + const dictionary& dict, + fieldsDataBase& fieldsDB, + const baseTimeControl& defaultTimeControl + ); + + ~particleProbePostprocessComponent()override = default; + + add_vCtor + ( + postprocessComponent, + particleProbePostprocessComponent, + dictionary + ); + + 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_; + } + + bool write(const fileSystem& parDir)const override; + +}; + +} + +#endif //__particleProbePostprocessComponent_hpp__ \ No newline at end of file diff --git a/src/PostprocessData/postprocessComponent/postprocessComponent/postprocessComponent.cpp b/src/PostprocessData/postprocessComponent/postprocessComponent/postprocessComponent.cpp new file mode 100644 index 00000000..ed2e3b6c --- /dev/null +++ b/src/PostprocessData/postprocessComponent/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/postprocessData.cpp b/src/PostprocessData/postprocessData/postprocessData.cpp new file mode 100644 index 00000000..064b5ad1 --- /dev/null +++ b/src/PostprocessData/postprocessData/postprocessData.cpp @@ -0,0 +1,120 @@ + +/*------------------------------- 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 "postprocessGlobals.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_)) +{ + postProcessGlobals::defaultDir__ = CWD()/pFlow::postProcessGlobals::defaultRelDir__; + + // 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()<executed()) + { + continue; + } + if(!component->write(postProcessGlobals::defaultDir__/component->name())) + { + fatalErrorInFunction + <<"Error occured in writing 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 write()const override; + + +}; + +} // namespace pFlow + +#endif // __postprocessData_hpp__ \ No newline at end of file diff --git a/src/PostprocessData/postprocessData/postprocessGlobals.hpp b/src/PostprocessData/postprocessData/postprocessGlobals.hpp new file mode 100644 index 00000000..99d04038 --- /dev/null +++ b/src/PostprocessData/postprocessData/postprocessGlobals.hpp @@ -0,0 +1,35 @@ +/*------------------------------- 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 __postProcessGlobals_hpp__ +#define __postProcessGlobals_hpp__ + +#include "fileSystem.hpp" + +namespace pFlow::postProcessGlobals +{ + +static fileSystem defaultDir__; +inline const word defaultRelDir__ = "VTK/postprocessData"; + +} + + +#endif // __postProcessGlobals_hpp__ \ No newline at end of file diff --git a/src/PostprocessData/postprocessData/postprocessTimeControl.hpp b/src/PostprocessData/postprocessData/postprocessTimeControl.hpp new file mode 100644 index 00000000..f70cfd2a --- /dev/null +++ b/src/PostprocessData/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/processMethod/GaussianDistribution.hpp b/src/PostprocessData/processMethod/GaussianDistribution.hpp new file mode 100644 index 00000000..53889b76 --- /dev/null +++ b/src/PostprocessData/processMethod/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/processMethod/arithmetic.hpp b/src/PostprocessData/processMethod/arithmetic.hpp new file mode 100644 index 00000000..67a7fd30 --- /dev/null +++ b/src/PostprocessData/processMethod/arithmetic.hpp @@ -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. + +-----------------------------------------------------------------------------*/ + +#ifndef __arithmetic_hpp__ +#define __arithmetic_hpp__ + +#include + +#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/processMethod/uniformDistribution.hpp b/src/PostprocessData/processMethod/uniformDistribution.hpp new file mode 100644 index 00000000..d0445615 --- /dev/null +++ b/src/PostprocessData/processMethod/uniformDistribution.hpp @@ -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. + +-----------------------------------------------------------------------------*/ + +#ifndef __uniformDistribution_hpp__ +#define __uniformDistribution_hpp__ + +#include + +#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& indices, + const span& points + ) + { + return updateWeights(indices.size()); + } + + 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/region/regionFields/regionField.hpp b/src/PostprocessData/region/regionFields/regionField.hpp new file mode 100644 index 00000000..8d47a281 --- /dev/null +++ b/src/PostprocessData/region/regionFields/regionField.hpp @@ -0,0 +1,110 @@ +/*------------------------------- 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; + + const regionPoints& regPoints() const + { + return regionPoints_; + } + + /// 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(); + } + + 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 + 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/regionFieldTemplate.cpp b/src/PostprocessData/region/regionFields/regionFieldTemplate.cpp new file mode 100644 index 00000000..65112474 --- /dev/null +++ b/src/PostprocessData/region/regionFields/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/centerPointsRegionPoints.cpp b/src/PostprocessData/region/regionPoints/centerPointsRegionPoints/centerPointsRegionPoints.cpp new file mode 100644 index 00000000..e16ef774 --- /dev/null +++ b/src/PostprocessData/region/regionPoints/centerPointsRegionPoints/centerPointsRegionPoints.cpp @@ -0,0 +1,95 @@ +#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 true; +} + +pFlow::centerPointsRegionPoints::centerPointsRegionPoints( + const dictionary &dict, + fieldsDataBase &fieldsDataBase) + : regionPoints(dict, fieldsDataBase), + idName_(dict.getValOrSet("idName", "id")), + probDict_(dict) +{} + +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 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"< 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; + + bool writeToSameTimeFile()const override + { + return true; + } + + bool write(iOstream& os)const override; + +}; // class centerPointsRegionPoints + +} // namespace pFlow + + + +#endif // __centerPointsRegionPoints_hpp__ \ No newline at end of file diff --git a/src/PostprocessData/region/regionPoints/lineRegionPoints/lineRegionPoints.cpp b/src/PostprocessData/region/regionPoints/lineRegionPoints/lineRegionPoints.cpp new file mode 100644 index 00000000..c8adfca8 --- /dev/null +++ b/src/PostprocessData/region/regionPoints/lineRegionPoints/lineRegionPoints.cpp @@ -0,0 +1,100 @@ +#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; +} + +bool pFlow::lineRegionPoints::write(iOstream &os) const +{ + os <<"# Spheres along a straight line \n"; + os <<"# No."< 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; + + bool writeToSameTimeFile()const override + { + return true; + } + + bool write(iOstream& os) const override; +}; + +} + + +#endif // __lineRegionPoints_hpp__ \ No newline at end of file diff --git a/src/PostprocessData/region/regionPoints/regionPoints/regionPoints.cpp b/src/PostprocessData/region/regionPoints/regionPoints/regionPoints.cpp new file mode 100644 index 00000000..20599503 --- /dev/null +++ b/src/PostprocessData/region/regionPoints/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/regionPoints.hpp b/src/PostprocessData/region/regionPoints/regionPoints/regionPoints.hpp new file mode 100644 index 00000000..b6a9df66 --- /dev/null +++ b/src/PostprocessData/region/regionPoints/regionPoints/regionPoints.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 __regionPoints_hpp__ +#define __regionPoints_hpp__ + +#include "iOstream.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 writeToSameTimeFile()const = 0; + + virtual + bool write(iOstream& os)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/sphereRegionPoints.cpp b/src/PostprocessData/region/regionPoints/sphereRegionPoints/sphereRegionPoints.cpp new file mode 100644 index 00000000..4022c00e --- /dev/null +++ b/src/PostprocessData/region/regionPoints/sphereRegionPoints/sphereRegionPoints.cpp @@ -0,0 +1,41 @@ +#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 true; +} + +bool pFlow::sphereRegionPoints::write(iOstream &os) const +{ + os <<"# Single sphere\n"; + os <<"# center point: "< 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; + + bool writeToSameTimeFile()const override + { + return true; + } + + bool write(iOstream& os)const override; + +}; + +} + +#endif // __sphereRegionPoints_hpp__ \ No newline at end of file diff --git a/src/PostprocessData/sampleDictionary/postprocessDataDict b/src/PostprocessData/sampleDictionary/postprocessDataDict new file mode 100755 index 00000000..8fed2b42 --- /dev/null +++ b/src/PostprocessData/sampleDictionary/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; + + } + ); + } +);