diff --git a/cmake/autoComplete b/cmake/autoComplete index 6c289ce5..babf3843 100644 --- a/cmake/autoComplete +++ b/cmake/autoComplete @@ -1,48 +1,89 @@ PF_cFlags="--description --help --version" AllTimeFolders= __getAllTime(){ - files=( $(ls) ) - deleteFiles=(settings caseSetup cleanThisCase VTK runThisCase stl postprocess postProcess) - declare -A delk - for del in "${deleteFiles[@]}" ; do delk[$del]=1 ; done - # Tag items to remove, based on - for k in "${!files[@]}" ; do - [ "${delk[${files[$k]}]-}" ] && unset 'files[k]' - done - # Compaction - COMPREPLY=("${files[@]}") - AllTimeFolders="${files[@]}" + # Initialize empty array for time folders + local time_folders=() + + # Loop through all directories in current folder + for dir in */; do + # Remove trailing slash + dir=${dir%/} + + # Check if directory name is a valid floating point number + # This pattern matches integers and floating point numbers + if [[ $dir =~ ^[0-9]+(\.[0-9]+)?$ ]]; then + time_folders+=("$dir") + fi + done + + # Set completion reply to the time folders + COMPREPLY=("${time_folders[@]}") + AllTimeFolders="${time_folders[@]}" } __getFields(){ - __getAllTime - local -A unique_files=() + __getAllTime + local -A unique_files=() + # Files to exclude from suggestions + local exclude_files=("shapeHash" "pStructure" "particleInsertion" "p" "alpha" "U" "Sp" "Su" "phi") + declare -A exclude_dict + + # Build exclude dictionary for faster lookups + for file in "${exclude_files[@]}"; do + exclude_dict["$file"]=1 + done - for dir in $AllTimeFolders; do - # Check if the directory exists - if [ ! -d "$dir" ]; then - continue # Skip to the next directory - fi - - files_in_dir=$(find "$dir" -maxdepth 1 -type f -printf '%f\n' | sort -u) - - # Add filenames to the associative array (duplicates will be overwritten) - while IFS= read -r filename; do - unique_files["$filename"]=1 # Just the key is important, value can be anything - done <<< "$files_in_dir" - - done - COMPREPLY=("${!unique_files[@]}") - AllTimeFolders= + for dir in $AllTimeFolders; do + # Skip if not a directory + [ ! -d "$dir" ] && continue + + # Find all files in this time directory + while IFS= read -r filename; do + # Skip empty lines and excluded files + [ -z "$filename" ] || [ "${exclude_dict[$filename]+exists}" ] && continue + + # Add to unique files + unique_files["$filename"]=1 + done < <(find "$dir" -maxdepth 1 -type f -printf '%f\n') + done + + # Set completion reply to the unique filenames + COMPREPLY=(${!unique_files[@]}) + + # Clear global variable + AllTimeFolders= } _pFlowToVTK(){ - if [ "$3" == "--time" ] ; then + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + + # Check if we're completing a field + local is_field=0 + for ((i=1; i const word& baseName, pointStructure& pStruct, const word& method, - const realx3Field_D& initialValField + const realx3Field_D& initialValField, + bool keepHistory ) { if( wordvCtorSelector_.search(method) ) { - return wordvCtorSelector_[method] (baseName, pStruct, method, initialValField); + return wordvCtorSelector_[method] (baseName, pStruct, method, initialValField, keepHistory); } else { diff --git a/src/Integration/integration/integration.hpp b/src/Integration/integration/integration.hpp index fb0d84df..1161bd1e 100644 --- a/src/Integration/integration/integration.hpp +++ b/src/Integration/integration/integration.hpp @@ -24,6 +24,7 @@ Licence: #include "virtualConstructor.hpp" #include "pointFields.hpp" +#include "Logical.hpp" namespace pFlow @@ -63,6 +64,8 @@ private: /// The base name for integration const word baseName_; + bool keepHistory_; + protected: bool insertValues( @@ -83,7 +86,8 @@ public: const word& baseName, pointStructure& pStruct, const word& method, - const realx3Field_D& initialValField); + const realx3Field_D& initialValField, + bool keepHistory); /// Copy constructor integration(const integration&) = default; @@ -109,9 +113,10 @@ public: const word& baseName, pointStructure& pStruct, const word& method, - const realx3Field_D& initialValField + const realx3Field_D& initialValField, + bool keepHistory ), - (baseName, pStruct, method, initialValField) + (baseName, pStruct, method, initialValField, keepHistory) ); @@ -138,6 +143,11 @@ public: return owner_; } + bool keepHistory()const + { + return keepHistory_; + } + virtual void updateBoundariesSlaveToMasterIfRequested() = 0; /// return integration method @@ -164,7 +174,8 @@ public: const word& baseName, pointStructure& pStruct, const word& method, - const realx3Field_D& initialValField); + const realx3Field_D& initialValField, + bool keepHistory); }; // integration diff --git a/src/Particles/GrainParticles/grainParticles/grainParticles.cpp b/src/Particles/GrainParticles/grainParticles/grainParticles.cpp index 1e6cc065..d4d5bf05 100644 --- a/src/Particles/GrainParticles/grainParticles/grainParticles.cpp +++ b/src/Particles/GrainParticles/grainParticles/grainParticles.cpp @@ -248,7 +248,8 @@ pFlow::grainParticles::grainParticles( "rVelocity", dynPointStruct(), intMethod, - rAcceleration_.field() + rAcceleration_.field(), + control.keepIntegrationHistory() ); if( !rVelIntegration_ ) diff --git a/src/Particles/GrainParticles/grainShape/grainShape.cpp b/src/Particles/GrainParticles/grainShape/grainShape.cpp index 4558940b..246b5be8 100644 --- a/src/Particles/GrainParticles/grainShape/grainShape.cpp +++ b/src/Particles/GrainParticles/grainShape/grainShape.cpp @@ -73,6 +73,18 @@ pFlow::grainShape::grainShape } } +pFlow::grainShape::grainShape +( + const word &shapeType, + const word &fileName, + repository *owner, + const property &prop +) +: + grainShape(fileName, owner, prop) +{ +} + pFlow::real pFlow::grainShape::maxBoundingSphere() const { return max(grainDiameters_); @@ -99,9 +111,12 @@ pFlow::real pFlow::grainShape::boundingDiameter(uint32 index) const { return grainDiameters_[index]; } - fatalErrorInFunction<<"Invalid index for diameter "<< - index< pFlow::shape::create +( + const word &shapeType, + const word &fileName, + repository *owner, + const property &prop +) +{ + word type = angleBracketsNames("shape", shapeType); + + if( wordvCtorSelector_.search(type) ) + { + auto objPtr = + wordvCtorSelector_[type] + (shapeType, fileName, owner, prop); + return objPtr; + } + else + { + printKeys + ( + fatalError << "Ctor Selector "<< + type << " dose not exist. \n" + <<"Avaiable ones are: \n\n" + , + wordvCtorSelector_ + ); + fatalExit; + return nullptr; + } + +} diff --git a/src/Particles/particles/shape/shape.hpp b/src/Particles/particles/shape/shape.hpp index 5a4007aa..4c7d74e9 100644 --- a/src/Particles/particles/shape/shape.hpp +++ b/src/Particles/particles/shape/shape.hpp @@ -60,9 +60,28 @@ public: const word& fileName, repository* owner, const property& prop); + + shape( + const word& shapeType, + const word& fileName, + repository* owner, + const property& prop); ~shape() override=default; + create_vCtor + ( + shape, + word, + ( + const word& shapeType, + const word& fileName, + repository* owner, + const property& prop + ), + (shapeType, fileName, owner, prop) + ); + inline const auto& properties()const { @@ -148,6 +167,9 @@ public: virtual realVector boundingDiameter()const = 0; + virtual + realVector volume()const = 0; + virtual bool mass(uint32 index, real& m)const = 0; @@ -187,6 +209,13 @@ public: virtual real Inertial_zz(uint32 index)const = 0; + static + uniquePtr create( + const word& shapeType, + const word& fileName, + repository* owner, + const property& prop); + }; } diff --git a/src/PostprocessData/CMakeLists.txt b/src/PostprocessData/CMakeLists.txt new file mode 100644 index 00000000..a68a6d75 --- /dev/null +++ b/src/PostprocessData/CMakeLists.txt @@ -0,0 +1,35 @@ +set(SourceFiles + # Main postprocess data + postprocessData/postprocessData.cpp + + # Fields database + fieldsDataBase/fieldsDataBase.cpp + fieldsDataBase/simulationFieldsDataBase.cpp + + # Regions + region/regionPoints/regionPoints/regionPoints.cpp + region/regionPoints/sphereRegionPoints/sphereRegionPoints.cpp + region/regionPoints/lineRegionPoints/lineRegionPoints.cpp + region/regionPoints/centerPointsRegionPoints/centerPointsRegionPoints.cpp + region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.cpp + + # Postprocess components + postprocessComponent/postprocessComponent/postprocessComponent.cpp + postprocessComponent/particleProbePostprocessComponent/particleProbePostprocessComponent.cpp + postprocessComponent/PostprocessComponent/PostprocessComponents.cpp + + # Operations + operation/postprocessOperation/postprocessOperation.cpp + operation/PostprocessOperation/PostprocessOperationSum.cpp + operation/PostprocessOperation/PostprocessOperationAverage.cpp + operation/PostprocessOperation/PostprocessOperationAvMassVelocity.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 "systemControl.hpp" +#include "fieldsDataBase.hpp" +#include "fieldFunctions.hpp" + + +namespace pFlow +{ + +bool pointFieldGetType(const word& TYPENAME, word& fieldType, word& fieldSpace); + +} + +bool pFlow::fieldsDataBase::loadPointStructureToTime() +{ + return false; +} + +pFlow::word pFlow::fieldsDataBase::getPointFieldType(const word &name) const +{ + word pfType = time_.lookupObjectTypeName(name); + word type, space; + if(!pointFieldGetType(pfType, type, space)) + { + fatalErrorInFunction + <<"Error in retriving the type of pointField " + << pfType<second < t || forceUpdate; + iter->second = t; + } + else + { + shouldUpdate = true; + captureTime_.insertIf(compoundName, 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()); +} + +pFlow::span pFlow::fieldsDataBase::createOrGetVolume(bool forceUpdate) +{ + const word fName = "volume"; + bool shouldUpdate = checkForUpdate(fName, forceUpdate); + + if(shouldUpdate) + { + const auto index = updateFieldUint32("shapeIndex", true); + auto vols = getShape().volume(); + + FieldTypeHost volField + ( + fName, + "value", + pointFieldSize() + ); + + for(uint32 i=0; i< volField.size(); i++) + { + volField[i] = vols[index[i]]; + } + + allFields_.emplaceBackOrReplace> + ( + fName, + std::move(volField) + ); + } + + auto& field = allFields_.getObject>(fName); + return span( + field.data(), + field.size()); + +} + +pFlow::span pFlow::fieldsDataBase::createOrGetDensity(bool forceUpdate) +{ + const word fName = "density"; + + bool shouldUpdate = checkForUpdate(fName, forceUpdate); + + if(shouldUpdate) + { + const auto index = updateFieldUint32("shapeIndex", true); + const auto dens = getShape().density(); + + FieldTypeHost denFeild + ( + fName, + "value", + pointFieldSize() + ); + + for(uint32 i=0; i< denFeild.size(); i++) + { + denFeild[i] = dens[index[i]]; + } + + allFields_.emplaceBackOrReplace> + ( + fName, + std::move(denFeild) + ); + } + + auto& field = allFields_.getObject>(fName); + return span( + field.data(), + field.size()); +} + +pFlow::span pFlow::fieldsDataBase::createOrGetOne(bool forceUpdate) +{ + const word fName = "one"; + + bool shouldUpdate = checkForUpdate(fName, forceUpdate); + + if(shouldUpdate) + { + allFields_.emplaceBackOrReplace> + ( + fName, + FieldTypeHost + ( + fName, + "value", + pointFieldSize(), + 1.0 + ) + ); + } + + auto& field = allFields_.getObject>(fName); + return span( + field.data(), + field.size()); +} + +bool pFlow::fieldsDataBase::findFunction( + const word &compoundFieldName, + word &fieldName, + 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 + { + // the name is in the Time object + if(pointFieldNameExists(pointFieldName)) + { + originalType = getPointFieldType(pointFieldName); + } + else + { + fatalErrorInFunction + << "The field name: "<< pointFieldName + << " is not in the Time object.\n" + <<" Avaiable ones are: \n"<< time().objectNames()< pFlow::fieldsDataBase::updatePoints(bool forceUpdate) +{ + const word fName = "position"; + bool shouldUpdate = checkForUpdate(fName, forceUpdate); + + if(shouldUpdate) + { + // load pointStructure + if(!loadPointStructureToTime()) + { + fatalErrorInFunction<< "Error in loading pointStructure to Time object."< + ( + fName, + pstruct.activePointsHost() + ); + } + + auto& points = allFields_.getObject(fName); + + return span( + points.data(), + points.size()); + +} + +pFlow::span pFlow::fieldsDataBase::updateFieldRealx3 +( + const word &compoundName, + bool forceUpdate +) +{ + word originalType, typeAfterFunction, fieldName; + Functions func; + + if( !getFieldTypeNameFunction( + compoundName, + fieldName, + originalType, + typeAfterFunction, + func) ) + { + fatalErrorInFunction<< "Error in getting the type name of field: "<< + compoundName<<", with type name: "<< originalType <(nullptr, 0); + } + + if( 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( !getFieldTypeNameFunction( + 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( !getFieldTypeNameFunction( + 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 typeAfterFunction, originalType; + + if( !getFieldType(compoundName, originalType, typeAfterFunction)) + { + 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); + } +} + + + +pFlow::uniquePtr + pFlow::fieldsDataBase::create(systemControl& control, bool inSimulation) +{ + word dbType; + if(inSimulation) + { + dbType = "fieldsDataBase"; + } + else + { + dbType = "fieldsDataBase"; + } + + if( boolvCtorSelector_.search(dbType) ) + { + auto objPtr = + boolvCtorSelector_[dbType](control, inSimulation); + return objPtr; + } + else + { + printKeys + ( + fatalError << "Ctor Selector "<< + dbType << " does not exist. \n" + <<"Available ones are: \n\n" + , + boolvCtorSelector_ + ); + fatalExit; + } + + return nullptr; +} + +bool pFlow::pointFieldGetType(const word& TYPENAME, word& fieldType, word& fieldSpace) +{ + 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..ec8c577e --- /dev/null +++ b/src/PostprocessData/fieldsDataBase/fieldsDataBase.hpp @@ -0,0 +1,277 @@ +/*------------------------------- 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 "fieldsDataBaseDclr.hpp" + +#include "pointStructure.hpp" +#include "pointFields.hpp" +#include "anyList.hpp" +#include "Map.hpp" +#include "shape.hpp" + + +namespace pFlow +{ + +class systemControl; +class Time; + + +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 + + /// List to store all the point fields + anyList allFields_; + + /// Map to store the last capture time of each field + wordMap captureTime_; + + /// Reference to the Time object + Time& time_; + + /// Flag indicating if we're in simulation mode + bool inSimulation_ = false; + +protected: + + /// Map of reserved field names with their corresponding types + static const inline std::map reservedFieldNames_ + { + {"position", "realx3"}, + {"one", "real"}, + {"volume", "real"}, + {"density", "real"} + }; + + /// check if pointField name exists in Time or time folder + virtual + bool pointFieldNameExists(const word& name)const = 0; + + /// Loads a pointField with a given name to the Time object + virtual + bool loadPointFieldToTime(const word& name)= 0; + + virtual + bool loadPointStructureToTime()=0; + + /// get the type name of the pointField in the Time object + word getPointFieldType(const word& name)const; + + /// Checks if a field needs to be updated based on capture time + bool checkForUpdate(const word& compoundName, bool forceUpdate = false); + + template + span updateField(const word& name, bool forceUpdate = false); + + template + span updateReservedField(const word& name, bool forceUpdate = false); + + span createOrGetRealField(const word& name); + + span createOrGetVolume(bool forceUpdate=false); + + span createOrGetDensity(bool forceUpdate=false); + + span createOrGetOne(bool forceUpdate=false); + + static + bool findFunction( + const word& compoundFieldName, + word& fieldName, + fieldsDataBase::Functions& func ); + + static + bool inputOutputType( + fieldsDataBase::Functions func, + const word& inputType, + word& outputType); + + +protected: + + // - protected member functions + + + virtual + bool checkTimeFolder(const word& fieldName) const = 0; + + virtual + const shape& getShape() const= 0; + + + /// @brief return the size of pointStructure + uint32 pointFieldSize() + { + auto s = updatePoints(); + return s.size(); + } + +public: + + // - Type info + + TypeInfo("fieldsDataBase"); + + // - constructors + + fieldsDataBase(systemControl& control, 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 + virtual ~fieldsDataBase() = default; + + create_vCtor + ( + fieldsDataBase, + bool, + (systemControl& control, bool inSimulation), + (control, inSimulation) + ); + + + // - Public Access Functions + /// returns the current time + timeValue currentTime()const; + + /// const ref to object Time + const Time& time()const + { + return time_; + } + + Time& time() + { + return time_; + } + + // - Public Member Functions + + bool getFieldTypeNameFunction + ( + const word& compoundName, + word& pointFieldName, + word& originalType, + word& typeAfterFunction, + Functions& func + )const; + + + bool getFieldType + ( + const word& compoundName, + word& originalType, + word& typeAfterFunction + ) const; + + bool getFieldType + ( + const word& compoundName, + word& typeAfterFunction + ) const; + + + /// update pointStructure if necessary + span updatePoints(bool forceUpdate = false); + + /// update a field with realx3 type + span updateFieldRealx3( + const word& compoundName, + bool forceUpdate = false); + + span updateFieldRealx4( + const word& compoundName, + bool forceUpdate = false); + + 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); + + virtual + const pointStructure& pStruct()const = 0; + + virtual + void resetTimeFolder() = 0; + + static + uniquePtr create( + systemControl& control, + bool inSimulation); +}; + +} // namespace pFlow + +#include "fieldsDataBaseTemplates.cpp" + +#endif //__fieldsDataBased_hpp__ diff --git a/src/PostprocessData/fieldsDataBase/fieldsDataBaseDclr.hpp b/src/PostprocessData/fieldsDataBase/fieldsDataBaseDclr.hpp new file mode 100644 index 00000000..283b5e7b --- /dev/null +++ b/src/PostprocessData/fieldsDataBase/fieldsDataBaseDclr.hpp @@ -0,0 +1,45 @@ + +#ifndef __fieldsDataBaseDclr_hpp__ +#define __fieldsDataBaseDclr_hpp__ + +#include +#include +#include + +#include "types.hpp" +#include "span.hpp" + +namespace pFlow +{ + + +template +concept ValidFieldType = + std::same_as || + std::same_as || + std::same_as || + std::same_as; + +template +concept VectorType = + std::same_as || + std::same_as; + +template +concept ScalarType = + std::same_as; + + +template +concept ValidRegionFieldType = + std::same_as || + std::same_as || + std::same_as ; + + +using allPointFieldTypes = std::variant, span, span>; + + +} // namespace pFlow + +#endif //__fieldsDataBaseDclr_hpp__ \ No newline at end of file diff --git a/src/PostprocessData/fieldsDataBase/fieldsDataBaseTemplates.cpp b/src/PostprocessData/fieldsDataBase/fieldsDataBaseTemplates.cpp new file mode 100644 index 00000000..a36eb95c --- /dev/null +++ b/src/PostprocessData/fieldsDataBase/fieldsDataBaseTemplates.cpp @@ -0,0 +1,141 @@ +/*------------------------------- 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(reservedFieldNames_.contains(name)) + { + return updateReservedField(name, true); + } + else + { + if( loadPointFieldToTime(name) ) + { + const auto& pField = time_.lookupObject>(name); + allFields_.emplaceBackOrReplace>( + name, + pField.activeValuesHost()); + } + else + { + fatalErrorInFunction<<"Error in loading the pointField "<>(name); + + return span( + field.data(), + field.size()); + +} + + +template +inline +pFlow::span pFlow::fieldsDataBase::updateReservedField +( + const word& name, + bool forceUpdate +) +{ + if(name == "one") + { + if constexpr( std::same_as) + { + return createOrGetOne(forceUpdate); + } + else + { + fatalErrorInFunction + << "This type: " + << getTypeName() + <<" is not supported for field one."<) + { + return createOrGetVolume(forceUpdate); + } + else + { + fatalErrorInFunction + << "This type: " + << getTypeName() + <<" is not supported for field volume."<) + { + return createOrGetDensity(forceUpdate); + } + else + { + fatalErrorInFunction + << "This type: " + << getTypeName() + <<" is not supported for field density."<) + { + return updatePoints(forceUpdate); + } + else + { + fatalErrorInFunction + << "This type: " + << getTypeName() + <<" is not supported for field position."<(nullptr, 0); + +} + +#endif //__fieldsDataBaseTemplates_hpp__ \ No newline at end of file diff --git a/src/PostprocessData/fieldsDataBase/simulationFieldsDataBase.cpp b/src/PostprocessData/fieldsDataBase/simulationFieldsDataBase.cpp new file mode 100644 index 00000000..312f8e51 --- /dev/null +++ b/src/PostprocessData/fieldsDataBase/simulationFieldsDataBase.cpp @@ -0,0 +1,62 @@ +#include "Time.hpp" +#include "simulationFieldsDataBase.hpp" +#include "dynamicPointStructure.hpp" +#include "vocabs.hpp" + +namespace pFlow +{ + bool pointFieldGetType(const word& TYPENAME, word& fieldType, word& fieldSpace); +} + +bool pFlow::simulationFieldsDataBase::pointFieldNameExists(const word &name) const +{ + return time().lookupObjectName(name); +} + +bool pFlow::simulationFieldsDataBase::loadPointFieldToTime(const word &name) +{ + return time().lookupObjectName(name); +} + +bool pFlow::simulationFieldsDataBase::loadPointStructureToTime() +{ + // it is already in the Time object + return time().lookupObjectName(pointStructureFile__); +} + +bool pFlow::simulationFieldsDataBase::checkTimeFolder(const word &fieldName) const +{ + return true; +} + +const pFlow::shape& pFlow::simulationFieldsDataBase::getShape() const +{ + return shape_; +} + +pFlow::simulationFieldsDataBase::simulationFieldsDataBase +( + systemControl &control, + bool inSimulation +) +: + fieldsDataBase(control, inSimulation), + shape_ + ( + dynamic_cast(*control.caseSetup().lookupObjectPtr(shapeFile__)) + ) +{ +} + +const pFlow::pointStructure &pFlow::simulationFieldsDataBase::pStruct() const +{ + return + static_cast + ( + time().lookupObject(pointStructureFile__) + ); +} + +void pFlow::simulationFieldsDataBase::resetTimeFolder() +{ +} diff --git a/src/PostprocessData/fieldsDataBase/simulationFieldsDataBase.hpp b/src/PostprocessData/fieldsDataBase/simulationFieldsDataBase.hpp new file mode 100644 index 00000000..d7ea7f50 --- /dev/null +++ b/src/PostprocessData/fieldsDataBase/simulationFieldsDataBase.hpp @@ -0,0 +1,79 @@ +/*------------------------------- phasicFlow --------------------------------- + O C enter of + O O E ngineering and + O O M ultiscale modeling of + OOOOOOO F luid flow +------------------------------------------------------------------------------ + Copyright (C): www.cemf.ir + email: hamid.r.norouzi AT gmail.com +------------------------------------------------------------------------------ +Licence: + This file is part of phasicFlow code. It is a free software for simulating + granular and multiphase flows. You can redistribute it and/or modify it under + the terms of GNU General Public License v3 or any other later versions. + + phasicFlow is distributed to help others in their research in the field of + granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +-----------------------------------------------------------------------------*/ + +#ifndef __simulationFieldsDataBase_hpp__ +#define __simulationFieldsDataBase_hpp__ + +#include "fieldsDataBase.hpp" + +namespace pFlow +{ + +class simulationFieldsDataBase +: + public fieldsDataBase +{ +private: + + const shape& shape_; + +protected: + + /// check if pointField name exists in Time or time folder + bool pointFieldNameExists(const word& name)const override; + + /// Loads a pointField with a given name to the Time object. + /// For simulation, it just checks if the name exists + bool loadPointFieldToTime(const word& name) override; + + /// Loads pointStructure to the Time object + /// For simulation, it just checks if the name exists + bool loadPointStructureToTime() override; + + bool checkTimeFolder(const word& fieldName) const override; + + const shape& getShape() const override; + +public: + + TypeInfo("fieldsDataBase"); + + simulationFieldsDataBase(systemControl& control, bool inSimulation); + + ~simulationFieldsDataBase() override = default; + + add_vCtor + ( + fieldsDataBase, + simulationFieldsDataBase, + bool + ); + + const pointStructure& pStruct()const override; + + void resetTimeFolder() override; + +}; + + +} + + +#endif //__simulationFieldsDataBase_hpp__ \ No newline at end of file diff --git a/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAvMassVelocity.cpp b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAvMassVelocity.cpp new file mode 100644 index 00000000..580d5ae0 --- /dev/null +++ b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAvMassVelocity.cpp @@ -0,0 +1,20 @@ +#include "PostprocessOperationAvMassVelocity.hpp" + +pFlow::PostprocessOperationAvMassVelocity::PostprocessOperationAvMassVelocity +( + const dictionary &opDict, + const regionPoints ®Points, + fieldsDataBase &fieldsDB +) +: + PostprocessOperationAverage + ( + opDict, + opDict.getValOrSet("velocityName", "velocity"), + opDict.getValOrSet("massName", "mass"), + "all", + regPoints, + fieldsDB + ) +{ +} \ No newline at end of file diff --git a/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAvMassVelocity.hpp b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAvMassVelocity.hpp new file mode 100644 index 00000000..5c0f164e --- /dev/null +++ b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAvMassVelocity.hpp @@ -0,0 +1,173 @@ +/*------------------------------- phasicFlow --------------------------------- + O C enter of + O O E ngineering and + O O M ultiscale modeling of + OOOOOOO F luid flow +------------------------------------------------------------------------------ + Copyright (C): www.cemf.ir + email: hamid.r.norouzi AT gmail.com +------------------------------------------------------------------------------ +Licence: + This file is part of phasicFlow code. It is a free software for simulating + granular and multiphase flows. You can redistribute it and/or modify it under + the terms of GNU General Public License v3 or any other later versions. + + phasicFlow is distributed to help others in their research in the field of + granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +-----------------------------------------------------------------------------*/ + +#ifndef __PostprocessOperationAvMassVelocity_hpp__ +#define __PostprocessOperationAvMassVelocity_hpp__ + +/*! + * @class PostprocessOperationAvMassVelocity + * @brief A class for averaging field values within specified regions during post-processing. + * + * @details + * The PostprocessOperationAvMassVelocity class is a specialized post-processing operation that + * calculates the average of field values within specified regions. It inherits from the + * postprocessOperation base class and implements a weighted averaging operation that + * can be applied to scalar (real), vector (realx3), and tensor (realx4) fields. + * + * The average operation follows the mathematical formula: + * \f[ + * \text{result} = \frac{\sum_{j \in \text{includeMask}} w_j \cdot \phi_j \cdot \text{field}_j} + * {\sum_{i \in \text{processRegion}} w_i \cdot \phi_i} + * \f] + * + * Where: + * - \f$ i \f$ represents all particles within the specified processing region + * - \f$ j \f$ belongs to a subset of \f$ i \f$ based on an includeMask + * - \f$ w_i \f$ is the weight factor for particle \f$ i \f$ + * - \f$ \phi_i \f$ is the value from the phi field for particle \f$ i \f$ + * - \f$ \text{field}_j \f$ is the value from the target field for particle \f$ j \f$ + * + * The calculation can optionally be divided by the region volume (when divideByVolume is set to yes), + * which allows calculating normalized averages: + * \f[ + * \text{result} = \frac{1}{V_{\text{region}}} \frac{\sum_{j \in \text{includeMask}} w_j \cdot \phi_j \cdot \text{field}_j} + * {\sum_{i \in \text{processRegion}} w_i \cdot \phi_i} + * \f] + * + * The averaging can be further filtered using an includeMask to selectively include only + * specific particles that satisfy certain criteria. + * + * This class supports the following field types: + * - real (scalar values) + * - realx3 (vector values) + * - realx4 (tensor values) + * + * @section usage Usage Example + * Below is a sample dictionary showing how to configure and use this class: + * + * ``` + * processMethod arithmetic; // method of performing the sum (arithmetic, uniformDistribution, GaussianDistribution) + * processRegion sphere; // type of region on which processing is performed + * + * sphereInfo + * { + * radius 0.01; + * center (-0.08 -0.08 0.015); + * } + * + * timeControl default; + * + * /// all the post process operations to be done + * operations + * ( + * // computes the arithmetic mean of particle velocity + * averageVel + * { + * function average; + * field velocity; + * dividedByVolume no; // default is no + * threshold 3; // default is 1 + * includeMask all; // include all particles in the calculation + * } + * + * // computes the fraction of par1 in the region + * par1Fraction + * { + * function average; + * field one; // the "one" field is special - all members have value 1.0 + * phi one; // default is "one" + * dividedByVolume no; + * includeMask lessThan; + * + * // diameter of par1 is 0.003, so these settings + * // will select only particles of type par1 + * lessThanInfo + * { + * field diameter; + * value 0.0031; + * } + * } + * ); + * ``` + * + * @section defaults Default Behavior + * - By default, `phi` is set to the field named "one" which contains value 1.0 for all entries + * - `dividedByVolume` is set to "no" by default + * - `threshold` is set to 1 by default + * - `includeMask` can be set to various filters, with "all" being the default to include all particles + * + * @section special Special Fields + * The field named "one" is a special field where all members have the value 1.0. This makes it + * particularly useful for calculating: + * + * 1. Volume or number fractions (as shown in the par1Fraction example) + * 2. Simple counts when used with an appropriate mask + * 3. Normalizing values by particle count + * + * @see postprocessOperation + * @see executeAverageOperation + */ + +#include +#include + +#include "PostprocessOperationAverage.hpp" +#include "regionField.hpp" +#include "includeMask.hpp" + +namespace pFlow +{ + + +class PostprocessOperationAvMassVelocity +: + public PostprocessOperationAverage +{ + +public: + + TypeInfo("PostprocessOperation"); + + /// @brief Constructs average operation processor + /// @param opDict Operation parameters dictionary + /// @param regPoints Region points data + /// @param fieldsDB Fields database + PostprocessOperationAvMassVelocity( + const dictionary& opDict, + const regionPoints& regPoints, + fieldsDataBase& fieldsDB); + + /// destructor + ~PostprocessOperationAvMassVelocity() override = default; + + /// add this virtual constructor to the base class + add_vCtor + ( + postprocessOperation, + PostprocessOperationAvMassVelocity, + dictionary + ); + +}; + + +} + +#endif //__PostprocessOperationAvMassVelocity_hpp__ \ No newline at end of file diff --git a/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAverage.cpp b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAverage.cpp new file mode 100644 index 00000000..3ffbd5b8 --- /dev/null +++ b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAverage.cpp @@ -0,0 +1,140 @@ +#include "PostprocessOperationAverage.hpp" +#include "dictionary.hpp" +#include "fieldsDataBase.hpp" +#include "operationFunctions.hpp" + +/// Constructs average processor and initializes result field based on input field type +pFlow::PostprocessOperationAverage::PostprocessOperationAverage +( + const dictionary &opDict, + const regionPoints ®Points, + fieldsDataBase &fieldsDB +) +: + postprocessOperation(opDict, regPoints, fieldsDB), + calculateFluctuation2_(opDict.getValOrSet("fluctuation2", Logical(false))) +{ + if( fieldType() == getTypeName() ) + { + processedRegFieldPtr_ = makeUnique( + regionField(processedFieldName(), regPoints, real(0))); + } + else if( fieldType() == getTypeName() ) + { + processedRegFieldPtr_ = makeUnique( + regionField(processedFieldName(), regPoints, realx3(0))); + } + else if( fieldType() == getTypeName() ) + { + processedRegFieldPtr_ = makeUnique( + regionField(processedFieldName(), regPoints, realx4(0))); + } + else + { + fatalErrorInFunction<<" in dictionary "<< opDict.globalName() + << " field type is not supported for average operation" + << " field type is "<< fieldType() + << endl; + fatalExit; + } +} + +pFlow::PostprocessOperationAverage::PostprocessOperationAverage +( + const dictionary &opDict, + const word &fieldName, + const word &phiName, + const word &includeName, + const regionPoints ®Points, + fieldsDataBase &fieldsDB +) +: + postprocessOperation(opDict, fieldName, phiName, includeName, regPoints, fieldsDB), + calculateFluctuation2_(opDict.getValOrSet("fluctuation2", Logical(false))) +{ + if( fieldType() == getTypeName() ) + { + processedRegFieldPtr_ = makeUnique( + regionField(processedFieldName(), regPoints, real(0))); + } + else if( fieldType() == getTypeName() ) + { + processedRegFieldPtr_ = makeUnique( + regionField(processedFieldName(), regPoints, realx3(0))); + } + else if( fieldType() == getTypeName() ) + { + processedRegFieldPtr_ = makeUnique( + regionField(processedFieldName(), regPoints, realx4(0))); + } + else + { + fatalErrorInFunction<<" in dictionary "<< opDict.globalName() + << " field type is not supported for average operation" + << " field type is "<< fieldType() + << endl; + fatalExit; + } +} + +/// Performs weighted average of field values within each region +bool pFlow::PostprocessOperationAverage::execute +( + const std::vector>& weights, + const regionField& volFactor +) +{ + auto allField = database().updateFieldAll(fieldName()); + auto phi = database().updateFieldReal( + phiFieldName()); + + auto mask = getMask(); + word procName = processedFieldName(); + const auto& regP = regPoints(); + bool dbVol = divideByVolume(); + + processedRegFieldPtr_ = makeUnique + ( + std::visit([&](auto&& field)->processedRegFieldType + { + return executeAverageOperation( + procName, + field, + volFactor, + dbVol, + weights, + phi, + mask); + }, + allField) + ); + + if(calculateFluctuation2_) + { + auto& processedRegField = processedRegFieldPtr_(); + fluctuation2FieldPtr_ = makeUnique + ( + std::visit([&](auto& field)->processedRegFieldType + { + using T = typename std::decay_t>::valueType; + if constexpr( std::is_same_v || + std::is_same_v|| + std::is_same_v) + { + return executeFluctuation2Operation( + procName, + field, + std::get>(processedRegField), + volFactor, + dbVol, + weights, + mask); + } + }, + allField) + ); + } + + + return true; +} \ No newline at end of file diff --git a/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAverage.hpp b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAverage.hpp new file mode 100644 index 00000000..6620d588 --- /dev/null +++ b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationAverage.hpp @@ -0,0 +1,205 @@ +/*------------------------------- phasicFlow --------------------------------- + O C enter of + O O E ngineering and + O O M ultiscale modeling of + OOOOOOO F luid flow +------------------------------------------------------------------------------ + Copyright (C): www.cemf.ir + email: hamid.r.norouzi AT gmail.com +------------------------------------------------------------------------------ +Licence: + This file is part of phasicFlow code. It is a free software for simulating + granular and multiphase flows. You can redistribute it and/or modify it under + the terms of GNU General Public License v3 or any other later versions. + + phasicFlow is distributed to help others in their research in the field of + granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +-----------------------------------------------------------------------------*/ + +#ifndef __PostprocessOperationAverage_hpp__ +#define __PostprocessOperationAverage_hpp__ + +/*! + * @class PostprocessOperationAverage + * @brief A class for averaging field values within specified regions during post-processing. + * + * @details + * The PostprocessOperationAverage class is a specialized post-processing operation that + * calculates the average of field values within specified regions. It inherits from the + * postprocessOperation base class and implements a weighted averaging operation that + * can be applied to scalar (real), vector (realx3), and tensor (realx4) fields. + * + * The average operation follows the mathematical formula: + * \f[ + * \text{result} = \frac{\sum_{j \in \text{includeMask}} w_j \cdot \phi_j \cdot \text{field}_j} + * {\sum_{i \in \text{processRegion}} w_i \cdot \phi_i} + * \f] + * + * Where: + * - \f$ i \f$ represents all particles within the specified processing region + * - \f$ j \f$ belongs to a subset of \f$ i \f$ based on an includeMask + * - \f$ w_i \f$ is the weight factor for particle \f$ i \f$ + * - \f$ \phi_i \f$ is the value from the phi field for particle \f$ i \f$ + * - \f$ \text{field}_j \f$ is the value from the target field for particle \f$ j \f$ + * + * The calculation can optionally be divided by the region volume (when divideByVolume is set to yes), + * which allows calculating normalized averages: + * \f[ + * \text{result} = \frac{1}{V_{\text{region}}} \frac{\sum_{j \in \text{includeMask}} w_j \cdot \phi_j \cdot \text{field}_j} + * {\sum_{i \in \text{processRegion}} w_i \cdot \phi_i} + * \f] + * + * The averaging can be further filtered using an includeMask to selectively include only + * specific particles that satisfy certain criteria. + * + * This class supports the following field types: + * - real (scalar values) + * - realx3 (vector values) + * - realx4 (tensor values) + * + * @section usage Usage Example + * Below is a sample dictionary showing how to configure and use this class: + * + * ``` + * processMethod arithmetic; // method of performing the sum (arithmetic, uniformDistribution, GaussianDistribution) + * processRegion sphere; // type of region on which processing is performed + * + * sphereInfo + * { + * radius 0.01; + * center (-0.08 -0.08 0.015); + * } + * + * timeControl default; + * + * /// all the post process operations to be done + * operations + * ( + * // computes the arithmetic mean of particle velocity + * averageVel + * { + * function average; + * field velocity; + * dividedByVolume no; // default is no + * threshold 3; // default is 1 + * includeMask all; // include all particles in the calculation + * } + * + * // computes the fraction of par1 in the region + * par1Fraction + * { + * function average; + * field one; // the "one" field is special - all members have value 1.0 + * phi one; // default is "one" + * dividedByVolume no; + * includeMask lessThan; + * + * // diameter of par1 is 0.003, so these settings + * // will select only particles of type par1 + * lessThanInfo + * { + * field diameter; + * value 0.0031; + * } + * } + * ); + * ``` + * + * @section defaults Default Behavior + * - By default, `phi` is set to the field named "one" which contains value 1.0 for all entries + * - `dividedByVolume` is set to "no" by default + * - `threshold` is set to 1 by default + * - `includeMask` can be set to various filters, with "all" being the default to include all particles + * + * @section special Special Fields + * The field named "one" is a special field where all members have the value 1.0. This makes it + * particularly useful for calculating: + * + * 1. Volume or number fractions (as shown in the par1Fraction example) + * 2. Simple counts when used with an appropriate mask + * 3. Normalizing values by particle count + * + * @see postprocessOperation + * @see executeAverageOperation + */ + +#include +#include + +#include "postprocessOperation.hpp" +#include "regionField.hpp" +#include "includeMask.hpp" + +namespace pFlow +{ + + +class PostprocessOperationAverage +: + public postprocessOperation +{ +private: + + ///< Flag to calculate fluctuation powered by 2 + Logical calculateFluctuation2_; + + /// Result field containing averages for each region (real, realx3, or realx4) + uniquePtr processedRegFieldPtr_ = nullptr; + + uniquePtr fluctuation2FieldPtr_ = nullptr; + +public: + + TypeInfo("PostprocessOperation"); + + /// @brief Constructs average operation processor + /// @param opDict Operation parameters dictionary + /// @param regPoints Region points data + /// @param fieldsDB Fields database + PostprocessOperationAverage( + const dictionary& opDict, + const regionPoints& regPoints, + fieldsDataBase& fieldsDB); + + PostprocessOperationAverage( + const dictionary& opDict, + const word& fieldName, + const word& phiName, + const word& includeName, + const regionPoints& regPoints, + fieldsDataBase& fieldsDB); + + + /// destructor + ~PostprocessOperationAverage() override = default; + + /// add this virtual constructor to the base class + add_vCtor + ( + postprocessOperation, + PostprocessOperationAverage, + dictionary + ); + + /// @brief Get the processed field containing regional averages + /// @return Const reference to average results + const processedRegFieldType& processedField()const override + { + return processedRegFieldPtr_(); + } + + /// @brief Execute average operation on field values + /// @param weights Weight factors for particles + /// @return True if successful + bool execute( + const std::vector>& weights, + const regionField& volFactor) override; + +}; + + +} + +#endif //__PostprocessOperationAverage_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..c10315d7 --- /dev/null +++ b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.cpp @@ -0,0 +1,74 @@ +#include "PostprocessOperationSum.hpp" +#include "dictionary.hpp" +#include "fieldsDataBase.hpp" +#include "operationFunctions.hpp" + +/// Constructs sum processor and initializes result field based on input field type +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; + } +} + +/// Performs weighted sum of field values within each region +bool pFlow::PostprocessOperationSum::execute +( + const std::vector>& weights, + const regionField& volFactor +) +{ + 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, + volFactor, + 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..b811e89b --- /dev/null +++ b/src/PostprocessData/operation/PostprocessOperation/PostprocessOperationSum.hpp @@ -0,0 +1,187 @@ +/*------------------------------- 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__ + +/*! + * @class PostprocessOperationSum + * @brief A class for summing field values within specified regions during post-processing. + * + * @details + * The PostprocessOperationSum class is a specialized post-processing operation that + * calculates the sum of field values within specified regions. It inherits from the + * postprocessOperation base class and implements a weighted summation operation that + * can be applied to scalar (real), vector (realx3), and tensor (realx4) fields. + * + * The sum operation follows the mathematical formula: + * \f[ + * \text{result} = \sum_{i \in \text{processRegion}} w_i \cdot \phi_i \cdot \text{field}_i + * \f] + * + * Where: + * - \f$ i \f$ represents particles within the specified processing region + * - \f$ w_i \f$ is the weight factor for particle \f$ i \f$ + * - \f$ \phi_i \f$ is the value from the phi field for particle \f$ i \f$ + * - \f$ \text{field}_i \f$ is the value from the target field for particle \f$ i \f$ + * + * The calculation can optionally be divided by the region volume (when divideByVolume is set to yes), + * which allows calculating density-like quantities: + * \f[ + * \text{result} = \frac{1}{V_{\text{region}}} \sum_{i \in \text{processRegion}} w_i \cdot \phi_i \cdot \text{field}_i + * \f] + * + * The summation can be further filtered using an includeMask to selectively include only + * specific particles that satisfy certain criteria. + * + * This class supports the following field types: + * - real (scalar values) + * - realx3 (vector values) + * - realx4 (tensor values) + * + * @section usage Usage + * + * To use the PostprocessOperationSum class in a postprocessDataDict file, the following + * parameters can be specified: + * + * - function: Must be set to "sum" to use this operation + * - field: The name of the field to process (e.g., "velocity", "diameter", "one") + * - Special fields like "one" (constant value 1) are also supported + * - Expressions like "cube(diameter)" can be used for mathematical operations + * - dividedByVolume: Whether to divide the sum by the region volume (yes/no, default: no) + * - includeMask: Optional mask to filter which particles to include in the calculation + * + * @section example Example Configuration + * + * Here is an example configuration in the postprocessDataDict file: + * + * @code + * { + * processMethod arithmetic; + * processRegion line; + * + * // the time interval for executing the post-processing + * // other options: timeStep, default, and settings + * timeControl simulationTime; + * startTime 1.0; + * endTime 3.0; + * executionInterval 0.1; + * + * // 10 spheres with radius 0.01 along the straight line defined by p1 and p2 + * lineInfo + * { + * p1 (0 0 0); + * p2 (0 0.15 0.15); + * numPoints 10; + * radius 0.01; + * } + * + * operations + * ( + * // computes the number density (particles per unit volume) + * numberDensity + * { + * function sum; + * field one; // constant field with value 1.0 + * dividedByVolume yes; // divide by region volume + * } + * + * // computes an approximation of volume fraction + * volumeDensity + * { + * function sum; + * field cube(diameter); // d^3, although it differs by pi/6 + * dividedByVolume yes; + * } + * ); + * } + * @endcode + * + * In this example: + * - numberDensity: Calculates the number of particles per unit volume + * - volumeDensity: Calculates an approximation of the volume fraction using d³ + * + * @see postprocessOperation + * @see executeSumOperation + */ + +#include +#include + +#include "postprocessOperation.hpp" +#include "regionField.hpp" +#include "includeMask.hpp" + +namespace pFlow +{ + + +class PostprocessOperationSum +: + public postprocessOperation +{ +private: + /// Result field containing sums for each region (real, realx3, or realx4) + uniquePtr processedRegField_ = nullptr; + +public: + + TypeInfo("PostprocessOperation"); + + /// @brief Constructs sum operation processor + /// @param opDict Operation parameters dictionary + /// @param regPoints Region points data + /// @param fieldsDB Fields database + PostprocessOperationSum( + const dictionary& opDict, + const regionPoints& regPoints, + fieldsDataBase& fieldsDB); + + /// destructor + ~PostprocessOperationSum() override = default; + + /// add this virtual constructor to the base class + add_vCtor + ( + postprocessOperation, + PostprocessOperationSum, + dictionary + ); + + /// @brief Get the processed field containing regional sums + /// @return Const reference to sum results + const processedRegFieldType& processedField()const override + { + return processedRegField_(); + } + + /// @brief Execute sum operation on field values + /// @param weights Weight factors for particles + /// @return True if successful + bool execute( + const std::vector>& weights, + const regionField& volFactor) override; + +}; + + +} + +#endif //__PostprocessOperationSum_hpp__ \ No newline at end of file diff --git a/src/PostprocessData/operation/PostprocessOperation/operationFunctions.hpp b/src/PostprocessData/operation/PostprocessOperation/operationFunctions.hpp new file mode 100644 index 00000000..8dbe643b --- /dev/null +++ b/src/PostprocessData/operation/PostprocessOperation/operationFunctions.hpp @@ -0,0 +1,195 @@ +/*------------------------------- 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 __operationFunctions_hpp__ +#define __operationFunctions_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 regionField& volFactor, + const bool devideByVol, + const std::vector>& weights, + const span& phi, + const includeMask::Mask& mask +) +{ + const auto& regPoints = volFactor.regPoints(); + regionField processedField(regFieldName, regPoints, T{}); + auto vols = regPoints.volumes(); + + for(uint32 reg =0; reg +regionField executeAverageOperation +( + const word& regFieldName, + const span& field, + const regionField& volFactor, + const bool devideByVol, + const std::vector>& weights, + const span& phi, + const includeMask::Mask& mask +) +{ + + const auto& regPoints = volFactor.regPoints(); + regionField processedField(regFieldName, regPoints, T{}); + auto vols = regPoints.volumes(); + + for(uint32 reg =0; reg +regionField executeFluctuation2Operation +( + const word& regFieldName, + const span& field, + const regionField& fieldAvg, + const regionField& volFactor, + const bool devideByVol, + const std::vector>& weights, + const includeMask::Mask& mask +) +{ + const auto& regPoints = fieldAvg.regPoints(); + regionField processedField(regFieldName, regPoints, T{}); + auto vols = regPoints.volumes(); + + for(uint32 reg =0; reg(2)); + } + sumDen += w[n]; + } + n++; + } + + if(devideByVol) + { + processedField[reg] = sumNum / max(sumDen, smallValue) / vol; + } + else + { + processedField[reg] = sumNum / max(sumDen, smallValue); + } + + } + + return processedField; +} + +} // namespace pFlow + +#endif //__operationFunctions_hpp__ diff --git a/src/PostprocessData/operation/includeMask/IncludeMask.hpp b/src/PostprocessData/operation/includeMask/IncludeMask.hpp new file mode 100644 index 00000000..34ae4dfb --- /dev/null +++ b/src/PostprocessData/operation/includeMask/IncludeMask.hpp @@ -0,0 +1,277 @@ +/*------------------------------- 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. + +-----------------------------------------------------------------------------*/ + +/** + * @brief A template class implementing includeMask for filtering data based on field values + * + * The IncludeMask class creates boolean masks that identify which elements from a field + * satisfy a given condition. It applies an operator to each element of a field and + * generates a mask (vector of booleans) where true means the element satisfies the + * condition and should be included. + * + * @tparam T The data type of the field (real, realx3, realx4) + * @tparam Operator The operation class that defines the condition (e.g., greaterThanOp) + * + * The class has a specialized implementation for allOp operator which includes all elements. + * + * Usage example in postprocessDataDict: + * ``` + * // Create a dictionary with the required configuration for filtering + * + * { + * includeMask lessThan; + * + * // Diameter of par1 is 0.003, so these settings + * // will select only particles of type par1 + * lessThanInfo + * { + * field diameter; + * value 0.0031; + * } + * + * } + * + * ``` + */ + +#ifndef __IncludeMask_hpp__ +#define __IncludeMask_hpp__ + +#include "dictionary.hpp" +#include "includeMask.hpp" +#include "fieldsDataBase.hpp" +#include "maskOperations.hpp" +#include "Time.hpp" + + +namespace pFlow +{ + +template +class IncludeMask +: + public includeMask +{ +public: + + /// Type alias for the mask container returned by getMask() + using Mask = typename includeMask::Mask; + +private: + + /// Boolean vector the filtering status of each element (true = include) + std::vector mask_; + + /// Comparison operator instance that evaluates the filtering condition + Operator operator_; + + /// Name of the field to apply filtering on + word fieldName_; + + /// Timestamp when mask was last updated (-1 indicates never updated) + timeValue lastUpdated_ = -1; + + /// Updates the mask based on current field values if needed, returns true if successful + bool updateMask() + { + timeValue t = database().currentTime(); + + 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")) + {} + + IncludeMask( + const word& type, + const dictionary& dict, + fieldsDataBase& feildsDB) + : + includeMask(type, dict, feildsDB), + operator_(dict.subDict(operatorName()+"Info")), + fieldName_( + dict.subDict + ( + operatorName()+"Info" + ).getVal("field")) + {} + + /// Add virtual constructor pattern for creating instances + add_vCtor + ( + includeMask, + IncludeMask, + dictionary + ); + + add_vCtor + ( + includeMask, + IncludeMask, + word + ); + + /// Returns the mask for filtering elements (updates the mask if necessary) + 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); + } + + IncludeMask( + const word& type, + const dictionary& opDict, + fieldsDataBase& feildsDB) + : + includeMask(type, opDict, feildsDB) + { + span s = database().updatePoints(); + mask_.resize(s.size(), true); + } + + add_vCtor + ( + includeMask, + IncludeMask, + dictionary + ); + + add_vCtor + ( + includeMask, + IncludeMask, + word + ); + + Mask getMask()override + { + 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..209391be --- /dev/null +++ b/src/PostprocessData/operation/includeMask/includeMask.cpp @@ -0,0 +1,152 @@ +/*------------------------------- 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::includeMask::includeMask +( + const word &type, + const dictionary &opDict, + fieldsDataBase &fieldsDB +) +: + database_(fieldsDB) +{ +} + +pFlow::uniquePtr pFlow::includeMask::create +( + const dictionary& opDict, + fieldsDataBase& fieldsDB +) +{ + word mask = opDict.getValOrSet("includeMask", "all"); + word fieldType; + if( mask != "all") + { + auto& maskDict = opDict.subDict(mask+"Info"); + word maskField = maskDict.getVal("field"); + + if( !fieldsDB.getFieldType(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, fieldsDB); + return objPtr; + } + else + { + printKeys + ( + fatalError << "Ctor Selector "<< + method << " dose not exist. \n" + <<"Avaiable ones are: \n\n" + , + dictionaryvCtorSelector_ + ); + fatalExit; + return nullptr; + } + return nullptr; +} + +pFlow::uniquePtr + pFlow::includeMask::create +( + const word &type, + const dictionary &opDict, + fieldsDataBase &fieldsDB +) +{ + word fieldType; + if( type != "all") + { + auto& maskDict = opDict.subDict(type+"Info"); + word maskField = maskDict.getVal("field"); + + if( !fieldsDB.getFieldType(maskField, fieldType) ) + { + fatalErrorInFunction<<"Error in retriving the type of field" + << maskField <<" from dictionary " + << maskDict.globalName() + << endl; + fatalExit; + return nullptr; + } + } + else + { + fieldType = getTypeName(); + } + + word method = angleBracketsNames2("IncludeMask", fieldType, type); + + if( wordvCtorSelector_.search(method) ) + { + auto objPtr = + wordvCtorSelector_[method] + (type, opDict, fieldsDB); + return objPtr; + } + else + { + printKeys + ( + fatalError << "Ctor Selector "<< + method << " dose not exist. \n" + <<"Avaiable ones are: \n\n" + , + wordvCtorSelector_ + ); + 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..928822b8 --- /dev/null +++ b/src/PostprocessData/operation/includeMask/includeMask.hpp @@ -0,0 +1,195 @@ +/*------------------------------- phasicFlow --------------------------------- + O C enter of + O O E ngineering and + O O M ultiscale modeling of + OOOOOOO F luid flow +------------------------------------------------------------------------------ + Copyright (C): www.cemf.ir + email: hamid.r.norouzi AT gmail.com +------------------------------------------------------------------------------ +Licence: + This file is part of phasicFlow code. It is a free software for simulating + granular and multiphase flows. You can redistribute it and/or modify it under + the terms of GNU General Public License v3 or any other later versions. + + phasicFlow is distributed to help others in their research in the field of + granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +-----------------------------------------------------------------------------*/ + +/** + * @class includeMask +* @brief Base class for creating inclusion masks for data filtering +* + * includeMask is an abstract base class for creating masks that filter data + * from a fieldsDataBase. Derived classes implement specific filtering criteria + * through the getMask() method which returns a Mask object - a wrapper around + * a vector of booleans that indicates which elements to include/exclude. + * + * This class follows a factory pattern with create() methods that instantiate + * the appropriate derived mask type based on dictionary settings. + * + * Derived classes can implement various filtering strategies such as: + * - Filtering by field values + * - Filtering by spatial regions + * - Filtering by predefined criteria + * + * The Mask objects returned by getMask() can be used in postprocessing operations + * to include only the data points that match the specified criteria. + */ + +#ifndef __includeMask_hpp__ +#define __includeMask_hpp__ + +#include + +#include "virtualConstructor.hpp" + +namespace pFlow +{ + +// forward declaration +class fieldsDataBase; +class dictionary; + + +class includeMask +{ +public: + + /// @brief Wrapper around a boolean vector that represents elements to include/exclude + /// Provides a functional interface to access the underlying mask vector + /// where true indicates inclusion and false indicates exclusion. + class Mask + { + /// @brief Reference to the underlying boolean vector + const std::vector& mask_; + + public: + + /// @brief Constructor from a boolean vector + /// @param msk Boolean vector where true means include, false means exclude + Mask(const std::vector& msk) + : + mask_(msk) + {} + + /// @brief Copy constructor + Mask(const Mask&) = default; + + /// @brief Move constructor + Mask(Mask&&) = default; + + /// @brief Destructor + ~Mask()=default; + + /// @brief Get the size of the mask + auto size()const + { + return mask_.size(); + } + + /// @brief Check if element at index i should be included + /// @param i Index to check + bool operator()(uint32 i)const + { + return mask_[i]; + } + }; + +private: + + /// @brief Reference to the database containing fields to be filtered + fieldsDataBase& database_; + +public: + + TypeInfo("includeMask"); + + /// @brief Constructor + /// @param opDict Dictionary containing operation settings + /// @param feildsDB Database of fields + includeMask(const dictionary& opDict, fieldsDataBase& feildsDB); + + /// @brief Constructor with explicit type + /// @param type Type of mask to create + /// @param opDict Dictionary containing operation settings + /// @param feildsDB Database of fields + includeMask(const word& type, const dictionary& opDict, fieldsDataBase& feildsDB); + + /// @brief Virtual destructor + virtual ~includeMask() = default; + + /// @brief Virtual constructor pattern implementation using dictionary + create_vCtor + ( + includeMask, + dictionary, + ( + const dictionary& opDict, fieldsDataBase& feildsDB + ), + (opDict, feildsDB) + ); + + /// @brief Virtual constructor pattern implementation using type and dictionary + create_vCtor + ( + includeMask, + word, + ( + const word& type, + const dictionary& opDict, + fieldsDataBase& feildsDB + ), + (type, opDict, feildsDB) + ); + + /// @brief Get const access to the database + /// @return Const reference to the fields database + const fieldsDataBase& database()const + { + return database_; + } + + /// @brief Get non-const access to the database + /// @return Reference to the fields database + fieldsDataBase& database() + { + return database_; + } + + /// @brief Get the mask for filtering elements + /// @return Mask object indicating which elements to include + virtual + Mask getMask()= 0; + + /// @brief Factory method to create appropriate mask type from dictionary + /// @param opDict Dictionary with mask settings including type + /// @param feildsDB Database of fields to filter + /// @return Unique pointer to created mask instance + static + uniquePtr create( + const dictionary& opDict, + fieldsDataBase& feildsDB); + + /// @brief Factory method to create mask with explicit type + /// @param type Type of mask to create + /// @param opDict Dictionary with mask settings + /// @param feildsDB Database of fields to filter + /// @return Unique pointer to created mask instance + static + uniquePtr create( + const word& type, + 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..63bb5665 --- /dev/null +++ b/src/PostprocessData/operation/includeMask/maskOperations.hpp @@ -0,0 +1,181 @@ +/*------------------------------- phasicFlow --------------------------------- + O C enter of + O O E ngineering and + O O M ultiscale modeling of + OOOOOOO F luid flow +------------------------------------------------------------------------------ + Copyright (C): www.cemf.ir + email: hamid.r.norouzi AT gmail.com +------------------------------------------------------------------------------ +Licence: + This file is part of phasicFlow code. It is a free software for simulating + granular and multiphase flows. You can redistribute it and/or modify it under + the terms of GNU General Public License v3 or any other later versions. + + phasicFlow is distributed to help others in their research in the field of + granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +-----------------------------------------------------------------------------*/ + +#ifndef __maskOperation_hpp__ +#define __maskOperation_hpp__ + +#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..e752f359 --- /dev/null +++ b/src/PostprocessData/operation/postprocessOperation/postprocessOperation.cpp @@ -0,0 +1,211 @@ +/*------------------------------- 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<("field"), + opDict.getValOrSet("phi", "one"), + opDict.getValOrSet("includeMask", "all"), + regPoints, + fieldsDB + ) +{} + +pFlow::postprocessOperation::postprocessOperation +( + const dictionary &opDict, + const word &fieldName, + const word &phiName, + const word& includeName, + const regionPoints ®Points, + fieldsDataBase &fieldsDB +) +: + operationDict_(opDict), + threshold_ + ( + opDict.getValOrSet("threshold", 1) + ), + divideByVolume_ + ( + opDict.getValOrSet("divideByVolume", Logical(false)) + ), + regionPoints_ + ( + regPoints + ), + database_ + ( + fieldsDB + ), + fieldName_ + ( + fieldName + ), + phiFieldName_ + ( + phiName + ), + includeMask_ + ( + includeMask::create(includeName, opDict, fieldsDB) + ) +{ + + if(!fieldsDB.getFieldType(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.timeName()); + 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 +{ + +/// Type alias for processed region field types. +/// Only regionField, regionField, and regionField are supported +/// in the postprocessOperation class. +using processedRegFieldType = std::variant + < + regionField, + regionField, + regionField + >; + +/// - forward declaration +class fieldsDataBase; +class Time; + +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: + + /// Type info + TypeInfo("postprocessOperation"); + + /// Constructor + /// @param opDict Dictionary containing operation-specific parameters. + /// @param regPoints Reference to the region points used in the operation. + /// @param fieldsDB Reference to the fields database containing field data. + postprocessOperation( + const dictionary& opDict, + const regionPoints& regPoints, + fieldsDataBase& fieldsDB ); + + postprocessOperation( + const dictionary& opDict, + const word& fieldName, + const word& phiName, + const word& includeName, + const regionPoints& regPoints, + fieldsDataBase& fieldsDB + ); + + /// destructor + virtual ~postprocessOperation()=default; + + /// Active the virtual constructor for creating derived classes. + create_vCtor( + postprocessOperation, + dictionary, + ( + const dictionary& opDict, + const regionPoints& regPoints, + fieldsDataBase& fieldsDB + ), + (opDict, regPoints, fieldsDB)); + + /// Access to regionPoints instance + const regionPoints& regPoints()const + { + return regionPoints_; + } + + /// Access to fields database instance + const fieldsDataBase& database()const + { + return database_; + } + + /// Access to fields database instance + fieldsDataBase& database() + { + return database_; + } + + /// Access to the time instance + const Time& time()const; + + /// Return the name of the processed field. + word processedFieldName()const + { + return operationDict_.name(); + } + + /// return the name of the field to be processed. + const word& fieldName()const + { + return fieldName_; + } + + /// return the type name of the field to be processed. + const word& fieldType()const + { + return fieldType_; + } + + /// return the name of the phi field to be processed. + const word& phiFieldName()const + { + return phiFieldName_; + } + + /// Access to the operation dictionary + const dictionary& operationDict()const + { + return operationDict_; + } + + /// return threshold value + /// which is used to exclude the regions which contain + /// particles fewer than this value. + const uint32 threshold()const + { + return threshold_; + } + + /// whether the result is divided by volume of the region + bool divideByVolume()const + { + return divideByVolume_(); + } + + /// return the include mask + Mask getMask() + { + return includeMask_().getMask(); + } + + /// return the processed field + virtual + const processedRegFieldType& processedField()const=0; + + /// execute the operation + /// @param weights Vector of weights for the operation. + /// @param volFactor a factor to be multiplied by the volume of the region + virtual bool execute( + const std::vector>& weights, + const regionField& volFactor) = 0; + + /// write the result to a file + /// @param parDir Parent directory for the output file. + virtual + bool write(const fileSystem &parDir)const; + + /// write the result to output stream (possibly a file) + /// @param os Output stream to write the result. + virtual + bool write(iOstream& os)const {return true;} + + /// Create the polymorphic object using the virtual constructor. + /// @param opDict Dictionary containing operation-specific parameters. + /// @param regPoints Reference to the region points used in the operation. + /// @param fieldsDB Reference to the fields database containing field data. + static + uniquePtr create( + const dictionary& opDict, + 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..10590f7c --- /dev/null +++ b/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponent.cpp @@ -0,0 +1,162 @@ +#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() + ), + volumeFactor_ + ( + "volumeFactor", + regionPointsPtr_(), + 1.0 + ), + 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; + } + + REPORT(1)<<"Executing postprocess component (" + <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, volumeFactor_) ) + { + 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_; + + regionField volumeFactor_; + + bool executed_{false}; + + dictionaryList operationDicts_; + +protected: + + std::vector& regionProecessMethod() + { + return regionsProcessMethod_; + } + + regionField& volumeFactor() + { + return volumeFactor_; + } + + const regionField& volumeFactor()const + { + return volumeFactor_; + } + +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..7b9a37c3 --- /dev/null +++ b/src/PostprocessData/postprocessComponent/PostprocessComponent/PostprocessComponentArithmetic.hpp @@ -0,0 +1,75 @@ +/*------------------------------- 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(); + auto& volFactor = this->volumeFactor(); + 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(); + auto& volFactor = this->volumeFactor(); + + 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(); + auto& volFactor = this->volumeFactor(); + const uint32 n = d.size(); + for(uint32 i=0; i; +template class pFlow::PostprocessComponentUniform; +template class pFlow::PostprocessComponentArithmetic; + +template class pFlow::PostprocessComponentGaussian; +template class pFlow::PostprocessComponentUniform; +template class pFlow::PostprocessComponentArithmetic; + +template class pFlow::PostprocessComponentGaussian; +template class pFlow::PostprocessComponentUniform; +template class pFlow::PostprocessComponentArithmetic; + diff --git a/src/PostprocessData/postprocessComponent/particleProbePostprocessComponent/particleProbePostprocessComponent.cpp b/src/PostprocessData/postprocessComponent/particleProbePostprocessComponent/particleProbePostprocessComponent.cpp new file mode 100644 index 00000000..7588e602 --- /dev/null +++ b/src/PostprocessData/postprocessComponent/particleProbePostprocessComponent/particleProbePostprocessComponent.cpp @@ -0,0 +1,152 @@ +#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; + } + + REPORT(1)<<"Executing postprocess component (" + < + ( + 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.timeName()); + 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..dc1dc479 --- /dev/null +++ b/src/PostprocessData/postprocessData/postprocessData.cpp @@ -0,0 +1,137 @@ + +/*------------------------------- 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()), + fieldsDataBasePtr_ + ( + fieldsDataBase::create + ( + const_cast(control), + true + ) + ), + dict_ + ( + objectFile + ( + "postprocessDataDict", + control.settings().path(), + objectFile::READ_IF_PRESENT, + objectFile::WRITE_NEVER + ) + ) +{ + postProcessGlobals::defaultDir__ = CWD()/pFlow::postProcessGlobals::defaultRelDir__; + + // if dictionary is not provided, no extra action is required. + if( !dict_.fileExist() || !dict_.headerOk() ) + { + WARNING<<"You requested postprocessData function while," + <<" the dictionary system/postprocessDataDict does not exist." + <<" This feature is disabled in the current run."<( + "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"); + } + + shapeType_ = dict_.getValOrSet + ( + "shapeType", + word("sphere") + ); + + componentsDictsPtr_ = makeUnique(readDictList("components", dict_)); + + for(auto& compDict:*componentsDictsPtr_) + { + postprocesses_.push_back( postprocessComponent::create( + compDict, + fieldsDataBasePtr_(), + 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 + uniquePtr fieldsDataBasePtr_; + + /// file dictionary that is constructed from the file (postProcessDataDict) + fileDictionary dict_; + + /// name of the shape for use in the time of postprocess after simulation + word shapeType_; + + /// list of dictionaries for postprocess components + uniquePtr componentsDictsPtr_ = nullptr; + + /// @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..335bc267 --- /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__ = "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..6248bfa0 --- /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" +#include "numericConstants.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..1996fed1 --- /dev/null +++ b/src/PostprocessData/region/regionFields/regionField.hpp @@ -0,0 +1,126 @@ +/*------------------------------- 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 +{ +public: + using FieldType = Field; + + using iterator = typename FieldType::iterator; + + using const_iterator = typename FieldType::const_iterator; + + using reference = typename FieldType::reference; + + using const_reference = typename FieldType::const_reference; + + using value_type = typename FieldType::value_type; + + using pointer = typename FieldType::pointer; + + using const_pointer = typename FieldType::const_pointer; +private: + + /// the field value + 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..b5ffb730 --- /dev/null +++ b/src/PostprocessData/region/regionPoints/centerPointsRegionPoints/centerPointsRegionPoints.cpp @@ -0,0 +1,97 @@ +#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 + // TODO: this should be corrected to select ids of particles + // that are selected based on the selector (this is visa versa) + { + auto selectorPtr = pStructSelector::create( + selector, + database().pStruct(), + probDict_.subDict(selector+"Info")); + auto selectedPoints = selectorPtr->selectedPoints(); + ids_.resize(selectedPoints.size()); + ids_.assign(selectedPoints.begin(), selectedPoints.end()); + } + + 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()); + } + + /// @brief Returns the equivalent diameters of the regions (this is normally not used ) + span eqDiameters()const override + { + return span(diameter_.data(), diameter_.size()); + } + + /// @brief Returns the center positions of the selected points + /// @return Span containing the center positions of all selected points + span centers()const override + { + return span(center_.data(), center_.size()); + } + + /// @brief Returns the indices of the selected points (const version) + /// @param elem Element index (not used in this implementation) + /// @return Span containing the indices of all selected points + span indices(uint32 elem)const override + { + return span(selectedPoints_.data(), selectedPoints_.size()); + } + + /// @brief Returns the indices of the selected points (non-const version) + /// @param elem Element index (not used in this implementation) + /// @return Span containing the indices of all selected points + span indices(uint32 elem) override + { + return span(selectedPoints_.data(), selectedPoints_.size()); + } + + /// @brief Updates the selected points based on the particle IDs + /// @return True if the operation is successful, false otherwise + bool update() override; + + /// @brief Checks if the data should be written to the same time file + /// @return True if data should be written to the same time file, false otherwise + bool writeToSameTimeFile()const override + { + return true; + } + + /// @brief Writes the data to the output stream + /// @param os Output stream + /// @return True if the operation is successful, false otherwise + bool write(iOstream& os)const override; + +}; // class centerPointsRegionPoints + +} // 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..979a51a6 --- /dev/null +++ b/src/PostprocessData/region/regionPoints/lineRegionPoints/lineRegionPoints.cpp @@ -0,0 +1,120 @@ +#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()); +} + +pFlow::span pFlow::lineRegionPoints::indices(uint32 elem) +{ + if(elem >= size()) + { + fatalErrorInFunction + << "The element index is out of range. elem: " << elem + << " size: " << size() << endl; + fatalExit; + } + + return span( + selectedPoints_[elem].data(), + selectedPoints_[elem].size()); +} + +bool pFlow::lineRegionPoints::update() +{ + const auto points = database().updatePoints(); + 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." << tab << "centerPoint" << tab << "diameter" << endl; + for(uint32 i=0; i < sphereRegions_.size(); ++i) + { + os << "# " << i << tab << sphereRegions_[i].center() + << tab << diameters_[i] << '\n'; + } + os << "time/No. "; + for(uint32 i=0; i < sphereRegions_.size(); ++i) + { + os << i << tab; + } + os << endl; + return true; +} diff --git a/src/PostprocessData/region/regionPoints/lineRegionPoints/lineRegionPoints.hpp b/src/PostprocessData/region/regionPoints/lineRegionPoints/lineRegionPoints.hpp new file mode 100644 index 00000000..58989aab --- /dev/null +++ b/src/PostprocessData/region/regionPoints/lineRegionPoints/lineRegionPoints.hpp @@ -0,0 +1,148 @@ +/*------------------------------- phasicFlow --------------------------------- + O C enter of + O O E ngineering and + O O M ultiscale modeling of + OOOOOOO F luid flow +------------------------------------------------------------------------------ + Copyright (C): www.cemf.ir + email: hamid.r.norouzi AT gmail.com +------------------------------------------------------------------------------ +Licence: + This file is part of phasicFlow code. It is a free software for simulating + granular and multiphase flows. You can redistribute it and/or modify it under + the terms of GNU General Public License v3 or any other later versions. + + phasicFlow is distributed to help others in their research in the field of + granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +-----------------------------------------------------------------------------*/ + +/** + * @class lineRegionPoints + * @brief Spherical regions along a line for selecting points/particles + * + * The lineRegionPoints class is responsible for selecting points/particles along a + * specified line and creating sphere regions around those points. It partitions + * the line into multiple sphere regions (equally spaced) and keeps track of + * which points/particles in the simulation fall into each region. + * + * This class is used for post-processing data by analyzing distributions of + * particles along a linear path through the simulation domain. It maintains: + * - A line defining the sampling path + * - Spherical regions along this line that include particles + * - Center points for each region + * - Volumes and diameters of regions + * - Indices of points/particles contained in each region + * + * The regions can be updated as the simulation progresses, and the data + * can be written to output for analysis. + * + * @see regionPoints + * @see line + * @see sphere + * @see fieldsDataBase + */ + +#ifndef __lineRegionPoints_hpp__ +#define __lineRegionPoints_hpp__ + + +#include "regionPoints.hpp" +#include "line.hpp" +#include "sphere.hpp" +#include "Vectors.hpp" + + +namespace pFlow +{ + +class lineRegionPoints +: + public regionPoints +{ +private: + + /// Line path defining the axis of the spherical regions + line line_; + + /// Collection of sphere regions along the line + Vector sphereRegions_; + + /// Center points of all spherical regions + realx3Vector centerPoints_; + + /// Volumes of all spherical regions + realVector volumes_; + + /// Diameters of all spherical regions + realVector diameters_; + + /// Point/particles indices selected by each region + Vector selectedPoints_; + +public: + + /// Type information for runtime type identification + TypeInfo(line::TYPENAME()); + + /// Construct from dictionary that contains lineInfo and fields database + lineRegionPoints( + const dictionary& dict, + fieldsDataBase& fieldsDataBase); + + /// Default destructor + ~lineRegionPoints() override = default; + + /// Return number of regions + uint32 size()const override + { + return sphereRegions_.size(); + } + + /// Check if regions list is empty + bool empty()const override + { + return sphereRegions_.empty(); + } + + /// Return volumes of all regions + span volumes()const override + { + return span(volumes_.data(), volumes_.size()); + } + + /// Return equivalent diameters of all regions + span eqDiameters()const override + { + return span(diameters_.data(), diameters_.size()); + } + + /// Return center points of all regions + span centers()const override + { + return span(centerPoints_.data(), centerPoints_.size()); + } + + /// Return indices of points in the specified element/region + span indices(uint32 elem)const override; + + span indices(uint32 elem) override; + + /// Update regions based on current particle positions + bool update() override; + + /// Whether to write all data to the same time file + bool writeToSameTimeFile()const override + { + return true; + } + + /// Write data to output stream + bool write(iOstream& os) const override; +}; + +} + + +#endif // __lineRegionPoints_hpp__ \ No newline at end of file diff --git a/src/PostprocessData/region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.cpp b/src/PostprocessData/region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.cpp new file mode 100644 index 00000000..e983c602 --- /dev/null +++ b/src/PostprocessData/region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.cpp @@ -0,0 +1,112 @@ +#include "multipleSpheresRegionPoints.hpp" +#include "fieldsDataBase.hpp" + +pFlow::multipleSpheresRegionPoints::multipleSpheresRegionPoints +( + const dictionary &dict, + fieldsDataBase &fieldsDataBase +) +: + regionPoints(dict, fieldsDataBase) +{ + const auto& multiSphereInfo = dict.subDict("multipleSphereInfo"); + + // Read centers and radii lists + auto centers = multiSphereInfo.getVal>("centers"); + auto radii = multiSphereInfo.getVal>("radii"); + + // Check if lists have the same length + if(centers.size() != radii.size()) + { + fatalErrorInFunction + << "The number of centers (" << centers.size() + << ") does not match the number of radii (" << radii.size() << ")" + << endl; + fatalExit; + } + + uint32 nSpheres = centers.size(); + + // Initialize data structures + sphereRegions_.resize(nSpheres, sphere(realx3(0.0, 0.0, 0.0), 1.0)); + centerPoints_.resize(nSpheres); + diameters_.resize(nSpheres); + volumes_.resize(nSpheres); + selectedPoints_.resize(nSpheres); + + // Setup each sphere + for (uint32 i = 0; i < nSpheres; ++i) + { + real diameter = 2.0 * radii[i]; // Convert radius to diameter + + sphereRegions_[i] = pFlow::sphere(centers[i], radii[i]); + centerPoints_[i] = centers[i]; + diameters_[i] = diameter; + volumes_[i] = sphereRegions_[i].volume(); + } +} + +pFlow::span pFlow::multipleSpheresRegionPoints::indices(uint32 elem) const +{ + if (elem >= size()) + { + fatalErrorInFunction + << "The element index is out of range. elem: " << elem + << " size: " << size() << endl; + fatalExit; + } + + return span(selectedPoints_[elem].data(), selectedPoints_[elem].size()); +} + +pFlow::span pFlow::multipleSpheresRegionPoints::indices(uint32 elem) +{ + if (elem >= size()) + { + fatalErrorInFunction + << "The element index is out of range. elem: " << elem + << " size: " << size() << endl; + fatalExit; + } + + return span(selectedPoints_[elem].data(), selectedPoints_[elem].size()); +} + + +bool pFlow::multipleSpheresRegionPoints::update() +{ + const auto points = database().updatePoints(); + for (auto& elem : selectedPoints_) + { + elem.clear(); + } + + for (uint32 i = 0; i < points.size(); ++i) + { + for (uint32 j = 0; j < sphereRegions_.size(); ++j) + { + if (sphereRegions_[j].isInside(points[i])) + { + selectedPoints_[j].push_back(i); + } + } + } + return true; +} + +bool pFlow::multipleSpheresRegionPoints::write(iOstream &os) const +{ + os << "# Multiple spheres region points\n"; + os << "# No." << tab << "centerPoint" << tab << "diameter" << endl; + for (uint32 i = 0; i < sphereRegions_.size(); ++i) + { + os << "# " << i << tab << sphereRegions_[i].center() << tab << diameters_[i] << '\n'; + } + os << "time/No. "; + for (uint32 i = 0; i < sphereRegions_.size(); ++i) + { + os << i << " "; + } + os << endl; + return true; +} diff --git a/src/PostprocessData/region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.hpp b/src/PostprocessData/region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.hpp new file mode 100644 index 00000000..e01da658 --- /dev/null +++ b/src/PostprocessData/region/regionPoints/multipleSpheresRegionPoints/multipleSpheresRegionPoints.hpp @@ -0,0 +1,166 @@ +/*------------------------------- phasicFlow --------------------------------- + O C enter of + O O E ngineering and + O O M ultiscale modeling of + OOOOOOO F luid flow +------------------------------------------------------------------------------ + Copyright (C): www.cemf.ir + email: hamid.r.norouzi AT gmail.com +------------------------------------------------------------------------------ +Licence: + This file is part of phasicFlow code. It is a free software for simulating + granular and multiphase flows. You can redistribute it and/or modify it under + the terms of GNU General Public License v3 or any other later versions. + + phasicFlow is distributed to help others in their research in the field of + granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +-----------------------------------------------------------------------------*/ + +/** + * @class multipleSpheresRegionPoints + * @brief A class to select and track particles contained within multiple + * spherical regions + * @details This class defines multiple spherical regions in the simulation + * domain and identifies which particles are contained within each + * sphere at each time step. It inherits from the regionPoints base + * class and specializes it for handling multiple spherical regions + * simultaneously. + * + * The class reads a list of center points and radii from a dictionary, + * creates sphere objects for each, and provides methods to: + * - Track which particles are inside each spherical region + * - Return volumetric information about the regions + * - Access center points and size information for each sphere + * + * + * @note Used in post-processing workflows to analyze particle behavior + * in specific regions of interest within the simulation domain. + * + * @see regionPoints Base class for all region-based point selection + * @see sphere Geometric primitive used to define spherical regions + * @see postprocessPhasicFlow Utility for post-processing simulation data + * @see fieldsDataBase Database containing simulation field data + */ + +#ifndef __multipleSpheresRegionPoints_hpp__ +#define __multipleSpheresRegionPoints_hpp__ + +#include "regionPoints.hpp" +#include "sphere.hpp" +#include "Vectors.hpp" + +namespace pFlow +{ + +class multipleSpheresRegionPoints +: + public regionPoints +{ +private: + + /// Vector containing all spherical regions used for particle selection + Vector sphereRegions_; + + /// Center coordinates of all spherical regions + realx3Vector centerPoints_; + + /// Diameters of all spherical regions + realVector diameters_; + + /// Volumes of all spherical regions + realVector volumes_; + + /// Vectors of point indices for particles contained in each spherical region + /// Each element corresponds to a particular sphere region + Vector selectedPoints_; + +public: + + /// Type identification for run-time type information + TypeInfo("multipleSpheres"); + + /// Constructor + /// @param dict Dictionary containing multipleSpheresInfo for the regions + /// @param fieldsDataBase Reference to the database containing field data + multipleSpheresRegionPoints( + const dictionary& dict, + fieldsDataBase& fieldsDataBase); + + /// Virtual destructor for proper inheritance cleanup + ~multipleSpheresRegionPoints() override = default; + + /// Returns the number of spherical regions + /// @return Number of spherical regions + uint32 size()const override + { + return sphereRegions_.size(); + } + + /// Checks if there are any spherical regions defined + /// @return True if no regions exist, false otherwise + bool empty()const override + { + return sphereRegions_.empty(); + } + + /// Returns the volumes of all spherical regions + /// @return Span containing the volumes of all regions + span volumes()const override + { + return span(volumes_.data(), volumes_.size()); + } + + /// Returns the diameters of all spherical regions + /// @return Span containing the diameters of all regions + span diameters()const + { + return span(diameters_.data(), diameters_.size()); + } + + /// Returns the equivalent diameters of all spherical regions + /// @return Span containing the equivalent diameters (same as diameters) + span eqDiameters()const + { + return diameters(); + } + + /// Returns the center coordinates of all spherical regions + /// @return Span containing the center points of all regions + span centers()const override + { + return span(centerPoints_.data(), centerPoints_.size()); + } + + /// Returns the indices of particles contained in a specific spherical region + /// @param elem Index of the spherical region to query + /// @return Span containing indices of particles within the specified region + span indices(uint32 elem)const override; + + /// Returns the indices of particles contained in a specific spherical region + /// @param elem Index of the spherical region to query + /// @return Span containing indices of particles within the specified region + span indices(uint32 elem) override; + + /// Updates the selection of particles within each spherical region + /// @return True if update was successful, false otherwise + bool update() override; + + /// Determines if data should be written to the same time file + /// @return True to indicate regions should be written to the same time file + bool writeToSameTimeFile()const override + { + return true; + } + + /// Writes region data to the output stream + /// @param os Output stream to write data to + /// @return True if write operation was successful, false otherwise + bool write(iOstream& os) const override; +}; + +} + + +#endif // __multipleSpheresRegionPoints_hpp__ \ No newline at end of file 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..0931175f --- /dev/null +++ b/src/PostprocessData/region/regionPoints/regionPoints/regionPoints.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 __regionPoints_hpp__ +#define __regionPoints_hpp__ + +#include "iOstream.hpp" +#include "dictionary.hpp" +#include "pointStructure.hpp" + + +namespace pFlow +{ + +class fieldsDataBase; +class Time; + +/** + * @class regionPoints + * @brief Abstract base class for managing and processing volumetric regions + * in the simulation. Particles are selected based on their positions within + * these defined regions. + * + * This class provides an interface for accessing and manipulating data + * related to regions of points (particles), including their volumes, equivalent + * diameters, center points, and particle indices that they contain. It interacts with the + * fieldsDataBase and Time classes to retrieve simulation data. + */ +class regionPoints +{ + using PointsTypeHost = typename pointStructure::PointsTypeHost; + + /// Reference to the fields database containing simulation data + fieldsDataBase& fieldsDataBase_; + +public: + + TypeInfo("regionPoints"); + + /// Constructor with dictionary and fields database reference + regionPoints( + const dictionary& dict, + fieldsDataBase& fieldsDataBase); + + /// Default virtual destructor + virtual ~regionPoints() = default; + + /// Returns reference to the time object from the database + const Time& time()const; + + /// Returns const reference to the fields database + const fieldsDataBase& database()const; + + /// Returns non-const reference to the fields database + fieldsDataBase& database(); + + /// @brief size of elements + virtual + uint32 size()const = 0; + + /// @brief check if the region is empty + virtual + bool empty()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; + + /// Returns const span of particle indices inside the specified element region + virtual + span indices(uint32 elem)const = 0; + + /// Returns non-const span of particle indices inside the specified element region + virtual + span indices(uint32 elem) = 0; + + /// Updates the points (particles) inside regions based on current particle positions + virtual + bool update() = 0; + + /// Returns true if the region should be written to the same time file + virtual + bool writeToSameTimeFile()const = 0; + + /// Writes region data to the output stream + virtual + bool write(iOstream& os)const=0; + +}; + +} + +#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); + } + + /** + * @brief Get the equivalent diameter of the spherical region + * @return A span containing the diameter of the region + */ + span eqDiameters()const override + { + return span(&diameter_, 1); + } + + /** + * @brief Get the center of the spherical region + * @return A span containing the center point of the region + */ + span centers()const override + { + return span(&sphereRegion_.center(), 1); + } + + /** + * @brief Get the indices of points within the region (const version) + * @param elem Element index (ignored as there's only one sphere) + * @return A span containing indices of points within the region + */ + span indices(uint32 elem)const override + { + return span(selectedPoints_.data(), selectedPoints_.size()); + } + + /** + * @brief Get the indices of points within the region (non-const version) + * @param elem Element index (ignored as there's only one sphere) + * @return A span containing indices of points within the region + */ + span indices(uint32 elem) override + { + return span(selectedPoints_.data(), selectedPoints_.size()); + } + + /** + * @brief Update the points selected by this region + * @return True if update was successful + */ + bool update()override; + + /** + * @brief Determine if data should be written to the same time file + * @return Always returns true + */ + bool writeToSameTimeFile()const override + { + return true; + } + + /** + * @brief Write region data to output stream + * @param os Output stream to write to + * @return True if write was successful + */ + bool write(iOstream& os)const override; + +}; + +} + +#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..92e7d8a5 --- /dev/null +++ b/src/PostprocessData/sampleDictionary/postprocessDataDict @@ -0,0 +1,129 @@ +/* -------------------------------*- C++ -*--------------------------------- *\ +| phasicFlow File | +| copyright: www.cemf.ir | +\* ------------------------------------------------------------------------- */ +objectName postprocessDataDict; +objectType dictionary;; +fileFormat ASCII; +/*---------------------------------------------------------------------------*/ + +runTimeActive yes; + +defaultTimeControl +{ + timeControl timeStep; + startTime 0; + endTime 1000; + executionInterval 150; +} + +components +( + velocityProb + { + processMethod particleProbe; + processRegion centerPoints; + selector id; + field component(position,y); + ids (0 10 100); + } + + onSingleSphere + { + // method of performing the sum (arithmetic, uniformDistribution, GaussianDistribution) + processMethod arithmetic; + processRegion sphere; // type of region on which processing is performed + + sphereInfo + { + radius 0.01; + center (-0.08 -0.08 0.015); + } + + timeControl default; // settings, timeStep, simulationTime + + /// all the post process operations to be done + operations + ( + // computes the arithmetic mean of particle velocity + averageVel + { + function average; + field velocity; + divideByVolume no; //default + threshold 3; //default is 1; + includeMask all; + } + + // computes the fraction of par1 in the region + par1Fraction + { + function average; + field one; + phi one; // default + divideByVolume no; + includeMask lessThan; + + // diameter of par1 is 0.003, so these settings + // will select only particles of type par1 + lessThanInfo + { + field diameter; + + value 0.0031; + } + } + + numberDensity + { + function sum; + field one; + phi one; // default + divideByVolume yes; + + } + ); + } + + alongALine + { + processMethod arithmetic; + processRegion line; + + // the time interval for executing the post-processing + // other options: timeStep, default, and settings + timeControl simulationTime; + startTime 1.0; + endTime 3.0; + executionInterval 0.1; + + + // 10 spheres with radius 0.01 along the straight line defined by p1 and p2 + lineInfo + { + p1 (0 0 0); + p2 (0 0.15 0.15); + numPoints 10; + radius 0.01; + } + + operations + ( + // computes the arithmetic mean of particle velocity + numberDensity + { + function sum; + field one; + divideByVolume yes; //default is no + } + + volumeDensity + { + function sum; + field cube(diameter); // d^3, although it differs by pi/6 + divideByVolume yes; //default is no + } + ); + } + +); \ No newline at end of file diff --git a/src/phasicFlow/CMakeLists.txt b/src/phasicFlow/CMakeLists.txt index eb50c1a7..c8a697ea 100644 --- a/src/phasicFlow/CMakeLists.txt +++ b/src/phasicFlow/CMakeLists.txt @@ -47,6 +47,7 @@ repository/Time/Time.cpp repository/Time/timeControl.cpp repository/Time/baseTimeControl.cpp repository/systemControl/systemControl.cpp +repository/systemControl/auxFunctions/auxFunctions.cpp repository/systemControl/dynamicLinkLibs.cpp commandLine/commandLine.cpp diff --git a/src/phasicFlow/containers/List/anyList/anyList.hpp b/src/phasicFlow/containers/List/anyList/anyList.hpp index 91a93360..b720a783 100644 --- a/src/phasicFlow/containers/List/anyList/anyList.hpp +++ b/src/phasicFlow/containers/List/anyList/anyList.hpp @@ -79,6 +79,27 @@ public: /// List of varibales names const wordList& names()const; + template + void emplaceBackOrReplace(const word& name, Args&&... args) + { + if( contains(name)) + { + int32 i = names_.findi(name); + types_[i] = getTypeName(); + anyList_.pos(i)->reset(); + anyList_.pos(i)-> emplace(std::forward(args)...); + } + else + { + names_.push_back(name); + types_.push_back(getTypeName()); + anyList_.emplace_back( + std::in_place_type, + std::forward(args)...); + } + + } + /// Create variable using constructor in-place template reference emplaceBack(const word& name, Args&&... args) diff --git a/src/phasicFlow/dictionary/dictionaryList.hpp b/src/phasicFlow/dictionary/dictionaryList.hpp new file mode 100644 index 00000000..d47e891e --- /dev/null +++ b/src/phasicFlow/dictionary/dictionaryList.hpp @@ -0,0 +1,114 @@ +/*------------------------------- phasicFlow --------------------------------- + O C enter of + O O E ngineering and + O O M ultiscale modeling of + OOOOOOO F luid flow +------------------------------------------------------------------------------ + Copyright (C): www.cemf.ir + email: hamid.r.norouzi AT gmail.com +------------------------------------------------------------------------------ +Licence: + This file is part of phasicFlow code. It is a free software for simulating + granular and multiphase flows. You can redistribute it and/or modify it under + the terms of GNU General Public License v3 or any other later versions. + + phasicFlow is distributed to help others in their research in the field of + granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +-----------------------------------------------------------------------------*/ + +#ifndef __dictionaryList_hpp__ +#define __dictionaryList_hpp__ + +#include "List.hpp" +#include "dictionary.hpp" + + +namespace pFlow +{ + +class dictionaryList +: + public List +{ +private: + + const dictionary& parrent_; + + word name_; + + +public: + + TypeInfoNV("dictionaryList"); + + dictionaryList(const word& name, const dictionary& parrent) + : + List(), + parrent_(parrent), + name_(name) + {} + + dictionaryList(const dictionaryList&) = default; + + dictionaryList(dictionaryList&&) = default; + + dictionaryList& operator = (const dictionaryList&) = default; + + dictionaryList& operator = (dictionaryList&&) = default; + + ~dictionaryList() = default; + + const word& name()const + { + return name_; + } + + const word globalName()const + { + return parrent_.globalName(); + } + + List& dicts() + { + return *this; + } + + const List& dicts()const + { + return *this; + } + + const dictionary& parrent()const + { + return parrent_; + } + +}; + +inline +dictionaryList readDictList(const word& name, const dictionary& dict) +{ + if(!dict.containsDataEntry(name)) + { + fatalErrorInFunction + <<"data entry: "<< name + <<" does not exist in dictionary "<< dict.globalName()<>(name); + for(auto& d:dicts) + { + allDicts.emplace_back(d.name(), dict, d); + } + + return allDicts; +} + +} + + + +#endif \ No newline at end of file diff --git a/src/phasicFlow/globals/vocabs.hpp b/src/phasicFlow/globals/vocabs.hpp index 9cb2c5bd..33844862 100755 --- a/src/phasicFlow/globals/vocabs.hpp +++ b/src/phasicFlow/globals/vocabs.hpp @@ -47,6 +47,7 @@ const inline char* const contactSearchFile__ = "contactSearch"; const inline char* const propertyFile__ = "interaction"; const inline char* const interactionFile__ = "interaction"; const inline char* const postprocessFile__ = "postprocessDict"; +const inline char* const postprocessDataFiel__ = "postprocessDataDict"; const inline char* const uniform__ = "uniform"; const inline char* const nonUniform__ = "nonUniform"; diff --git a/src/phasicFlow/repository/Time/baseTimeControl.cpp b/src/phasicFlow/repository/Time/baseTimeControl.cpp index b3bba368..c4a83327 100644 --- a/src/phasicFlow/repository/Time/baseTimeControl.cpp +++ b/src/phasicFlow/repository/Time/baseTimeControl.cpp @@ -21,14 +21,24 @@ Licence: #include "baseTimeControl.hpp" #include "timeInfo.hpp" -pFlow::baseTimeControl::baseTimeControl +void pFlow::baseTimeControl::setTimeControl ( - const dictionary &dict, - const word& intervalPrefix, - timeValue defStartTime + timeValue startTime, + timeValue endTime, + timeValue interval, + const word &intervalPrefix ) -: - intervalPrefix_(intervalPrefix) +{ + isTimeStep_ = false; + intervalPrefix_ = intervalPrefix; + rRange_ = stridedRange(startTime, endTime, interval); +} + +pFlow::baseTimeControl::baseTimeControl( + const dictionary &dict, + const word &intervalPrefix, + timeValue defStartTime) + : intervalPrefix_(intervalPrefix) { auto tControl = dict.getVal("timeControl"); if(tControl == "timeStep") @@ -119,6 +129,24 @@ pFlow::baseTimeControl::baseTimeControl(int32 start, int32 end, int32 stride, co { } +pFlow::baseTimeControl::baseTimeControl +( + timeValue start, + timeValue end, + timeValue stride, + const word &intervalPrefix +) +: + isTimeStep_(false), + rRange_( + start, end, stride + ), + intervalPrefix_( + intervalPrefix.size()==0uL? word("interval"): intervalPrefix+"Interval" + ) +{ +} + bool pFlow::baseTimeControl::eventTime(uint32 iter, timeValue t, timeValue dt) const { if(isTimeStep_) diff --git a/src/phasicFlow/repository/Time/baseTimeControl.hpp b/src/phasicFlow/repository/Time/baseTimeControl.hpp index f49d97be..8e9dd62f 100644 --- a/src/phasicFlow/repository/Time/baseTimeControl.hpp +++ b/src/phasicFlow/repository/Time/baseTimeControl.hpp @@ -32,13 +32,21 @@ class baseTimeControl { private: - bool isTimeStep_; + bool isTimeStep_; - int32StridedRagne iRange_; + int32StridedRagne iRange_; - stridedRange rRange_; + stridedRange rRange_; - const word intervalPrefix_; + word intervalPrefix_; + +protected: + + void setTimeControl( + timeValue startTime, + timeValue endTime, + timeValue interval, + const word& intervalPrefix); public: @@ -59,8 +67,33 @@ public: int32 end, int32 stride, const word& intervalPrefix = "" + ); + + baseTimeControl( + timeValue start, + timeValue end, + timeValue stride, + const word& intervalPrefix = "" ); + baseTimeControl( + const baseTimeControl& other + ) = default; + + baseTimeControl( + baseTimeControl&& other + ) = default; + + baseTimeControl& operator=( + const baseTimeControl& other + ) = default; + + baseTimeControl& operator=( + baseTimeControl&& other + ) = default; + + ~baseTimeControl() = default; + inline bool isTimeStep() const { return isTimeStep_; diff --git a/src/phasicFlow/repository/Time/timeControl.hpp b/src/phasicFlow/repository/Time/timeControl.hpp index 065b3777..dc2bb80b 100644 --- a/src/phasicFlow/repository/Time/timeControl.hpp +++ b/src/phasicFlow/repository/Time/timeControl.hpp @@ -120,6 +120,16 @@ public: return startTime_; } + timeValue endTime()const + { + return endTime_; + } + + timeValue saveInterval()const + { + return saveInterval_; + } + word timeName()const; timeValue currentTime() const diff --git a/src/phasicFlow/repository/Time/timeInfo.hpp b/src/phasicFlow/repository/Time/timeInfo.hpp index fc759614..ee0cff61 100644 --- a/src/phasicFlow/repository/Time/timeInfo.hpp +++ b/src/phasicFlow/repository/Time/timeInfo.hpp @@ -106,6 +106,12 @@ public: return real2FixedStripZeros(currentTime_, presicion_); } + inline + word prevTimeName()const + { + return real2FixedStripZeros( max(currentTime_-dt_, timeValue(0)), presicion_); + } + static uint32 precision() { diff --git a/src/phasicFlow/repository/repository/repository.cpp b/src/phasicFlow/repository/repository/repository.cpp index 648b912f..2815956f 100644 --- a/src/phasicFlow/repository/repository/repository.cpp +++ b/src/phasicFlow/repository/repository/repository.cpp @@ -236,7 +236,42 @@ size_t pFlow::repository::numRepositories()const return repositories_.size(); } -pFlow::repository& pFlow::repository::lookupRepository(const word& name) +const pFlow::IOobject *pFlow::repository::lookupObjectPtr +( + const word &name +) const +{ + if( auto [iter, success] = objects_.findIf(name); success ) + { + return iter->second; + } + else + { + fatalErrorInFunction << + "Object with name " << name << " is not found in repository " << this->name()<second; + } + else + { + fatalErrorInFunction << + "Object with name " << name << " is not found in repository " << this->name()< T& lookupObject(const word& name); diff --git a/src/phasicFlow/repository/systemControl/auxFunctions/auxFunctions.cpp b/src/phasicFlow/repository/systemControl/auxFunctions/auxFunctions.cpp new file mode 100644 index 00000000..8214a3c2 --- /dev/null +++ b/src/phasicFlow/repository/systemControl/auxFunctions/auxFunctions.cpp @@ -0,0 +1,56 @@ +/*------------------------------- phasicFlow --------------------------------- + O C enter of + O O E ngineering and + O O M ultiscale modeling of + OOOOOOO F luid flow +------------------------------------------------------------------------------ + Copyright (C): www.cemf.ir + email: hamid.r.norouzi AT gmail.com +------------------------------------------------------------------------------ +Licence: + This file is part of phasicFlow code. It is a free software for simulating + granular and multiphase flows. You can redistribute it and/or modify it under + the terms of GNU General Public License v3 or any other later versions. + + phasicFlow is distributed to help others in their research in the field of + granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +-----------------------------------------------------------------------------*/ + +#include "auxFunctions.hpp" +#include "systemControl.hpp" + + +pFlow::uniquePtr + pFlow::auxFunctions::create(const systemControl& control) +{ + const auto& setDict = control.settingsDict(); + + if( !setDict.containsDataEntry("auxFunctions")) + { + return nullptr; + } + + word func = setDict.getVal("auxFunctions"); + + if( systemControlvCtorSelector_.search(func) ) + { + REPORT(1)<<"Creating auxiliary function "<< Green_Text(func)<< " ..."< create(const systemControl& control); + +}; + +} // namespace pFlow + +#endif \ No newline at end of file diff --git a/src/phasicFlow/repository/systemControl/systemControl.cpp b/src/phasicFlow/repository/systemControl/systemControl.cpp index 75109c71..0d5348bb 100644 --- a/src/phasicFlow/repository/systemControl/systemControl.cpp +++ b/src/phasicFlow/repository/systemControl/systemControl.cpp @@ -24,6 +24,10 @@ Licence: #include "iOstream.hpp" #include "types.hpp" #include "vocabs.hpp" +#include "Logical.hpp" + + +inline static bool axuFunctionsInitialized__ = false; bool pFlow::systemControl::readIncludeExclue(const dictionary& dict) { @@ -185,7 +189,20 @@ pFlow::systemControl::systemControl( bool pFlow::systemControl::operator++(int) { - auto toContinue = time()++; + + if(!axuFunctionsInitialized__) + { + auxFunctions_ = auxFunctions::create(*this); + axuFunctionsInitialized__ = true; + } + + if(auxFunctions_) + { + auxFunctions_().execute(); + auxFunctions_().write(); + } + + auto toContinue = time()++; if (toContinue) { @@ -221,3 +238,11 @@ bool pFlow::systemControl::operator++(int) return toContinue; } + +bool pFlow::systemControl::keepIntegrationHistory()const +{ + auto keepHistory = settingsDict_().getValOrSet( + "integrationHistory", + Logical{false}); + return keepHistory(); +} diff --git a/src/phasicFlow/repository/systemControl/systemControl.hpp b/src/phasicFlow/repository/systemControl/systemControl.hpp index 94d3b939..47af5052 100644 --- a/src/phasicFlow/repository/systemControl/systemControl.hpp +++ b/src/phasicFlow/repository/systemControl/systemControl.hpp @@ -34,10 +34,13 @@ Licence: #include "Timers.hpp" #include "dynamicLinkLibs.hpp" #include "Set.hpp" +#include "auxFunctions.hpp" + namespace pFlow { + class systemControl : public repository @@ -83,6 +86,7 @@ protected: wordSet excludeList_; + uniquePtr auxFunctions_ = nullptr; bool readIncludeExclue(const dictionary& dict); @@ -189,6 +193,7 @@ public: return outFilePrecision_; } + bool keepIntegrationHistory()const; bool isIncluded(const word& objName)const final { diff --git a/src/phasicFlow/smartPointers/uniquePtr.hpp b/src/phasicFlow/smartPointers/uniquePtr.hpp index c28490c7..23e7f3a6 100644 --- a/src/phasicFlow/smartPointers/uniquePtr.hpp +++ b/src/phasicFlow/smartPointers/uniquePtr.hpp @@ -38,15 +38,16 @@ namespace pFlow template< - typename T + typename T, + typename Deleter = std::default_delete > class uniquePtr : - public std::unique_ptr + public std::unique_ptr { public: - using uniquePtrType = std::unique_ptr; + using uniquePtrType = std::unique_ptr; // using base constructors using uniquePtrType::unique_ptr; diff --git a/src/phasicFlow/structuredData/pointStructure/selectors/selectorRandomPoints/selectorRandomPoints.cpp b/src/phasicFlow/structuredData/pointStructure/selectors/selectorRandomPoints/selectorRandomPoints.cpp index 3a4a28f0..2e1591de 100644 --- a/src/phasicFlow/structuredData/pointStructure/selectors/selectorRandomPoints/selectorRandomPoints.cpp +++ b/src/phasicFlow/structuredData/pointStructure/selectors/selectorRandomPoints/selectorRandomPoints.cpp @@ -93,9 +93,18 @@ pFlow::selectorRandomPoints::selectorRandomPoints( const dictionary& dict ) : pStructSelector(type, pStruct, dict), - begin_(dict.getVal("begin")), - end_(dict.getValOrSet("end", pStruct.size())), - number_(dict.getValOrSet("number", 1)) + begin_ + ( + dict.getValOrSet("begin",0u) + ), + end_ + ( + dict.getValOrSetMax("end", pStruct.size()) + ), + number_ + ( + dict.getValOrSetMax("number", 0u) + ) { begin_ = max(begin_, 1u); end_ = min(end_, static_cast(pStruct.size())); diff --git a/src/phasicFlow/structuredData/sphere/sphere.hpp b/src/phasicFlow/structuredData/sphere/sphere.hpp index 21b20d1c..2586723c 100644 --- a/src/phasicFlow/structuredData/sphere/sphere.hpp +++ b/src/phasicFlow/structuredData/sphere/sphere.hpp @@ -105,6 +105,12 @@ public: return sqrt(radius2_); } + INLINE_FUNCTION_HD + real volume()const + { + return 4.0/3.0* Pi * pow(radius(),3.0); + } + //// - IO operation FUNCTION_H bool read(iIstream & is); diff --git a/src/phasicFlow/types/quadruple/quadruple.hpp b/src/phasicFlow/types/quadruple/quadruple.hpp index 6b4133da..a535a592 100644 --- a/src/phasicFlow/types/quadruple/quadruple.hpp +++ b/src/phasicFlow/types/quadruple/quadruple.hpp @@ -278,6 +278,6 @@ struct quadruple } // pFlow #include "quadrupleI.hpp" -// #include "quadrupleMath.hpp" +#include "quadrupleMath.hpp" #endif