Merge pull request #202 from PhasicFlow/postprocessPhasicFlow

postprocessPhasicFlow is now updated with new postprocessData auxFunc…
This commit is contained in:
PhasicFlow
2025-04-21 10:29:55 +03:30
committed by GitHub
41 changed files with 1000 additions and 2912 deletions

View File

@ -24,7 +24,7 @@ Licence:
#include "systemControl.hpp"
#include "fieldsDataBase.hpp"
#include "fieldFunctions.hpp"
#include "dictionary.hpp"
namespace pFlow
{
@ -38,19 +38,6 @@ 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<<endl;
fatalExit;
}
return type;
}
bool pFlow::fieldsDataBase::checkForUpdate(const word &compoundName, bool forceUpdate)
{
@ -195,6 +182,78 @@ pFlow::span<pFlow::real> pFlow::fieldsDataBase::createOrGetOne(bool forceUpdate)
field.size());
}
pFlow::span<pFlow::real> pFlow::fieldsDataBase::createOrGetMass(bool forceUpdate)
{
const word fName = "mass";
bool shouldUpdate = checkForUpdate(fName, forceUpdate);
if(shouldUpdate)
{
const auto index = updateFieldUint32("shapeIndex", true);
const auto ms = getShape().mass();
FieldTypeHost<real> massField
(
fName,
"value",
pointFieldSize()
);
for(uint32 i=0; i< massField.size(); i++)
{
massField[i] = ms[index[i]];
}
allFields_.emplaceBackOrReplace<FieldTypeHost<real>>
(
fName,
std::move(massField)
);
}
auto& field = allFields_.getObject<FieldTypeHost<real>>(fName);
return span<real>(
field.data(),
field.size());
}
pFlow::span<pFlow::real> pFlow::fieldsDataBase::createOrGetI(bool forceUpdate)
{
const word fName = "I";
bool shouldUpdate = checkForUpdate(fName, forceUpdate);
if(shouldUpdate)
{
const auto index = updateFieldUint32("shapeIndex", true);
const auto Is = getShape().Inertia();
FieldTypeHost<real> IField
(
fName,
"value",
pointFieldSize()
);
for(uint32 i=0; i< IField.size(); i++)
{
IField[i] = Is[index[i]];
}
allFields_.emplaceBackOrReplace<FieldTypeHost<real>>
(
fName,
std::move(IField)
);
}
auto& field = allFields_.getObject<FieldTypeHost<real>>(fName);
return span<real>(
field.data(),
field.size());
}
bool pFlow::fieldsDataBase::findFunction(
const word &compoundFieldName,
word &fieldName,
@ -399,11 +458,35 @@ bool pFlow::fieldsDataBase::inputOutputType
return false;
}
pFlow::fieldsDataBase::fieldsDataBase(systemControl& control, bool inSimulation)
pFlow::fieldsDataBase::fieldsDataBase
(
systemControl& control,
const dictionary& postDict,
bool inSimulation,
timeValue startTime
)
:
time_(control.time()),
inSimulation_(inSimulation)
{}
{
if(!inSimulation_)
{
shapeType_ = postDict.getValOrSet<word>("shapeType", "");
if(shapeType_.empty())
{
WARNING
<< "shapeType is not set in dictionary: "
<< postDict.globalName()
<< " and you may need to set for some postprocess operations"<<END_WARNING;
}
}
else
{
// this is not required for execution during simulation
shapeType_ = "";
}
}
pFlow::timeValue pFlow::fieldsDataBase::currentTime() const
{
@ -808,7 +891,13 @@ pFlow::allPointFieldTypes pFlow::fieldsDataBase::updateFieldAll
pFlow::uniquePtr<pFlow::fieldsDataBase>
pFlow::fieldsDataBase::create(systemControl& control, bool inSimulation)
pFlow::fieldsDataBase::create
(
systemControl& control,
const dictionary& postDict,
bool inSimulation,
timeValue startTime
)
{
word dbType;
if(inSimulation)
@ -823,7 +912,7 @@ pFlow::uniquePtr<pFlow::fieldsDataBase>
if( boolvCtorSelector_.search(dbType) )
{
auto objPtr =
boolvCtorSelector_[dbType](control, inSimulation);
boolvCtorSelector_[dbType](control, postDict, inSimulation, startTime);
return objPtr;
}
else

View File

@ -33,6 +33,7 @@ Licence:
namespace pFlow
{
class dictionary;
class systemControl;
class Time;
@ -83,16 +84,9 @@ private:
/// Flag indicating if we're in simulation mode
bool inSimulation_ = false;
protected:
word shapeType_;
/// Map of reserved field names with their corresponding types
static const inline std::map<word, word> reservedFieldNames_
{
{"position", "realx3"},
{"one", "real"},
{"volume", "real"},
{"density", "real"}
};
protected:
/// check if pointField name exists in Time or time folder
virtual
@ -104,12 +98,28 @@ protected:
virtual
bool loadPointStructureToTime()=0;
virtual
const shape& getShape() const= 0;
const word& shapeTypeName()const
{
return shapeType_;
}
/// get the type name of the pointField in the Time object
word getPointFieldType(const word& name)const;
virtual
word getPointFieldType(const word& name)const = 0;
/// Checks if a field needs to be updated based on capture time
bool checkForUpdate(const word& compoundName, bool forceUpdate = false);
/// @brief return the size of pointStructure
uint32 pointFieldSize()
{
auto s = updatePoints();
return s.size();
}
template<ValidFieldType T>
span<T> updateField(const word& name, bool forceUpdate = false);
@ -125,6 +135,21 @@ protected:
span<real> createOrGetOne(bool forceUpdate=false);
span<real> createOrGetMass(bool forceUpdate=false);
span<real> createOrGetI(bool forceUpdate=false);
/// Map of reserved field names with their corresponding types
static const inline std::map<word, word> reservedFieldNames_
{
{"position", "realx3"},
{"one", "real"},
{"volume", "real"},
{"density", "real"},
{"mass", "real"},
{"I", "real"}
};
static
bool findFunction(
const word& compoundFieldName,
@ -137,25 +162,7 @@ protected:
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:
@ -165,7 +172,11 @@ public:
// - constructors
fieldsDataBase(systemControl& control, bool inSimulation);
fieldsDataBase(
systemControl& control,
const dictionary& postDict,
bool inSimulation,
timeValue startTime);
/// no copy constructor
fieldsDataBase(const fieldsDataBase&) = delete;
@ -186,8 +197,13 @@ public:
(
fieldsDataBase,
bool,
(systemControl& control, bool inSimulation),
(control, inSimulation)
(
systemControl& control,
const dictionary& postDict,
bool inSimulation,
timeValue startTime
),
(control, postDict, inSimulation, startTime)
);
@ -260,14 +276,39 @@ public:
virtual
const pointStructure& pStruct()const = 0;
/// Get the next avaiable time folder after the current time folder
/// This is only used for post-simulation processing
virtual
timeValue getNextTimeFolder()const
{
return -1.0;
}
/// Sets the current folder to the next time folder.
/// This is used only for post-simulation processing
/// @returns the time value of the next folder.
virtual
void resetTimeFolder() = 0;
timeValue setToNextTimeFolder()
{
return -1.0;
}
/// Skips the next time folder.
/// This is used only for post-simulation processing
/// @returns the time value of the skipped folder
virtual
timeValue skipNextTimeFolder()
{
return -1.0;
}
static
uniquePtr<fieldsDataBase> create(
systemControl& control,
bool inSimulation);
const dictionary& postDict,
bool inSimulation,
timeValue startTime);
};
} // namespace pFlow

View File

@ -116,6 +116,36 @@ pFlow::span<T> pFlow::fieldsDataBase::updateReservedField
fatalExit;
}
}
else if( name == "mass")
{
if constexpr( std::same_as<T,real>)
{
return createOrGetMass(forceUpdate);
}
else
{
fatalErrorInFunction
<< "This type: "
<< getTypeName<T>()
<<" is not supported for field mass."<<endl;
fatalExit;
}
}
else if( name == "I")
{
if constexpr( std::same_as<T,real>)
{
return createOrGetI(forceUpdate);
}
else
{
fatalErrorInFunction
<< "This type: "
<< getTypeName<T>()
<<" is not supported for field I."<<endl;
fatalExit;
}
}
else if( name == "position")
{
if constexpr( std::same_as<T, realx3>)

View File

@ -24,23 +24,35 @@ bool pFlow::simulationFieldsDataBase::loadPointStructureToTime()
return time().lookupObjectName(pointStructureFile__);
}
bool pFlow::simulationFieldsDataBase::checkTimeFolder(const word &fieldName) const
{
return true;
}
const pFlow::shape& pFlow::simulationFieldsDataBase::getShape() const
{
return shape_;
}
pFlow::word pFlow::simulationFieldsDataBase::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<<endl;
fatalExit;
}
return type;
}
pFlow::simulationFieldsDataBase::simulationFieldsDataBase
(
systemControl &control,
bool inSimulation
systemControl &control,
const dictionary& postDict,
bool inSimulation,
timeValue startTime
)
:
fieldsDataBase(control, inSimulation),
fieldsDataBase(control, postDict, inSimulation, startTime),
shape_
(
dynamic_cast<const shape&>(*control.caseSetup().lookupObjectPtr(shapeFile__))
@ -57,6 +69,3 @@ const pFlow::pointStructure &pFlow::simulationFieldsDataBase::pStruct() const
);
}
void pFlow::simulationFieldsDataBase::resetTimeFolder()
{
}

View File

@ -38,6 +38,7 @@ 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
@ -47,15 +48,19 @@ protected:
/// For simulation, it just checks if the name exists
bool loadPointStructureToTime() override;
bool checkTimeFolder(const word& fieldName) const override;
const shape& getShape() const override;
word getPointFieldType(const word& name)const override;
public:
TypeInfo("fieldsDataBase<simulation>");
simulationFieldsDataBase(systemControl& control, bool inSimulation);
simulationFieldsDataBase(
systemControl& control,
const dictionary& postDict,
bool inSimulation,
timeValue startTime);
~simulationFieldsDataBase() override = default;
@ -68,8 +73,6 @@ public:
const pointStructure& pStruct()const override;
void resetTimeFolder() override;
};

View File

@ -22,22 +22,18 @@ Licence:
#include "List.hpp"
#include "systemControl.hpp"
#include "postprocessData.hpp"
#include "fileDictionary.hpp"
#include "postprocessGlobals.hpp"
#include "postprocessComponent.hpp"
pFlow::postprocessData::postprocessData(const systemControl &control)
pFlow::postprocessData::postprocessData
(
const systemControl &control,
timeValue startTime
)
:
auxFunctions(control),
inSimulation_(startTime<0.0?true:false),
time_(control.time()),
fieldsDataBasePtr_
(
fieldsDataBase::create
(
const_cast<systemControl&>(control),
true
)
),
dict_
(
objectFile
@ -59,6 +55,15 @@ pFlow::postprocessData::postprocessData(const systemControl &control)
<<" This feature is disabled in the current run."<<END_WARNING;
return;
}
fieldsDataBasePtr_= fieldsDataBase::create
(
const_cast<systemControl&>(control),
dict_,
inSimulation_,
startTime
);
activeInSimulation_ = dict_.getValOrSet<Logical>(
"activeInSimulation",
@ -80,12 +85,6 @@ pFlow::postprocessData::postprocessData(const systemControl &control)
control.time().saveInterval(),
"execution");
}
shapeType_ = dict_.getValOrSet<word>
(
"shapeType",
word("sphere")
);
componentsDictsPtr_ = makeUnique<dictionaryList>(readDictList("components", dict_));
@ -105,10 +104,10 @@ bool pFlow::postprocessData::execute()
for(auto& component:postprocesses_)
{
if(!component->execute(ti))
if(!component->execute(ti, !inSimulation_) )
{
fatalErrorInFunction
<<"Error occured in executing postprocess component: "
<<"Error occurred in executing postprocess component: "
<<component->name()<<endl;
return false;
}
@ -125,6 +124,7 @@ bool pFlow::postprocessData::write() const
{
continue;
}
if(!component->write(postProcessGlobals::defaultDir__/component->name()))
{
fatalErrorInFunction
@ -135,3 +135,8 @@ bool pFlow::postprocessData::write() const
}
return true;
}
void pFlow::postprocessData::setOutputDirectory(const fileSystem &path) const
{
postProcessGlobals::defaultDir__ = path;
}

View File

@ -20,14 +20,14 @@ Licence:
#ifndef __postprocessData_hpp__
#define __postprocessData_hpp__
#include "auxFunctions.hpp"
#include "Logical.hpp"
#include "ListPtr.hpp"
#include "fileDictionary.hpp"
#include "baseTimeControl.hpp"
#include "dictionaryList.hpp"
#include "auxFunctions.hpp"
#include "fieldsDataBase.hpp"
#include "postprocessComponent.hpp"
#include "dictionaryList.hpp"
namespace pFlow
{
@ -36,6 +36,7 @@ class systemControl;
class Time;
class timeInfo;
/**
* @class postprocessData
* @brief An interface class for handling post-processing of simulation data.
@ -47,7 +48,11 @@ class postprocessData
:
public auxFunctions
{
/// Indicates if a post-processing is active during simulatoin
/// Indicates if this is post-processing during simulation or
/// post-simulation
bool inSimulation_;
/// Indicates if a post-processing is active during simulation
Logical activeInSimulation_{false};
/// a list of active post-process components
@ -62,9 +67,6 @@ class postprocessData
/// 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<dictionaryList> componentsDictsPtr_ = nullptr;
@ -79,7 +81,7 @@ public:
/// this constructor is used when postprocesing is active
/// during simulation.
/// @param control const reference to systemControl
postprocessData(const systemControl& control);
postprocessData(const systemControl& control, timeValue startTime = -1.0);
~postprocessData()override = default;
@ -92,11 +94,19 @@ public:
bool execute() override;
bool write()const override;
fieldsDataBase& database()
{
return fieldsDataBasePtr_();
}
const fieldsDataBase& database()const
{
return fieldsDataBasePtr_();
}
void setOutputDirectory(const fileSystem& path)const;
};
} // namespace pFlow

View File

@ -49,6 +49,7 @@ repository/Time/baseTimeControl.cpp
repository/systemControl/systemControl.cpp
repository/systemControl/auxFunctions/auxFunctions.cpp
repository/systemControl/dynamicLinkLibs.cpp
repository/systemControl/timeFolder.cpp
commandLine/commandLine.cpp

View File

@ -128,6 +128,42 @@ public:
return false;
}
T minVal()const
{
T m = largestPositive<T>();
for(const auto& sr:sRanges_)
{
m = min(m, sr.begin());
}
for(const auto& iR:iRanges_)
{
m = min(m, iR.begin());
}
for(const auto& i:individuals_)
{
m = min(m, i);
}
return m;
}
T maxVal()const
{
T m = largestNegative<T>();
for(const auto& sr:sRanges_)
{
m = max(m, sr.begin());
}
for(const auto& iR:iRanges_)
{
m = max(m, iR.begin());
}
for(const auto& i:individuals_)
{
m = max(m, i);
}
return m;
}
bool isMember(T val)const
{
for(auto& sR:sRanges_)

View File

@ -68,6 +68,15 @@ public:
}
}
T begin()const
{
return begin_;
}
T end()const
{
return end_;
}
inline
bool isMember(T val)const

View File

@ -30,6 +30,25 @@ Licence:
namespace pFlow
{
template<typename T>
constexpr T getEpsilon()
{
return 0;
}
template<>
constexpr float getEpsilon<float>()
{
return 10*std::numeric_limits<float>::epsilon();
}
template<>
constexpr double getEpsilon<double>()
{
return 10*std::numeric_limits<double>::epsilon();
}
template<typename T>
class
stridedRange
@ -107,7 +126,7 @@ public:
}
inline
bool isMember(T val, T epsilon = 0)const
bool isMember(T val, T epsilon = getEpsilon<T>())const
{
if(!isInRange(val)) return false;
@ -151,7 +170,7 @@ public:
template<>
inline
bool stridedRange<float>::isMember(float val, float epsilon)const
bool stridedRange<float>::isMember(float val, float epsilon )const
{
if(!isInRange(val)) return false;
@ -171,7 +190,7 @@ bool stridedRange<float>::isMember(float val, float epsilon)const
template<>
inline
bool stridedRange<double>::isMember(double val, double epsilon)const
bool stridedRange<double>::isMember(double val, double epsilon )const
{
/*if(!isInRange(val)) return false;
if(const double dist = val-begin_; abs(remainder(dist,stride_)<= epsilon)) return true;

View File

@ -0,0 +1,131 @@
/*------------------------------- 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 "timeFolder.hpp"
#include "vocabs.hpp"
bool pFlow::timeFolder::validateForPointStructure()
{
std::erase_if
(
folders_,
[this](const auto& folder)
{
return !containsPointStructure(folder.second);
}
);
return true;
}
bool pFlow::timeFolder::validFieldFile(const fileSystem &filePath) const
{
IOfileHeader fieldHeader(
objectFile(
filePath.fileName(),
filePath.dirPath(),
objectFile::READ_ALWAYS,
objectFile::WRITE_NEVER)
);
return fieldHeader.headerOk(true);
}
bool pFlow::timeFolder::validFieldFile
(
const fileSystem &filePath,
word &fieldName,
word &objectType
) const
{
IOfileHeader fieldHeader(
objectFile(
filePath.fileName(),
filePath.dirPath(),
objectFile::READ_ALWAYS,
objectFile::WRITE_NEVER)
);
if(!fieldHeader.headerOk(true))
{
return false;
}
else
{
fieldName = fieldHeader.objectName();
objectType = fieldHeader.objectType();
return true;
}
}
pFlow::timeFolder::timeFolder
(
const systemControl& control,
bool pointStructureOnly
)
:
timeFolder(control.path(), pointStructureOnly)
{}
pFlow::timeFolder::timeFolder
(
const fileSystem& path,
bool pointStructureOnly
)
:
folders_(getTimeFolders(path)),
currentFolder_(folders_.begin())
{
if(pointStructureOnly)
{
validateForPointStructure();
}
currentFolder_ = folders_.begin();
}
bool pFlow::timeFolder::containsPointStructure(const fileSystem &dirPath) const
{
auto files = containingFiles(dirPath);
for (const auto &file : files)
{
if (file.fileName() == pointStructureFile__)
{
return validFieldFile(file);
}
}
return false;
}
pFlow::Map<pFlow::word, pFlow::word> pFlow::timeFolder::currentFolderFiles() const
{
Map<word,word> fileList;
if( folders_.empty()) return fileList;
auto files = containingFiles(folder());
word name, objectType;
for (const auto &file : files)
{
if(validFieldFile(file, name, objectType))
{
fileList.insertIf(name, objectType);
}
}
return fileList;
}

View File

@ -27,38 +27,55 @@ Licence:
namespace pFlow
{
Map<real, fileSystem> getTimeFolders(const fileSystem& path);
Map<timeValue, fileSystem> getTimeFolders(const fileSystem& path);
class timeFolder
{
using timeList = Map<real, fileSystem>;
using timeList = Map<timeValue, fileSystem>;
protected:
timeList folders_;
timeList::iterator currentFolder_;
bool validateForPointStructure();
bool validFieldFile(const fileSystem& filePath)const;
bool validFieldFile(
const fileSystem& filePath,
word& fieldName,
word& objectType)const;
public:
timeFolder(const systemControl& control )
:
timeFolder(control.path())
{}
timeFolder(const fileSystem& path)
:
folders_(getTimeFolders(path)),
currentFolder_(folders_.begin())
timeFolder(const systemControl& control, bool pointStructureOnly = false );
timeFolder(const fileSystem& path, bool pointStructureOnly = false);
inline
bool empty()const
{
return folders_.empty();
}
real time()const
inline
timeValue currentTime()const
{
if(folders_.empty()) return -1;
return currentFolder_->first;
}
inline
timeValue nextTime()const
{
auto next = currentFolder_;
next++;
if(next == folders_.end()) return -1;
return next->first;
}
fileSystem folder()const
{
return currentFolder_->second;
@ -81,6 +98,27 @@ public:
return !finished();
}
bool setTime(timeValue upto)
{
timeList::iterator orgFolder = currentFolder_;
rewind();
while(!finished())
{
auto t = currentTime();
if( equal(upto, t) || t>upto)
{
return true;
}
(*this)++;
}
currentFolder_ = orgFolder;
return false;
}
explicit operator bool()const
{
return !finished();
@ -102,30 +140,38 @@ public:
return false;
}
real startTime()const
timeValue startTime()const
{
if(folders_.empty()) return -1;
auto [t,f] = *folders_.begin();
return t;
}
real endTime()const
timeValue endTime()const
{
if(folders_.empty()) return -1;
auto [t,f] = *(--folders_.end());
return t;
}
bool containsPointStructure(const fileSystem& dirPath)const;
/// Get the list of files in the current folder
/// the first element is file name and the second is the objectType
Map<word, word> currentFolderFiles()const;
};
inline
Map<real, fileSystem> getTimeFolders(const fileSystem& path)
Map<timeValue, fileSystem> getTimeFolders(const fileSystem& path)
{
Map<real, fileSystem> tFolders;
Map<timeValue, fileSystem> tFolders;
auto subDirs = subDirectories(path);
for(auto& subD: subDirs)
{
auto timeName = tailName(subD.wordPath(), '/');
real TIME;
timeValue TIME;
if( auto success = readReal(timeName, TIME); success)
{
if(!tFolders.insertIf(TIME, subD))