mirror of
https://github.com/PhasicFlow/phasicFlow.git
synced 2025-06-22 16:28:30 +00:00
The main structure is tested. functons like execute and write are added and tested.
other components are left
This commit is contained in:
165
src/PostprocessData/fieldsDataBase/fieldFunctions.hpp
Normal file
165
src/PostprocessData/fieldsDataBase/fieldFunctions.hpp
Normal file
@ -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<typename T>
|
||||
inline
|
||||
void funcCast(span<T> src, span<real> dst)
|
||||
{
|
||||
for(uint32 i=0; i<src.size(); i++)
|
||||
{
|
||||
dst[i] = static_cast<real>(src[i]);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline
|
||||
void funcAbs(span<T> src, span<real> dst)
|
||||
{
|
||||
for(uint32 i=0; i<src.size(); i++)
|
||||
{
|
||||
dst[i] = abs(src[i]);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline
|
||||
void funcSquare(span<T> src, span<real> dst)
|
||||
{
|
||||
for( uint32 i=0; i<src.size(); i++)
|
||||
{
|
||||
dst[i] = pow(static_cast<real>(src[i]),2);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline
|
||||
void funcCube(span<T> src, span<real> dst)
|
||||
{
|
||||
for( uint32 i=0; i<src.size(); i++)
|
||||
{
|
||||
dst[i] = pow(static_cast<real>(src[i]),3);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline
|
||||
void funcSquareRoot(span<T> src, span<real> dst)
|
||||
{
|
||||
for( uint32 i=0; i<src.size(); i++)
|
||||
{
|
||||
dst[i] = sqrt(static_cast<real>(src[i]));
|
||||
}
|
||||
}
|
||||
|
||||
template<VectorType T>
|
||||
inline
|
||||
void funcMagnitude(span<T> src, span<real> dst)
|
||||
{
|
||||
for( uint32 i=0; i<src.size(); i++)
|
||||
{
|
||||
dst[i] = src[i].length();
|
||||
}
|
||||
}
|
||||
|
||||
template<VectorType T>
|
||||
inline
|
||||
void funcMagnitudeSquare(span<T> src, span<real> dst)
|
||||
{
|
||||
for( uint32 i=0; i<src.size(); i++)
|
||||
{
|
||||
dst[i] = dot(src[i],src[i]);
|
||||
}
|
||||
}
|
||||
|
||||
template<VectorType T>
|
||||
inline
|
||||
void funcMagnitudeCube(span<T> src, span<real> dst)
|
||||
{
|
||||
for( uint32 i=0; i<src.size(); i++)
|
||||
{
|
||||
dst[i] = pow(src[i].length(),3);
|
||||
}
|
||||
}
|
||||
|
||||
template<VectorType T>
|
||||
inline
|
||||
void funcMagnitudeSquareRoot(span<T> src, span<real> dst)
|
||||
{
|
||||
for( uint32 i=0; i<src.size(); i++)
|
||||
{
|
||||
dst[i] = sqrt(src[i].length());
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void funcComponent(span<realx3> src, span<real> dst, char component)
|
||||
{
|
||||
for( uint32 i=0; i<src.size(); i++)
|
||||
{
|
||||
switch(component)
|
||||
{
|
||||
case 'x':
|
||||
dst[i] = src[i].x();
|
||||
break;
|
||||
case 'y':
|
||||
dst[i] = src[i].y();
|
||||
break;
|
||||
case 'z':
|
||||
dst[i] = src[i].z();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void funcComponent(span<realx4> src, span<real> dst, char component)
|
||||
{
|
||||
for( uint32 i=0; i<src.size(); i++)
|
||||
{
|
||||
switch(component)
|
||||
{
|
||||
case 'x':
|
||||
dst[i] = src[i].x();
|
||||
break;
|
||||
case 'y':
|
||||
dst[i] = src[i].y();
|
||||
break;
|
||||
case 'z':
|
||||
dst[i] = src[i].z();
|
||||
break;
|
||||
case 'w':
|
||||
dst[i] = src[i].w();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace pFlow
|
||||
|
||||
#endif //__fieldFunctions_hpp__
|
670
src/PostprocessData/fieldsDataBase/fieldsDataBase.cpp
Normal file
670
src/PostprocessData/fieldsDataBase/fieldsDataBase.cpp
Normal file
@ -0,0 +1,670 @@
|
||||
/*------------------------------- 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 <regex>
|
||||
|
||||
#include "vocabs.hpp"
|
||||
#include "Time.hpp"
|
||||
#include "fieldsDataBase.hpp"
|
||||
#include "fieldFunctions.hpp"
|
||||
#include "dynamicPointStructure.hpp"
|
||||
|
||||
bool pFlow::fieldsDataBase::checkForUpdate(const word &name, bool forceUpdate)
|
||||
{
|
||||
auto t = currentTime();
|
||||
bool shouldUpdate = false;
|
||||
|
||||
if(auto [iter, found]= captureTime_.findIf(name); found)
|
||||
{
|
||||
shouldUpdate = iter->second < t;
|
||||
iter->second = t;
|
||||
}
|
||||
else
|
||||
{
|
||||
shouldUpdate = true;
|
||||
captureTime_.insertIf(name, t);
|
||||
}
|
||||
|
||||
return shouldUpdate;
|
||||
}
|
||||
|
||||
pFlow::span<pFlow::real> pFlow::fieldsDataBase::createOrGetRealField(const word &name)
|
||||
{
|
||||
|
||||
bool shouldUpdate = checkForUpdate(name);
|
||||
|
||||
if(shouldUpdate)
|
||||
{
|
||||
allFields_.emplaceBackOrReplace<FieldTypeHost<real>>
|
||||
(
|
||||
name,
|
||||
FieldTypeHost<real>
|
||||
(
|
||||
name,
|
||||
"value",
|
||||
pointFieldSize()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
auto& field = allFields_.getObject<FieldTypeHost<real>>(name);
|
||||
return span<real>(
|
||||
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: "<<compoundFieldName << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(match[3].matched)
|
||||
{
|
||||
fatalErrorInFunction <<
|
||||
"The function: " << functionName <<
|
||||
" does not accept component (x, y, z, or w) as the second argument (in: "
|
||||
<< compoundFieldName<<" )." << endl;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
else if (match[4].matched) // Only fieldName is present
|
||||
{
|
||||
fieldName = match[4].str();
|
||||
func = fieldsDataBase::Functions::None; // No function
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false; // No match
|
||||
}
|
||||
|
||||
bool pFlow::fieldsDataBase::inputOutputType
|
||||
(
|
||||
fieldsDataBase::Functions func,
|
||||
const word &inputType,
|
||||
word &outputType
|
||||
)
|
||||
{
|
||||
switch (func)
|
||||
{
|
||||
case Functions::ComponentX:
|
||||
case Functions::ComponentY:
|
||||
case Functions::ComponentZ:
|
||||
if(inputType == getTypeName<realx3>() ||
|
||||
inputType == getTypeName<realx4>() )
|
||||
{
|
||||
outputType = getTypeName<real>();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
fatalErrorInFunction<<"Wrong function: component(u,comp), for input field type: "<<inputType<<endl;
|
||||
return false;
|
||||
}
|
||||
case Functions::ComponentW:
|
||||
if(inputType == getTypeName<realx4>() )
|
||||
{
|
||||
outputType = getTypeName<real>();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
fatalErrorInFunction<<"Wrong function: component(u,w), for input field type: "<<inputType<<endl;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case Functions::Abs:
|
||||
case Functions::Square:
|
||||
case Functions::Cube:
|
||||
case Functions::SqureRoot:
|
||||
if(inputType == getTypeName<real>() ||
|
||||
inputType == getTypeName<uint32>() ||
|
||||
inputType == getTypeName<int32>() ||
|
||||
inputType == getTypeName<int64>() )
|
||||
{
|
||||
outputType = getTypeName<real>();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
fatalErrorInFunction<<"Wrong input field type for functions abs, squqre, cube, and sqrt."<<
|
||||
" field type is "<< inputType<<endl;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case Functions::Magnitude:
|
||||
case Functions::MagnitudeSquare:
|
||||
case Functions::MagnitudeCube:
|
||||
case Functions::MagnitudeSquareRoot:
|
||||
if(inputType == getTypeName<realx3>() ||
|
||||
inputType == getTypeName<realx4>() )
|
||||
{
|
||||
outputType = getTypeName<real>();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
fatalErrorInFunction<<"Wroing input field type for functions mag, magSquare, magCube, magSqrt. "<<
|
||||
" Input field type is "<< inputType<<endl;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case Functions::None:
|
||||
if(inputType == getTypeName<realx3>() ||
|
||||
inputType == getTypeName<realx4>() ||
|
||||
inputType == getTypeName<real>())
|
||||
{
|
||||
outputType = inputType;
|
||||
return true;
|
||||
}
|
||||
else if( inputType == getTypeName<uint32>() ||
|
||||
inputType == getTypeName<int32>() )
|
||||
{
|
||||
outputType = getTypeName<real>();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
fatalErrorInFunction<< "Wroing input field type "<< inputType<<endl;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fatalErrorInFunction<<"Wroing function"<<endl;
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pFlow::fieldsDataBase::fieldsDataBase(const Time &time, bool inSimulation)
|
||||
:
|
||||
time_(time),
|
||||
inSimulation_(inSimulation)
|
||||
{}
|
||||
|
||||
pFlow::timeValue pFlow::fieldsDataBase::currentTime() const
|
||||
{
|
||||
return time_.currentTime();
|
||||
}
|
||||
|
||||
bool pFlow::fieldsDataBase::getPointFieldType
|
||||
(
|
||||
const word& compoundName,
|
||||
word& fieldName,
|
||||
word& originalType,
|
||||
word& typeAfterFunction,
|
||||
Functions& func
|
||||
)
|
||||
{
|
||||
if( !findFunction(compoundName, fieldName, func))
|
||||
{
|
||||
fatalErrorInFunction;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(reservedFieldNames_.contains(fieldName))
|
||||
{
|
||||
originalType = reservedFieldNames_.find(fieldName)->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
word fieldTypeName = time_.lookupObjectTypeName(fieldName);
|
||||
word space;
|
||||
if(!pointFieldGetType(fieldTypeName, originalType, space))
|
||||
{
|
||||
fatalErrorInFunction<<"Cannot extract type name from "<< fieldTypeName<<endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
word outputType;
|
||||
if(!inputOutputType(func, originalType, outputType))
|
||||
{
|
||||
fatalErrorInFunction<<"Cannnot determine the input and output types for: "<< compoundName<<endl;
|
||||
return false;
|
||||
}
|
||||
typeAfterFunction = outputType;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pFlow::fieldsDataBase::getPointFieldType
|
||||
(
|
||||
const word &compoundName,
|
||||
word &originalType,
|
||||
word &typeAfterFunction
|
||||
)
|
||||
{
|
||||
Functions func;
|
||||
word fieldName;
|
||||
return getPointFieldType(compoundName, fieldName, originalType, typeAfterFunction, func);
|
||||
}
|
||||
|
||||
bool pFlow::fieldsDataBase::getPointFieldType
|
||||
(
|
||||
const word &compoundName,
|
||||
word &typeAfterFunction
|
||||
)
|
||||
{
|
||||
Functions func;
|
||||
word originalType;
|
||||
word fieldName;
|
||||
return getPointFieldType(compoundName, fieldName, originalType, typeAfterFunction, func);
|
||||
}
|
||||
|
||||
pFlow::span<pFlow::realx3> pFlow::fieldsDataBase::updatePoints(bool forceUpdate)
|
||||
{
|
||||
|
||||
bool shouldUpdate = checkForUpdate("position", forceUpdate);
|
||||
|
||||
if(shouldUpdate)
|
||||
{
|
||||
const auto& pstruct = pStruct();
|
||||
allFields_.emplaceBackOrReplace<PointsTypeHost>(
|
||||
"position",
|
||||
pstruct.activePointsHost());
|
||||
}
|
||||
|
||||
auto& points = allFields_.getObject<PointsTypeHost>("position");
|
||||
|
||||
return span<realx3>(
|
||||
points.data(),
|
||||
points.size());
|
||||
|
||||
}
|
||||
|
||||
pFlow::span<pFlow::realx3> pFlow::fieldsDataBase::updateFieldRealx3
|
||||
(
|
||||
const word &compoundName,
|
||||
bool forceUpdate
|
||||
)
|
||||
{
|
||||
word originalType, typeAfterFunction, fieldName;
|
||||
Functions func;
|
||||
|
||||
if( !getPointFieldType(compoundName, fieldName, originalType, typeAfterFunction, func))
|
||||
{
|
||||
fatalErrorInFunction<< "Error in getting the type name of field: "<<
|
||||
compoundName<<", with type name: "<< originalType <<endl;
|
||||
fatalExit;
|
||||
return span<realx3>(nullptr, 0);
|
||||
}
|
||||
|
||||
if( originalType == getTypeName<realx3>() && func == Functions::None )
|
||||
{
|
||||
return updateField<realx3>(fieldName, forceUpdate);
|
||||
}
|
||||
else
|
||||
{
|
||||
fatalErrorInFunction<< "Error in getting the type name of field: "<<
|
||||
compoundName<<", with type name: "<< originalType <<endl;
|
||||
fatalExit;
|
||||
return span<realx3>(nullptr, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pFlow::span<pFlow::realx4> pFlow::fieldsDataBase::updateFieldRealx4
|
||||
(
|
||||
const word &compoundName,
|
||||
bool forceUpdate
|
||||
)
|
||||
{
|
||||
word originalType, typeAfterFunction, fieldName;
|
||||
Functions func;
|
||||
|
||||
if( !getPointFieldType(compoundName, fieldName, originalType, typeAfterFunction, func))
|
||||
{
|
||||
fatalErrorInFunction<< "Error in getting the type name of field: "<<
|
||||
compoundName<<", with type name: "<< originalType <<endl;
|
||||
fatalExit;
|
||||
return span<realx4>(nullptr, 0);
|
||||
}
|
||||
|
||||
if( originalType == getTypeName<realx4>() && func == Functions::None )
|
||||
{
|
||||
return updateField<realx4>(fieldName, forceUpdate);
|
||||
}
|
||||
else
|
||||
{
|
||||
fatalErrorInFunction<< "Error in getting the type name of field: "<<
|
||||
compoundName<<", with type name: "<< originalType <<endl;
|
||||
fatalExit;
|
||||
return span<realx4>(nullptr, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pFlow::span<pFlow::real> pFlow::fieldsDataBase::updateFieldReal
|
||||
(
|
||||
const word &compoundName,
|
||||
bool forceUpdate
|
||||
)
|
||||
{
|
||||
word originalType, typeAfterFunction, fieldName;
|
||||
Functions func;
|
||||
|
||||
if( !getPointFieldType(compoundName, fieldName, originalType, typeAfterFunction, func))
|
||||
{
|
||||
fatalErrorInFunction<< "Error in getting the type name of field: "<<
|
||||
compoundName<<", with type name: "<< originalType <<endl;
|
||||
fatalExit;
|
||||
return span<real>(nullptr, 0);
|
||||
}
|
||||
|
||||
// if the output type is not real, then it is not supported yet
|
||||
if(typeAfterFunction != getTypeName<real>())
|
||||
{
|
||||
fatalErrorInFunction<< "The output type of field "<< compoundName<<
|
||||
" is not real, it is: "<< typeAfterFunction<<endl;
|
||||
fatalExit;
|
||||
return span<real>(nullptr, 0);
|
||||
}
|
||||
|
||||
// if the orginal type is real and no function, then it is a normal field
|
||||
if( originalType == getTypeName<real>() && func == Functions::None )
|
||||
{
|
||||
return updateField<real>(fieldName, forceUpdate);
|
||||
}
|
||||
|
||||
// if the original type is uint32, and no funciton, cast to real
|
||||
if( originalType == getTypeName<uint32>())
|
||||
{
|
||||
if(func == Functions::None)
|
||||
{
|
||||
auto sp = updateField<uint32>(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<<endl;
|
||||
return span<real>(nullptr, 0);
|
||||
fatalExit;
|
||||
}
|
||||
}
|
||||
|
||||
if( originalType == getTypeName<real>() )
|
||||
{
|
||||
switch(func)
|
||||
{
|
||||
case Functions::Abs:
|
||||
{
|
||||
auto sp = updateField<real>(fieldName, forceUpdate);
|
||||
auto spReal = createOrGetRealField(compoundName);
|
||||
funcAbs(sp, spReal);
|
||||
return spReal;
|
||||
}
|
||||
case Functions::Square:
|
||||
{
|
||||
auto sp = updateField<real>(fieldName, forceUpdate);
|
||||
auto spReal = createOrGetRealField(compoundName);
|
||||
funcSquare(sp, spReal);
|
||||
return spReal;
|
||||
}
|
||||
case Functions::Cube:
|
||||
{
|
||||
auto sp = updateField<real>(fieldName, forceUpdate);
|
||||
auto spReal = createOrGetRealField(compoundName);
|
||||
funcCube(sp, spReal);
|
||||
return spReal;
|
||||
}
|
||||
case Functions::SqureRoot:
|
||||
{
|
||||
auto sp = updateField<real>(fieldName, forceUpdate);
|
||||
auto spReal = createOrGetRealField(compoundName+".sqrt");
|
||||
funcSquareRoot(sp, spReal);
|
||||
return spReal;
|
||||
}
|
||||
default:
|
||||
{
|
||||
fatalErrorInFunction<< "Wrong function for field type real in :"<<
|
||||
compoundName<<endl;
|
||||
fatalExit;
|
||||
return span<real>(nullptr, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( originalType == getTypeName<realx3>())
|
||||
{
|
||||
switch(func)
|
||||
{
|
||||
case Functions::Magnitude:
|
||||
{
|
||||
auto sp = updateField<realx3>(fieldName, forceUpdate);
|
||||
auto spReal = createOrGetRealField(compoundName);
|
||||
funcMagnitude(sp, spReal);
|
||||
return spReal;
|
||||
}
|
||||
case Functions::MagnitudeSquare:
|
||||
{
|
||||
auto sp = updateField<realx3>(fieldName, forceUpdate);
|
||||
auto spReal = createOrGetRealField(compoundName);
|
||||
funcMagnitudeSquare(sp, spReal);
|
||||
return spReal;
|
||||
}
|
||||
case Functions::MagnitudeCube:
|
||||
{
|
||||
auto sp = updateField<realx3>(fieldName, forceUpdate);
|
||||
auto spReal = createOrGetRealField(compoundName);
|
||||
funcMagnitudeCube(sp, spReal);
|
||||
return spReal;
|
||||
}
|
||||
case Functions::MagnitudeSquareRoot:
|
||||
{
|
||||
auto sp = updateField<realx3>(fieldName, forceUpdate);
|
||||
auto spReal = createOrGetRealField(compoundName);
|
||||
funcMagnitudeSquareRoot(sp, spReal);
|
||||
return spReal;
|
||||
}
|
||||
case Functions::ComponentX:
|
||||
{
|
||||
auto sp = updateField<realx3>(fieldName, forceUpdate);
|
||||
auto spReal = createOrGetRealField(compoundName);
|
||||
funcComponent(sp, spReal, 'x');
|
||||
return spReal;
|
||||
}
|
||||
case Functions::ComponentY:
|
||||
{
|
||||
auto sp = updateField<realx3>(fieldName, forceUpdate);
|
||||
auto spReal = createOrGetRealField(compoundName);
|
||||
funcComponent(sp, spReal, 'y');
|
||||
return spReal;
|
||||
}
|
||||
case Functions::ComponentZ:
|
||||
{
|
||||
auto sp = updateField<realx3>(fieldName, forceUpdate);
|
||||
auto spReal = createOrGetRealField(compoundName);
|
||||
funcComponent(sp, spReal, 'z');
|
||||
return spReal;
|
||||
}
|
||||
default:
|
||||
{
|
||||
fatalErrorInFunction<< "Wrong function for field type realx3 in :"<<
|
||||
compoundName<<endl;
|
||||
fatalExit;
|
||||
return span<real>(nullptr, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fatalErrorInFunction<<"NOT SUPPORTED "<<compoundName<<endl;
|
||||
fatalExit;
|
||||
// This line should never be reached
|
||||
return span<real>(nullptr, 0);
|
||||
}
|
||||
|
||||
pFlow::span<pFlow::uint32> pFlow::fieldsDataBase::updateFieldUint32
|
||||
(
|
||||
const word& name,
|
||||
bool forceUpdate
|
||||
)
|
||||
{
|
||||
return updateField<uint32>(name, forceUpdate);
|
||||
}
|
||||
|
||||
pFlow::allPointFieldTypes pFlow::fieldsDataBase::updateFieldAll
|
||||
(
|
||||
const word &compoundName,
|
||||
bool forceUpdate
|
||||
)
|
||||
{
|
||||
|
||||
word originalType, typeAfterFunction, fieldName;
|
||||
Functions func;
|
||||
|
||||
if( !getPointFieldType(compoundName, fieldName, originalType, typeAfterFunction, func))
|
||||
{
|
||||
fatalErrorInFunction<< "Error in getting the type name of field: "<<
|
||||
compoundName<<", with type name: "<< originalType <<endl;
|
||||
fatalExit;
|
||||
return span<real>(nullptr, 0);
|
||||
}
|
||||
|
||||
|
||||
if( typeAfterFunction== getTypeName<realx3>() )
|
||||
{
|
||||
return updateFieldRealx3(compoundName, forceUpdate);
|
||||
}
|
||||
else if( typeAfterFunction == getTypeName<realx4>() )
|
||||
{
|
||||
return updateFieldRealx4(compoundName, forceUpdate);
|
||||
}
|
||||
else if( typeAfterFunction == getTypeName<real>() )
|
||||
{
|
||||
return updateFieldReal(compoundName, forceUpdate);
|
||||
}
|
||||
else
|
||||
{
|
||||
fatalErrorInFunction<< "Invalid feild "<< compoundName<<endl;
|
||||
fatalExit;
|
||||
return span<real>(nullptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
const pFlow::pointStructure &pFlow::fieldsDataBase::pStruct() const
|
||||
{
|
||||
if(inSimulation_)
|
||||
{
|
||||
return
|
||||
static_cast<const pointStructure&>(
|
||||
time_.lookupObject<dynamicPointStructure>(pointStructureFile__)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
return time_.lookupObject<pointStructure>(pointStructureFile__);
|
||||
}
|
||||
}
|
||||
|
||||
bool pFlow::pointFieldGetType(const word& TYPENAME, word& fieldType, word& fieldSpace)
|
||||
{
|
||||
std::regex match("pointField\\<([A-Za-z1-9_]*)\\,([A-Za-z1-9_]*)\\>");
|
||||
std::smatch search;
|
||||
if(!std::regex_match(TYPENAME, search, match)) return false;
|
||||
if(search.size()!= 3) return false;
|
||||
fieldType = search[1];
|
||||
fieldSpace = search[2];
|
||||
return true;
|
||||
}
|
||||
|
389
src/PostprocessData/fieldsDataBase/fieldsDataBase.hpp
Normal file
389
src/PostprocessData/fieldsDataBase/fieldsDataBase.hpp
Normal file
@ -0,0 +1,389 @@
|
||||
/*------------------------------- phasicFlow ---------------------------------
|
||||
O C enter of
|
||||
O O E ngineering and
|
||||
O O M ultiscale modeling of
|
||||
OOOOOOO F luid flow
|
||||
------------------------------------------------------------------------------
|
||||
Copyright (C): www.cemf.ir
|
||||
email: hamid.r.norouzi AT gmail.com
|
||||
------------------------------------------------------------------------------
|
||||
Licence:
|
||||
This file is part of phasicFlow code. It is a free software for simulating
|
||||
granular and multiphase flows. You can redistribute it and/or modify it under
|
||||
the terms of GNU General Public License v3 or any other later versions.
|
||||
|
||||
phasicFlow is distributed to help others in their research in the field of
|
||||
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __fieldsDataBase_hpp__
|
||||
#define __fieldsDataBase_hpp__
|
||||
|
||||
#include <variant>
|
||||
#include <concepts>
|
||||
|
||||
|
||||
#include "pointStructure.hpp"
|
||||
#include "pointFields.hpp"
|
||||
#include "anyList.hpp"
|
||||
#include "Map.hpp"
|
||||
#include "span.hpp"
|
||||
|
||||
namespace pFlow
|
||||
{
|
||||
|
||||
class Time;
|
||||
|
||||
bool pointFieldGetType(const word& TYPENAME, word& fieldType, word& fieldSpace);
|
||||
|
||||
template<typename T>
|
||||
concept ValidFieldType =
|
||||
std::same_as<T, real> ||
|
||||
std::same_as<T, realx3> ||
|
||||
std::same_as<T, realx4> ||
|
||||
std::same_as<T, uint32>;
|
||||
|
||||
template<typename T>
|
||||
concept VectorType =
|
||||
std::same_as<T, realx3> ||
|
||||
std::same_as<T, realx4>;
|
||||
|
||||
template<typename T>
|
||||
concept ScalarType =
|
||||
std::same_as<T, real>;
|
||||
|
||||
|
||||
template<typename T>
|
||||
concept ValidRegionFieldType =
|
||||
std::same_as<T, real> ||
|
||||
std::same_as<T, realx3> ||
|
||||
std::same_as<T, realx4> ;
|
||||
|
||||
|
||||
using allPointFieldTypes = std::variant<span<real>, span<realx3>, span<realx4>>;
|
||||
|
||||
|
||||
class fieldsDataBase
|
||||
|
||||
{
|
||||
private:
|
||||
|
||||
// - Typedefs
|
||||
|
||||
/// Point position data type
|
||||
using PointsTypeHost = typename pointStructure::PointsTypeHost;
|
||||
|
||||
/// Point field data type
|
||||
template<typename T>
|
||||
using FieldTypeHost = typename internalField<T>::FieldTypeHost;
|
||||
|
||||
/// @brief Enumeration of functions that can be applied to point fields.
|
||||
enum class Functions
|
||||
{
|
||||
None, /// no function
|
||||
ComponentX, /// component(u,x)
|
||||
ComponentY, /// component(u,y)
|
||||
ComponentZ, /// component(u,z)
|
||||
ComponentW, /// component(u,w)
|
||||
Abs, /// abs(s)
|
||||
Square, /// square(s)
|
||||
Cube, /// cube(s)
|
||||
SqureRoot, /// sqrt(s)
|
||||
Magnitude, /// mag(u)
|
||||
MagnitudeSquare, /// magSquare(u)
|
||||
MagnitudeCube, /// magCube(u)
|
||||
MagnitudeSquareRoot /// magSqrt(u)
|
||||
};
|
||||
|
||||
|
||||
// - Member variables
|
||||
|
||||
/// const reference to the Time object
|
||||
const Time& time_;
|
||||
|
||||
/// List to store all the point fields
|
||||
anyList allFields_;
|
||||
|
||||
/// Map to store the last capture time of each field
|
||||
wordMap<timeValue> captureTime_;
|
||||
|
||||
///
|
||||
bool inSimulation_ = false;
|
||||
|
||||
static const inline std::map<word, word> reservedFieldNames_
|
||||
{
|
||||
{"position", "realx3"},
|
||||
{"one", "real"}
|
||||
};
|
||||
|
||||
// - Private member functions
|
||||
|
||||
uint32 pointFieldSize()
|
||||
{
|
||||
auto s = updatePoints();
|
||||
return s.size();
|
||||
}
|
||||
|
||||
/// @brief Checks if a field needs to be updated.
|
||||
/// @param name The name of the field to check.
|
||||
/// @param forceUpdate Forces an update if true. Defaults to `false`.
|
||||
/// @return `true` if the field needs updating or `forceUpdate` is true, `false` otherwise.
|
||||
bool checkForUpdate(const word& name, bool forceUpdate = false);
|
||||
|
||||
/**
|
||||
* @brief Updates and retrieves a point field of a specified type from the database.
|
||||
*
|
||||
* This is a template function that updates and retrieves a point field of type `T`
|
||||
* from the database. It checks if the field needs to be updated based on the last
|
||||
* capture time or if a forced update is requested. If an update is necessary, it
|
||||
* retrieves the latest data for the field.
|
||||
*
|
||||
* @tparam T The type of the point field to update and retrieve. Must be a ValidFieldType.
|
||||
* @param name The name of the field to update.
|
||||
* @param forceUpdate A boolean flag indicating whether to force an update of the field
|
||||
* regardless of its current state. Defaults to `false`.
|
||||
*
|
||||
* @return A span of `T` representing the updated field data.
|
||||
*
|
||||
* @throws message If the field cannot be found in the database or if there is a type mismatch.
|
||||
*/
|
||||
template<ValidFieldType T>
|
||||
span<T> updateField(const word& name, bool forceUpdate = false);
|
||||
|
||||
/// @brief Creates a new real field or retrieves an existing one.
|
||||
///
|
||||
/// If a field with the given name already exists, it returns a span to that field.
|
||||
/// If the field does not exist, it creates a new real field with the given name
|
||||
/// and returns a span to the newly created field.
|
||||
///
|
||||
/// @param name The name of the field to create or retrieve.
|
||||
/// @return span<real> of the field
|
||||
span<real> createOrGetRealField(const word& name);
|
||||
|
||||
/**
|
||||
* @brief Parses a compound field name to extract the base field name and function.
|
||||
*
|
||||
* This function takes a compound field name, which may include a function applied
|
||||
* to a base field (e.g., "mag(velocity)"), and parses it to extract the base field
|
||||
* name (e.g., "velocity") and the function to be applied (e.g., `Functions::Magnitude`).
|
||||
*
|
||||
* The function supports the following syntax for compound field names:
|
||||
* - `fieldName` (no function applied)
|
||||
* - `functionName(fieldName)`
|
||||
*
|
||||
* Supported function names are defined in the `Functions` enum.
|
||||
*
|
||||
* @param compoundFieldName The compound field name to parse.
|
||||
* @param fieldName A reference to a `word` where the extracted base field name
|
||||
* will be stored.
|
||||
* @param func A reference to a `Functions` enum where the identified function
|
||||
* will be stored. If no function is applied, this will be set to
|
||||
* `Functions::None`.
|
||||
*
|
||||
* @return `true` if the compound field name was successfully parsed and the base
|
||||
* field name and function were extracted, `false` otherwise.
|
||||
*
|
||||
* @note The function modifies the `fieldName` and `func` parameters to return the
|
||||
* extracted information.
|
||||
*/
|
||||
static
|
||||
bool findFunction(
|
||||
const word& compoundFieldName,
|
||||
word& fieldName,
|
||||
fieldsDataBase::Functions& func );
|
||||
|
||||
/**
|
||||
* @brief Determines the input and output types for a given function.
|
||||
*
|
||||
* This function takes a `Functions` enum value and an input type as a string
|
||||
* and determines the corresponding output type based on the function being applied.
|
||||
*
|
||||
* @param func The function for which to determine the input and output types.
|
||||
* @param inputType The input type as a string.
|
||||
* @param outputType A reference to a string where the determined output type will be stored.
|
||||
*
|
||||
* @return `true` if the input and output types were successfully determined, `false` otherwise.
|
||||
*/
|
||||
static
|
||||
bool inputOutputType(
|
||||
fieldsDataBase::Functions func,
|
||||
const word& inputType,
|
||||
word& outputType);
|
||||
|
||||
public:
|
||||
|
||||
// - constructors
|
||||
|
||||
fieldsDataBase(const Time& time, bool inSimulation);
|
||||
|
||||
/// no copy constructor
|
||||
fieldsDataBase(const fieldsDataBase&) = delete;
|
||||
|
||||
/// no move constructor
|
||||
fieldsDataBase(fieldsDataBase&&) = delete;
|
||||
|
||||
/// no copy assignment
|
||||
fieldsDataBase& operator=(const fieldsDataBase&) = delete;
|
||||
|
||||
/// no move assignment
|
||||
fieldsDataBase& operator=(fieldsDataBase&&) = delete;
|
||||
|
||||
/// destructor
|
||||
~fieldsDataBase() = default;
|
||||
|
||||
// - Public Access Functions
|
||||
/// returns the current time
|
||||
timeValue currentTime()const;
|
||||
|
||||
/// const ref to object Time
|
||||
const Time& time()const
|
||||
{
|
||||
return time_;
|
||||
}
|
||||
|
||||
// - Public Member Functions
|
||||
|
||||
/**
|
||||
* @brief Retrieves the type of a point field based on its compound name.
|
||||
*
|
||||
* This function attempts to extract the type of a point field from its compound name.
|
||||
* The compound name may include additional information such as a function or operation
|
||||
* applied to the field, ie. mag(velcoty). If the type is successfully determined, it
|
||||
* is stored in the provided `typeName` parameter.
|
||||
*
|
||||
* @param compoundName The compound name of the field, which may include additional
|
||||
* information about operations or functions applied to the field.
|
||||
* @param originalType A reference to a `word` where the original type name is obtained.
|
||||
* This will be set to the type of the field before any function is applied.
|
||||
* @param typeAfterFunction A reference to a `word` where the type name after applying
|
||||
* the function is obtained.
|
||||
* @param func the applied function to the field.
|
||||
*
|
||||
* @return `true` if the type was successfully determined and stored in `typeName`,
|
||||
* `false` otherwise.
|
||||
*/
|
||||
bool getPointFieldType(
|
||||
const word& compoundName,
|
||||
word& fieldName,
|
||||
word& originalType,
|
||||
word& typeAfterFunction,
|
||||
Functions& func);
|
||||
|
||||
/// overload for the function getPointFieldType without `func` argument
|
||||
bool getPointFieldType(
|
||||
const word& compoundName,
|
||||
word& originalType,
|
||||
word& typeAfterFunction);
|
||||
|
||||
/// overload for function getPointFieldType without `originalType` argument
|
||||
bool getPointFieldType(
|
||||
const word& compoundName,
|
||||
word& typeAfterFunction);
|
||||
|
||||
/**
|
||||
* @brief Updates the points data and returns a span to the updated points.
|
||||
*
|
||||
* This function ensures that the points data is up-to-date by checking if an update
|
||||
* is necessary. If the data is outdated or if a forced update is requested, it retrieves
|
||||
* the latest points data and stores it in the internal fields database. The function
|
||||
* then returns a span to the updated points data for further use.
|
||||
*
|
||||
* @param forceUpdate A boolean flag indicating whether to force an update of the points
|
||||
* data regardless of its current state. Defaults to `false`.
|
||||
*
|
||||
* @return A span of `realx3` representing the updated points data.
|
||||
*/
|
||||
span<realx3> updatePoints(bool forceUpdate = false);
|
||||
|
||||
/**
|
||||
* @brief Updates and retrieves a realx3 point field from the database.
|
||||
*
|
||||
* This function retrieves or updates a realx3 field based on its compound name.
|
||||
* The compound name cannot include any function operation.
|
||||
* If the field needs to be updated or if forceUpdate is true, the method will
|
||||
* fetch the latest data from the database.
|
||||
*
|
||||
* @param compoundName The name of the field, possibly including a function operation
|
||||
* @param forceUpdate If true, forces an update of the field regardless of its current state.
|
||||
* Defaults to false.
|
||||
*
|
||||
* @return A span containing the updated realx3 field data
|
||||
*
|
||||
* @throws message If the field type is not compatible with realx3 or if the field
|
||||
* cannot be found in the database
|
||||
*/
|
||||
span<realx3> updateFieldRealx3(
|
||||
const word& compoundName,
|
||||
bool forceUpdate = false);
|
||||
|
||||
/**
|
||||
* @brief Updates and retrieves a realx4 point field from the database.
|
||||
*
|
||||
* This function retrieves or updates a realx4 field based on its compound name.
|
||||
* The compound name cannot include any function operation.
|
||||
* If the field needs to be updated or if forceUpdate is true, the method will
|
||||
* fetch the latest data from the database.
|
||||
*
|
||||
* @param compoundName The name of the field, possibly including a function operation
|
||||
* @param forceUpdate If true, forces an update of the field regardless of its current state.
|
||||
* Defaults to false.
|
||||
*
|
||||
* @return A span containing the updated realx3 field data
|
||||
*
|
||||
* @throws message If the field type is not compatible with realx4 or if the field
|
||||
* cannot be found in the database
|
||||
*/
|
||||
span<realx4> updateFieldRealx4(
|
||||
const word& compoundName,
|
||||
bool forceUpdate = false);
|
||||
|
||||
/**
|
||||
* @brief Updates and retrieves a real point field from the database.
|
||||
*
|
||||
* This function retrieves or updates a real field based on its compound name.
|
||||
* The compound name may include a function operation (e.g., abs, square, etc.).
|
||||
* If the field needs to be updated or if forceUpdate is true, the method will
|
||||
* fetch the latest data from the database and apply the specified function.
|
||||
*
|
||||
* Supported functions include:
|
||||
* - None: Retrieves the field as is.
|
||||
* - abs: Computes the absolute value of the field.
|
||||
* - square: Computes the square of the field.
|
||||
* - cube: Computes the cube of the field.
|
||||
* - sqrt: Computes the square root of the field.
|
||||
* - mag, magSquare, magCube, magSqrt: Compute magnitude-related operations for vector fields.
|
||||
* - component(x, y, z): Extracts a specific component from a vector field.
|
||||
*
|
||||
* @param compoundName The name of the field, possibly including a function operation.
|
||||
* @param forceUpdate If true, forces an update of the field regardless of its current state.
|
||||
* Defaults to false.
|
||||
*
|
||||
* @return A span containing the updated real field data.
|
||||
*
|
||||
* @throws message If the field type is not compatible with real or if the field
|
||||
* cannot be found in the database.
|
||||
*/
|
||||
span<real> updateFieldReal(
|
||||
const word& compoundName,
|
||||
bool forceUpdate = false);
|
||||
|
||||
span<uint32> updateFieldUint32(
|
||||
const word& name,
|
||||
bool forceUpdate = false);
|
||||
|
||||
/// Updates and retrieves a point field of any type from the database.
|
||||
/// It returns types real, realx3 and realx4 only.
|
||||
allPointFieldTypes updateFieldAll(
|
||||
const word& compoundName,
|
||||
bool forceUpdate = false);
|
||||
|
||||
const pointStructure& pStruct()const;
|
||||
};
|
||||
|
||||
} // nampespace pFlow
|
||||
|
||||
#include "fieldsDataBaseTemplates.cpp"
|
||||
|
||||
#endif //__fieldsDataBased_hpp__
|
@ -0,0 +1,80 @@
|
||||
/*------------------------------- phasicFlow ---------------------------------
|
||||
O C enter of
|
||||
O O E ngineering and
|
||||
O O M ultiscale modeling of
|
||||
OOOOOOO F luid flow
|
||||
------------------------------------------------------------------------------
|
||||
Copyright (C): www.cemf.ir
|
||||
email: hamid.r.norouzi AT gmail.com
|
||||
------------------------------------------------------------------------------
|
||||
Licence:
|
||||
This file is part of phasicFlow code. It is a free software for simulating
|
||||
granular and multiphase flows. You can redistribute it and/or modify it under
|
||||
the terms of GNU General Public License v3 or any other later versions.
|
||||
|
||||
phasicFlow is distributed to help others in their research in the field of
|
||||
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __fieldsDataBaseTemplates_hpp__
|
||||
#define __fieldsDataBaseTemplates_hpp__
|
||||
|
||||
#include "fieldsDataBase.hpp"
|
||||
|
||||
template<pFlow::ValidFieldType T>
|
||||
inline
|
||||
pFlow::span<T> pFlow::fieldsDataBase::updateField(const word& name, bool forceUpdate)
|
||||
{
|
||||
|
||||
bool shouldUpdate = checkForUpdate(name, forceUpdate);
|
||||
|
||||
if(shouldUpdate)
|
||||
{
|
||||
if(name == "one")
|
||||
{
|
||||
allFields_.emplaceBackOrReplace<FieldTypeHost<T>>
|
||||
(
|
||||
"one",
|
||||
FieldTypeHost<T>
|
||||
(
|
||||
"one",
|
||||
"value",
|
||||
pointFieldSize(),
|
||||
T{1}
|
||||
)
|
||||
);
|
||||
}
|
||||
else if( name == "position")
|
||||
{
|
||||
if constexpr( std::same_as<T, realx3>)
|
||||
{
|
||||
return updatePoints(forceUpdate);
|
||||
}
|
||||
else
|
||||
{
|
||||
fatalErrorInFunction<< "Error in getting the type name of field: "<<
|
||||
name<<", with type name: "<< getTypeName<T>() <<endl;
|
||||
fatalExit;
|
||||
return span<T>(nullptr, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto& pField = time_.lookupObject<pointField_D<T>>(name);
|
||||
allFields_.emplaceBackOrReplace<FieldTypeHost<T>>(
|
||||
name,
|
||||
pField.activeValuesHost());
|
||||
}
|
||||
}
|
||||
|
||||
auto& field = allFields_.getObject<FieldTypeHost<T>>(name);
|
||||
|
||||
return span<T>(
|
||||
field.data(),
|
||||
field.size());
|
||||
|
||||
}
|
||||
|
||||
#endif //__fieldsDataBaseTemplates_hpp__
|
Reference in New Issue
Block a user