added phasicFlow

This commit is contained in:
hamidrezanorouzi
2022-09-01 21:35:35 +04:30
parent 908a2217cf
commit ed27eb978c
178 changed files with 32208 additions and 84 deletions

View File

@ -0,0 +1,135 @@
/*------------------------------- 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 __KokkosTypes_H__
#define __KokkosTypes_H__
#include <Kokkos_Core.hpp>
#include <Kokkos_DualView.hpp>
#include <Kokkos_UnorderedMap.hpp>
namespace pFlow
{
class DeviceSide{};
class HostSide{};
template<typename side>
struct selectSide{};
using HostSpace = Kokkos::HostSpace;
using Serial = Kokkos::Serial;
#ifdef _OPENMP
using OpenMP = Kokkos::OpenMP;
#endif
using DefaultHostExecutionSpace = Kokkos::DefaultHostExecutionSpace;
using DefaultExecutionSpace = Kokkos::DefaultExecutionSpace;
template<typename T1, typename T2>
using kPair = Kokkos::pair<T1,T2>;
using range = kPair<int,int>;
using range64 = kPair<int long,int long>;
template<typename T, typename... properties>
using ViewTypeScalar = Kokkos::View<T,properties...>;
template<typename T, typename... properties>
using ViewType1D = Kokkos::View<T*,properties...>;
template<typename T, typename... properties>
using ViewType3D = Kokkos::View<T***,properties...>;
template<typename Key, typename Value, typename... properties>
using unorderedMap = Kokkos::UnorderedMap<Key, Value, properties...>;
template<typename Key, typename... properties>
using unorderedSet = Kokkos::UnorderedMap<Key, void, properties...>;
template<typename Key, typename Value>
using deviceHashMap= Kokkos::UnorderedMap<Key, Value>;
template<typename Key, typename Value>
using hostHashMap= Kokkos::UnorderedMap<Key, Value, Kokkos::HostSpace>;
template<typename Key>
using deviceHashSet= Kokkos::UnorderedMap<Key, void>;
template<typename Key>
using hostHashSet = Kokkos::UnorderedMap<Key,void, Kokkos::HostSpace>;
// a 1D array (vector) with default device (memory space and execution space)
template<typename T>
using deviceViewTypeScalar = Kokkos::View<T>;
template<typename T>
using deviceViewType1D = Kokkos::View<T*>;
template<typename T, typename Layout=void>
using deviceViewType2D = Kokkos::View<T**,Layout, void>;
// a 1D array (vector with host memeory space)
template<typename T>
using hostViewTypeScalar = Kokkos::View<T, Kokkos::HostSpace>;
template<typename T>
using hostViewType1D = Kokkos::View<T*, Kokkos::HostSpace>;
template<typename T, typename Layout=void>
using hostViewType2D = Kokkos::View<T**,Layout, Kokkos::HostSpace>;
#ifdef __CUDACC__
using Cuda = Kokkos::Cuda;
template<typename T>
using cudaViewTypeScalar = Kokkos::View<T, Kokkos::CudaSpace>;
template<typename T>
using cudaViewType1D = Kokkos::View<T*, Kokkos::CudaSpace>;
template<typename T, typename Layout=void>
using cudaViewType2D = Kokkos::View<T*,Layout, Kokkos::CudaSpace>;
#endif
template<typename T>
using deviceAtomicViewType1D =
Kokkos::View<
T*,
Kokkos::MemoryTraits<std::is_same<DefaultExecutionSpace,Serial>::value?0:Kokkos::Atomic>>;
template<typename T>
using deviceAtomicViewType3D =
Kokkos::View<
T***,
Kokkos::MemoryTraits<std::is_same<DefaultExecutionSpace,Serial>::value?0:Kokkos::Atomic>>;
} // pFlow
#endif //__KokkosTypes_H__

View File

@ -0,0 +1,92 @@
/*------------------------------- 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 __KokkosUtilities_H__
#define __KokkosUtilities_H__
#include "KokkosTypes.H"
namespace pFlow
{
template<typename ExecutionSpace>
INLINE_FUNCTION_H
bool constexpr isHostAccessible()
{
return Kokkos::SpaceAccessibility<ExecutionSpace,HostSpace>::accessible;
}
template<typename ExecutionSpace, typename MemoerySpace>
INLINE_FUNCTION_H
bool constexpr areAccessible()
{
return Kokkos::SpaceAccessibility<ExecutionSpace,MemoerySpace>::accessible;
}
template <
typename Type,
typename... Properties>
INLINE_FUNCTION_H
void realloc( ViewType1D<Type,Properties...>& view, int32 len)
{
Kokkos::realloc(view, len);
}
template <
typename Type,
typename... Properties>
INLINE_FUNCTION_H
void reallocNoInit(ViewType1D<Type,Properties...>& view, int32 len)
{
using ViewType = ViewType1D<Type,Properties...>;
word vl = view.label();
view = ViewType(); // Deallocate first
view = ViewType(
Kokkos::view_alloc(
Kokkos::WithoutInitializing,
vl),
len);
}
template <
typename Type,
typename... Properties>
INLINE_FUNCTION_H
void reallocFill( ViewType1D<Type,Properties...>& view, int32 len, Type val)
{
reallocNoInit(view, len);
Kokkos::deep_copy(view, val);
}
template<typename ViewType>
INLINE_FUNCTION_H
void swapViews(ViewType& v1, ViewType &v2)
{
auto tmp = v1;
v1 = v2;
v2 = tmp;
}
} // pFlow
#endif //__KokkosUtilities_H__

View File

@ -0,0 +1,593 @@
/*------------------------------- 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 __ViewAlgorithms_H__
#define __ViewAlgorithms_H__
#include "numericConstants.H"
#include "KokkosUtilities.H"
#include "kokkosAlgorithms.H"
#include "stdAlgorithms.H"
#include "cudaAlgorithms.H"
namespace pFlow
{
inline const size_t maxSizeToSerial__ = 64;
template<typename T, typename... properties>
INLINE_FUNCTION_H
int32 count(
const ViewType1D<T, properties...>& view,
int32 start,
int32 end,
const T& val)
{
using ExecutionSpace = typename ViewType1D<T, properties...>::execution_space;
int32 numElems = end-start;
if constexpr( isHostAccessible<ExecutionSpace>())
{
if(numElems<maxSizeToSerial__)
{
return pFlow::algorithms::STD::count<T,false>(
view.data()+start,
numElems,
val);
}
}
return pFlow::algorithms::KOKKOS::count<T, ExecutionSpace>(
view.data()+start,
numElems,
val);
}
template<typename T, typename... properties>
INLINE_FUNCTION_H
void fill
(
ViewType1D<T, properties...>& view,
range span,
T val
)
{
using ExecutionSpace = typename ViewType1D<T, properties...>::execution_space;
if constexpr( isHostAccessible<ExecutionSpace>())
{
int32 numElems = span.second-span.first;
if( numElems<maxSizeToSerial__)
{
pFlow::algorithms::STD::fill<T,false>(
view.data()+span.first,
numElems,
val);
return;
}
}
auto subV = Kokkos::subview(view, span);
Kokkos::deep_copy(subV, val);
}
template<typename T, typename... properties>
void fill
(
ViewType1D<T, properties...>& view,
int32 start,
int32 end,
T val
)
{
fill(view, range(start,end),val);
}
template<
typename Type,
typename... properties>
void fillSequence(
ViewType1D<Type, properties...>& view,
int32 start,
int32 end,
const Type startVal
)
{
using ExecutionSpace = typename ViewType1D<Type, properties...>::execution_space;
int32 numElems = end-start;
if constexpr( isHostAccessible<ExecutionSpace>())
{
if(numElems<maxSizeToSerial__)
{
pFlow::algorithms::STD::fillSequence<Type,false>(
view.data()+start,
numElems,
startVal);
return ;
}
}
pFlow::algorithms::KOKKOS::fillSequence<Type, ExecutionSpace>(
view.data()+start,
numElems,
startVal);
return ;
}
template<
typename Type,
typename... properties,
typename indexType,
typename... indexProperties>
bool fillSelected(
ViewType1D<Type, properties...> view,
const ViewType1D<indexType, indexProperties...> indices,
const int32 numElems,
const Type val,
typename std::enable_if_t<
areAccessible<
typename ViewType1D<Type, properties...>::execution_space,
typename ViewType1D<indexType, indexProperties...>::memory_space>(),
bool> = true )
{
using ExecutionSpace = typename ViewType1D<Type, properties...>::execution_space;
if constexpr( isHostAccessible<ExecutionSpace>())
{
if(numElems<maxSizeToSerial__)
{
pFlow::algorithms::STD::fillSelected<Type,indexType,false>(
view.data(),
indices.data(),
numElems,
val);
return true;
}
}
pFlow::algorithms::KOKKOS::fillSelected<Type, indexType, ExecutionSpace>(
view.data(),
indices.data(),
numElems,
val);
return true;
}
template<
typename Type,
typename... properties,
typename indexType,
typename... indexProperties>
//typename valType> //,
//typename... valProperties>
bool fillSelected(
ViewType1D<Type, properties...> view,
const ViewType1D<indexType, indexProperties...> indices,
const ViewType1D<Type, indexProperties...> vals,
const int32 numElems ,
typename std::enable_if_t<
areAccessible<
typename ViewType1D<Type, properties...>::execution_space,
typename ViewType1D<indexType, indexProperties...>::memory_space>(),
bool> = true )
{
using ExecutionSpace = typename ViewType1D<Type, properties...>::execution_space;
if constexpr( isHostAccessible<ExecutionSpace>())
{
if(numElems<maxSizeToSerial__)
{
pFlow::algorithms::STD::fillSelected<Type,indexType,false>(
view.data(),
indices.data(),
vals.data(),
numElems
);
return true;
}
}
pFlow::algorithms::KOKKOS::fillSelected<Type, indexType, ExecutionSpace>(
view.data(),
indices.data(),
vals.data(),
numElems
);
return true;
}
template<typename T, typename... properties>
INLINE_FUNCTION_H
T min(
const ViewType1D<T, properties...>& view,
int32 start,
int32 end)
{
using ExecutionSpace = typename ViewType1D<T, properties...>::execution_space;
int32 numElems = end-start;
if constexpr( isHostAccessible<ExecutionSpace>())
{
if(numElems<maxSizeToSerial__)
{
return
pFlow::algorithms::STD::min<T,false>(
view.data()+start,
numElems);
}
}
return
pFlow::algorithms::KOKKOS::min<T, ExecutionSpace>(
view.data()+start,
numElems);
}
template<typename T, typename... properties>
INLINE_FUNCTION_H
T max(
const ViewType1D<T, properties...>& view,
int32 start,
int32 end)
{
using ExecutionSpace = typename ViewType1D<T, properties...>::execution_space;
int32 numElems = end-start;
if constexpr( isHostAccessible<ExecutionSpace>())
{
if(numElems<maxSizeToSerial__)
{
return
pFlow::algorithms::STD::max<T,false>(
view.data()+start,
numElems);
}
}
return
pFlow::algorithms::KOKKOS::max<T, ExecutionSpace>(
view.data()+start,
numElems);
}
template <
typename dType,
typename... dProperties,
typename sType,
typename... sProperties>
INLINE_FUNCTION_H
void copy(
const ViewType1D<dType, dProperties...>& dst,
const ViewType1D<sType, sProperties...>& src
)
{
Kokkos::deep_copy(dst,src);
}
template <
typename dType,
typename... dProperties,
typename sType,
typename... sProperties>
INLINE_FUNCTION_H
void copy(
const ViewType1D<dType, dProperties...>& dst,
int32 dStart,
const ViewType1D<sType, sProperties...>& src,
int32 sStart,
int32 sEnd
)
{
range sSpan(sStart,sEnd);
range dSpan(dStart,dStart+(sEnd-sStart));
auto srcSub = Kokkos::subview(src, sSpan);
auto dstSub = Kokkos::subview(dst, dSpan);
Kokkos::deep_copy(dstSub,srcSub);
}
template <
typename dType,
typename sType,
typename... sProperties>
INLINE_FUNCTION_H
void getNth(
dType& dst,
const ViewType1D<sType, sProperties...>& src,
const int32 n
)
{
range span(n,n+1);
auto subV = Kokkos::subview(src, span);
hostViewType1D<dType> dstView("getNth",1);
Kokkos::deep_copy(dstView,subV);
dst = *dstView.data();
}
template<typename T, typename... properties>
INLINE_FUNCTION_H
void sort(
ViewType1D<T, properties...>& view,
int32 start,
int32 end)
{
using ExecutionSpace = typename ViewType1D<T, properties...>::execution_space;
int32 numElems = end-start;
if constexpr( isHostAccessible<ExecutionSpace>())
{
if(numElems<maxSizeToSerial__)
{
pFlow::algorithms::STD::sort<T,false>(
view.data()+start,
numElems);
return;
}
else
{
pFlow::algorithms::STD::sort<T,true>(
view.data()+start,
numElems);
return;
}
}
#ifdef __CUDACC__
pFlow::algorithms::CUDA::sort<T>(
view.data()+start,
numElems);
#else
static_assert("sort on device is not defined!");
#endif
return;
}
template<typename T, typename... properties, typename CompareFunc>
INLINE_FUNCTION_H
void sort(
ViewType1D<T, properties...>& view,
int32 start,
int32 end,
CompareFunc compare)
{
using ExecutionSpace = typename ViewType1D<T, properties...>::execution_space;
int32 numElems = end-start;
if constexpr( isHostAccessible<ExecutionSpace>())
{
if(numElems<maxSizeToSerial__)
{
pFlow::algorithms::STD::sort<T,CompareFunc,false>(
view.data()+start,
numElems,
compare);
return;
}
else
{
pFlow::algorithms::STD::sort<T,CompareFunc,true>(
view.data()+start,
numElems,
compare);
return;
}
}
#ifdef __CUDACC__
pFlow::algorithms::CUDA::sort<T, CompareFunc>(
view.data()+start,
numElems,
compare);
#else
static_assert("sort on device is not defined!");
#endif
return;
}
template<
typename Type,
typename... properties,
typename permType,
typename... permProperties>
void permuteSort(
const ViewType1D<Type, properties...>& view,
int32 start,
int32 end,
ViewType1D<permType, permProperties...>& permuteView,
int32 permStart,
typename std::enable_if_t<
areAccessible<
typename ViewType1D<Type, properties...>::execution_space,
typename ViewType1D<permType, permProperties...>::memory_space>(),
bool> = true )
{
using ExecutionSpace = typename ViewType1D<Type, properties...>::execution_space;
int32 numElems = end-start;
if constexpr( isHostAccessible<ExecutionSpace>())
{
if(numElems<maxSizeToSerial__)
{
pFlow::algorithms::STD::permuteSort<Type,permType,false>(
view.data()+start,
permuteView.data()+permStart,
numElems );
return;
}
else
{
pFlow::algorithms::STD::permuteSort<Type,permType,true>(
view.data()+start,
permuteView.data()+permStart,
numElems);
return;
}
}
#ifdef __CUDACC__
pFlow::algorithms::CUDA::permuteSort(
view.data()+start,
permuteView.data()+permStart,
numElems);
#else
static_assert("sort on device is not defined!");
#endif
}
template<
typename Type,
typename... properties>
INLINE_FUNCTION_HD
int32 binarySearch(
const ViewType1D<Type, properties...>& view,
int32 start,
int32 end,
const Type& val)
{
if(end<=start)return -1;
if(auto res =
pFlow::algorithms::binarySearch(view.data()+start,end-start,val); res>=0) {
return res+start;
}
else{
return res;
}
}
template<
typename Type,
typename... properties,
typename dType,
typename... dProperties>
void exclusiveScan(
const ViewType1D<Type, properties...>& view,
int32 start,
int32 end,
ViewType1D<dType, dProperties...>& dView,
int32 dStart,
typename std::enable_if_t<
areAccessible<
typename ViewType1D<Type, properties...>::execution_space,
typename ViewType1D<dType, dProperties...>::memory_space>(),
bool> = true )
{
using ExecutionSpace = typename ViewType1D<Type, properties...>::execution_space;
int32 numElems = end-start;
if constexpr( isHostAccessible<ExecutionSpace>())
{
if(numElems<maxSizeToSerial__)
{
pFlow::algorithms::STD::exclusiveScan<Type,dType,false>(
view.data()+start,
dView.data()+dStart,
numElems);
return;
}
}
pFlow::algorithms::KOKKOS::exclusiveScan<Type,dType,ExecutionSpace>(
view.data()+start,
dView.data()+dStart,
numElems);
}
template<
typename Type,
typename... properties,
typename dType,
typename... dProperties>
void inclusiveScan(
const ViewType1D<Type, properties...>& view,
int32 start,
int32 end,
ViewType1D<dType, dProperties...>& dView,
int32 dStart,
typename std::enable_if_t<
areAccessible<
typename ViewType1D<Type, properties...>::execution_space,
typename ViewType1D<dType, dProperties...>::memory_space>(),
bool> = true )
{
using ExecutionSpace = typename ViewType1D<Type, properties...>::execution_space;
int32 numElems = end-start;
if constexpr( isHostAccessible<ExecutionSpace>())
{
if(numElems<maxSizeToSerial__)
{
pFlow::algorithms::STD::inclusiveScan<Type,dType,false>(
view.data()+start,
dView.data()+dStart,
numElems);
return;
}
}
pFlow::algorithms::KOKKOS::inclusiveScan<Type,dType,ExecutionSpace>(
view.data()+start,
dView.data()+dStart,
numElems);
}
} // pFlow
#endif // Viewalgorithms

View File

@ -0,0 +1,245 @@
/*------------------------------- 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 __baseAlgorithms_H__
#define __baseAlgorithms_H__
#include "numericConstants.H"
inline const size_t sizeToSerial__ = 64;
namespace pFlow
{
// counts the number of elements that matches val
// the execution space is selected based on the View::execution_spcae
/*template<typename T, typename... properties>
INLINE_FUNCTION_H
size_t count(
const ViewType1D<T, properties...>& view,
size_t start,
size_t end,
const T& val
)
{
auto RP = Kokkos::RangePolicy<
Kokkos::IndexType<size_t>,
typename ViewType1D<T, properties...>::execution_space >(start, end);
size_t totalNum=0;
Kokkos::parallel_reduce(
"baseAlgorithms-count",
RP,
LAMBDA_HD(label i, size_t & valueToUpdate){
if( equal(view[i], val) ) valueToUpdate += 1;
}, totalNum );
return totalNum;
}*/
template<typename T, typename... properties>
INLINE_FUNCTION_H
T min( const ViewType1D<T, properties...>& view, size_t start, size_t end )
{
T minValue = largestPositive<T>();
auto RP = Kokkos::RangePolicy<
Kokkos::IndexType<size_t>,
typename ViewType1D<T, properties...>::execution_space >(start, end);
Kokkos::parallel_reduce("baseAlgorithms-min",
RP,
LAMBDA_HD(label i, T& valueToUpdate){
valueToUpdate = min(view[i],valueToUpdate);
},
Kokkos :: Min < T >( minValue )
);
return minValue;
}
template<typename T, typename... properties>
INLINE_FUNCTION_H
T max( const ViewType1D<T, properties...>& view, size_t start, size_t end )
{
T maxValue = largestNegative<T>();
auto RP = Kokkos::RangePolicy<
Kokkos::IndexType<size_t>,
typename ViewType1D<T, properties...>::execution_space >(start, end);
Kokkos::parallel_reduce("baseAlgorithms-max",
RP,
LAMBDA_HD(label i, T& valueToUpdate){
valueToUpdate = max(view[i],valueToUpdate);
},
Kokkos::Max<T>( maxValue )
);
return maxValue;
}
template<typename T, typename... properties>
INLINE_FUNCTION_H
T min_serial(const ViewType1D<T, properties...>& view, size_t start, size_t end)
{
T minValue = largestPositive<T>();
for(label i=start; i<end; ++i)
{
minValue = min(minValue, view[i]);
}
return minValue;
}
template<typename T, typename... properties>
INLINE_FUNCTION_H
T max_serial(const ViewType1D<T, properties...>& view, size_t start, size_t end)
{
T maxValue = largestNegative<T>();
for(label i=start; i<end; ++i)
{
maxValue = max(maxValue, view[i]);
}
return maxValue;
}
template<typename UnaryFunction, typename T, typename... properties>
void apply_to_each(const ViewType1D<T, properties...>& view, size_t start, size_t end, UnaryFunction func)
{
auto RP = Kokkos::RangePolicy<
Kokkos::IndexType<size_t>,
typename ViewType1D<T, properties...>::execution_space >(start, end);
Kokkos::parallel_for("baseAlgorithms-for_each",
RP,
LAMBDA_HD(label i){
view[i] = func(i);
}
);
}
template<typename T, typename... properties>
void insertSetElementH
(
ViewType1D<T, properties...>& view,
hostViewType1D<label>& selected,
T val
)
{
for(auto i=0; i<selected.size();++i)
{
view[selected[i]] = val;
}
}
template<typename T, typename... properties>
void insertSetElementH
(
ViewType1D<T, properties...>& view,
hostViewType1D<label>& selected,
hostViewType1D<T>& vals
)
{
for(auto i=0; i<selected.size(); ++i)
{
view[selected[i]] = static_cast<const T&>(vals[i]);
}
}
template<typename T, typename... properties>
void insertSetElementD
(
ViewType1D<T, properties...>& view,
deviceViewType1D<label>& selected,
T val
)
{
auto RP = Kokkos::RangePolicy<
Kokkos::IndexType<size_t>,
typename ViewType1D<T, properties...>::execution_space >(0, selected.size());
Kokkos::parallel_for(
"baseAlgorithms-insertSetElementD",
RP,
LAMBDA_D(size_t i) {
view[selected[i]] = val; } );
}
template<typename T, typename... properties>
void insertSetElementD
(
ViewType1D<T, properties...>& view,
deviceViewType1D<label>& selected,
deviceViewType1D<T>& vals
)
{
auto RP = Kokkos::RangePolicy<
Kokkos::IndexType<size_t>,
typename ViewType1D<T, properties...>::execution_space >(0, selected.size());
Kokkos::parallel_for(
"baseAlgorithms-insertSetElementD",
RP,
LAMBDA_D(size_t i) {
view[selected[i]] = vals[i]; } );
}
/*template<typename T, typename... properties>
void fill
(
ViewType1D<T, properties...>& view,
range range,
T val
)
{
auto subV = Kokkos::subview(view, range);
Kokkos::deep_copy(subV, val);
}*/
template<typename T, typename... properties>
void fill
(
ViewType3D<T, properties...>& view,
range range1,
range range2,
range range3,
T val
)
{
auto subV = Kokkos::subview(view, range1, range2, range3);
Kokkos::deep_copy(subV, val);
}
}
#endif // __VectorSingleMath_H__

View File

@ -0,0 +1,51 @@
/*------------------------------- 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<typename T, typename... properties>
void insertSetElementH
(
ViewType1D<T, properties...>& view,
hostViewType1D<label>& selected,
T val
);
template<typename T, typename... properties>
void insertSetElementH
(
ViewType1D<T, properties...>& view,
hostViewType1D<label>& selected,
hostViewType1D<T>& vals
);
template<typename T, typename... properties>
void insertSetElementD
(
ViewType1D<T, properties...>& view,
deviceViewType1D<label>& selected,
T val
);
template<typename T, typename... properties>
void insertSetElementD
(
ViewType1D<T, properties...>& view,
deviceViewType1D<label>& selected,
deviceViewType1D<T>& vals
);

View File

@ -0,0 +1,97 @@
/*------------------------------- 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 "Timer.H"
#include "Timers.H"
#include "streams.H"
pFlow::Timer::Timer(const word name, Timers* parrent)
:
name_(name),
parrent_(parrent)
{
if(parrent_)
parrent_->addToList(this);
}
pFlow::Timer::~Timer()
{
if(parrent_)
{
parrent_->removeFromList(this);
}
}
pFlow::int32 pFlow::Timer::level()const
{
if(parrent_)
return parrent_->level()+1;
else
return 0;
}
bool pFlow::Timer::write(iOstream& os, bool subTree)const
{
if(!timerActive() && !master())return true;
int32 lvl = level();
for(int32 l=1; l<lvl; l++)
{
os<<"";
}
if(lvl>0)
{
if(master())
os<<"┣━━ ";
else
if(lvl==1)
os<<"┃└─ ";
else
os<<" └─ ";
}
else
; //os<<"⊿ ";
if(lvl==0)
os<<greenColor<<boldChar;
os<<name_;
if(timerActive())
if(master())
os<<" execution time (s): total ("<<
totalTime()<<"), av. ("<<
averageTime()<<").";
else
os<<" execution time (s): total ("<<
cyanText(totalTime())<<"), av. ("<<
cyanText(averageTime())<<").";
os<<defaultColor;
os<<'\n';
return true;
}

View File

@ -0,0 +1,163 @@
/*------------------------------- 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 __Timer_H__
#define __Timer_H__
#include <chrono>
#include "types.H"
namespace pFlow
{
// forward
class Timers;
class Timer
{
protected:
using timer = std::chrono::high_resolution_clock;
// - name for the timer
word name_ = "noNameTimer";
// start time
timer::time_point start_;
// number of times start() and end() are called
int32 numIteration_ = 0;
// sum of time duratios (in seconds) between all start() and end() calls
real accTime_ = 0.0;
//
real lastTime_ = 0.0;
Timers* parrent_ = nullptr;
public:
TypeName("Timer");
Timer(){}
Timer(const word name)
:
name_(name)
{}
Timer(const word name, Timers* parrent);
const word& name()const
{
return name_;
}
virtual ~Timer();
virtual void removeParrent()
{
parrent_ = nullptr;
}
virtual int32 level()const;
virtual bool master()const
{
return false;
}
void start()
{
start_ = timer::now();
}
void end()
{
auto end = timer::now();
lastTime_ = std::chrono::duration_cast
< std::chrono::duration<real> >(end - start_).count();
numIteration_++;
accTime_ += lastTime_;
}
bool timerActive()const
{
return numIteration_!=0;
}
real lastTime()const
{
return lastTime_;
}
real totalTime()const
{
return accTime_;
}
real averageTime()const
{
return accTime_/max(numIteration_, 1);
}
//// - IO operations
virtual bool write(iOstream& os, bool subTree)const;
virtual bool read(iIstream& is)
{
return true;
}
};
inline iOstream& operator<<(iOstream& os, const Timer& t)
{
t.write(os, false);
return os;
}
inline iIstream& operator>>(iIstream& is, Timer& t)
{
return is;
}
}
#endif //__Timer_H__

View File

@ -0,0 +1,40 @@
/*------------------------------- 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 "Timers.H"
bool pFlow::Timers::write(iOstream& os, bool subTree)const
{
if(level() == 0 )os<<"\n";
Timer::write(os, subTree);
if(subTree)
{
for(const auto& timer:timers_)
{
timer->write(os, subTree);
}
}
if(level() == 0 )os<<"\n";
return true;
}

View File

@ -0,0 +1,120 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
#ifndef __Timers_H__
#define __Timers_H__
#include "Timer.H"
#include "List.H"
namespace pFlow
{
class Timers
:
public Timer
{
protected:
List<Timer*> timers_;
int32 level_ = 0;
public:
TypeName("Timers");
Timers(const word& name)
:
Timer(name)
{}
Timers(const word& name, Timers* parrent)
:
Timer(name, parrent)
{
if(parrent_)
{
level_ = parrent_->level()+1;
}
}
virtual ~Timers()
{
for(auto& timer:timers_)
{
timer->removeParrent();
}
}
// add a timer to this node
uniquePtr<Timer> addTimer(const word& name)
{
return makeUnique<Timer>(name, this);
}
void addToList(Timer* timer)
{
timers_.push_back(timer);
}
void removeFromList(Timer* timer)
{
timers_.erase(timers_.find(timer));
}
virtual int32 level()const
{
return level_;
}
virtual bool master()const
{
return true;
}
virtual bool write(iOstream& os, bool subTree = true)const;
virtual bool read(iIstream& is)
{
return true;
}
};
inline iOstream& operator<<(iOstream& os, const Timers& t)
{
t.write(os, true);
return os;
}
inline iIstream& operator>>(iIstream& is, Timers& t)
{
return is;
}
}
#endif //__Timers_H__

View File

@ -0,0 +1,96 @@
/*------------------------------- 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 __algorithmFunctions_H__
#define __algorithmFunctions_H__
#include "pFlowMacros.H"
namespace pFlow::algorithms
{
template<typename T>
struct greater
{
INLINE_FUNCTION_HD
bool operator()(const T &lhs, const T &rhs) const {
return lhs > rhs; }
};
template<typename T>
struct less
{
INLINE_FUNCTION_HD
bool operator()(const T &lhs, const T &rhs) const {
return lhs < rhs; }
};
template<typename T>
struct maximum
{
INLINE_FUNCTION_HD
bool operator()(const T &lhs, const T &rhs) const {
return lhs < rhs ? rhs : lhs; }
};
template<typename T>
struct minimum
{
INLINE_FUNCTION_HD
bool operator()(const T &lhs, const T &rhs) const {
return lhs < rhs ? lhs : rhs; }
};
template<typename T>
INLINE_FUNCTION_HD
int binarySearch(const T* array, int length, const T& val)
{
int low = 0;
int high = length - 1;
while (low <= high)
{
int mid = low + (high - low)/2;
if ( array[mid] > val)
{
high = mid - 1;
}
else if ( array[mid] < val)
{
low = mid + 1;
}
else
{
return mid;
}
}
return -1; // val not found in array[0, length)
}
}
#endif // __algorithmFunctions_H__

View File

@ -0,0 +1,182 @@
/*------------------------------- 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 __cudaAlgorithms_H__
#define __cudaAlgorithms_H__
#ifdef __CUDACC__
#include <thrust/fill.h>
#include <thrust/count.h>
#include <thrust/scan.h>
#include <thrust/sort.h>
#include <thrust/extrema.h>
#include <thrust/execution_policy.h>
#include "pFlowMacros.H"
#include "algorithmFunctions.H"
#include "types.H"
namespace pFlow::algorithms::CUDA
{
template<typename Type>
INLINE_FUNCTION_H
int32 count(const Type* first, int32 numElems, const Type& val)
{
return thrust::count_if(
thrust::device,
first, first+numElems,
LAMBDA_HD(const Type& check){ return equal(check,val);} );
}
template<typename Type>
INLINE_FUNCTION_H
void fill(Type* first, int32 numElems, const Type& val)
{
thrust::fill(thrust::device, first, first+numElems, val);
}
template<typename Type>
INLINE_FUNCTION_H
void fillSequence(Type* first, int32 numElems, const Type& firstVal)
{
thrust::for_each_n(
thrust::device,
first,
numElems,
LAMBDA_HD(Type& ref){ ref = firstVal+(&ref - first);});
}
template<typename Type, typename indexType>
INLINE_FUNCTION_H
void fillSelected(Type* first, const indexType* indices, const int32 numElems, const Type val)
{
thrust::for_each_n(
thrust::device,
indices,
numElems,
LAMBDA_HD(indexType i){
first[i] = val;
});
}
template<typename Type>
INLINE_FUNCTION_H
Type max(const Type* first, int32 numElems)
{
Type resH;
auto* resD = thrust::max_element(
thrust::device,
first,
first+numElems,
less<Type>());
cudaMemcpy(&resH, resD, sizeof(Type),cudaMemcpyDeviceToHost);
return resH;
}
template<typename Type>
INLINE_FUNCTION_H
Type min(const Type* first, int32 numElems)
{
Type resH;
auto* resD = thrust::min_element(
thrust::device,
first,
first+numElems,
less<Type>());
cudaMemcpy(&resH, resD, sizeof(Type),cudaMemcpyDeviceToHost);
return resH;
}
template<typename Type>
INLINE_FUNCTION_H
void sort(Type* first, int32 numElems)
{
thrust::sort(
thrust::device,
first,
first+numElems,
less<Type>());
}
template<typename Type, typename CompareFunc>
INLINE_FUNCTION_H
void sort(Type* first, int32 numElems, CompareFunc compare)
{
thrust::sort(
thrust::device,
first,
first+numElems,
compare);
}
template<typename Type, typename PermuteType>
INLINE_FUNCTION_H
void permuteSort(const Type* first, PermuteType* pFirst, int32 numElems)
{
fillSequence(pFirst, numElems, static_cast<PermuteType>(0));
thrust::sort(
thrust::device,
pFirst,
pFirst+numElems,
LAMBDA_HD(const PermuteType& lhs, const PermuteType& rhs){
return first[lhs]<first[rhs]; });
}
template<typename Type, typename DestType>
void exclusiveScan(Type* first, DestType* dFirst, int32 numElems)
{
thrust::exclusive_scan(
thrust::device,
first, first+numElems,
dFirst, 0);
}
template<typename Type, typename DestType>
void inclusiveScan(Type* first, DestType* dFirst, int32 numElems)
{
thrust::inclusive_scan(
thrust::device,
first, first+numElems,
dFirst);
}
} // end of namespace
#endif //__CUDA__
#endif //__cudaAlgorithms_H__

View File

@ -0,0 +1,188 @@
/*------------------------------- 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 __kokkosAlgorithms_H__
#define __kokkosAlgorithms_H__
#include "KokkosTypes.H"
namespace pFlow::algorithms::KOKKOS
{
template<typename Type, typename ExecutionSpace>
INLINE_FUNCTION_H
int32 count(const Type* first, int32 numElems, const Type& val)
{
using policy = Kokkos::RangePolicy<
ExecutionSpace,
Kokkos::IndexType<int32> >;
int32 num = 0;
Kokkos::parallel_reduce("count",
policy(0, numElems),
LAMBDA_HD(int32 i, int32& updateVal){
if(equal(first[i],val)) updateVal++;
},
num);
return num;
}
// fill should be done using deep_copy by kokkos
//void fill(Type* first, int32 numElems, const Type& val);
template<typename Type, typename ExecutionSpace>
INLINE_FUNCTION_H
void fillSequence(Type* first, int32 numElems, const Type& firstVal)
{
using policy = Kokkos::RangePolicy<
ExecutionSpace,
Kokkos::IndexType<int32> >;
Kokkos::parallel_for(
"fillSequence",
policy(0, numElems),
LAMBDA_HD(int32 i){
first[i] = firstVal+i;
});
Kokkos::fence();
}
template<typename Type, typename indexType, typename ExecutionSpace>
INLINE_FUNCTION_H
void fillSelected(Type* first, const indexType* indices, const int32 numElems, const Type val)
{
using policy = Kokkos::RangePolicy<
ExecutionSpace,
Kokkos::IndexType<int32> >;
Kokkos::parallel_for(
"fillSelected",
policy(0,numElems),
LAMBDA_HD(int32 i){
first[indices[i]]= val;
});
Kokkos::fence();
}
template<typename Type, typename indexType, typename ExecutionSpace>
INLINE_FUNCTION_H
void fillSelected(Type* first, const indexType* indices, const Type* vals, const int32 numElems)
{
using policy = Kokkos::RangePolicy<
ExecutionSpace,
Kokkos::IndexType<int32> >;
Kokkos::parallel_for(
"fillSelected",
policy(0,numElems),
LAMBDA_HD(int32 i){
first[indices[i]]= vals[i];
});
Kokkos::fence();
}
template<typename Type, typename ExecutionSpace>
INLINE_FUNCTION_H
Type max(const Type* first, int32 numElems)
{
using policy = Kokkos::RangePolicy<
ExecutionSpace,
Kokkos::IndexType<int32> >;
Type maxElement=0;
Kokkos::parallel_reduce(
"max",
policy(0, numElems),
LAMBDA_HD(int32 i, Type& maxUpdate){
if(maxUpdate<first[i]) maxUpdate = first[i];
},
Kokkos::Max<Type>(maxElement));
return maxElement;
}
template<typename Type, typename ExecutionSpace>
INLINE_FUNCTION_H
Type min(const Type* first, int32 numElems)
{
using policy = Kokkos::RangePolicy<
ExecutionSpace,
Kokkos::IndexType<int32> >;
Type minElement;
Kokkos::parallel_reduce(
"min",
policy(0, numElems),
LAMBDA_HD(int32 i, Type& minUpdate){
if(first[i] < minUpdate) minUpdate = first[i];
},
Kokkos::Min<Type>(minElement));
return minElement;
}
// we either use CUDA or STD srots
//void sort(Type* first, int32 numElems);
//void sort(Type* first, int32 numElems, CompareFunc compare);
//void permuteSort(const Type* first, PermuteType* pFirst, int32 numElems);
template<typename Type, typename DestType, typename ExecutionSpace>
void exclusiveScan(Type* first, DestType* dFirst, int32 numElems)
{
using policy = Kokkos::RangePolicy<
ExecutionSpace,
Kokkos::IndexType<int32> >;
Kokkos::parallel_scan(
"exclusiveScan",
policy(0, numElems),
LAMBDA_HD(const int32 i, DestType& valToUpdate, const bool final)
{
const int32 val = first[i];
if(final)
dFirst[i] = valToUpdate;
valToUpdate += val;
});
}
template<typename Type, typename DestType, typename ExecutionSpace>
void inclusiveScan(Type* first, DestType* dFirst, int32 numElems)
{
using policy = Kokkos::RangePolicy<
ExecutionSpace,
Kokkos::IndexType<int32> >;
Kokkos::parallel_scan(
"inclusiveScan",
policy(0, numElems),
LAMBDA_HD(const int32 i, int32& valToUpdate, const bool final)
{
const int32 val = first[i];
valToUpdate += val;
if(final)
dFirst[i] = valToUpdate;
});
}
} //pFlow::algorithms::KOKKOS
#endif //__kokkosAlgorithms_H__

View File

@ -0,0 +1,243 @@
/*------------------------------- 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 __stdAlgorithms_H__
#define __stdAlgorithms_H__
#include <algorithm>
#include <execution>
#include "pFlowMacros.H"
#include "algorithmFunctions.H"
#include "types.H"
namespace pFlow::algorithms::STD
{
template<typename Type, bool useParallel = useStdParallel__>
INLINE_FUNCTION_H
int32 count(const Type* first, int32 numElems, const Type& val)
{
if constexpr (useParallel)
return std::count_if(
std::execution::par_unseq,
first, first+numElems,
[=](const Type& check){ return equal(check,val);} );
else
return std::count_if(
first, first+numElems,
[=](const Type& check){ return equal(check,val);} );
return 0; // for nvcc
}
template<typename Type, bool useParallel = useStdParallel__>
INLINE_FUNCTION_H
void fill(Type* first, int32 numElems, const Type& val)
{
if constexpr (useParallel)
std::fill(std::execution::par_unseq, first, first+numElems, val);
else
std::fill(first, first+numElems, val);
}
template<typename Type, typename indexType, bool useParallel = useStdParallel__>
INLINE_FUNCTION_H
void fillSelected(Type* first, const indexType* indices, const int32 numElems, const Type val)
{
if constexpr(useParallel)
{
std::for_each_n(
std::execution::par_unseq,
indices,
numElems,
[=](indexType i){
first[i] = val;
});
}
else
{
std::for_each_n(
indices,
numElems,
[=](indexType i){
first[i] = val;
});
}
}
template<typename Type, typename indexType, bool useParallel = useStdParallel__>
INLINE_FUNCTION_H
void fillSelected(Type* first, const indexType* indices, const Type* vals, const int32 numElems)
{
for(indexType i=0; i<numElems; i++)
{
first[indices[i]]=vals[i];
}
}
template<typename Type, bool useParallel = useStdParallel__>
INLINE_FUNCTION_H
void fillSequence(Type* first, int32 numElems, const Type& firstVal)
{
if constexpr (useParallel)
std::for_each_n(
std::execution::par_unseq,
first,
numElems,
[=](Type& ref){ ref = firstVal+std::distance(first,&ref);});
else
std::iota(first, first+numElems, firstVal);
}
template<typename Type, bool useParallel = useStdParallel__>
INLINE_FUNCTION_H
Type max(const Type* first, int32 numElems)
{
if constexpr(useParallel)
return *std::max_element(
std::execution::par_unseq,
first,
first+numElems,
less<Type>());
else
return *std::max_element(
first,
first+numElems,
less<Type>());
}
template<typename Type, bool useParallel = useStdParallel__>
INLINE_FUNCTION_H
Type min(const Type* first, int32 numElems)
{
if constexpr(useParallel)
return *(std::min_element(
std::execution::par_unseq,
first,
first+numElems,
less<Type>()));
else
return *(std::min_element(
first,
first+numElems,
less<Type>()));
}
template<typename Type, bool useParallel = useStdParallel__>
INLINE_FUNCTION_H
void sort(Type* first, int32 numElems)
{
if constexpr(useParallel)
{
std::sort(
std::execution::par,
first,
first+numElems,
less<Type>());
}
else
{
std::sort(
first,
first+numElems,
less<Type>());
}
}
template<typename Type, typename CompareFunc, bool useParallel = useStdParallel__>
INLINE_FUNCTION_H
void sort(Type* first, int32 numElems, CompareFunc compare)
{
if constexpr(useParallel)
{
std::sort(
std::execution::par_unseq,
first,
first+numElems,
compare);
}
else
{
std::sort(
first,
first+numElems,
compare);
}
}
template<typename Type, typename PermuteType, bool useParallel = useStdParallel__>
INLINE_FUNCTION_H
void permuteSort(const Type* first, PermuteType* pFirst, int32 numElems)
{
struct compOperator
{
const Type* first_;
bool operator()(const PermuteType& lhs, const PermuteType& rhs)const {
return first_[lhs]<first_[rhs]; }
};
compOperator compare{first};
fillSequence<Type, useParallel>(pFirst, numElems, static_cast<PermuteType>(0));
sort<Type, compOperator, useParallel>(pFirst, numElems, compare);
}
template<typename Type, typename DestType, bool useParallel = useStdParallel__>
void exclusiveScan(Type* first, DestType* dFirst, int32 numElems)
{
if constexpr (useParallel)
{
//// - this does not work when first and dFirst point to the same location
std::exclusive_scan(
//std::execution::par_unseq,
first, first+numElems,
dFirst, 0);
}
else
{
std::exclusive_scan(
first, first+numElems,
dFirst,0);
}
}
template<typename Type, typename DestType, bool useParallel = useStdParallel__>
void inclusiveScan(Type* first, DestType* dFirst, int32 numElems)
{
if constexpr (useParallel)
{
std::inclusive_scan(
std::execution::par_unseq,
first, first+numElems,
dFirst);
}
else
{
std::inclusive_scan(
first, first+numElems,
dFirst);
}
}
}
#endif //__stdAlgorithms_H__

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,36 @@
// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
// under NSF AWARD 1414736 and by the respective contributors.
// All rights reserved.
//
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
// CLI Library includes
// Order is important for combiner script
#include "Version.hpp"
#include "Macros.hpp"
#include "StringTools.hpp"
#include "Error.hpp"
#include "TypeTools.hpp"
#include "Split.hpp"
#include "ConfigFwd.hpp"
#include "Validators.hpp"
#include "FormatterFwd.hpp"
#include "Option.hpp"
#include "App.hpp"
#include "Config.hpp"
#include "Formatter.hpp"

View File

@ -0,0 +1,396 @@
// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
// under NSF AWARD 1414736 and by the respective contributors.
// All rights reserved.
//
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
// [CLI11:public_includes:set]
#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <utility>
#include <vector>
// [CLI11:public_includes:set]
#include "App.hpp"
#include "ConfigFwd.hpp"
#include "StringTools.hpp"
namespace CLI {
// [CLI11:config_hpp:verbatim]
namespace detail {
inline std::string convert_arg_for_ini(const std::string &arg, char stringQuote = '"', char characterQuote = '\'') {
if(arg.empty()) {
return std::string(2, stringQuote);
}
// some specifically supported strings
if(arg == "true" || arg == "false" || arg == "nan" || arg == "inf") {
return arg;
}
// floating point conversion can convert some hex codes, but don't try that here
if(arg.compare(0, 2, "0x") != 0 && arg.compare(0, 2, "0X") != 0) {
double val;
if(detail::lexical_cast(arg, val)) {
return arg;
}
}
// just quote a single non numeric character
if(arg.size() == 1) {
return std::string(1, characterQuote) + arg + characterQuote;
}
// handle hex, binary or octal arguments
if(arg.front() == '0') {
if(arg[1] == 'x') {
if(std::all_of(arg.begin() + 2, arg.end(), [](char x) {
return (x >= '0' && x <= '9') || (x >= 'A' && x <= 'F') || (x >= 'a' && x <= 'f');
})) {
return arg;
}
} else if(arg[1] == 'o') {
if(std::all_of(arg.begin() + 2, arg.end(), [](char x) { return (x >= '0' && x <= '7'); })) {
return arg;
}
} else if(arg[1] == 'b') {
if(std::all_of(arg.begin() + 2, arg.end(), [](char x) { return (x == '0' || x == '1'); })) {
return arg;
}
}
}
if(arg.find_first_of(stringQuote) == std::string::npos) {
return std::string(1, stringQuote) + arg + stringQuote;
} else {
return characterQuote + arg + characterQuote;
}
}
/// Comma separated join, adds quotes if needed
inline std::string ini_join(const std::vector<std::string> &args,
char sepChar = ',',
char arrayStart = '[',
char arrayEnd = ']',
char stringQuote = '"',
char characterQuote = '\'') {
std::string joined;
if(args.size() > 1 && arrayStart != '\0') {
joined.push_back(arrayStart);
}
std::size_t start = 0;
for(const auto &arg : args) {
if(start++ > 0) {
joined.push_back(sepChar);
if(isspace(sepChar) == 0) {
joined.push_back(' ');
}
}
joined.append(convert_arg_for_ini(arg, stringQuote, characterQuote));
}
if(args.size() > 1 && arrayEnd != '\0') {
joined.push_back(arrayEnd);
}
return joined;
}
inline std::vector<std::string> generate_parents(const std::string &section, std::string &name, char parentSeparator) {
std::vector<std::string> parents;
if(detail::to_lower(section) != "default") {
if(section.find(parentSeparator) != std::string::npos) {
parents = detail::split(section, parentSeparator);
} else {
parents = {section};
}
}
if(name.find(parentSeparator) != std::string::npos) {
std::vector<std::string> plist = detail::split(name, parentSeparator);
name = plist.back();
detail::remove_quotes(name);
plist.pop_back();
parents.insert(parents.end(), plist.begin(), plist.end());
}
// clean up quotes on the parents
for(auto &parent : parents) {
detail::remove_quotes(parent);
}
return parents;
}
/// assuming non default segments do a check on the close and open of the segments in a configItem structure
inline void
checkParentSegments(std::vector<ConfigItem> &output, const std::string &currentSection, char parentSeparator) {
std::string estring;
auto parents = detail::generate_parents(currentSection, estring, parentSeparator);
if(!output.empty() && output.back().name == "--") {
std::size_t msize = (parents.size() > 1U) ? parents.size() : 2;
while(output.back().parents.size() >= msize) {
output.push_back(output.back());
output.back().parents.pop_back();
}
if(parents.size() > 1) {
std::size_t common = 0;
std::size_t mpair = (std::min)(output.back().parents.size(), parents.size() - 1);
for(std::size_t ii = 0; ii < mpair; ++ii) {
if(output.back().parents[ii] != parents[ii]) {
break;
}
++common;
}
if(common == mpair) {
output.pop_back();
} else {
while(output.back().parents.size() > common + 1) {
output.push_back(output.back());
output.back().parents.pop_back();
}
}
for(std::size_t ii = common; ii < parents.size() - 1; ++ii) {
output.emplace_back();
output.back().parents.assign(parents.begin(), parents.begin() + static_cast<std::ptrdiff_t>(ii) + 1);
output.back().name = "++";
}
}
} else if(parents.size() > 1) {
for(std::size_t ii = 0; ii < parents.size() - 1; ++ii) {
output.emplace_back();
output.back().parents.assign(parents.begin(), parents.begin() + static_cast<std::ptrdiff_t>(ii) + 1);
output.back().name = "++";
}
}
// insert a section end which is just an empty items_buffer
output.emplace_back();
output.back().parents = std::move(parents);
output.back().name = "++";
}
} // namespace detail
inline std::vector<ConfigItem> ConfigBase::from_config(std::istream &input) const {
std::string line;
std::string currentSection = "default";
std::string previousSection = "default";
std::vector<ConfigItem> output;
bool isDefaultArray = (arrayStart == '[' && arrayEnd == ']' && arraySeparator == ',');
bool isINIArray = (arrayStart == '\0' || arrayStart == ' ') && arrayStart == arrayEnd;
bool inSection{false};
char aStart = (isINIArray) ? '[' : arrayStart;
char aEnd = (isINIArray) ? ']' : arrayEnd;
char aSep = (isINIArray && arraySeparator == ' ') ? ',' : arraySeparator;
int currentSectionIndex{0};
while(getline(input, line)) {
std::vector<std::string> items_buffer;
std::string name;
detail::trim(line);
std::size_t len = line.length();
// lines have to be at least 3 characters to have any meaning to CLI just skip the rest
if(len < 3) {
continue;
}
if(line.front() == '[' && line.back() == ']') {
if(currentSection != "default") {
// insert a section end which is just an empty items_buffer
output.emplace_back();
output.back().parents = detail::generate_parents(currentSection, name, parentSeparatorChar);
output.back().name = "--";
}
currentSection = line.substr(1, len - 2);
// deal with double brackets for TOML
if(currentSection.size() > 1 && currentSection.front() == '[' && currentSection.back() == ']') {
currentSection = currentSection.substr(1, currentSection.size() - 2);
}
if(detail::to_lower(currentSection) == "default") {
currentSection = "default";
} else {
detail::checkParentSegments(output, currentSection, parentSeparatorChar);
}
inSection = false;
if(currentSection == previousSection) {
++currentSectionIndex;
} else {
currentSectionIndex = 0;
previousSection = currentSection;
}
continue;
}
// comment lines
if(line.front() == ';' || line.front() == '#' || line.front() == commentChar) {
continue;
}
// Find = in string, split and recombine
auto pos = line.find(valueDelimiter);
if(pos != std::string::npos) {
name = detail::trim_copy(line.substr(0, pos));
std::string item = detail::trim_copy(line.substr(pos + 1));
auto cloc = item.find(commentChar);
if(cloc != std::string::npos) {
item.erase(cloc, std::string::npos);
detail::trim(item);
}
if(item.size() > 1 && item.front() == aStart) {
for(std::string multiline; item.back() != aEnd && std::getline(input, multiline);) {
detail::trim(multiline);
item += multiline;
}
items_buffer = detail::split_up(item.substr(1, item.length() - 2), aSep);
} else if((isDefaultArray || isINIArray) && item.find_first_of(aSep) != std::string::npos) {
items_buffer = detail::split_up(item, aSep);
} else if((isDefaultArray || isINIArray) && item.find_first_of(' ') != std::string::npos) {
items_buffer = detail::split_up(item);
} else {
items_buffer = {item};
}
} else {
name = detail::trim_copy(line);
auto cloc = name.find(commentChar);
if(cloc != std::string::npos) {
name.erase(cloc, std::string::npos);
detail::trim(name);
}
items_buffer = {"true"};
}
if(name.find(parentSeparatorChar) == std::string::npos) {
detail::remove_quotes(name);
}
// clean up quotes on the items
for(auto &it : items_buffer) {
detail::remove_quotes(it);
}
std::vector<std::string> parents = detail::generate_parents(currentSection, name, parentSeparatorChar);
if(parents.size() > maximumLayers) {
continue;
}
if(!configSection.empty() && !inSection) {
if(parents.empty() || parents.front() != configSection) {
continue;
}
if(configIndex >= 0 && currentSectionIndex != configIndex) {
continue;
}
parents.erase(parents.begin());
inSection = true;
}
if(!output.empty() && name == output.back().name && parents == output.back().parents) {
output.back().inputs.insert(output.back().inputs.end(), items_buffer.begin(), items_buffer.end());
} else {
output.emplace_back();
output.back().parents = std::move(parents);
output.back().name = std::move(name);
output.back().inputs = std::move(items_buffer);
}
}
if(currentSection != "default") {
// insert a section end which is just an empty items_buffer
std::string ename;
output.emplace_back();
output.back().parents = detail::generate_parents(currentSection, ename, parentSeparatorChar);
output.back().name = "--";
while(output.back().parents.size() > 1) {
output.push_back(output.back());
output.back().parents.pop_back();
}
}
return output;
}
inline std::string
ConfigBase::to_config(const App *app, bool default_also, bool write_description, std::string prefix) const {
std::stringstream out;
std::string commentLead;
commentLead.push_back(commentChar);
commentLead.push_back(' ');
std::vector<std::string> groups = app->get_groups();
bool defaultUsed = false;
groups.insert(groups.begin(), std::string("Options"));
if(write_description && (app->get_configurable() || app->get_parent() == nullptr || app->get_name().empty())) {
out << commentLead << detail::fix_newlines(commentLead, app->get_description()) << '\n';
}
for(auto &group : groups) {
if(group == "Options" || group.empty()) {
if(defaultUsed) {
continue;
}
defaultUsed = true;
}
if(write_description && group != "Options" && !group.empty()) {
out << '\n' << commentLead << group << " Options\n";
}
for(const Option *opt : app->get_options({})) {
// Only process options that are configurable
if(opt->get_configurable()) {
if(opt->get_group() != group) {
if(!(group == "Options" && opt->get_group().empty())) {
continue;
}
}
std::string name = prefix + opt->get_single_name();
std::string value = detail::ini_join(
opt->reduced_results(), arraySeparator, arrayStart, arrayEnd, stringQuote, characterQuote);
if(value.empty() && default_also) {
if(!opt->get_default_str().empty()) {
value = detail::convert_arg_for_ini(opt->get_default_str(), stringQuote, characterQuote);
} else if(opt->get_expected_min() == 0) {
value = "false";
} else if(opt->get_run_callback_for_default()) {
value = "\"\""; // empty string default value
}
}
if(!value.empty()) {
if(write_description && opt->has_description()) {
out << '\n';
out << commentLead << detail::fix_newlines(commentLead, opt->get_description()) << '\n';
}
out << name << valueDelimiter << value << '\n';
}
}
}
}
auto subcommands = app->get_subcommands({});
for(const App *subcom : subcommands) {
if(subcom->get_name().empty()) {
if(write_description && !subcom->get_group().empty()) {
out << '\n' << commentLead << subcom->get_group() << " Options\n";
}
out << to_config(subcom, default_also, write_description, prefix);
}
}
for(const App *subcom : subcommands) {
if(!subcom->get_name().empty()) {
if(subcom->get_configurable() && app->got_subcommand(subcom)) {
if(!prefix.empty() || app->get_parent() == nullptr) {
out << '[' << prefix << subcom->get_name() << "]\n";
} else {
std::string subname = app->get_name() + parentSeparatorChar + subcom->get_name();
auto p = app->get_parent();
while(p->get_parent() != nullptr) {
subname = p->get_name() + parentSeparatorChar + subname;
p = p->get_parent();
}
out << '[' << subname << "]\n";
}
out << to_config(subcom, default_also, write_description, "");
} else {
out << to_config(
subcom, default_also, write_description, prefix + subcom->get_name() + parentSeparatorChar);
}
}
}
return out.str();
}
// [CLI11:config_hpp:end]
} // namespace CLI

View File

@ -0,0 +1,182 @@
// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
// under NSF AWARD 1414736 and by the respective contributors.
// All rights reserved.
//
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
// [CLI11:public_includes:set]
#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
// [CLI11:public_includes:end]
#include "Error.hpp"
#include "StringTools.hpp"
namespace CLI {
// [CLI11:config_fwd_hpp:verbatim]
class App;
/// Holds values to load into Options
struct ConfigItem {
/// This is the list of parents
std::vector<std::string> parents{};
/// This is the name
std::string name{};
/// Listing of inputs
std::vector<std::string> inputs{};
/// The list of parents and name joined by "."
std::string fullname() const {
std::vector<std::string> tmp = parents;
tmp.emplace_back(name);
return detail::join(tmp, ".");
}
};
/// This class provides a converter for configuration files.
class Config {
protected:
std::vector<ConfigItem> items{};
public:
/// Convert an app into a configuration
virtual std::string to_config(const App *, bool, bool, std::string) const = 0;
/// Convert a configuration into an app
virtual std::vector<ConfigItem> from_config(std::istream &) const = 0;
/// Get a flag value
virtual std::string to_flag(const ConfigItem &item) const {
if(item.inputs.size() == 1) {
return item.inputs.at(0);
}
throw ConversionError::TooManyInputsFlag(item.fullname());
}
/// Parse a config file, throw an error (ParseError:ConfigParseError or FileError) on failure
std::vector<ConfigItem> from_file(const std::string &name) {
std::ifstream input{name};
if(!input.good())
throw FileError::Missing(name);
return from_config(input);
}
/// Virtual destructor
virtual ~Config() = default;
};
/// This converter works with INI/TOML files; to write INI files use ConfigINI
class ConfigBase : public Config {
protected:
/// the character used for comments
char commentChar = '#';
/// the character used to start an array '\0' is a default to not use
char arrayStart = '[';
/// the character used to end an array '\0' is a default to not use
char arrayEnd = ']';
/// the character used to separate elements in an array
char arraySeparator = ',';
/// the character used separate the name from the value
char valueDelimiter = '=';
/// the character to use around strings
char stringQuote = '"';
/// the character to use around single characters
char characterQuote = '\'';
/// the maximum number of layers to allow
uint8_t maximumLayers{255};
/// the separator used to separator parent layers
char parentSeparatorChar{'.'};
/// Specify the configuration index to use for arrayed sections
int16_t configIndex{-1};
/// Specify the configuration section that should be used
std::string configSection{};
public:
std::string
to_config(const App * /*app*/, bool default_also, bool write_description, std::string prefix) const override;
std::vector<ConfigItem> from_config(std::istream &input) const override;
/// Specify the configuration for comment characters
ConfigBase *comment(char cchar) {
commentChar = cchar;
return this;
}
/// Specify the start and end characters for an array
ConfigBase *arrayBounds(char aStart, char aEnd) {
arrayStart = aStart;
arrayEnd = aEnd;
return this;
}
/// Specify the delimiter character for an array
ConfigBase *arrayDelimiter(char aSep) {
arraySeparator = aSep;
return this;
}
/// Specify the delimiter between a name and value
ConfigBase *valueSeparator(char vSep) {
valueDelimiter = vSep;
return this;
}
/// Specify the quote characters used around strings and characters
ConfigBase *quoteCharacter(char qString, char qChar) {
stringQuote = qString;
characterQuote = qChar;
return this;
}
/// Specify the maximum number of parents
ConfigBase *maxLayers(uint8_t layers) {
maximumLayers = layers;
return this;
}
/// Specify the separator to use for parent layers
ConfigBase *parentSeparator(char sep) {
parentSeparatorChar = sep;
return this;
}
/// get a reference to the configuration section
std::string &sectionRef() { return configSection; }
/// get the section
const std::string &section() const { return configSection; }
/// specify a particular section of the configuration file to use
ConfigBase *section(const std::string &sectionName) {
configSection = sectionName;
return this;
}
/// get a reference to the configuration index
int16_t &indexRef() { return configIndex; }
/// get the section index
int16_t index() const { return configIndex; }
/// specify a particular index in the section to use (-1) for all sections to use
ConfigBase *index(int16_t sectionIndex) {
configIndex = sectionIndex;
return this;
}
};
/// the default Config is the TOML file format
using ConfigTOML = ConfigBase;
/// ConfigINI generates a "standard" INI compliant output
class ConfigINI : public ConfigTOML {
public:
ConfigINI() {
commentChar = ';';
arrayStart = '\0';
arrayEnd = '\0';
arraySeparator = ' ';
valueDelimiter = '=';
}
};
// [CLI11:config_fwd_hpp:end]
} // namespace CLI

View File

@ -0,0 +1,351 @@
// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
// under NSF AWARD 1414736 and by the respective contributors.
// All rights reserved.
//
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
// [CLI11:public_includes:set]
#include <exception>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>
// [CLI11:public_includes:end]
// CLI library includes
#include "StringTools.hpp"
namespace CLI {
// [CLI11:error_hpp:verbatim]
// Use one of these on all error classes.
// These are temporary and are undef'd at the end of this file.
#define CLI11_ERROR_DEF(parent, name) \
protected: \
name(std::string ename, std::string msg, int exit_code) : parent(std::move(ename), std::move(msg), exit_code) {} \
name(std::string ename, std::string msg, ExitCodes exit_code) \
: parent(std::move(ename), std::move(msg), exit_code) {} \
\
public: \
name(std::string msg, ExitCodes exit_code) : parent(#name, std::move(msg), exit_code) {} \
name(std::string msg, int exit_code) : parent(#name, std::move(msg), exit_code) {}
// This is added after the one above if a class is used directly and builds its own message
#define CLI11_ERROR_SIMPLE(name) \
explicit name(std::string msg) : name(#name, msg, ExitCodes::name) {}
/// These codes are part of every error in CLI. They can be obtained from e using e.exit_code or as a quick shortcut,
/// int values from e.get_error_code().
enum class ExitCodes {
Success = 0,
IncorrectConstruction = 100,
BadNameString,
OptionAlreadyAdded,
FileError,
ConversionError,
ValidationError,
RequiredError,
RequiresError,
ExcludesError,
ExtrasError,
ConfigError,
InvalidError,
HorribleError,
OptionNotFound,
ArgumentMismatch,
BaseClass = 127
};
// Error definitions
/// @defgroup error_group Errors
/// @brief Errors thrown by CLI11
///
/// These are the errors that can be thrown. Some of them, like CLI::Success, are not really errors.
/// @{
/// All errors derive from this one
class Error : public std::runtime_error {
int actual_exit_code;
std::string error_name{"Error"};
public:
int get_exit_code() const { return actual_exit_code; }
std::string get_name() const { return error_name; }
Error(std::string name, std::string msg, int exit_code = static_cast<int>(ExitCodes::BaseClass))
: runtime_error(msg), actual_exit_code(exit_code), error_name(std::move(name)) {}
Error(std::string name, std::string msg, ExitCodes exit_code) : Error(name, msg, static_cast<int>(exit_code)) {}
};
// Note: Using Error::Error constructors does not work on GCC 4.7
/// Construction errors (not in parsing)
class ConstructionError : public Error {
CLI11_ERROR_DEF(Error, ConstructionError)
};
/// Thrown when an option is set to conflicting values (non-vector and multi args, for example)
class IncorrectConstruction : public ConstructionError {
CLI11_ERROR_DEF(ConstructionError, IncorrectConstruction)
CLI11_ERROR_SIMPLE(IncorrectConstruction)
static IncorrectConstruction PositionalFlag(std::string name) {
return IncorrectConstruction(name + ": Flags cannot be positional");
}
static IncorrectConstruction Set0Opt(std::string name) {
return IncorrectConstruction(name + ": Cannot set 0 expected, use a flag instead");
}
static IncorrectConstruction SetFlag(std::string name) {
return IncorrectConstruction(name + ": Cannot set an expected number for flags");
}
static IncorrectConstruction ChangeNotVector(std::string name) {
return IncorrectConstruction(name + ": You can only change the expected arguments for vectors");
}
static IncorrectConstruction AfterMultiOpt(std::string name) {
return IncorrectConstruction(
name + ": You can't change expected arguments after you've changed the multi option policy!");
}
static IncorrectConstruction MissingOption(std::string name) {
return IncorrectConstruction("Option " + name + " is not defined");
}
static IncorrectConstruction MultiOptionPolicy(std::string name) {
return IncorrectConstruction(name + ": multi_option_policy only works for flags and exact value options");
}
};
/// Thrown on construction of a bad name
class BadNameString : public ConstructionError {
CLI11_ERROR_DEF(ConstructionError, BadNameString)
CLI11_ERROR_SIMPLE(BadNameString)
static BadNameString OneCharName(std::string name) { return BadNameString("Invalid one char name: " + name); }
static BadNameString BadLongName(std::string name) { return BadNameString("Bad long name: " + name); }
static BadNameString DashesOnly(std::string name) {
return BadNameString("Must have a name, not just dashes: " + name);
}
static BadNameString MultiPositionalNames(std::string name) {
return BadNameString("Only one positional name allowed, remove: " + name);
}
};
/// Thrown when an option already exists
class OptionAlreadyAdded : public ConstructionError {
CLI11_ERROR_DEF(ConstructionError, OptionAlreadyAdded)
explicit OptionAlreadyAdded(std::string name)
: OptionAlreadyAdded(name + " is already added", ExitCodes::OptionAlreadyAdded) {}
static OptionAlreadyAdded Requires(std::string name, std::string other) {
return OptionAlreadyAdded(name + " requires " + other, ExitCodes::OptionAlreadyAdded);
}
static OptionAlreadyAdded Excludes(std::string name, std::string other) {
return OptionAlreadyAdded(name + " excludes " + other, ExitCodes::OptionAlreadyAdded);
}
};
// Parsing errors
/// Anything that can error in Parse
class ParseError : public Error {
CLI11_ERROR_DEF(Error, ParseError)
};
// Not really "errors"
/// This is a successful completion on parsing, supposed to exit
class Success : public ParseError {
CLI11_ERROR_DEF(ParseError, Success)
Success() : Success("Successfully completed, should be caught and quit", ExitCodes::Success) {}
};
/// -h or --help on command line
class CallForHelp : public Success {
CLI11_ERROR_DEF(Success, CallForHelp)
CallForHelp() : CallForHelp("This should be caught in your main function, see examples", ExitCodes::Success) {}
};
/// Usually something like --help-all on command line
class CallForAllHelp : public Success {
CLI11_ERROR_DEF(Success, CallForAllHelp)
CallForAllHelp()
: CallForAllHelp("This should be caught in your main function, see examples", ExitCodes::Success) {}
};
/// -v or --version on command line
class CallForVersion : public Success {
CLI11_ERROR_DEF(Success, CallForVersion)
CallForVersion()
: CallForVersion("This should be caught in your main function, see examples", ExitCodes::Success) {}
};
/// Does not output a diagnostic in CLI11_PARSE, but allows main() to return with a specific error code.
class RuntimeError : public ParseError {
CLI11_ERROR_DEF(ParseError, RuntimeError)
explicit RuntimeError(int exit_code = 1) : RuntimeError("Runtime error", exit_code) {}
};
/// Thrown when parsing an INI file and it is missing
class FileError : public ParseError {
CLI11_ERROR_DEF(ParseError, FileError)
CLI11_ERROR_SIMPLE(FileError)
static FileError Missing(std::string name) { return FileError(name + " was not readable (missing?)"); }
};
/// Thrown when conversion call back fails, such as when an int fails to coerce to a string
class ConversionError : public ParseError {
CLI11_ERROR_DEF(ParseError, ConversionError)
CLI11_ERROR_SIMPLE(ConversionError)
ConversionError(std::string member, std::string name)
: ConversionError("The value " + member + " is not an allowed value for " + name) {}
ConversionError(std::string name, std::vector<std::string> results)
: ConversionError("Could not convert: " + name + " = " + detail::join(results)) {}
static ConversionError TooManyInputsFlag(std::string name) {
return ConversionError(name + ": too many inputs for a flag");
}
static ConversionError TrueFalse(std::string name) {
return ConversionError(name + ": Should be true/false or a number");
}
};
/// Thrown when validation of results fails
class ValidationError : public ParseError {
CLI11_ERROR_DEF(ParseError, ValidationError)
CLI11_ERROR_SIMPLE(ValidationError)
explicit ValidationError(std::string name, std::string msg) : ValidationError(name + ": " + msg) {}
};
/// Thrown when a required option is missing
class RequiredError : public ParseError {
CLI11_ERROR_DEF(ParseError, RequiredError)
explicit RequiredError(std::string name) : RequiredError(name + " is required", ExitCodes::RequiredError) {}
static RequiredError Subcommand(std::size_t min_subcom) {
if(min_subcom == 1) {
return RequiredError("A subcommand");
}
return RequiredError("Requires at least " + std::to_string(min_subcom) + " subcommands",
ExitCodes::RequiredError);
}
static RequiredError
Option(std::size_t min_option, std::size_t max_option, std::size_t used, const std::string &option_list) {
if((min_option == 1) && (max_option == 1) && (used == 0))
return RequiredError("Exactly 1 option from [" + option_list + "]");
if((min_option == 1) && (max_option == 1) && (used > 1)) {
return RequiredError("Exactly 1 option from [" + option_list + "] is required and " + std::to_string(used) +
" were given",
ExitCodes::RequiredError);
}
if((min_option == 1) && (used == 0))
return RequiredError("At least 1 option from [" + option_list + "]");
if(used < min_option) {
return RequiredError("Requires at least " + std::to_string(min_option) + " options used and only " +
std::to_string(used) + "were given from [" + option_list + "]",
ExitCodes::RequiredError);
}
if(max_option == 1)
return RequiredError("Requires at most 1 options be given from [" + option_list + "]",
ExitCodes::RequiredError);
return RequiredError("Requires at most " + std::to_string(max_option) + " options be used and " +
std::to_string(used) + "were given from [" + option_list + "]",
ExitCodes::RequiredError);
}
};
/// Thrown when the wrong number of arguments has been received
class ArgumentMismatch : public ParseError {
CLI11_ERROR_DEF(ParseError, ArgumentMismatch)
CLI11_ERROR_SIMPLE(ArgumentMismatch)
ArgumentMismatch(std::string name, int expected, std::size_t received)
: ArgumentMismatch(expected > 0 ? ("Expected exactly " + std::to_string(expected) + " arguments to " + name +
", got " + std::to_string(received))
: ("Expected at least " + std::to_string(-expected) + " arguments to " + name +
", got " + std::to_string(received)),
ExitCodes::ArgumentMismatch) {}
static ArgumentMismatch AtLeast(std::string name, int num, std::size_t received) {
return ArgumentMismatch(name + ": At least " + std::to_string(num) + " required but received " +
std::to_string(received));
}
static ArgumentMismatch AtMost(std::string name, int num, std::size_t received) {
return ArgumentMismatch(name + ": At Most " + std::to_string(num) + " required but received " +
std::to_string(received));
}
static ArgumentMismatch TypedAtLeast(std::string name, int num, std::string type) {
return ArgumentMismatch(name + ": " + std::to_string(num) + " required " + type + " missing");
}
static ArgumentMismatch FlagOverride(std::string name) {
return ArgumentMismatch(name + " was given a disallowed flag override");
}
};
/// Thrown when a requires option is missing
class RequiresError : public ParseError {
CLI11_ERROR_DEF(ParseError, RequiresError)
RequiresError(std::string curname, std::string subname)
: RequiresError(curname + " requires " + subname, ExitCodes::RequiresError) {}
};
/// Thrown when an excludes option is present
class ExcludesError : public ParseError {
CLI11_ERROR_DEF(ParseError, ExcludesError)
ExcludesError(std::string curname, std::string subname)
: ExcludesError(curname + " excludes " + subname, ExitCodes::ExcludesError) {}
};
/// Thrown when too many positionals or options are found
class ExtrasError : public ParseError {
CLI11_ERROR_DEF(ParseError, ExtrasError)
explicit ExtrasError(std::vector<std::string> args)
: ExtrasError((args.size() > 1 ? "The following arguments were not expected: "
: "The following argument was not expected: ") +
detail::rjoin(args, " "),
ExitCodes::ExtrasError) {}
ExtrasError(const std::string &name, std::vector<std::string> args)
: ExtrasError(name,
(args.size() > 1 ? "The following arguments were not expected: "
: "The following argument was not expected: ") +
detail::rjoin(args, " "),
ExitCodes::ExtrasError) {}
};
/// Thrown when extra values are found in an INI file
class ConfigError : public ParseError {
CLI11_ERROR_DEF(ParseError, ConfigError)
CLI11_ERROR_SIMPLE(ConfigError)
static ConfigError Extras(std::string item) { return ConfigError("INI was not able to parse " + item); }
static ConfigError NotConfigurable(std::string item) {
return ConfigError(item + ": This option is not allowed in a configuration file");
}
};
/// Thrown when validation fails before parsing
class InvalidError : public ParseError {
CLI11_ERROR_DEF(ParseError, InvalidError)
explicit InvalidError(std::string name)
: InvalidError(name + ": Too many positional arguments with unlimited expected args", ExitCodes::InvalidError) {
}
};
/// This is just a safety check to verify selection and parsing match - you should not ever see it
/// Strings are directly added to this error, but again, it should never be seen.
class HorribleError : public ParseError {
CLI11_ERROR_DEF(ParseError, HorribleError)
CLI11_ERROR_SIMPLE(HorribleError)
};
// After parsing
/// Thrown when counting a non-existent option
class OptionNotFound : public Error {
CLI11_ERROR_DEF(Error, OptionNotFound)
explicit OptionNotFound(std::string name) : OptionNotFound(name + " not found", ExitCodes::OptionNotFound) {}
};
#undef CLI11_ERROR_DEF
#undef CLI11_ERROR_SIMPLE
/// @}
// [CLI11:error_hpp:end]
} // namespace CLI

View File

@ -0,0 +1,292 @@
// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
// under NSF AWARD 1414736 and by the respective contributors.
// All rights reserved.
//
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
// [CLI11:public_includes:set]
#include <algorithm>
#include <string>
#include <vector>
// [CLI11:public_includes:end]
#include "App.hpp"
#include "FormatterFwd.hpp"
namespace CLI {
// [CLI11:formatter_hpp:verbatim]
inline std::string
Formatter::make_group(std::string group, bool is_positional, std::vector<const Option *> opts) const {
std::stringstream out;
out << "\n" << group << ":\n";
for(const Option *opt : opts) {
out << make_option(opt, is_positional);
}
return out.str();
}
inline std::string Formatter::make_positionals(const App *app) const {
std::vector<const Option *> opts =
app->get_options([](const Option *opt) { return !opt->get_group().empty() && opt->get_positional(); });
if(opts.empty())
return std::string();
return make_group(get_label("Positionals"), true, opts);
}
inline std::string Formatter::make_groups(const App *app, AppFormatMode mode) const {
std::stringstream out;
std::vector<std::string> groups = app->get_groups();
// Options
for(const std::string &group : groups) {
std::vector<const Option *> opts = app->get_options([app, mode, &group](const Option *opt) {
return opt->get_group() == group // Must be in the right group
&& opt->nonpositional() // Must not be a positional
&& (mode != AppFormatMode::Sub // If mode is Sub, then
|| (app->get_help_ptr() != opt // Ignore help pointer
&& app->get_help_all_ptr() != opt)); // Ignore help all pointer
});
if(!group.empty() && !opts.empty()) {
out << make_group(group, false, opts);
if(group != groups.back())
out << "\n";
}
}
return out.str();
}
inline std::string Formatter::make_description(const App *app) const {
std::string desc = app->get_description();
auto min_options = app->get_require_option_min();
auto max_options = app->get_require_option_max();
if(app->get_required()) {
desc += " REQUIRED ";
}
if((max_options == min_options) && (min_options > 0)) {
if(min_options == 1) {
desc += " \n[Exactly 1 of the following options is required]";
} else {
desc += " \n[Exactly " + std::to_string(min_options) + "options from the following list are required]";
}
} else if(max_options > 0) {
if(min_options > 0) {
desc += " \n[Between " + std::to_string(min_options) + " and " + std::to_string(max_options) +
" of the follow options are required]";
} else {
desc += " \n[At most " + std::to_string(max_options) + " of the following options are allowed]";
}
} else if(min_options > 0) {
desc += " \n[At least " + std::to_string(min_options) + " of the following options are required]";
}
return (!desc.empty()) ? desc + "\n" : std::string{};
}
inline std::string Formatter::make_usage(const App *app, std::string name) const {
std::stringstream out;
out << get_label("Usage") << ":" << (name.empty() ? "" : " ") << name;
std::vector<std::string> groups = app->get_groups();
// Print an Options badge if any options exist
std::vector<const Option *> non_pos_options =
app->get_options([](const Option *opt) { return opt->nonpositional(); });
if(!non_pos_options.empty())
out << " [" << get_label("OPTIONS") << "]";
// Positionals need to be listed here
std::vector<const Option *> positionals = app->get_options([](const Option *opt) { return opt->get_positional(); });
// Print out positionals if any are left
if(!positionals.empty()) {
// Convert to help names
std::vector<std::string> positional_names(positionals.size());
std::transform(positionals.begin(), positionals.end(), positional_names.begin(), [this](const Option *opt) {
return make_option_usage(opt);
});
out << " " << detail::join(positional_names, " ");
}
// Add a marker if subcommands are expected or optional
if(!app->get_subcommands(
[](const CLI::App *subc) { return ((!subc->get_disabled()) && (!subc->get_name().empty())); })
.empty()) {
out << " " << (app->get_require_subcommand_min() == 0 ? "[" : "")
<< get_label(app->get_require_subcommand_max() < 2 || app->get_require_subcommand_min() > 1 ? "SUBCOMMAND"
: "SUBCOMMANDS")
<< (app->get_require_subcommand_min() == 0 ? "]" : "");
}
out << std::endl;
return out.str();
}
inline std::string Formatter::make_footer(const App *app) const {
std::string footer = app->get_footer();
if(footer.empty()) {
return std::string{};
}
return footer + "\n";
}
inline std::string Formatter::make_help(const App *app, std::string name, AppFormatMode mode) const {
// This immediately forwards to the make_expanded method. This is done this way so that subcommands can
// have overridden formatters
if(mode == AppFormatMode::Sub)
return make_expanded(app);
std::stringstream out;
if((app->get_name().empty()) && (app->get_parent() != nullptr)) {
if(app->get_group() != "Subcommands") {
out << app->get_group() << ':';
}
}
out << make_description(app);
out << make_usage(app, name);
out << make_positionals(app);
out << make_groups(app, mode);
out << make_subcommands(app, mode);
out << '\n' << make_footer(app);
return out.str();
}
inline std::string Formatter::make_subcommands(const App *app, AppFormatMode mode) const {
std::stringstream out;
std::vector<const App *> subcommands = app->get_subcommands({});
// Make a list in definition order of the groups seen
std::vector<std::string> subcmd_groups_seen;
for(const App *com : subcommands) {
if(com->get_name().empty()) {
if(!com->get_group().empty()) {
out << make_expanded(com);
}
continue;
}
std::string group_key = com->get_group();
if(!group_key.empty() &&
std::find_if(subcmd_groups_seen.begin(), subcmd_groups_seen.end(), [&group_key](std::string a) {
return detail::to_lower(a) == detail::to_lower(group_key);
}) == subcmd_groups_seen.end())
subcmd_groups_seen.push_back(group_key);
}
// For each group, filter out and print subcommands
for(const std::string &group : subcmd_groups_seen) {
out << "\n" << group << ":\n";
std::vector<const App *> subcommands_group = app->get_subcommands(
[&group](const App *sub_app) { return detail::to_lower(sub_app->get_group()) == detail::to_lower(group); });
for(const App *new_com : subcommands_group) {
if(new_com->get_name().empty())
continue;
if(mode != AppFormatMode::All) {
out << make_subcommand(new_com);
} else {
out << new_com->help(new_com->get_name(), AppFormatMode::Sub);
out << "\n";
}
}
}
return out.str();
}
inline std::string Formatter::make_subcommand(const App *sub) const {
std::stringstream out;
detail::format_help(out, sub->get_display_name(true), sub->get_description(), column_width_);
return out.str();
}
inline std::string Formatter::make_expanded(const App *sub) const {
std::stringstream out;
out << sub->get_display_name(true) << "\n";
out << make_description(sub);
if(sub->get_name().empty() && !sub->get_aliases().empty()) {
detail::format_aliases(out, sub->get_aliases(), column_width_ + 2);
}
out << make_positionals(sub);
out << make_groups(sub, AppFormatMode::Sub);
out << make_subcommands(sub, AppFormatMode::Sub);
// Drop blank spaces
std::string tmp = detail::find_and_replace(out.str(), "\n\n", "\n");
tmp = tmp.substr(0, tmp.size() - 1); // Remove the final '\n'
// Indent all but the first line (the name)
return detail::find_and_replace(tmp, "\n", "\n ") + "\n";
}
inline std::string Formatter::make_option_name(const Option *opt, bool is_positional) const {
if(is_positional)
return opt->get_name(true, false);
return opt->get_name(false, true);
}
inline std::string Formatter::make_option_opts(const Option *opt) const {
std::stringstream out;
if(!opt->get_option_text().empty()) {
out << " " << opt->get_option_text();
} else {
if(opt->get_type_size() != 0) {
if(!opt->get_type_name().empty())
out << " " << get_label(opt->get_type_name());
if(!opt->get_default_str().empty())
out << "=" << opt->get_default_str();
if(opt->get_expected_max() == detail::expected_max_vector_size)
out << " ...";
else if(opt->get_expected_min() > 1)
out << " x " << opt->get_expected();
if(opt->get_required())
out << " " << get_label("REQUIRED");
}
if(!opt->get_envname().empty())
out << " (" << get_label("Env") << ":" << opt->get_envname() << ")";
if(!opt->get_needs().empty()) {
out << " " << get_label("Needs") << ":";
for(const Option *op : opt->get_needs())
out << " " << op->get_name();
}
if(!opt->get_excludes().empty()) {
out << " " << get_label("Excludes") << ":";
for(const Option *op : opt->get_excludes())
out << " " << op->get_name();
}
}
return out.str();
}
inline std::string Formatter::make_option_desc(const Option *opt) const { return opt->get_description(); }
inline std::string Formatter::make_option_usage(const Option *opt) const {
// Note that these are positionals usages
std::stringstream out;
out << make_option_name(opt, true);
if(opt->get_expected_max() >= detail::expected_max_vector_size)
out << "...";
else if(opt->get_expected_max() > 1)
out << "(" << opt->get_expected() << "x)";
return opt->get_required() ? out.str() : "[" + out.str() + "]";
}
// [CLI11:formatter_hpp:end]
} // namespace CLI

View File

@ -0,0 +1,184 @@
// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
// under NSF AWARD 1414736 and by the respective contributors.
// All rights reserved.
//
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
// [CLI11:public_includes:set]
#include <map>
#include <string>
#include <utility>
#include <vector>
// [CLI11:public_includes:end]
#include "StringTools.hpp"
namespace CLI {
// [CLI11:formatter_fwd_hpp:verbatim]
class Option;
class App;
/// This enum signifies the type of help requested
///
/// This is passed in by App; all user classes must accept this as
/// the second argument.
enum class AppFormatMode {
Normal, ///< The normal, detailed help
All, ///< A fully expanded help
Sub, ///< Used when printed as part of expanded subcommand
};
/// This is the minimum requirements to run a formatter.
///
/// A user can subclass this is if they do not care at all
/// about the structure in CLI::Formatter.
class FormatterBase {
protected:
/// @name Options
///@{
/// The width of the first column
std::size_t column_width_{30};
/// @brief The required help printout labels (user changeable)
/// Values are Needs, Excludes, etc.
std::map<std::string, std::string> labels_{};
///@}
/// @name Basic
///@{
public:
FormatterBase() = default;
FormatterBase(const FormatterBase &) = default;
FormatterBase(FormatterBase &&) = default;
/// Adding a destructor in this form to work around bug in GCC 4.7
virtual ~FormatterBase() noexcept {} // NOLINT(modernize-use-equals-default)
/// This is the key method that puts together help
virtual std::string make_help(const App *, std::string, AppFormatMode) const = 0;
///@}
/// @name Setters
///@{
/// Set the "REQUIRED" label
void label(std::string key, std::string val) { labels_[key] = val; }
/// Set the column width
void column_width(std::size_t val) { column_width_ = val; }
///@}
/// @name Getters
///@{
/// Get the current value of a name (REQUIRED, etc.)
std::string get_label(std::string key) const {
if(labels_.find(key) == labels_.end())
return key;
else
return labels_.at(key);
}
/// Get the current column width
std::size_t get_column_width() const { return column_width_; }
///@}
};
/// This is a specialty override for lambda functions
class FormatterLambda final : public FormatterBase {
using funct_t = std::function<std::string(const App *, std::string, AppFormatMode)>;
/// The lambda to hold and run
funct_t lambda_;
public:
/// Create a FormatterLambda with a lambda function
explicit FormatterLambda(funct_t funct) : lambda_(std::move(funct)) {}
/// Adding a destructor (mostly to make GCC 4.7 happy)
~FormatterLambda() noexcept override {} // NOLINT(modernize-use-equals-default)
/// This will simply call the lambda function
std::string make_help(const App *app, std::string name, AppFormatMode mode) const override {
return lambda_(app, name, mode);
}
};
/// This is the default Formatter for CLI11. It pretty prints help output, and is broken into quite a few
/// overridable methods, to be highly customizable with minimal effort.
class Formatter : public FormatterBase {
public:
Formatter() = default;
Formatter(const Formatter &) = default;
Formatter(Formatter &&) = default;
/// @name Overridables
///@{
/// This prints out a group of options with title
///
virtual std::string make_group(std::string group, bool is_positional, std::vector<const Option *> opts) const;
/// This prints out just the positionals "group"
virtual std::string make_positionals(const App *app) const;
/// This prints out all the groups of options
std::string make_groups(const App *app, AppFormatMode mode) const;
/// This prints out all the subcommands
virtual std::string make_subcommands(const App *app, AppFormatMode mode) const;
/// This prints out a subcommand
virtual std::string make_subcommand(const App *sub) const;
/// This prints out a subcommand in help-all
virtual std::string make_expanded(const App *sub) const;
/// This prints out all the groups of options
virtual std::string make_footer(const App *app) const;
/// This displays the description line
virtual std::string make_description(const App *app) const;
/// This displays the usage line
virtual std::string make_usage(const App *app, std::string name) const;
/// This puts everything together
std::string make_help(const App * /*app*/, std::string, AppFormatMode) const override;
///@}
/// @name Options
///@{
/// This prints out an option help line, either positional or optional form
virtual std::string make_option(const Option *opt, bool is_positional) const {
std::stringstream out;
detail::format_help(
out, make_option_name(opt, is_positional) + make_option_opts(opt), make_option_desc(opt), column_width_);
return out.str();
}
/// @brief This is the name part of an option, Default: left column
virtual std::string make_option_name(const Option *, bool) const;
/// @brief This is the options part of the name, Default: combined into left column
virtual std::string make_option_opts(const Option *) const;
/// @brief This is the description. Default: Right column, on new line if left column too large
virtual std::string make_option_desc(const Option *) const;
/// @brief This is used to print the name on the USAGE line
virtual std::string make_option_usage(const Option *opt) const;
///@}
};
// [CLI11:formatter_fwd_hpp:end]
} // namespace CLI

View File

@ -0,0 +1,25 @@
CLI11 1.8 Copyright (c) 2017-2019 University of Cincinnati, developed by Henry
Schreiner under NSF AWARD 1414736. All rights reserved.
Redistribution and use in source and binary forms of CLI11, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,44 @@
// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
// under NSF AWARD 1414736 and by the respective contributors.
// All rights reserved.
//
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
// [CLI11:macros_hpp:verbatim]
// The following version macro is very similar to the one in pybind11
#if !(defined(_MSC_VER) && __cplusplus == 199711L) && !defined(__INTEL_COMPILER)
#if __cplusplus >= 201402L
#define CLI11_CPP14
#if __cplusplus >= 201703L
#define CLI11_CPP17
#if __cplusplus > 201703L
#define CLI11_CPP20
#endif
#endif
#endif
#elif defined(_MSC_VER) && __cplusplus == 199711L
// MSVC sets _MSVC_LANG rather than __cplusplus (supposedly until the standard is fully implemented)
// Unless you use the /Zc:__cplusplus flag on Visual Studio 2017 15.7 Preview 3 or newer
#if _MSVC_LANG >= 201402L
#define CLI11_CPP14
#if _MSVC_LANG > 201402L && _MSC_VER >= 1910
#define CLI11_CPP17
#if __MSVC_LANG > 201703L && _MSC_VER >= 1910
#define CLI11_CPP20
#endif
#endif
#endif
#endif
#if defined(CLI11_CPP14)
#define CLI11_DEPRECATED(reason) [[deprecated(reason)]]
#elif defined(_MSC_VER)
#define CLI11_DEPRECATED(reason) __declspec(deprecated(reason))
#else
#define CLI11_DEPRECATED(reason) __attribute__((deprecated(reason)))
#endif
// [CLI11:macros_hpp:end]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,143 @@
// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
// under NSF AWARD 1414736 and by the respective contributors.
// All rights reserved.
//
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
// [CLI11:public_includes:set]
#include <string>
#include <tuple>
#include <utility>
#include <vector>
// [CLI11:public_includes:end]
#include "Error.hpp"
#include "StringTools.hpp"
namespace CLI {
// [CLI11:split_hpp:verbatim]
namespace detail {
// Returns false if not a short option. Otherwise, sets opt name and rest and returns true
inline bool split_short(const std::string &current, std::string &name, std::string &rest) {
if(current.size() > 1 && current[0] == '-' && valid_first_char(current[1])) {
name = current.substr(1, 1);
rest = current.substr(2);
return true;
}
return false;
}
// Returns false if not a long option. Otherwise, sets opt name and other side of = and returns true
inline bool split_long(const std::string &current, std::string &name, std::string &value) {
if(current.size() > 2 && current.substr(0, 2) == "--" && valid_first_char(current[2])) {
auto loc = current.find_first_of('=');
if(loc != std::string::npos) {
name = current.substr(2, loc - 2);
value = current.substr(loc + 1);
} else {
name = current.substr(2);
value = "";
}
return true;
}
return false;
}
// Returns false if not a windows style option. Otherwise, sets opt name and value and returns true
inline bool split_windows_style(const std::string &current, std::string &name, std::string &value) {
if(current.size() > 1 && current[0] == '/' && valid_first_char(current[1])) {
auto loc = current.find_first_of(':');
if(loc != std::string::npos) {
name = current.substr(1, loc - 1);
value = current.substr(loc + 1);
} else {
name = current.substr(1);
value = "";
}
return true;
}
return false;
}
// Splits a string into multiple long and short names
inline std::vector<std::string> split_names(std::string current) {
std::vector<std::string> output;
std::size_t val;
while((val = current.find(",")) != std::string::npos) {
output.push_back(trim_copy(current.substr(0, val)));
current = current.substr(val + 1);
}
output.push_back(trim_copy(current));
return output;
}
/// extract default flag values either {def} or starting with a !
inline std::vector<std::pair<std::string, std::string>> get_default_flag_values(const std::string &str) {
std::vector<std::string> flags = split_names(str);
flags.erase(std::remove_if(flags.begin(),
flags.end(),
[](const std::string &name) {
return ((name.empty()) || (!(((name.find_first_of('{') != std::string::npos) &&
(name.back() == '}')) ||
(name[0] == '!'))));
}),
flags.end());
std::vector<std::pair<std::string, std::string>> output;
output.reserve(flags.size());
for(auto &flag : flags) {
auto def_start = flag.find_first_of('{');
std::string defval = "false";
if((def_start != std::string::npos) && (flag.back() == '}')) {
defval = flag.substr(def_start + 1);
defval.pop_back();
flag.erase(def_start, std::string::npos);
}
flag.erase(0, flag.find_first_not_of("-!"));
output.emplace_back(flag, defval);
}
return output;
}
/// Get a vector of short names, one of long names, and a single name
inline std::tuple<std::vector<std::string>, std::vector<std::string>, std::string>
get_names(const std::vector<std::string> &input) {
std::vector<std::string> short_names;
std::vector<std::string> long_names;
std::string pos_name;
for(std::string name : input) {
if(name.length() == 0) {
continue;
}
if(name.length() > 1 && name[0] == '-' && name[1] != '-') {
if(name.length() == 2 && valid_first_char(name[1]))
short_names.emplace_back(1, name[1]);
else
throw BadNameString::OneCharName(name);
} else if(name.length() > 2 && name.substr(0, 2) == "--") {
name = name.substr(2);
if(valid_name_string(name))
long_names.push_back(name);
else
throw BadNameString::BadLongName(name);
} else if(name == "-" || name == "--") {
throw BadNameString::DashesOnly(name);
} else {
if(pos_name.length() > 0)
throw BadNameString::MultiPositionalNames(name);
pos_name = name;
}
}
return std::tuple<std::vector<std::string>, std::vector<std::string>, std::string>(
short_names, long_names, pos_name);
}
} // namespace detail
// [CLI11:split_hpp:end]
} // namespace CLI

View File

@ -0,0 +1,430 @@
// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
// under NSF AWARD 1414736 and by the respective contributors.
// All rights reserved.
//
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
// [CLI11:public_includes:set]
#include <algorithm>
#include <iomanip>
#include <locale>
#include <sstream>
#include <stdexcept>
#include <string>
#include <type_traits>
#include <vector>
// [CLI11:public_includes:end]
namespace CLI {
// [CLI11:string_tools_hpp:verbatim]
/// Include the items in this namespace to get free conversion of enums to/from streams.
/// (This is available inside CLI as well, so CLI11 will use this without a using statement).
namespace enums {
/// output streaming for enumerations
template <typename T, typename = typename std::enable_if<std::is_enum<T>::value>::type>
std::ostream &operator<<(std::ostream &in, const T &item) {
// make sure this is out of the detail namespace otherwise it won't be found when needed
return in << static_cast<typename std::underlying_type<T>::type>(item);
}
} // namespace enums
/// Export to CLI namespace
using enums::operator<<;
namespace detail {
/// a constant defining an expected max vector size defined to be a big number that could be multiplied by 4 and not
/// produce overflow for some expected uses
constexpr int expected_max_vector_size{1 << 29};
// Based on http://stackoverflow.com/questions/236129/split-a-string-in-c
/// Split a string by a delim
inline std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems;
// Check to see if empty string, give consistent result
if(s.empty()) {
elems.emplace_back();
} else {
std::stringstream ss;
ss.str(s);
std::string item;
while(std::getline(ss, item, delim)) {
elems.push_back(item);
}
}
return elems;
}
/// Simple function to join a string
template <typename T> std::string join(const T &v, std::string delim = ",") {
std::ostringstream s;
auto beg = std::begin(v);
auto end = std::end(v);
if(beg != end)
s << *beg++;
while(beg != end) {
s << delim << *beg++;
}
return s.str();
}
/// Simple function to join a string from processed elements
template <typename T,
typename Callable,
typename = typename std::enable_if<!std::is_constructible<std::string, Callable>::value>::type>
std::string join(const T &v, Callable func, std::string delim = ",") {
std::ostringstream s;
auto beg = std::begin(v);
auto end = std::end(v);
auto loc = s.tellp();
while(beg != end) {
auto nloc = s.tellp();
if(nloc > loc) {
s << delim;
loc = nloc;
}
s << func(*beg++);
}
return s.str();
}
/// Join a string in reverse order
template <typename T> std::string rjoin(const T &v, std::string delim = ",") {
std::ostringstream s;
for(std::size_t start = 0; start < v.size(); start++) {
if(start > 0)
s << delim;
s << v[v.size() - start - 1];
}
return s.str();
}
// Based roughly on http://stackoverflow.com/questions/25829143/c-trim-whitespace-from-a-string
/// Trim whitespace from left of string
inline std::string &ltrim(std::string &str) {
auto it = std::find_if(str.begin(), str.end(), [](char ch) { return !std::isspace<char>(ch, std::locale()); });
str.erase(str.begin(), it);
return str;
}
/// Trim anything from left of string
inline std::string &ltrim(std::string &str, const std::string &filter) {
auto it = std::find_if(str.begin(), str.end(), [&filter](char ch) { return filter.find(ch) == std::string::npos; });
str.erase(str.begin(), it);
return str;
}
/// Trim whitespace from right of string
inline std::string &rtrim(std::string &str) {
auto it = std::find_if(str.rbegin(), str.rend(), [](char ch) { return !std::isspace<char>(ch, std::locale()); });
str.erase(it.base(), str.end());
return str;
}
/// Trim anything from right of string
inline std::string &rtrim(std::string &str, const std::string &filter) {
auto it =
std::find_if(str.rbegin(), str.rend(), [&filter](char ch) { return filter.find(ch) == std::string::npos; });
str.erase(it.base(), str.end());
return str;
}
/// Trim whitespace from string
inline std::string &trim(std::string &str) { return ltrim(rtrim(str)); }
/// Trim anything from string
inline std::string &trim(std::string &str, const std::string filter) { return ltrim(rtrim(str, filter), filter); }
/// Make a copy of the string and then trim it
inline std::string trim_copy(const std::string &str) {
std::string s = str;
return trim(s);
}
/// remove quotes at the front and back of a string either '"' or '\''
inline std::string &remove_quotes(std::string &str) {
if(str.length() > 1 && (str.front() == '"' || str.front() == '\'')) {
if(str.front() == str.back()) {
str.pop_back();
str.erase(str.begin(), str.begin() + 1);
}
}
return str;
}
/// Add a leader to the beginning of all new lines (nothing is added
/// at the start of the first line). `"; "` would be for ini files
///
/// Can't use Regex, or this would be a subs.
inline std::string fix_newlines(const std::string &leader, std::string input) {
std::string::size_type n = 0;
while(n != std::string::npos && n < input.size()) {
n = input.find('\n', n);
if(n != std::string::npos) {
input = input.substr(0, n + 1) + leader + input.substr(n + 1);
n += leader.size();
}
}
return input;
}
/// Make a copy of the string and then trim it, any filter string can be used (any char in string is filtered)
inline std::string trim_copy(const std::string &str, const std::string &filter) {
std::string s = str;
return trim(s, filter);
}
/// Print a two part "help" string
inline std::ostream &format_help(std::ostream &out, std::string name, const std::string &description, std::size_t wid) {
name = " " + name;
out << std::setw(static_cast<int>(wid)) << std::left << name;
if(!description.empty()) {
if(name.length() >= wid)
out << "\n" << std::setw(static_cast<int>(wid)) << "";
for(const char c : description) {
out.put(c);
if(c == '\n') {
out << std::setw(static_cast<int>(wid)) << "";
}
}
}
out << "\n";
return out;
}
/// Print subcommand aliases
inline std::ostream &format_aliases(std::ostream &out, const std::vector<std::string> &aliases, std::size_t wid) {
if(!aliases.empty()) {
out << std::setw(static_cast<int>(wid)) << " aliases: ";
bool front = true;
for(const auto &alias : aliases) {
if(!front) {
out << ", ";
} else {
front = false;
}
out << detail::fix_newlines(" ", alias);
}
out << "\n";
}
return out;
}
/// Verify the first character of an option
/// - is a trigger character, ! has special meaning and new lines would just be annoying to deal with
template <typename T> bool valid_first_char(T c) { return ((c != '-') && (c != '!') && (c != ' ') && c != '\n'); }
/// Verify following characters of an option
template <typename T> bool valid_later_char(T c) {
// = and : are value separators, { has special meaning for option defaults,
// and \n would just be annoying to deal with in many places allowing space here has too much potential for
// inadvertent entry errors and bugs
return ((c != '=') && (c != ':') && (c != '{') && (c != ' ') && c != '\n');
}
/// Verify an option/subcommand name
inline bool valid_name_string(const std::string &str) {
if(str.empty() || !valid_first_char(str[0])) {
return false;
}
auto e = str.end();
for(auto c = str.begin() + 1; c != e; ++c)
if(!valid_later_char(*c))
return false;
return true;
}
/// Verify an app name
inline bool valid_alias_name_string(const std::string &str) {
static const std::string badChars(std::string("\n") + '\0');
return (str.find_first_of(badChars) == std::string::npos);
}
/// check if a string is a container segment separator (empty or "%%")
inline bool is_separator(const std::string &str) {
static const std::string sep("%%");
return (str.empty() || str == sep);
}
/// Verify that str consists of letters only
inline bool isalpha(const std::string &str) {
return std::all_of(str.begin(), str.end(), [](char c) { return std::isalpha(c, std::locale()); });
}
/// Return a lower case version of a string
inline std::string to_lower(std::string str) {
std::transform(std::begin(str), std::end(str), std::begin(str), [](const std::string::value_type &x) {
return std::tolower(x, std::locale());
});
return str;
}
/// remove underscores from a string
inline std::string remove_underscore(std::string str) {
str.erase(std::remove(std::begin(str), std::end(str), '_'), std::end(str));
return str;
}
/// Find and replace a substring with another substring
inline std::string find_and_replace(std::string str, std::string from, std::string to) {
std::size_t start_pos = 0;
while((start_pos = str.find(from, start_pos)) != std::string::npos) {
str.replace(start_pos, from.length(), to);
start_pos += to.length();
}
return str;
}
/// check if the flag definitions has possible false flags
inline bool has_default_flag_values(const std::string &flags) {
return (flags.find_first_of("{!") != std::string::npos);
}
inline void remove_default_flag_values(std::string &flags) {
auto loc = flags.find_first_of('{', 2);
while(loc != std::string::npos) {
auto finish = flags.find_first_of("},", loc + 1);
if((finish != std::string::npos) && (flags[finish] == '}')) {
flags.erase(flags.begin() + static_cast<std::ptrdiff_t>(loc),
flags.begin() + static_cast<std::ptrdiff_t>(finish) + 1);
}
loc = flags.find_first_of('{', loc + 1);
}
flags.erase(std::remove(flags.begin(), flags.end(), '!'), flags.end());
}
/// Check if a string is a member of a list of strings and optionally ignore case or ignore underscores
inline std::ptrdiff_t find_member(std::string name,
const std::vector<std::string> names,
bool ignore_case = false,
bool ignore_underscore = false) {
auto it = std::end(names);
if(ignore_case) {
if(ignore_underscore) {
name = detail::to_lower(detail::remove_underscore(name));
it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {
return detail::to_lower(detail::remove_underscore(local_name)) == name;
});
} else {
name = detail::to_lower(name);
it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {
return detail::to_lower(local_name) == name;
});
}
} else if(ignore_underscore) {
name = detail::remove_underscore(name);
it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {
return detail::remove_underscore(local_name) == name;
});
} else {
it = std::find(std::begin(names), std::end(names), name);
}
return (it != std::end(names)) ? (it - std::begin(names)) : (-1);
}
/// Find a trigger string and call a modify callable function that takes the current string and starting position of the
/// trigger and returns the position in the string to search for the next trigger string
template <typename Callable> inline std::string find_and_modify(std::string str, std::string trigger, Callable modify) {
std::size_t start_pos = 0;
while((start_pos = str.find(trigger, start_pos)) != std::string::npos) {
start_pos = modify(str, start_pos);
}
return str;
}
/// Split a string '"one two" "three"' into 'one two', 'three'
/// Quote characters can be ` ' or "
inline std::vector<std::string> split_up(std::string str, char delimiter = '\0') {
const std::string delims("\'\"`");
auto find_ws = [delimiter](char ch) {
return (delimiter == '\0') ? (std::isspace<char>(ch, std::locale()) != 0) : (ch == delimiter);
};
trim(str);
std::vector<std::string> output;
bool embeddedQuote = false;
char keyChar = ' ';
while(!str.empty()) {
if(delims.find_first_of(str[0]) != std::string::npos) {
keyChar = str[0];
auto end = str.find_first_of(keyChar, 1);
while((end != std::string::npos) && (str[end - 1] == '\\')) { // deal with escaped quotes
end = str.find_first_of(keyChar, end + 1);
embeddedQuote = true;
}
if(end != std::string::npos) {
output.push_back(str.substr(1, end - 1));
if(end + 2 < str.size()) {
str = str.substr(end + 2);
} else {
str.clear();
}
} else {
output.push_back(str.substr(1));
str = "";
}
} else {
auto it = std::find_if(std::begin(str), std::end(str), find_ws);
if(it != std::end(str)) {
std::string value = std::string(str.begin(), it);
output.push_back(value);
str = std::string(it + 1, str.end());
} else {
output.push_back(str);
str = "";
}
}
// transform any embedded quotes into the regular character
if(embeddedQuote) {
output.back() = find_and_replace(output.back(), std::string("\\") + keyChar, std::string(1, keyChar));
embeddedQuote = false;
}
trim(str);
}
return output;
}
/// This function detects an equal or colon followed by an escaped quote after an argument
/// then modifies the string to replace the equality with a space. This is needed
/// to allow the split up function to work properly and is intended to be used with the find_and_modify function
/// the return value is the offset+1 which is required by the find_and_modify function.
inline std::size_t escape_detect(std::string &str, std::size_t offset) {
auto next = str[offset + 1];
if((next == '\"') || (next == '\'') || (next == '`')) {
auto astart = str.find_last_of("-/ \"\'`", offset - 1);
if(astart != std::string::npos) {
if(str[astart] == ((str[offset] == '=') ? '-' : '/'))
str[offset] = ' '; // interpret this as a space so the split_up works properly
}
}
return offset + 1;
}
/// Add quotes if the string contains spaces
inline std::string &add_quotes_if_needed(std::string &str) {
if((str.front() != '"' && str.front() != '\'') || str.front() != str.back()) {
char quote = str.find('"') < str.find('\'') ? '\'' : '"';
if(str.find(' ') != std::string::npos) {
str.insert(0, 1, quote);
str.append(1, quote);
}
}
return str;
}
} // namespace detail
// [CLI11:string_tools_hpp:end]
} // namespace CLI

View File

@ -0,0 +1,134 @@
// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
// under NSF AWARD 1414736 and by the respective contributors.
// All rights reserved.
//
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
// On GCC < 4.8, the following define is often missing. Due to the
// fact that this library only uses sleep_for, this should be safe
#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5 && __GNUC_MINOR__ < 8
#define _GLIBCXX_USE_NANOSLEEP
#endif
#include <array>
#include <chrono>
#include <functional>
#include <iostream>
#include <string>
#include <utility>
namespace CLI {
/// This is a simple timer with pretty printing. Creating the timer starts counting.
class Timer {
protected:
/// This is a typedef to make clocks easier to use
using clock = std::chrono::steady_clock;
/// This typedef is for points in time
using time_point = std::chrono::time_point<clock>;
/// This is the type of a printing function, you can make your own
using time_print_t = std::function<std::string(std::string, std::string)>;
/// This is the title of the timer
std::string title_;
/// This is the function that is used to format most of the timing message
time_print_t time_print_;
/// This is the starting point (when the timer was created)
time_point start_;
/// This is the number of times cycles (print divides by this number)
std::size_t cycles{1};
public:
/// Standard print function, this one is set by default
static std::string Simple(std::string title, std::string time) { return title + ": " + time; }
/// This is a fancy print function with --- headers
static std::string Big(std::string title, std::string time) {
return std::string("-----------------------------------------\n") + "| " + title + " | Time = " + time + "\n" +
"-----------------------------------------";
}
public:
/// Standard constructor, can set title and print function
explicit Timer(std::string title = "Timer", time_print_t time_print = Simple)
: title_(std::move(title)), time_print_(std::move(time_print)), start_(clock::now()) {}
/// Time a function by running it multiple times. Target time is the len to target.
std::string time_it(std::function<void()> f, double target_time = 1) {
time_point start = start_;
double total_time;
start_ = clock::now();
std::size_t n = 0;
do {
f();
std::chrono::duration<double> elapsed = clock::now() - start_;
total_time = elapsed.count();
} while(n++ < 100u && total_time < target_time);
std::string out = make_time_str(total_time / static_cast<double>(n)) + " for " + std::to_string(n) + " tries";
start_ = start;
return out;
}
/// This formats the numerical value for the time string
std::string make_time_str() const {
time_point stop = clock::now();
std::chrono::duration<double> elapsed = stop - start_;
double time = elapsed.count() / static_cast<double>(cycles);
return make_time_str(time);
}
// LCOV_EXCL_START
/// This prints out a time string from a time
std::string make_time_str(double time) const {
auto print_it = [](double x, std::string unit) {
const unsigned int buffer_length = 50;
std::array<char, buffer_length> buffer;
std::snprintf(buffer.data(), buffer_length, "%.5g", x);
return buffer.data() + std::string(" ") + unit;
};
if(time < .000001)
return print_it(time * 1000000000, "ns");
else if(time < .001)
return print_it(time * 1000000, "us");
else if(time < 1)
return print_it(time * 1000, "ms");
else
return print_it(time, "s");
}
// LCOV_EXCL_STOP
/// This is the main function, it creates a string
std::string to_string() const { return time_print_(title_, make_time_str()); }
/// Division sets the number of cycles to divide by (no graphical change)
Timer &operator/(std::size_t val) {
cycles = val;
return *this;
}
};
/// This class prints out the time upon destruction
class AutoTimer : public Timer {
public:
/// Reimplementing the constructor is required in GCC 4.7
explicit AutoTimer(std::string title = "Timer", time_print_t time_print = Simple) : Timer(title, time_print) {}
// GCC 4.7 does not support using inheriting constructors.
/// This destructor prints the string
~AutoTimer() { std::cout << to_string() << std::endl; }
};
} // namespace CLI
/// This prints out the time if shifted into a std::cout like stream.
inline std::ostream &operator<<(std::ostream &in, const CLI::Timer &timer) { return in << timer.to_string(); }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
// under NSF AWARD 1414736 and by the respective contributors.
// All rights reserved.
//
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
// [CLI11:version_hpp:verbatim]
#define CLI11_VERSION_MAJOR 2
#define CLI11_VERSION_MINOR 1
#define CLI11_VERSION_PATCH 1
#define CLI11_VERSION "2.1.1"
// [CLI11:version_hpp:end]

View File

@ -0,0 +1,63 @@
/*------------------------------- 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 "commandLine.H"
pFlow::commandLine::commandLine(word appName)
:
CLI::App(description),
appName_(appName)
{
CLI::App::set_help_flag("-h,--help", "Help for using "+appName_+ " of "+versionName);
CLI::App::set_version_flag("-v,--version", versionName, "Program version information");
}
pFlow::commandLine::commandLine(word appName, word disptn)
:
commandLine(appName)
{
CLI::App::add_flag_callback(
"--discription",
[disptn, appName]() {
output<<"\n"<<yellowText(versoinCopyright)<<endl<<endl;
output<<"Discription for "<< boldText(appName)<<":\n";
output<<" "<<disptn<<endl;
},
"What does this app do?"
)->configurable(false);
}
bool pFlow::commandLine::parse(
int argc,
char** argv)
{
try {
CLI::App::parse(argc, argv);
if(CLI::App::count("--discription")) return false;
return true;
} catch(const ParseError &e) {
CLI::App::exit(e);
return false;
}
//if()
}

View File

@ -0,0 +1,140 @@
/*------------------------------- 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 __commandLine_H__
#define __commandLine_H__
#include <any>
#include "CLI.hpp"
#include "types.H"
#include "Lists.H"
#include "streams.H"
namespace pFlow
{
class commandLine
:
public CLI::App
{
public:
using Option = CLI::Option;
using ParseError = CLI::ParseError;
using any = std::any;
protected:
word appName_;
List<any> internalBinVars_;
inline static word versionStr = "v-"+
int322Word(phasicFlow_VERSION_MAJOR)+
"."+
int322Word(phasicFlow_VERSION_MINOR);
inline static word copyRight = "(copyright(C): www.cemf.ir)";
inline static word versionName = "phasicFlow "+ versionStr;
inline static word versoinCopyright = versionName + " " +copyRight;
inline static word description = "Command line help for "+
versoinCopyright +"\n";
public:
commandLine(word appName);
commandLine(word appName, word disptn);
bool parse(int argc, char** argv);
template<typename Type>
Option* addOption(
word optionName,
word description,
word opText = "");
template<typename Type>
Option* addOption(
word optionName,
Type& bindingVar,
word description,
word opText = "");
};
}// pFlow
template<typename Type>
pFlow::commandLine::Option*
pFlow::commandLine::addOption(
word optionName,
word description,
word opText)
{
try{
Type& bindingVar = std::any_cast<Type&>(
internalBinVars_.emplace_back( any(Type()))
);
return CLI::App::add_option(optionName, bindingVar, description)->option_text(opText);
}
catch (ParseError& err){
fatalExit;
return nullptr;
}
}
template<typename Type>
pFlow::commandLine::Option*
pFlow::commandLine::addOption(
word optionName,
Type& bindingVar,
word description,
word opText)
{
try{
return CLI::App::add_option(optionName, bindingVar, description)->option_text(opText);
}
catch (ParseError& err){
fatalExit;
return nullptr;
}
}
#endif

View File

@ -0,0 +1,170 @@
/*------------------------------- 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<template<class, class> class VectorField, class T, class PropType>
bool pFlow::Field<VectorField, T, PropType>::readUniform
(
iIstream& is,
size_t len,
bool readLength
)
{
size_t flen = 0;
if( readLength )
{
is>>flen;
if(is.bad() || is.eof() )
{
ioErrorInFile( is.name(), is.lineNumber() ) <<
"expected integer value to specify field length \n";
return false;
}
}
else
{
flen = len;
}
// create a vector with one element and read it in
T bF;
is >> bF;
VectorType::assign(flen, bF);
// read end statement char ;
is.readEndStatement("readField");
return true;
}
template<template<class, class> class VectorField, class T, class PropType>
bool pFlow::Field<VectorField, T, PropType>::readNonUniform
(
iIstream& is,
size_t len
)
{
size_t flen = 0;
is >> flen;
if(is.bad() || is.eof() )
{
ioErrorInFile( is.name(), is.lineNumber() ) <<
" expected integer value to specify field length \n";
return false;
}
if( len!=0 && flen != len )
{
ioErrorInFile( is.name(), is.lineNumber() ) <<
" expected "<< len <<" as the field length but found "<< flen <<" \n";
return false;
}
this->clear();
VectorType::read(is);
is.readEndStatement("readField");
if( this->size() != flen )
{
ioErrorInFile( is.name(), is.lineNumber() ) <<
" expected " << flen << " elements, but supplied "<<
this->size() << " elements in file "<< is.name() <<endl;
return false;
}
return true;
}
template<template<class, class> class VectorField, class T, class PropType>
bool pFlow::Field<VectorField, T, PropType>::readField
(
iIstream& is,
const size_t len,
bool readLength
)
{
if( !is.findToken(fieldKey_) )
{
ioErrorInFile( is.name(), is.lineNumber() ) <<
" error in searching for filedkey " << fieldKey_<<endl;
return false;
}
word fieldU;
is >> fieldU;
if(is.bad() || is.eof())
{
ioErrorInFile( is.name(), is.lineNumber()) <<
" error in reading keyword from file.";
return false;
}
if( fieldU == uniform__ )
{
return readUniform(is, len, readLength);
}
else if( fieldU == nonUniform__ )
{
return readNonUniform(is, len);
}
else
{
ioErrorInFile( is.name(), is.lineNumber() ) <<
"unknown keyword, expected uniform/nonUniform, but found " <<
fieldU << endl;
return false;
}
return true;
}
template<template<class, class> class VectorField, class T, class PropType>
bool pFlow::Field<VectorField, T, PropType>::readField
(
iIstream& is
)
{
return readField(is, 0, true);
}
template<template<class, class> class VectorField, class T, class PropType>
bool pFlow::Field<VectorField, T, PropType>::writeField(iOstream& os)const
{
os.writeWordKeyword(fieldKey_) << nonUniform__<<endl;
os<< this->size()<<endl;
VectorType::write(os);
os.endEntry();
return true;
}

View File

@ -0,0 +1,270 @@
/*------------------------------- 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 __Field_H__
#define __Field_H__
#include "VectorSingle.H"
#include "vocabs.H"
namespace pFlow
{
template<template<class, class> class VectorField, class T, class PropType=void>
class Field
:
public VectorField<T, PropType>
{
public:
using VectorType = VectorField<T,PropType>;
using FieldType = Field<VectorField, T, PropType>;
using iterator = typename VectorType::iterator;
using constIterator = typename VectorType::constIterator;
using reference = typename VectorType::reference;
using constReference = typename VectorType::constReference;
using valueType = typename VectorType::valueType;
using pointer = typename VectorType::pointer;
using constPointer = typename VectorType::constPointer;
protected:
static const inline word FKey = "value";
const word fieldKey_ = FKey;
bool readUniform( iIstream& is, size_t len, bool readLength = true);
bool readNonUniform( iIstream& is, size_t len);
public:
// - type info
TypeNameTemplateNV2("Field", T, VectorType::memoerySpaceName());
//// - Constructors
// construct an empty Filed with default fieldKey
Field()
:
VectorType()
{}
// construct an empty Field with fieldKey
Field(const word& fieldKey)
:
VectorType(),
fieldKey_(fieldKey)
{}
// construct an empty field with name and fieldKey
Field(const word& name, const word& fieldKey)
:
VectorType(name),
fieldKey_(fieldKey)
{}
// construct an empty Filed with default fieldKey
Field(size_t len)
:
VectorType(len)
{}
// construct an empty Field with fieldKey
Field(const word& fieldKey, size_t len)
:
VectorType(len),
fieldKey_(fieldKey)
{}
// construct an empty field with name and fieldKey
Field(const word& name, const word& fieldKey, size_t len)
:
VectorType(name, len),
fieldKey_(fieldKey)
{}
// construct an empty Filed with default fieldKey and set vector to val
Field(size_t len, const T& val)
:
VectorType(len, val)
{}
// construct an empty Field with fieldKey and set vector to val
Field(const word& fieldKey, size_t len, const T& val)
:
VectorType(len, val),
fieldKey_(fieldKey)
{}
// construct an empty field with name and fieldKey and set vector to val
Field(const word& name, const word& fieldKey, size_t len, const T& val)
:
VectorType(name, len, val),
fieldKey_(fieldKey)
{}
// construct a field with capacity and len and default fieldKey
Field(size_t capacity, size_t len, RESERVE)
:
VectorType(capacity, len, RESERVE())
{}
// construct an empty Field with fieldKey
Field(const word& fieldKey, size_t capacity, size_t len, RESERVE)
:
VectorType(capacity, len, RESERVE()),
fieldKey_(fieldKey)
{}
// construct an empty field with name and fieldKey
Field(const word& name, const word& fieldKey, size_t capacity, size_t len, RESERVE)
:
VectorType(name, capacity, len, RESERVE()),
fieldKey_(fieldKey)
{}
// construct with vec and default fieldKey
Field(const Vector<T>& vec)
:
VectorType(vec)
{}
// construct an empty Field with fieldKey
Field(const word& fieldKey, const Vector<T>& vec)
:
VectorType(vec),
fieldKey_(fieldKey)
{}
// construct an empty field with name and fieldKey
Field(const word& name, const word& fieldKey, const Vector<T>& vec)
:
VectorType(name, vec),
fieldKey_(fieldKey)
{}
// - copy construct with new name and fieldkey
Field(const word& name, const word& fieldKey, const FieldType& src):
VectorType(name, src),
fieldKey_(fieldKey)
{}
// - default copy constructor
Field(const FieldType&) = default;
// - default copy assignment
FieldType& operator = (const FieldType&) = default;
// - no move constructor
Field(FieldType&&) = delete;
// - no move assignment
FieldType& operator = (FieldType&&) = delete;
// - clone as a uniquePtr
INLINE_FUNCTION_H
uniquePtr<FieldType> clone() const
{
return makeUnique<FieldType>(*this);
}
// - clone as a raw pointer
INLINE_FUNCTION_H
FieldType* clonePtr()const
{
return new FieldType(*this);
}
//// - Methods
const word& fieldKey()const
{
return fieldKey_;
}
//// - IO operations
bool readField(iIstream& is, const size_t len, bool readLength = true);
bool readField(iIstream& is );
bool writeField(iOstream& os)const;
bool read(iIstream& is)
{
return readField(is);
}
bool write(iOstream& os)const
{
return writeField(os);
}
};
template<template<class, class> class VectorField, class T, class PropType>
inline iIstream& operator >> (iIstream & is, Field<VectorField, T, PropType> & ifld )
{
if( !ifld.readField(is) )
{
ioErrorInFile (is.name(), is.lineNumber());
fatalExit;
}
return is;
}
template<template<class, class> class VectorField, class T, class PropType>
inline iOstream& operator << (iOstream& os, const Field<VectorField, T, PropType>& ofld )
{
if( !ofld.writeField(os) )
{
ioErrorInFile(os.name(), os.lineNumber());
fatalExit;
}
return os;
}
}
#include "Field.C"
#endif //__Field_H__

View File

@ -0,0 +1,81 @@
/*------------------------------- 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 "Fields.H"
template class pFlow::Field<pFlow::VectorSingle, pFlow::int8>;
template class pFlow::Field<pFlow::VectorSingle, pFlow::int8, pFlow::HostSpace>;
template class pFlow::Field<pFlow::VectorSingle, pFlow::int16>;
template class pFlow::Field<pFlow::VectorSingle, pFlow::int16, pFlow::HostSpace>;
template class pFlow::Field<pFlow::VectorSingle, pFlow::int32>;
template class pFlow::Field<pFlow::VectorSingle, pFlow::int32, pFlow::HostSpace>;
template class pFlow::Field<pFlow::VectorSingle, pFlow::int64>;
template class pFlow::Field<pFlow::VectorSingle, pFlow::int64, pFlow::HostSpace>;
template class pFlow::Field<pFlow::VectorSingle, pFlow::uint32>;
template class pFlow::Field<pFlow::VectorSingle, pFlow::uint32, pFlow::HostSpace>;
template class pFlow::Field<pFlow::VectorSingle, pFlow::label>;
template class pFlow::Field<pFlow::VectorSingle, pFlow::label, pFlow::HostSpace>;
template class pFlow::Field<pFlow::VectorSingle, pFlow::real>;
template class pFlow::Field<pFlow::VectorSingle, pFlow::real, pFlow::HostSpace>;
template class pFlow::Field<pFlow::VectorSingle, pFlow::realx3>;
template class pFlow::Field<pFlow::VectorSingle, pFlow::realx3, pFlow::HostSpace>;
template class pFlow::Field<pFlow::VectorSingle, pFlow::realx3x3>;
template class pFlow::Field<pFlow::VectorSingle, pFlow::realx3x3, pFlow::HostSpace>;
template class pFlow::Field<pFlow::VectorDual, pFlow::int8>;
template class pFlow::Field<pFlow::VectorDual, pFlow::int16>;
template class pFlow::Field<pFlow::VectorDual, pFlow::int32>;
template class pFlow::Field<pFlow::VectorDual, pFlow::int64>;
template class pFlow::Field<pFlow::VectorDual, pFlow::uint32>;
template class pFlow::Field<pFlow::VectorDual, pFlow::label>;
template class pFlow::Field<pFlow::VectorDual, pFlow::real>;
template class pFlow::Field<pFlow::VectorDual, pFlow::realx3>;
template class pFlow::Field<pFlow::VectorDual, pFlow::realx3x3>;
template class pFlow::Field<pFlow::Vector, pFlow::word, pFlow::vecAllocator<pFlow::word>>;

View File

@ -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 __Fields_H__
#define __Fields_H__
#include "types.H"
#include "Field.H"
#include "VectorSingle.H"
#include "VectorDual.H"
namespace pFlow
{
using int8Field_D = Field<VectorSingle, int8>;
using int8Field_H = Field<VectorSingle, int8, HostSpace>;
using int16Field_D = Field<VectorSingle, int16>;
using int16Field_H = Field<VectorSingle, int16, HostSpace>;
using int32Field_D = Field<VectorSingle, int32>;
using int32Field_H = Field<VectorSingle, int32, HostSpace>;
using int64Field_D = Field<VectorSingle, int64>;
using int64Field_H = Field<VectorSingle, int64, HostSpace>;
using uint32Field_D = Field<VectorSingle, uint32>;
using uint32Field_H = Field<VectorSingle, uint32, HostSpace>;
using labelField_D = Field<VectorSingle, label>;
using labelField_H = Field<VectorSingle, label, HostSpace> ;
using realField_D = Field<VectorSingle, real>;
using realField_H = Field<VectorSingle, real, HostSpace> ;
using realx3Field_D = Field<VectorSingle, realx3>;
using realx3Field_H = Field<VectorSingle, realx3, HostSpace>;
using uint16x3Field_D = Field<VectorSingle, uint16x3>;
using uint16x3Field_H = Field<VectorSingle, uint16x3, HostSpace>;
using uint32x3Field_D = Field<VectorSingle, uint32x3>;
using uint32x3Field_H = Field<VectorSingle, uint32x3, HostSpace>;
using int32x3Field_D = Field<VectorSingle, int32x3>;
using int32x3Field_H = Field<VectorSingle, int32x3, HostSpace>;
using int64x3Field_D = Field<VectorSingle, int64x3>;
using int64x3Field_H = Field<VectorSingle, int64x3, HostSpace>;
using realx3x3Field_D = Field<VectorSingle, realx3x3>;
using realx3x3Field_H = Field<VectorSingle, realx3x3, HostSpace>;
// - no typedef on device (since word does not compile on CUDA)
using wordField_H = Field<VectorSingle, word, HostSpace>;
// host device fields
using int8Field_HD = Field<VectorDual, int8>;
using int16Field_HD = Field<VectorDual, int16>;
using int32Field_HD = Field<VectorDual, int32>;
using int64Field_HD = Field<VectorDual, int64>;
using uint32Field_HD = Field<VectorDual, uint32>;
using labelField_HD = Field<VectorDual, label>;
using realField_HD = Field<VectorDual, real>;
using realx3Field_HD = Field<VectorDual, realx3>;
using uint16x3Field_HD = Field<VectorDual, uint32x3>;
using uint32x3Field_HD = Field<VectorDual, uint32x3>;
using int32x3Field_HD = Field<VectorDual, int32x3>;
using int64x3Field_HD = Field<VectorDual, int64x3>;
using realx3x3Field_HD = Field<VectorDual, realx3x3>;
using wordField = Field<Vector, word , vecAllocator<word>>;
}
#endif //__Fields_H__

View File

@ -0,0 +1,250 @@
/*------------------------------- 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 __List_H__
#define __List_H__
#include <list>
#include "types.H"
#include "typeInfo.H"
#include "uniquePtr.H"
#include "iOstream.H"
#include "iIstream.H"
namespace pFlow
{
template<
typename T
> class List
:
public std::list<T, std::allocator<T> >
{
public:
using ListType = List<T>;
using listType = std::list<T,std::allocator<T>>;
using iterator = typename listType::iterator;
using constIterator = typename listType::const_iterator;
using reference = typename listType::reference;
using constReference= typename listType::const_reference;
using initList = typename std::initializer_list<T>;
using valueType = T;
protected:
// position of ith element
auto pos(size_t i);
// position of ith element
const auto pos(size_t i)const;
static inline size_t getListStride(const size_t& len)
{
size_t stride = 1;
if( len < 6 )
stride = len;
else if( len <16 )
stride = 3;
else if( len < 31)
stride = 2;
else
stride = 1;
return stride;
}
public:
// - Type info
TypeNameTemplateNV("List", T);
//// - Constructors
// - empty list
List()
{}
// - list with length len
List(size_t len)
:
listType(len)
{}
// - list with length len and value
List(size_t len, const T& value)
:
listType(len, value)
{}
// - construct from initList
List(initList lst)
:
listType(lst)
{}
// - copy construct
List(const List& src):
listType(src)
{}
// - move construct
List( List && mv)
:
listType(std::move(mv))
{}
// - copy assignment
ListType& operator=(const ListType& rhs)
{
listType::operator=(rhs);
return *this;
}
// - move assignment
ListType& operator=(ListType&& rhs)
{
listType::operator=(std::move(rhs));
return *this;
}
uniquePtr<ListType> clone()const{
return makeUnique<ListType>(*this);
}
ListType* clonePtr()const{
return new ListType(*this);
}
// - destructor
~List()
{
listType::clear();
}
//// - Methods
// - counts elements based on a given value
int32 countElement(const T& elm) const;
// - size of container
size_t size()const;
// - access to ith element
// fatal exit if out of range
T& operator[](size_t i);
// - const access to ith element
// fatal exit if our of range
const T& operator[](size_t i)const;
// - find the position of the first element with value val
// cend() if not found
constIterator find(const T& val) const;
// - find the position of the first element with value val
// end() if not found
iterator find(const T& val);
// - find the index of the first element with value val
// -1 if not found
int32 findi(const T& val) const;
// - search for element, if finds it,
// return true, otherwise false
bool search(const T& val) const;
// - set ith element with copy
// fatal error if out of range
void set(size_t i, const T& val);
// - set ith element with move operation
// fatal error if out of range
void set(size_t i, T&& val);
//// - IO operations
// - write to oStream
bool writeList(iOstream& os) const;
// - read from iStream
bool readList(iIstream& is);
bool read(iIstream& is)
{
return readList(is);
}
bool write(iOstream& os)const
{
return writeList(os);
}
};
template<typename T>
iOstream& operator << (iOstream& os, const List<T>& lst );
template<typename T>
iIstream& operator >>(iIstream& is, List<T>& lst);
using int64List = List<int64>;
using int32List = List<int32>;
using int16List = List<int16>;
using int8List = List<int8>;
using labelList = List<label>;
using uint32List = List<uint32>;
using realList = List<real>;
using realx3List = List<realx3>;
using realx3x3List = List<realx3x3>;
using boolList = List<bool>;
using wordList = List<word>;
} // pFlow
#include "ListI.H"
#endif //__List_H__

View File

@ -0,0 +1,257 @@
/*------------------------------- 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<typename T>
auto pFlow::List<T>::pos
(
size_t i
)
{
if( i >= size() )
{
fatalErrorInFunction<<
"our of range access to list element. \n";
fatalExit;
}
auto iter = listType::begin();
std::advance(iter, i);
return iter;
}
template<typename T>
const auto pFlow::List<T>::pos
(
size_t i
)const
{
if( i >= size() )
{
fatalErrorInFunction<<
"our of range access to list element. \n";
fatalExit;
}
auto iter = listType::cbegin();
std::advance(iter, i);
return iter;
}
template<typename T>
inline pFlow::int32 pFlow::List<T>::countElement
(
const T& elm
) const
{
return std::count( listType::begin(), listType::end(), elm);
}
template<typename T>
inline size_t pFlow::List<T>::size()const
{
return listType::size();
}
template<typename T>
inline T& pFlow::List<T>::operator[]
(
size_t i
)
{
return *pos(i);
}
template<typename T>
inline const T& pFlow::List<T>::operator[]
(
size_t i
)const
{
return *pos(i);
}
template<typename T>
inline typename pFlow::List<T>::constIterator pFlow::List<T>::find
(
const T& val
) const
{
return std::find(this->begin(),this->end(), val);
}
template<typename T>
inline typename pFlow::List<T>::iterator pFlow::List<T>::find
(
const T& val
)
{
return std::find(this->begin(),this->end(), val);
}
template<typename T>
pFlow::int32 pFlow::List<T>::findi(const T& val) const
{
auto pos = find(val);
if( pos == this->end() )return -1;
return static_cast<int32> (std::distance(this->begin(), pos));
}
template<typename T>
bool pFlow::List<T>::search
(
const T& val
) const
{
if( find(val) == this->end())return false;
return true;
}
template<typename T>
inline void pFlow::List<T>::set(size_t i, const T& val)
{
auto p = pos(i);
*p = val;
}
template<typename T>
inline void pFlow::List<T>::set(size_t i, T&& val)
{
auto p = pos(i);
*p = std::move(val);
}
template<typename T>
inline bool pFlow::List<T>::writeList
(
iOstream& os
) const
{
size_t len = size();
size_t stride = getListStride(len);
// start of List
os << beginListToken();
for(auto elm = listType::begin(); elm!=listType::end(); )
{
os<< *elm++;
for(size_t j=0; j<stride && elm!=listType::end(); j++)
{
os<<spaceToken()<< *elm++;
}
if( elm!=listType::end() )
os<<newLineToken();
}
os<< endListToken();
//os.check(FUNCTION_NAME);
return os.check(FUNCTION_NAME);
}
template<typename T>
inline bool pFlow::List<T>::readList
(
iIstream& is
)
{
// first clear the list
listType::clear();
is.fatalCheck(FUNCTION_NAME);
token firstToken(is);
if( firstToken.isPunctuation() ) // start of list
{
if(firstToken != beginListToken() )
{
ioErrorInFile(is.name(), is.lineNumber())
<< "expected token "<< token::BEGIN_LIST
<< " but found "<< firstToken ;
return false;
}
token lastToken(is);
is.fatalCheck(FUNCTION_NAME);
while
( !(
lastToken.isPunctuation()
&& lastToken == token::END_LIST
)
)
{
is.putBack(lastToken);
T val;
is >> val;
listType::push_back(val);
is >> lastToken;
is.fatalCheck(FUNCTION_NAME);
}
}
else
{
ioErrorInFile(is.name(), is.lineNumber())
<< "expected token "<< beginListToken()
<< " but found "<< firstToken ;
return false;
}
return is.fatalCheck(FUNCTION_NAME);
}
template<typename T>
inline pFlow::iOstream& pFlow::operator << (iOstream& os, const List<T>& lst )
{
if(!lst.writeList(os))
{
fatalExit;
}
return os;
}
template<typename T>
inline pFlow::iIstream& pFlow::operator >>(iIstream& is, List<T>& lst)
{
if( !lst.readList(is) )
{
fatalExit;
}
return is;
}

View File

@ -0,0 +1,197 @@
/*------------------------------- 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 __ListPtr_H__
#define __ListPtr_H__
#include <list>
#include "types.H"
#include "uniquePtr.H"
#include "error.H"
#include "iOstream.H"
namespace pFlow
{
template<typename T >
class ListPtr
{
public:
using ListPtrType = ListPtr<T> ;
using listType = std::list<T*>;
template<typename... Args>
inline static uniquePtr<T> makeSafe(Args&&... args)
{
return uniquePtr<T>(new T(std::forward<Args>(args)...));
}
protected:
//// - data members
// - list of pointers
std::list<T*> list_;
//// - Methods
// - copy the content to this list
bool copy(const ListPtrType& src);
// - return ith pointer
T* ptr(label i);
// - return ith const poiter
const T* ptr(label i)const;
// - iterator position of ith element
auto pos(label i);
// - const iterator position of ith element
auto pos(label i) const;
public:
// - Type info
TypeNameTemplateNV("ListPtr", T);
//// - Contructors
// - empty list
ListPtr()
:
list_()
{}
// - a list with initial length of len
ListPtr(size_t len)
:
list_(len)
{}
// - copy construct, create new objects out of the pointers in the src
ListPtr(const ListPtrType& src);
//- copy assignment, create new objects out of he pointers in the src
ListPtrType& operator=(const ListPtrType& rhs);
// - move construct
// Simply move the pointers, so the new object takes the
// ownership of the pointers.
ListPtr( ListPtrType&& src )
:
list_(std::move(src))
{}
// - move assignment
// the lhs object takes the ownership of pointers and rhs loses the ownership
ListPtrType& operator=(ListPtrType&& rhs)
{
// clears the content of this
clear();
list_.operator=(std::move(rhs));
return *this;
}
ListPtrType* clonePtr()const
{
auto ptr = makeUnique<ListPtrType>(*this);
return ptr.release();
}
uniquePtr<ListPtrType> clone()const
{
return makeUnique<ListPtrType>(*this);
}
// - remove /delete all the objectes associated with pointers
~ListPtr()
{
clear();
}
//// - Methods
// - set the ith element
T* set(label i, T* ptr);
// - set the ith element and take the ownership from uniquePtr
uniquePtr<T> set(label i, uniquePtr<T>& ptr );
// - create the object in-place and set the pointer in ith position
// if oject creation fails, uniquePtr deletes the memeory
template<typename... Args>
uniquePtr<T> setSafe(label i, Args&&... args);
// - put the pointer at the end
void push_back(T* ptr);
// - put the pointer at the end
void push_back(uniquePtr<T>& ptr);
// - safely create (in-place) and put the pointer at the end
template<typename... Args>
void push_backSafe(Args&&... args);
// - access to ith element
// fatalexit if out of range or nullptr
T& operator[](label i);
// - const access to ith element
// fatalexit if out of range or nullptr
const T& operator[](label i) const;
// size of container
size_t size()const;
// check if the container empty
auto empty() const;
// release the ownership of ith pointer
uniquePtr<T> release(label i);
// - clear the content of list and delete objects
void clear();
// - clear the ith element
void clear(label i);
// - clone the object
};
} // pFlow
#include "ListPtrI.H"
#endif

View File

@ -0,0 +1,301 @@
/*------------------------------- 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<typename T>
inline bool pFlow::ListPtr<T>::copy(const ListPtrType& src)
{
for( auto& iter : src.list_)
{
if( iter != nullptr)
{
push_back( iter->clone().release());
}
else
{
push_back(nullptr);
}
}
return true;
}
template<typename T>
T* pFlow::ListPtr<T>::ptr(label i)
{
if(i >= size() ) return nullptr;
auto iter = list_.begin();
std::advance(iter, i);
return *iter;
}
template<typename T>
const T* pFlow::ListPtr<T>::ptr
(
label i
) const
{
if(i >= size() ) return nullptr;
auto iter = list_.cbegin();
std::advance(iter, i);
return *iter;
}
template<typename T>
auto pFlow::ListPtr<T>::pos
(
label i
)
{
if(i >= size() )
{
fatalErrorInFunction<<
"out of range access to container element. \n";
fatalExit;
}
auto iter = list_.begin();
std::advance(iter, i);
return iter;
}
template<typename T>
auto pFlow::ListPtr<T>::pos
(
label i
)const
{
if(i >= size() )
{
fatalErrorInFunction<<
"out of range access to container element. \n";
fatalExit;
}
auto iter = list_.cbegin();
std::advance(iter, i);
return iter;
}
template<typename T>
pFlow::ListPtr<T>::ListPtr
(
const ListPtrType& src
)
{
if( !copy(src) )
{
fatalErrorInFunction<<
"cannot copy new item into ListPtr \n" <<
"ListPtr type is "<< typeid(T).name() <<endl;
fatalExit;
}
}
template<typename T>
pFlow::ListPtr<T>& pFlow::ListPtr<T>::operator=
(
const ListPtrType& rhs
)
{
if (this == &rhs)
{
return *this; // Self-assignment
}
// clears the content of this
clear();
if( !copy(rhs) )
{
fatalErrorInFunction<<
"cannot perform assignment from rhs into MapPtr \n" <<
"MapPtr type is "<< typeid(T).name() <<endl;
fatalExit;
}
return *this;
}
template<typename T>
T* pFlow::ListPtr<T>::set
(
label i, T* ptr
)
{
uniquePtr<T> uptr(ptr);
return set(i, uptr);
}
template<typename T>
pFlow::uniquePtr<T> pFlow::ListPtr<T>::set
(
label i,
uniquePtr<T>& ptr
)
{
if( i > size() )
{
fatalErrorInFunction<<
"Out of range access of list members. PtrList size is "<<
size() << "and you are accessing "<< i << "\n";
fatalExit;
}
auto iter = list_.begin();
std::advance(iter, i);
auto oldIter = iter;
*iter = ptr.release();
return *oldIter;
}
template<typename T>
template<typename... Args>
pFlow::uniquePtr<T> pFlow::ListPtr<T>::setSafe
(
label i,
Args&&... args
)
{
auto ptr(uniquePtr<T>::makeUnique(std::forward<Args>(args)...) );
return set(i,ptr);
}
template<typename T>
void pFlow::ListPtr<T>::push_back
(
T* ptr
)
{
list_.push_back(ptr);
}
template<typename T>
void pFlow::ListPtr<T>::push_back(uniquePtr<T>& ptr)
{
list_.push_back( ptr.release() );
}
template<typename T>
template<typename... Args>
void pFlow::ListPtr<T>::push_backSafe(Args&&... args)
{
auto ptr=makeUnique<T>(std::forward<Args>(args)...) ;
push_back(ptr);
}
template<typename T>
T& pFlow::ListPtr<T>::operator[]
(
label i
)
{
T* p = ptr(i);
if( !p )
{
fatalErrorInFunction<<
"trying to reach the reference of a nullptr or out of range access. \n";
fatalExit;
}
return *p;
}
template<typename T>
const T& pFlow::ListPtr<T>::operator[]
(
label i
) const
{
const T* p = ptr(i);
if(!p)
{
fatalErrorInFunction<<
"trying to reach the reference of a nullptr or out of range access. \n";
fatalExit;
}
return *p;
}
template<typename T>
size_t pFlow::ListPtr<T>::size()const
{
return list_.size();
}
template<typename T>
auto pFlow::ListPtr<T>::empty() const
{
return list_.emtpy();
}
template<typename T>
pFlow::uniquePtr<T> pFlow::ListPtr<T>::release
(
label i
)
{
auto p = ptr(i);
list_.erase(pos(i));
return p;
}
template<typename T>
void pFlow::ListPtr<T>::clear()
{
for( auto iter = list_.begin(); iter != list_.end(); ++iter )
{
if(*iter != nullptr)
{
delete *iter;
*iter = nullptr;
}
}
list_.clear();
}
template<typename T>
void pFlow::ListPtr<T>::clear
(
label i
)
{
T* p = ptr(i);
if( p )
{
delete p;
list_.erase(pos(i));
}
}

View File

@ -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 __Lists_H__
#define __Lists_H__
#include "List.H"
#include "ListPtr.H"
#endif //__Lists_H__

View File

@ -0,0 +1,174 @@
/*------------------------------- 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 __Map_H__
#define __Map_H__
#include <map>
#include "types.H"
#include "iOstream.H"
namespace pFlow
{
template<class Key, class T, class Compare = std::less<Key> >
class Map
:
public std::map<Key, T, Compare>
{
public:
using MapType = Map<Key, T, Compare>;
using mapType = std::map<Key, T, Compare>;
using iterator = typename mapType::iterator;
using constIterator = typename mapType::const_iterator;
using reference = typename mapType::reference;
using constReference= typename mapType::const_reference;
using initList = typename std::initializer_list<T>;
using keyType = typename mapType::key_type;
using mappedType = typename mapType::mapped_type;
using valueType = typename mapType::value_type;
// - type info
TypeNameTemplateNV("Map", Key);
//// - Constructors
// Empty Map
Map()
{}
// - with initList
Map(initList lst)
:
mapType(lst)
{}
// - Copy construct
Map(const MapType & src)
:
mapType(src)
{}
// - Move construct
Map( MapType&& src)
:
mapType(std::move(src))
{}
// - Copy assignment
MapType& operator=(const MapType& rhs)
{
mapType::operator=(rhs);
return *this;
}
// - Move assignment
MapType& operator=(MapType&& rhs)
{
mapType::operator=( std::move(rhs));
return *this;
}
uniquePtr<MapType> clone()const
{
return makeUnique<MapType>(*this);
}
MapType* clonePtr()const
{
return new MapType(*this);
}
~Map()
{
this->clear();
}
//// - Methods
// Insert an item with copy operation
bool insertIf(const keyType& k, const mappedType & v);
// insert an item with move operation
bool insertIf( keyType&& k, mappedType && v);
// search for a key
bool search(const keyType k) const;
std::pair<iterator, bool> findIf(const keyType& k);
const std::pair<constIterator, bool> findIf(const keyType& k) const;
};
template<typename T>
using wordMap = Map<word,T>;
template<typename T>
using labelMap = Map<label,T>;
template<typename T>
using uint32Map = Map<uint32,T>;
template<typename T>
using int32Map = Map<int32,T>;
template<typename T>
using int64Map = Map<int64,T>;
template<typename T>
inline iOstream& printKeys(iOstream& os, const wordMap<T> & m);
template<typename T>
inline iOstream& printKeys(iOstream& os, const labelMap<T> & m);
template<typename T>
inline iOstream& printKeys(iOstream& os, const uint32Map<T> & m);
template<typename T>
inline iOstream& printKeys(iOstream& os, const int32Map<T> & m);
template<typename T>
inline iOstream& printKeys(iOstream& os, const int64Map<T> & m);
#include "MapI.H"
} // pFlow
#endif

View File

@ -0,0 +1,134 @@
/*------------------------------- 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<class Key, class T, class Compare >
bool pFlow::Map<Key, T, Compare>::insertIf(const keyType& k, const mappedType & v)
{
auto [iter, success] = this->insert( valueType(k,v));
return success;
}
template<class Key, class T, class Compare >
bool pFlow::Map<Key, T, Compare>::insertIf( keyType&& k, mappedType && v)
{
auto [iter, success] = this->insert
(
std::move( valueType(k,v) )
);
return success;
}
template<class Key, class T, class Compare >
bool pFlow::Map<Key, T, Compare>::search(const keyType k) const
{
auto [iter, found] = findIf(k);
return found;
}
template<class Key, class T, class Compare >
std::pair<typename pFlow::Map<Key, T, Compare>::iterator, bool> pFlow::Map<Key, T, Compare>::findIf(const keyType& k)
{
if( auto iter = this->find(k); iter!= this->end() )
return {iter,true};
else
return {iter,false};
}
template<class Key, class T, class Compare >
const std::pair<typename pFlow::Map<Key, T, Compare>::constIterator, bool> pFlow::Map<Key, T, Compare>::findIf(const keyType& k) const
{
if( auto iter = this->find(k); iter!= this->end() )
return {iter,true};
else
return {iter,false};
}
template<typename T>
inline iOstream& printKeys(iOstream& os, const wordMap<T> & m)
{
if (m.empty())
return os<<"wordMap is empty"<<endl;
for(auto& iter : m)
{
os << iter.first<<endl;
}
return os;
}
template<typename T>
inline iOstream& printKeys(iOstream& os, const uint32Map<T> & m)
{
if (m.empty())
return os<<"uint32Map is empty"<<endl;
for(auto& iter : m)
{
os << iter.first<<endl;
}
return os;
}
template<typename T>
inline iOstream& printKeys(iOstream& os, const labelMap<T> & m)
{
if (m.empty())
return os<<"labelMap is empty"<<endl;
for(auto& iter : m)
{
os << iter.first<<endl;
}
return os;
}
template<typename T>
inline iOstream& printKeys(iOstream& os, const int32Map<T> & m)
{
if (m.empty())
return os<<"int32Map is empty"<<endl;
for(auto& iter : m )
{
os << iter.first<<endl;
}
return os;
}
template<typename T>
inline iOstream& printKeys(iOstream& os, const int64Map<T> & m)
{
if (m.empty())
return os<<"int64Map is empty"<<endl;
for(auto& iter : m )
{
os << iter.first<<endl;
}
return os;
}

View File

@ -0,0 +1,274 @@
/*------------------------------- 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 __MapPtr_H__
#define __MapPtr_H__
#include <typeinfo>
#include <map>
#include <unordered_map>
#include "types.H"
#include "uniquePtr.H"
#include "error.H"
#include "iOstream.H"
namespace pFlow
{
template< template<class, class> class Container, class Key, class T >
class MapPtr
{
public:
using MapPtrType = MapPtr<Container, Key, T>;
using mapType = Container<Key, T*>;
using keyType = typename mapType::key_type;
using mappedType = typename mapType::mapped_type;
using valueType = typename mapType::value_type;
using reference = typename mapType::reference;
using constReference = typename mapType::const_reference;
using iterator = typename mapType::iterator;
using constIterator = typename mapType::const_iterator;
template<typename... Args>
inline static uniquePtr<T> makeSafe(Args&&... args)
{
return std::make_unique(std::forward<Args>(args)...);
}
protected:
// data members
Container<Key, T*> map_;
// Methods
bool copy(const MapPtrType& src);
// - find a key and return the the pointer associated with the key
// nullptr if fails
T* findPtr(const keyType& k);
const T* findPtr(const keyType& k)const ;
public:
// - type info
TypeNameTemplateNV("MapPtr", Key);
//// Contructors
// - empty map
MapPtr()
:
map_()
{}
// - copy construct, create new objects out of the objects in the src
MapPtr(const MapPtrType& src);
// - copy assignment, create new objects out of he pointers in the src
MapPtrType& operator=(const MapPtrType& rhs);
// move construct
// it just simply move the pointers, so the new objects takes the
// ownership of the pointers.
MapPtr( MapPtrType&& src );
// move assignment
// the lhs object takes the ownership of the new objects and rhs loses the ownership
MapPtrType& operator=(MapPtrType&& rhs);
// removes /deletes all the objectes associated with pointers
uniquePtr<MapPtrType> clone()const
{
return makeUnique<MapPtrType>(*this);
}
MapPtrType* clonePtr()const
{
return new MapPtrType(*this);
}
~MapPtr()
{
clear();
}
//// - Methods
// - insert the object with key and replace if it already exists in the container
// return false if fails to insert, no action is taken for object deletion
bool insertReplace(const keyType& key, T* ptr);
// - insert the object with key and replace if it already exists in the container
// return false if fail to insert, no action is taken for object deletion
bool insertReplace(const keyType& key, uniquePtr<T>& ptr);
// - insert the object (construct in-place)
// return false if fail to insert, the object is deleted by default if fails
template<typename... Args>
bool insertReplaceSafe(const keyType& key, Args&&... args);
// - insert the object if key is new and return nullptr
// - if key exist, replace the new object and return the pointer to the old object
T* set(const keyType& key, T* ptr);
// - insert the object if key is new and return nullptr
// - if key exist, replace the new object and return the pointer to the old object
uniquePtr<T> set(const keyType& key, uniquePtr<T>& ptr );
// - insert the object (construct in-place), if key is new and return nullptr
// - if key exist, replace the new object and return the pointer to the old object
template<typename... Args>
uniquePtr<T> setSafe(const keyType& key, Args&&... args);
// - reference to the object found by key
// fatalError if not found
T& operator[] (const keyType& key);
// - const reference to the object found by key
// fatalError if not found
const T& operator[] (const keyType& key)const;
// - search if a key exists
bool search(const keyType k) const;
// - find a key and return the const pointer if successful
std::pair<const T*, bool> find(const keyType& k)const;
// - find a key and return the pointer if successful
std::pair<T*, bool> find(const keyType& k);
// - find the key and release the ownership of the object associated with it
// delete the key after release
uniquePtr<T> release(const keyType& k);
// - erase the element and delete the object if it is allocated
void erase( const keyType& key );
// - clear the content of the map with object deletion
void clear();
// - size of container
size_t size() const
{
return map_.size();
}
// - check if the container empty
auto empty() const
{
return map_.emtpy();
}
// - iterators
iterator begin()
{
return map_.begin();
}
constIterator begin() const
{
return map_.begin();
}
iterator end()
{
return map_.end();
}
constIterator end() const
{
return map_.end();
}
};
// ordered (sorted) map
template<typename key, typename T>
using orderedMapPtr = MapPtr<std::map, key, T>;
// unordered map (hash) map pointer
template<typename key, typename T>
using hashMapPtr = MapPtr<std::unordered_map , key, T>;
template<typename T>
using wordOrderedMapPtr = orderedMapPtr<word,T>;
template<typename T>
using wordHashMapPtr = hashMapPtr<word,T>;
template<typename T>
inline iOstream& printKeys(iOstream& os, const wordHashMapPtr<T> & m)
{
if (m.empty())
return os<<"wordHashMapPtr is empty"<<endl;
for(const auto iter : m )
{
os << iter->first<<endl;
}
return os;
}
template<typename T>
inline iOstream& printKeys(iOstream& os, const wordOrderedMapPtr<T> & m)
{
if (m.empty())
return os<<"wordOrderedMapPtr is empty"<<endl;
for(const auto iter : m )
{
os << iter->first<<endl;
}
return os;
}
} // pFlow
#include "MapPtrI.H"
#endif

View File

@ -0,0 +1,333 @@
/*------------------------------- 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< template<class, class> class Container, class Key, class T >
bool pFlow::MapPtr<Container, Key, T>::copy
(
const MapPtrType& src
)
{
for(constIterator iter= src.begin(); iter != src.end(); ++iter)
{
// first make sure that the new key can be inserted
auto [nIter, suc] = map_.insert(valueType(iter->first, nullptr));
// then insert the new item
if( suc )
{
if(iter->second != nullptr)
map_[iter->first] = iter->second->clonePtr();
}
else
{
return false;
}
}
return true;
}
template< template<class, class> class Container, class Key, class T >
T* pFlow::MapPtr<Container, Key, T>::findPtr
(
const keyType& k
)
{
if( auto iter = map_.find(k); iter!= map_.end() )
return iter->second;
else
return nullptr;
}
template< template<class, class> class Container, class Key, class T >
const T* pFlow::MapPtr<Container, Key, T>::findPtr
(
const keyType& k
)const
{
if( auto iter = map_.find(k); iter!= map_.cend() )
return iter->second;
else
return nullptr;
}
template< template<class, class> class Container, class Key, class T >
pFlow::MapPtr<Container, Key, T>::MapPtr
(
const MapPtrType& src
)
{
if( !copy(src) )
{
fatalErrorInFunction<<
"cannot copy new item into MapPtr \n" <<
"MapPtr type is "<< typeid(T).name() <<endl;
fatalExit;
}
}
template< template<class, class> class Container, class Key, class T >
pFlow::MapPtr<Container, Key, T>& pFlow::MapPtr<Container, Key, T>::operator=
(
const MapPtrType& rhs
)
{
if (this == &rhs)
{
return *this; // Self-assignment
}
// clears the content of this
clear();
if( !copy(rhs) )
{
fatalErrorInFunction<<
"cannot perform assignment from rhs into MapPtr \n" <<
"MapPtr type is "<< typeid(T).name() <<endl;
fatalExit;
}
return *this;
}
template< template<class, class> class Container, class Key, class T >
pFlow::MapPtr<Container, Key, T>::MapPtr
(
MapPtrType&& src
)
:
map_(std::move(src))
{}
template< template<class, class> class Container, class Key, class T >
pFlow::MapPtr<Container, Key, T>& pFlow::MapPtr<Container, Key, T>::operator=
(
MapPtrType&& rhs
)
{
// clears the content of this
clear();
map_.operator=(std::move(rhs));
return *this;
}
template< template<class, class> class Container, class Key, class T >
bool pFlow::MapPtr<Container, Key, T>::insertReplace
(
const keyType& key,
T* ptr
)
{
// delete the current key if it exists
erase(key);
auto [iter, success] = map_.insert( valueType(key,ptr));
return success;
}
template< template<class, class> class Container, class Key, class T >
bool pFlow::MapPtr<Container, Key, T>::insertReplace
(
const keyType& key,
uniquePtr<T>& ptr
)
{
erase(key);
if(auto [iter, success] = map_.insert(valueType(key, nullptr)); success)
{
map_[key] = ptr.release();
return true;
}
return false;
}
template< template<class, class> class Container, class Key, class T >
template<typename... Args>
bool pFlow::MapPtr<Container, Key, T>::insertReplaceSafe
(
const keyType& key,
Args&&... args
)
{
auto ptr = makeUnique<T>(std::forward<Args>(args)...);
return insertReplace(key, ptr);
}
template< template<class, class> class Container, class Key, class T >
T* pFlow::MapPtr<Container, Key, T>::set
(
const keyType& key,
T* ptr
)
{
auto [optr, exist] = find(key);
map_[key] = ptr;
return optr;
}
template< template<class, class> class Container, class Key, class T >
pFlow::uniquePtr<T> pFlow::MapPtr<Container, Key, T>::set
(
const keyType& key,
uniquePtr<T>& ptr)
{
auto[optr,exist] = find(key);
map_[key] = ptr.release();
return optr;
}
template< template<class, class> class Container, class Key, class T >
template<typename... Args>
pFlow::uniquePtr<T> pFlow::MapPtr<Container, Key, T>::setSafe
(
const keyType& key, Args&&... args
)
{
auto ptr = makeUnique<T>(std::forward<Args>(args)...);
return set(key, ptr);
}
template< template<class, class> class Container, class Key, class T >
T& pFlow::MapPtr<Container, Key, T>::operator[]
(
const keyType& key
)
{
T* p = findPtr(key);
if( !p )
{
fatalErrorInFunction<<
"trying to reach the reference of a nullptr or out of range access the element with key "
<<key<<endl;
fatalExit;
}
return *p;
}
template< template<class, class> class Container, class Key, class T >
const T& pFlow::MapPtr<Container, Key, T>::operator[]
(
const keyType& key
)const
{
const T* p = findPtr(key);
if( !p )
{
fatalErrorInFunction<<
"trying to reach the reference of a nullptr or out of range access the element with key "
<<key<<endl;
fatalExit;
}
return *p;
}
template< template<class, class> class Container, class Key, class T >
bool pFlow::MapPtr<Container, Key, T>::search
(
const keyType k
) const
{
auto [iter, found] = find(k);
return found;
}
template< template<class, class> class Container, class Key, class T >
std::pair<const T*, bool> pFlow::MapPtr<Container, Key, T>::find
(
const keyType& k
)const
{
if( auto iter = map_.find(k); iter!= map_.end() )
return {iter->second,true};
else
return {nullptr,false};
}
template< template<class, class> class Container, class Key, class T >
std::pair<T*, bool> pFlow::MapPtr<Container, Key, T>::find(const keyType& k)
{
if( auto iter = map_.find(k); iter!= map_.end() )
return {iter->second,true};
else
return {nullptr,false};
}
template< template<class, class> class Container, class Key, class T >
pFlow::uniquePtr<T> pFlow::MapPtr<Container, Key, T>::release
(
const keyType& key
)
{
auto p = findPtr(key);
map_.erase(key);
return p;
}
template< template<class, class> class Container, class Key, class T >
void pFlow::MapPtr<Container, Key, T>::erase
(
const keyType& key
)
{
if( auto ptr = findPtr(key); ptr )
{
delete ptr;
ptr = nullptr;
}
map_.erase(key);
}
template< template<class, class> class Container, class Key, class T >
void pFlow::MapPtr<Container, Key, T>::clear()
{
for( auto iter = map_.begin(); iter != map_.end(); ++iter )
{
if(iter->second != nullptr)
{
delete iter->second;
iter->second = nullptr;
}
}
map_.clear();
}

View File

@ -0,0 +1,30 @@
/*------------------------------- 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 __Maps_H__
#define __Maps_H__
#include "Map.H"
#include "hashMap.H"
#include "MapPtr.H"
#endif

View File

@ -0,0 +1,174 @@
/*------------------------------- 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 __hashMap_H__
#define __hashMap_H__
#include <unordered_map>
#include "types.H"
#include "typeInfo.H"
#include "iOstream.H"
namespace pFlow
{
template<class Key, class T, class Hash = std::hash<Key> >
class hashMap
:
public std::unordered_map<Key, T, Hash>
{
public:
using hashMapType = hashMap<Key, T, Hash>;
using hashmapType = std::unordered_map<Key, T, Hash>;
using iterator = typename hashmapType::iterator;
using constIterator = typename hashmapType::const_iterator;
using reference = typename hashmapType::reference;
using constReference= typename hashmapType::const_reference ;
using initList = typename std::initializer_list<T>;
using keyType = typename hashmapType::key_type;
using mappedType = typename hashmapType::mapped_type;
using valueType = typename hashmapType::value_type;
TypeNameTemplateNV("hashMap", Key);
//// - Constructors
// Empty hashMap
hashMap()
{}
// - with initList
hashMap(initList lst)
:
hashmapType(lst)
{}
// - Copy construct
hashMap(const hashMapType & src)
:
hashmapType(src)
{}
// - Move construct
hashMap( hashMapType&& src)
:
hashmapType(std::move(src))
{}
// - Copy assignment
hashMapType& operator=(const hashMapType& rhs)
{
hashmapType::operator=(rhs);
return *this;
}
// - Move assignment
hashMapType& operator=(hashMapType&& rhs)
{
hashmapType::operator=( std::move(rhs));
return *this;
}
uniquePtr<hashMapType> clone()const
{
return makeUnique<hashMapType>(*this);
}
hashMapType* clonePtr()const
{
return new hashMapType(*this);
}
~hashMap()
{
this->clear();
}
//// - Methods
// Insert an item with copy operation
bool insertIf(const keyType& k, const mappedType & v);
// insert an item with move operation
bool insertIf( keyType&& k, mappedType && v);
// search for a key
bool search(const keyType k) const;
std::pair<iterator, bool> findIf(const keyType& k);
const std::pair<constIterator, bool> findIf(const keyType& k) const;
};
template<typename T>
using wordHashMap = hashMap<word,T>;
template<typename T>
using labelHashMap = hashMap<label,T>;
template<typename T>
using uint32HashMap = hashMap<uint32,T>;
template<typename T>
using int64HashMap = hashMap<int64,T>;
template<typename T>
using int32HashMap = hashMap<int32,T>;
template<typename T>
inline iOstream& printKeys(iOstream& os, const wordHashMap<T> & m);
template<typename T>
inline iOstream& printKeys(iOstream& os, const labelHashMap<T> & m);
template<typename T>
inline iOstream& printKeys(iOstream& os, const uint32HashMap<T> & m);
template<typename T>
inline iOstream& printKeys(iOstream& os, const int64HashMap<T> & m);
template<typename T>
inline iOstream& printKeys(iOstream& os, const int32HashMap<T> & m);
#include "hashMapI.H"
} // pFlow
#endif

View File

@ -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.
-----------------------------------------------------------------------------*/
template<class Key, class T, class Compare >
bool pFlow::hashMap<Key, T, Compare>::insertIf(const keyType& k, const mappedType & v)
{
auto [iter, success] = this->insert( valueType(k,v));
return success;
}
template<class Key, class T, class Compare >
bool pFlow::hashMap<Key, T, Compare>::insertIf( keyType&& k, mappedType && v)
{
auto [iter, success] = this->insert
(
std::move( valueType(k,v) )
);
return success;
}
template<class Key, class T, class Compare >
bool pFlow::hashMap<Key, T, Compare>::search(const keyType k) const
{
auto [iter, found] = findIf(k);
return found;
}
template<class Key, class T, class Compare >
std::pair<typename pFlow::hashMap<Key, T, Compare>::iterator, bool>
pFlow::hashMap<Key, T, Compare>::findIf(const keyType& k)
{
if( auto iter = this->find(k); iter!= this->end() )
return {iter,true};
else
return {iter,false};
}
template<class Key, class T, class Compare >
const std::pair<typename pFlow::hashMap<Key, T, Compare>::constIterator, bool>
pFlow::hashMap<Key, T, Compare>::findIf(const keyType& k) const
{
if( auto iter = this->find(k); iter!= this->end() )
return {iter,true};
else
return {iter,false};
}
template<typename T>
inline iOstream& printKeys(iOstream& os, const wordHashMap<T> & m)
{
if (m.empty())
return os<<"wordHashMap is empty"<<endl;
for(auto iter = m.cbegin(); iter != m.cend(); iter++ )
{
os << iter->first<<endl;
}
return os;
}
template<typename T>
inline iOstream& printKeys(iOstream& os, const labelHashMap<T> & m)
{
if (m.empty())
return os<<"labelHashMap is empty"<<endl;
for(auto iter : m )
{
os << iter->first<<endl;
}
return os;
}
template<typename T>
inline iOstream& printKeys(iOstream& os, const uint32HashMap<T> & m)
{
if (m.empty())
return os<<"uint32HashMap is empty"<<endl;
for(auto iter : m )
{
os << iter->first<<endl;
}
return os;
}
template<typename T>
inline iOstream& printKeys(iOstream& os, const int64HashMap<T> & m)
{
if (m.empty())
return os<<"int64HashMap is empty"<<endl;
for(auto iter : m )
{
os << iter->first<<endl;
}
return os;
}
template<typename T>
inline iOstream& printKeys(iOstream& os, const int32HashMap<T> & m)
{
if (m.empty())
return os<<"int32HashMap is empty"<<endl;
for(auto iter : m )
{
os << iter->first<<endl;
}
return os;
}

View File

@ -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 __Set_H__
#define __Set_H__
#include <set>
namespace pFlow
{
template<typename Key>
using Set = std::set<Key,std::less<Key>,std::allocator<Key>>;
}
#endif

View File

@ -0,0 +1,352 @@
/*------------------------------- 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<typename T, typename Allocator>
pFlow::Vector<T, Allocator>::Vector(iIstream& is)
{
readVector(is);
}
template<typename T, typename Allocator>
bool pFlow::Vector<T, Allocator>::readVector
(
iIstream& is
)
{
this->clear();
is.fatalCheck(FUNCTION_NAME);
token firstToken(is);
T val{};
if( firstToken.isPunctuation() ) // start of vector
{
if(firstToken != token::BEGIN_LIST)
{
warningInFunction
<< "expected token "<< token::BEGIN_LIST
<< " but found "<< firstToken ;
return false;
}
token lastToken(is);
is.fatalCheck(FUNCTION_NAME);
while
( !(
lastToken.isPunctuation()
&& lastToken == token::END_LIST
)
)
{
is.putBack(lastToken);
is >> val;
this->push_back(val);
is >> lastToken;
is.fatalCheck(FUNCTION_NAME);
}
} else
{
warningInFunction
<< "expected token "<< token::BEGIN_LIST
<< " but found "<< firstToken ;
return false;
}
return true;
}
#include "streams.H"
template<typename T, typename Allocator>
bool pFlow::Vector<T, Allocator>::writeVector
(
iOstream& os
) const
{
auto len = size();
auto stride = getVectorStride(len);
// start of
os << token::BEGIN_LIST;
label i = 0;
while( i<len )
{
os << this->operator[](i++);
for(label j=0; j<stride-1 && i<len; j++ )
{
os << token::SPACE << this->operator[](i++);
}
if(i<len)
os<< token::NL;
}
os << token::END_LIST;
os.check(FUNCTION_NAME);
return true;
}
template<typename T, typename Allocator>
bool pFlow::Vector<T, Allocator>::deleteElement_sorted
(
const Vector<label>& indices
)
{
if( indices.size() == 0 )return true;
if( indices.size() == 1 )
{
return deleteElement(indices[0]);
}
if( *(indices.end()-1) >= size() ) return false;
VectorType tmp(capacity(), RESERVE());
tmp.clear();
label lindex = 0;
for(auto& delem: indices)
{
for(label i=lindex; i<delem; i++)
{
tmp.push_back( vectorType::operator[](i) );
}
lindex = delem+1;
}
// copy after the last delete element
for(label i=lindex; i<size(); i++)
{
tmp.push_back( vectorType::operator[](i) );
}
vectorType::swap(tmp);
return true;
}
template<typename T, typename Allocator>
bool pFlow::Vector<T, Allocator>::deleteElement
(
const Vector<label>& indices
)
{
if( indices.size() == 0 )return true;
if( indices.size() == 1)
{
return deleteElement(indices[0]);
}
// sorts
auto sorted = indices;
sort(sorted);
return deleteElement_sorted(sorted);
}
template<typename T, typename Allocator>
bool pFlow::Vector<T, Allocator>::deleteElement
(
label index
)
{
if(index < size())
{
auto iter = vectorType::begin();
advance(iter, index);
vectorType::erase(iter);
return true;
}
else
return false;
}
template<typename T, typename Allocator>
bool pFlow::Vector<T, Allocator>::insertSetElement(
const int32IndexContainer& indices,
const T& val)
{
if(indices.size() == 0)return true;
auto hIndices = indices.hostView();
forAll(i, indices)
{
auto s = size();
auto idx = hIndices[i];
if( idx < s )
{
this->operator[](idx) = val;
}
else if(idx == s )
{
this->push_back(val);
}
else
{
this->resize(idx+1);
this->operator[](idx) = val;
}
}
return true;
}
template<typename T, typename Allocator>
bool pFlow::Vector<T, Allocator>::insertSetElement(
const int32IndexContainer& indices,
const Vector<T>& vals)
{
if(indices.size() == 0)return true;
if(indices.size() != vals.size())return false;
auto hIndices = indices.hostView();
forAll(i, indices)
{
auto s = size();
auto idx = hIndices[i];
if( idx < s )
{
this->operator[](idx) = vals[i];
}
else if(idx == s )
{
this->push_back(vals[i]);
}
else
{
this->resize(idx+1);
this->operator[](idx) = vals[i];
}
}
return true;
}
template<typename T, typename Allocator>
bool pFlow::Vector<T, Allocator>::insertSetElement
(
const Vector<int32>& indices,
const T& val
)
{
if(indices.size() == 0)return true;
forAll(i, indices)
{
auto s = size();
auto idx = indices[i];
if( idx < s )
{
this->operator[](idx) = val;
}
else if(idx == s )
{
this->push_back(val);
}
else
{
this->resize(idx+1);
this->operator[](idx) = val;
}
}
return true;
}
template<typename T, typename Allocator>
bool pFlow::Vector<T, Allocator>::insertSetElement
(
const Vector<int32>& indices,
const Vector<T>& vals
)
{
if(indices.size() == 0)return true;
if(indices.size() != vals.size())return false;
forAll(i, indices)
{
auto s = size();
auto idx = indices[i];
if( idx < s )
{
this->operator[](idx) = vals[i];
}
else if(idx == s )
{
this->push_back(vals[i]);
}
else
{
this->resize(idx+1);
this->operator[](idx) = vals[i];
}
}
return true;
}
template<typename T, typename Allocator>
inline bool pFlow::Vector<T, Allocator>::insertSetElement
(
int32 idx,
const T & val
)
{
auto s = size();
if( idx < s )
{
this->operator[](idx) = val;
}
else if(idx == s)
{
this->push_back(val);
}
else
{
this->resize(idx+1);
this->operator[](idx) = val;
}
return true;
}

View File

@ -0,0 +1,425 @@
/*------------------------------- 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 __Vector_H__
#define __Vector_H__
#include <vector>
#include <algorithm>
#include "typeInfo.H"
#include "error.H"
#include "uniquePtr.H"
#include "stdAlgorithms.H"
#include "indexContainer.H"
#include "iOstream.H"
#include "iIstream.H"
#ifndef __RESERVE__
#define __RESERVE__
struct RESERVE{};
#endif
namespace pFlow
{
template<typename T, typename Allocator>
class Vector;
#include "VectorFwd.H"
template <class T>
class noConstructAllocator
: public std::allocator<T>
{
public:
using std::allocator<T>::allocator;
template <class U, class... Args> void construct(U*, Args&&...) {}
};
template<typename T>
using vecAllocator = std::allocator<T>;
template<typename T, typename Allocator = vecAllocator<T> >
class Vector
:
public std::vector<T, Allocator>
{
public:
typedef Vector<T, Allocator> VectorType;
typedef typename std::vector<T, Allocator> vectorType;
typedef typename vectorType::iterator iterator;
typedef typename vectorType::const_iterator constIterator;
typedef typename vectorType::reference reference;
typedef typename vectorType::const_reference constReference;
typedef T valueType;
typedef T* pointer;
typedef const T* constPointer;
typedef typename std::initializer_list<T> initList;
protected:
// - name of the vector
word name_;
static inline size_t getVectorStride(const size_t& len)
{
size_t stride = 1;
if( len < 6 ) stride = len;
else if( len <16 ) stride = 3;
else if( len < 31) stride = 2;
else stride = 1;
return stride;
}
static constexpr bool isHostAccessible_ = true;
constexpr static inline const char* memoerySpaceName()
{
return "std";
}
public:
// - Type info
TypeNameTemplateNV2("Vector", T, memoerySpaceName());
//// - Constructors
// - empty Vector
inline Vector()
:
Vector("Vector")
{}
inline Vector(const word& name)
:
name_(name)
{}
// - with sepcified length
inline Vector(const size_t len)
:
Vector("Vector",len)
{}
// - with specified length and name
inline Vector(const word& name, size_t len)
:
vectorType(len),
name_(name)
{
}
// - with length and value
inline Vector(size_t len, const T& val)
:
Vector("Vector", len, val)
{}
inline Vector(const word& name, size_t len, const T& val)
:
Vector(name, len)
{
this->assign(len, val);
}
// - zero length with specified capacity, use Logical
// to make it different from previous constructor.
inline Vector(const size_t cap, RESERVE ):
Vector("Vector", cap, 0, RESERVE())
{
}
inline Vector(const size_t cap, const size_t len, RESERVE )
:
Vector("Vector", cap, len, RESERVE())
{
}
Vector(const word& name, size_t cap, size_t len, RESERVE ):
name_(name)
{
this->reserve(cap);
this->resize(len);
}
inline Vector(const size_t cap, const size_t len, const T& val, RESERVE )
{
name_ = "Vector";
reserve(cap);
this->assign(len, val);
}
// from initializer list
inline Vector(const initList &l)
:
vectorType(l)
{}
// - from src and a new name
inline Vector(const word name, const Vector<T>& src):
vectorType(src),
name_(name)
{}
// copy construct
inline Vector(const VectorType& src) = default;
// move construct
inline Vector( VectorType && mv) = default;
inline Vector(const vectorType& src)
:
vectorType(src),
name_("Vector")
{
}
// copy assignment
inline VectorType& operator=( const VectorType& rhs ) = default;
inline VectorType& operator=(const vectorType& rhs)
{
Vector::assign(rhs.begin(), rhs.end());
return *this;
}
// move assignment
inline VectorType& operator=( VectorType && mv) = default;
// scalar assignment
inline void operator=(const T& val)
{
fill(val);
}
inline ~Vector()
{
vectorType::clear();
}
inline uniquePtr<VectorType> clone() const
{
return makeUnique<VectorType>(*this);
}
inline VectorType* clonePtr()const
{
return new VectorType(*this);
}
inline auto clear()
{
return vectorType::clear();
}
// access to this, mostly used by derived classes
const VectorType& VectorField() const
{
return *this;
}
VectorType& VectorField()
{
return *this;
}
const vectorType& vectorField()const
{
return *this;
}
vectorType& vectorField()
{
return *this;
}
auto& deviceVectorAll()
{
return *this;
}
const auto& deviceVectorAll()const
{
return *this;
}
auto& deviceVector()
{
return *this;
}
const auto& deviceVector()const
{
return *this;
}
const word& name()const
{
return name_;
}
inline auto size()const
{
return vectorType::size();
}
inline auto capacity()const
{
return vectorType::capacity();
}
inline auto reserve(label len)
{
return vectorType::reserve(len);
}
// - delete elemens of vector based on sorted indices
// return false if out of range
bool deleteElement_sorted(const Vector<label>& indices );
// - delete elemens of vector based on indices
// return false if out of range
bool deleteElement(const Vector<label>& indices );
// - delete elment with index
// return false if out of range
bool deleteElement(label index);
// - set or insert new elements into the vector
// return false if it fails
bool insertSetElement(const int32IndexContainer& indices, const T& val);
// - set or insert new elements into the vector
// return false if it fails
bool insertSetElement(const int32IndexContainer& indices, const Vector<T>& vals);
// - set or insert new elements into the vector
// return false if it fails
bool insertSetElement(const Vector<int32>& indices, const T& val);
// - set or insert new elements into the vector
// return false if it fails
bool insertSetElement(const Vector<int32>& indices, const Vector<T>& vals);
// - set or insert a new element into the vecor
// return false if it fails
inline bool insertSetElement(int32 idx, const T& val);
// - fill the whole content of vector, [begin, end), with val
inline void fill( const T& val);
static constexpr bool isHostAccessible()
{
return isHostAccessible_;
}
inline void operator +=( const T& val);
inline void operator -=( const T& val);
inline void operator *=( const T& val);
inline void operator /=( const T& val);
inline void operator +=( const VectorType& v );
inline void operator -=( const VectorType& v );
inline void operator /=( const VectorType& v );
inline void operator *=( const VectorType& v );
inline VectorType operator -()const;
// from iIstream and specified size
//Vector(iIstream & is, size_t len);
// from iIstream and free size
Vector(iIstream& is);
//bool readVector(iIstream & is, size_t len);
bool readVector(iIstream& is);
bool writeVector(iOstream& os) const;
bool read(iIstream& is)
{
return readVector(is);
}
bool write(iOstream& os)const
{
return writeVector(os);
}
};
template<typename T, typename Allocator>
inline iIstream& operator >> (iIstream & is, Vector<T, Allocator> & ivec )
{
if( !ivec.readVector(is) )
{
ioErrorInFile (is.name(), is.lineNumber());
fatalExit;
}
return is;
}
template<typename T, typename Allocator>
inline iOstream& operator << (iOstream& os, const Vector<T, Allocator>& ovec )
{
if( !ovec.writeVector(os) )
{
ioErrorInFile(os.name(), os.lineNumber());
fatalExit;
}
return os;
}
} // pFlow
#include "VectorI.H"
#include "Vector.C"
#include "VectorMath.H"
#include "VectorAlgorithm.H"
#endif

View File

@ -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.
-----------------------------------------------------------------------------*/
namespace pFlow
{
template<typename T, typename Allocator>
inline auto count(const Vector<T, Allocator>& vec, const T& val)
{
return std::count(vec.begin(), vec.end(), val);
}
template<typename T, typename Allocator, typename UnaryPredicate>
inline auto count_if(const Vector<T, Allocator>& vec, UnaryPredicate p)
{
return std::count_if(vec.begin(), vec.end(), p);
}
template<typename T, typename Allocator>
inline void fill_n(Vector<T, Allocator>& vec, size_t n, const T& val)
{
std::fill_n(vec.begin(), n, val);
}
template<typename T, typename Allocator>
inline void fill(Vector<T, Allocator>& vec, const T& val)
{
std::fill(vec.begin(), vec.end(), val);
}
template<typename T, typename Allocator>
inline void fillSequence(Vector<T, Allocator>& vec, int32 start, int32 end, const T& startVal)
{
pFlow::algorithms::STD::fillSequence<T, false>(vec.data()+start, end-start, startVal);
}
template<typename T, typename Allocator>
inline void fillSequence(Vector<T, Allocator>& vec, const T& startVal)
{
pFlow::fillSequence(vec, 0, vec.size(), startVal);
}
template<typename T, typename Allocator>
inline void sort(Vector<T, Allocator>& vec)
{
std::sort(vec.begin(), vec.end());
}
template<typename T, typename Allocator>
inline int64 find(Vector<T, Allocator>& vec, const T& val)
{
forAll( i,vec)
{
if ( vec[i] == val) return static_cast<int64>(i);
}
return -1;
}
} // pFlow

View File

@ -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.
-----------------------------------------------------------------------------*/
template<typename T, typename Allocator>
inline Vector<T, Allocator> operator+ (const Vector<T, Allocator>& op1, const T& op2 );
template<typename T, typename Allocator>
inline Vector<T, Allocator> operator+ (const T& op1, const Vector<T, Allocator>& op2 );
template<typename T, typename Allocator>
inline Vector<T, Allocator> operator+ (const Vector<T, Allocator>& op1, const Vector<T, Allocator>& op2 );
template<typename T, typename Allocator>
inline Vector<T, Allocator> operator - (const Vector<T, Allocator>& op1, const T& op2 );
template<typename T, typename Allocator>
inline Vector<T, Allocator> operator - (const T& op1, const Vector<T, Allocator>& op2 );
template<typename T, typename Allocator>
inline Vector<T, Allocator> operator - (const Vector<T, Allocator>& op1, const Vector<T, Allocator>& op2 );
template<typename T, typename Allocator>
inline Vector<T, Allocator> operator* (const Vector<T, Allocator>& op1, const T& op2 );
template<typename T, typename Allocator>
inline Vector<T, Allocator> operator* (const T& op1, const Vector<T, Allocator>& op2 );
template<typename T, typename Allocator>
inline Vector<T, Allocator> operator* (const Vector<T, Allocator>& op1, const Vector<T, Allocator>& op2 );
template<typename T, typename Allocator>
inline Vector<T, Allocator> operator / (const Vector<T, Allocator>& op1, const T& op2 );
template<typename T, typename Allocator>
inline Vector<T, Allocator> operator / (const T& op1, const Vector<T, Allocator>& op2 );
template<typename T, typename Allocator>
inline Vector<T, Allocator> operator / (const Vector<T, Allocator>& op1, const Vector<T, Allocator>& op2 );
template<typename T, typename Allocator>
inline auto count(const Vector<T, Allocator>& vec, const T& val);
template<typename T, typename Allocator, typename UnaryPredicate>
inline auto count_if(const Vector<T, Allocator>& vec, UnaryPredicate p);
template<typename T, typename Allocator>
inline void fill_n(Vector<T, Allocator>& vec, size_t n, const T& val);
template<typename T, typename Allocator>
inline void fill(Vector<T, Allocator>& vec, const T& val);
template<typename T, typename Allocator>
inline void sort(Vector<T, Allocator>& vec);

View File

@ -0,0 +1,302 @@
/*------------------------------- 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<typename T, typename Allocator>
inline void pFlow::Vector<T, Allocator>::fill( const T& val)
{
std::fill(this->begin(), this->end(), val);
}
#pragma hd_warning_disable
template<typename T, typename Allocator>
inline void pFlow::Vector<T, Allocator>::operator +=( const T& val)
{
for( auto& v:(*this) )
{
v+= val;
}
}
#pragma hd_warning_disable
template<typename T, typename Allocator>
inline void pFlow::Vector<T, Allocator>::operator -=( const T& val)
{
for( auto& v:(*this) )
{
v -= val;
}
}
#pragma hd_warning_disable
template<typename T, typename Allocator>
inline void pFlow::Vector<T, Allocator>::operator *=( const T& val)
{
for( auto& v:(*this) )
{
v *= val;
}
}
#pragma hd_warning_disable
template<typename T, typename Allocator>
inline void pFlow::Vector<T, Allocator>::operator /=( const T& val)
{
for( auto& v:(*this) )
{
v /= val;
}
}
#pragma hd_warning_disable
template<typename T, typename Allocator>
inline void pFlow::Vector<T, Allocator>::operator +=( const Vector<T, Allocator>& v )
{
if(size() != v.size() )
{
fatalErrorInFunction <<
"the += operator is invalid, vector size of right side (" << v.size() <<
") is not equal to the left side (" << size() << ").\n";
fatalExit;
}
for(label i=0; i<v.size(); i++)
{
this->operator[](i) += v[i];
}
}
#pragma hd_warning_disable
template<typename T, typename Allocator>
inline void pFlow::Vector<T, Allocator>::operator -=( const Vector<T, Allocator>& v )
{
if(size() != v.size() )
{
fatalErrorInFunction <<
"the -= operator is invalid, vector size of right side (" << v.size() <<
") is not equal to the left side (" << size() << ").\n";
fatalExit;
}
for(label i=0; i<v.size(); i++)
{
this->operator[](i) -= v[i];
}
}
#pragma hd_warning_disable
template<typename T, typename Allocator>
inline void pFlow::Vector<T, Allocator>::operator *=( const Vector<T, Allocator>& v )
{
if(size() != v.size() )
{
fatalErrorInFunction <<
"the * operator is invalid, vector size of right side (" << v.size() <<
") is not equal to the left side (" << size() << ").\n";
fatalExit;
}
for(label i=0; i<v.size(); i++)
{
this->operator[](i) *= v[i];
}
}
#pragma hd_warning_disable
template<typename T, typename Allocator>
inline void pFlow::Vector<T, Allocator>::operator /=( const Vector<T, Allocator>& v )
{
if(size() != v.size() )
{
fatalErrorInFunction <<
"the /= operator is invalid, vector size of right side (" << v.size() <<
") is not equal to the left side (" << size() << ").\n";
fatalExit;
}
for(label i=0; i<v.size(); i++)
{
this->operator[](i) /= v[i];
}
}
#pragma hd_warning_disable
template<typename T, typename Allocator>
inline pFlow::Vector<T, Allocator> pFlow::Vector<T, Allocator>::operator -
(
)const
{
Vector<T, Allocator> res(*this);
for( auto& vi:res)
{
vi = -vi;
}
return res;
}
#pragma hd_warning_disable
template<typename T, typename Allocator>
inline pFlow::Vector<T, Allocator> pFlow::operator+ (const Vector<T, Allocator>& op1, const T& op2 )
{
Vector<T, Allocator> res(op1);
res += op2;
return res;
}
#pragma hd_warning_disable
template<typename T, typename Allocator>
inline pFlow::Vector<T, Allocator> pFlow::operator+ (const T& op1, const Vector<T, Allocator>& op2 )
{
Vector<T, Allocator> res(op2);
res += op1;
return res;
}
#pragma hd_warning_disable
template<typename T, typename Allocator>
inline pFlow::Vector<T, Allocator> pFlow::operator+ (const Vector<T, Allocator>& op1, const Vector<T, Allocator>& op2 )
{
if( op1.size() != op2.size() )
{
fatalErrorInFunction <<
"the + operator is invalid, vector size of operand1 (" << op1.size() <<
") is not equal to vector size of operand2 (" << op1.size() << ").\n";
fatalExit;
}
Vector<T, Allocator> res(op1);
res += op2;
return res;
}
#pragma hd_warning_disable
template<typename T, typename Allocator>
inline pFlow::Vector<T, Allocator> pFlow::operator - (const Vector<T, Allocator>& op1, const T& op2 )
{
Vector<T, Allocator> res(op1);
res -= op2;
return res;
}
#pragma hd_warning_disable
template<typename T, typename Allocator>
inline pFlow::Vector<T, Allocator> pFlow::operator - (const T& op1, const Vector<T, Allocator>& op2 )
{
Vector<T, Allocator> res(op2.size(), op1);
res -= op2;
return res;
}
#pragma hd_warning_disable
template<typename T, typename Allocator>
inline pFlow::Vector<T, Allocator> pFlow::operator - (const Vector<T, Allocator>& op1, const Vector<T, Allocator>& op2 )
{
if( op1.size() != op2.size() )
{
fatalErrorInFunction <<
"the - operator is invalid, vector size of operand1 (" << op1.size() <<
") is not equal to vector size of operand2 (" << op1.size() << ").\n";
fatalExit;
}
Vector<T, Allocator> res(op1);
res -= op2;
return res;
}
#pragma hd_warning_disable
template<typename T, typename Allocator>
inline pFlow::Vector<T, Allocator> pFlow::operator* (const Vector<T, Allocator>& op1, const T& op2 )
{
Vector<T, Allocator> res(op1);
res *= op2;
return res;
}
#pragma hd_warning_disable
template<typename T, typename Allocator>
inline pFlow::Vector<T, Allocator> pFlow::operator* (const T& op1, const Vector<T, Allocator>& op2 )
{
Vector<T, Allocator> res(op2);
res *= op1;
return res;
}
#pragma hd_warning_disable
template<typename T, typename Allocator>
inline pFlow::Vector<T, Allocator> pFlow::operator* (const Vector<T, Allocator>& op1, const Vector<T, Allocator>& op2 )
{
if( op1.size() != op2.size() )
{
fatalErrorInFunction <<
"the * operator is invalid, vector size of operand1 (" << op1.size() <<
") is not equal to vector size of operand2 (" << op1.size() << ").\n";
fatalExit;
}
Vector<T, Allocator> res(op1);
res *= op2;
return res;
}
#pragma hd_warning_disable
template<typename T, typename Allocator>
inline pFlow::Vector<T, Allocator> pFlow::operator / (const Vector<T, Allocator>& op1, const T& op2 )
{
Vector<T, Allocator> res(op1);
res /= op2;
return res;
}
#pragma hd_warning_disable
template<typename T, typename Allocator>
inline pFlow::Vector<T, Allocator> pFlow::operator / (const T& op1, const Vector<T, Allocator>& op2 )
{
Vector<T, Allocator> res(op2.size(), op1);
res /= op2;
return res;
}
#pragma hd_warning_disable
template<typename T, typename Allocator>
inline pFlow::Vector<T, Allocator> pFlow::operator / (const Vector<T, Allocator>& op1, const Vector<T, Allocator>& op2 )
{
if( op1.size() != op2.size() )
{
fatalErrorInFunction <<
"the / operator is invalid, vector size of operand1 (" << op1.size() <<
") is not equal to vector size of operand2 (" << op1.size() << ").\n";
fatalExit;
}
Vector<T, Allocator> res(op1);
res /= op2;
return res;
}

View File

@ -0,0 +1,212 @@
/*------------------------------- 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.
-----------------------------------------------------------------------------*/
#define VecFunc(fnName) \
template<typename T, typename Allocator> \
inline pFlow::Vector<T, Allocator> pFlow::fnName(const Vector<T,Allocator>& v) \
{ \
Vector<T, Allocator> res(v.capacity(), Logical()); \
for(auto& e:v) \
{ \
res.push_back( fnName(e) ); \
} \
return std::move(res); \
} \
template<typename T, typename Allocator, typename indexFunc> \
inline pFlow::Vector<T, Allocator> pFlow::fnName(const Vector<T, Allocator>& v, indexFunc iFn) \
{ \
Vector<T, Allocator> res(v.capacity(), Logical()); \
for(label i=0; i<v.size(); i++) \
{ \
if( iFn(i) ) \
res.push_back(fnName(v[i])); \
else \
res.push_back(v[i]); \
} \
return std::move(res); \
}
#define VecFunc2(fnName) \
template<typename T, typename Allocator> \
inline pFlow::Vector<T, Allocator> pFlow::fnName(const Vector<T, Allocator>& v1, const Vector<T, Allocator>& v2) \
{ \
Vector<T, Allocator> res(v1.capacity(), Logical()); \
for(label i=0; i<v1.size(); i++) \
{ \
res.push_back( fnName(v1[i], v2[i])); \
} \
return std::move(res); \
} \
template<typename T, typename Allocator, typename indexFunc> \
inline pFlow::Vector<T, Allocator> pFlow::fnName(const Vector<T, Allocator>& v1, const Vector<T, Allocator>& v2, indexFunc iFn) \
{ \
Vector<T, Allocator> res(v1.capacity(), Logical()); \
for(label i=0; i<v1.size(); i++) \
{ \
if( iFn(i) ) \
res.push_back(fnName(v1[i], v2[i])); \
else \
res.push_back(v1[i]); \
} \
return std::move(res); \
}
//* * * * * * * * * * * List of functinos * * * * * * * * //
// abs, mod, exp, log, log10, pow, sqrt, cbrt
// sin, cos, tan, asin, acos, atan, atan2
// sinh, cosh, tanh, asinh, acosh, atanh
// min, max
//* * * * * * * * * * * * * * * * * * * * * * * * * * * * //
VecFunc(abs);
VecFunc2(mod);
VecFunc(exp);
VecFunc(log);
VecFunc(log10);
VecFunc2(pow);
VecFunc(sqrt);
VecFunc(cbrt);
VecFunc(sin);
VecFunc(cos);
VecFunc(tan);
VecFunc(asin);
VecFunc(acos);
VecFunc(atan);
VecFunc2(atan2);
VecFunc(sinh);
VecFunc(cosh);
VecFunc(tanh);
VecFunc(asinh);
VecFunc(acosh);
VecFunc(atanh);
#undef VecFunc
//// special implementation of math functions
namespace pFlow
{
template<typename T, typename Allocator>
inline Vector<T, Allocator> pow(const Vector<T, Allocator>& v, T e)
{
Vector<T, Allocator> res(v.capacity(), Logical());
for(auto& elm:v)
{
res.push_back(pow(elm,e));
}
return std::move(res);
}
template<typename T, typename Allocator, typename indexFunc>
inline Vector<T,Allocator> pow(const Vector<T,Allocator>& v, T e, indexFunc iFn)
{
Vector<T, Allocator> res(v.capacity(), Logical());
for(label i=0; i<v.size(); i++)
{
if(iFn(i))
{
res.push_back(pow(v[i],e));
}
else
{
res.push_back(v[i]);
}
}
return std::move(res);
}
template<typename T, typename Allocator>
inline T min(const Vector<T, Allocator>& v)
{
T minVal(largestPositive<T>());
for(auto& elm:v)
{
minVal = min(elm, minVal);
}
return minVal;
}
template<typename T, typename Allocator, typename indexFunc>
inline T min(const Vector<T, Allocator>& v, indexFunc iFn)
{
T minVal(largestPositive<T>());
for(label i=0; i<v.size(); i++)
{
if(iFn(i))
{
minVal = min(v[i], minVal);
}
}
return minVal;
}
template<typename T, typename Allocator>
inline T max(const Vector<T, Allocator>& v)
{
T maxVal(largestNegative<T>());
for(auto& elm:v)
{
maxVal = max(elm, maxVal);
}
return maxVal;
}
template<typename T, typename Allocator ,typename indexFunc>
inline T max(const Vector<T, Allocator>& v, indexFunc iFn)
{
T maxVal(largestNegative<T>());
for(label i=0; i<v.size(); i++)
{
if(iFn(i))
{
maxVal = max(v[i], maxVal);
}
}
return maxVal;
}
template<typename T, typename Allocator>
inline T sum(const Vector<T, Allocator>& v)
{
T s = static_cast<T>(0);
for(auto& elm:v)
{
s += elm;
}
return s;
}
template<typename T, typename Allocator, typename indexFunc>
inline T sum(const Vector<T, Allocator>& v, indexFunc iFn)
{
T s = static_cast<T>(0);
for(label i=0; i<v.size(); ++i)
{
if(iFn(i))
s += v[i];
}
return s;
}
}

View File

@ -0,0 +1,46 @@
/*------------------------------- 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 "Vectors.H"
// instantiation just for numeral types
template class pFlow::Vector<pFlow::int8>;
template class pFlow::Vector<pFlow::int16>;
template class pFlow::Vector<pFlow::int32>;
template class pFlow::Vector<pFlow::int64>;
template class pFlow::Vector<pFlow::uint32>;
template class pFlow::Vector<pFlow::label>;
template class pFlow::Vector<pFlow::real>;
template class pFlow::Vector<pFlow::realx3>;
template class pFlow::Vector<pFlow::realx3x3>;
//template class pFlow::Vector<pFlow::word>;

View File

@ -0,0 +1,101 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
#ifndef __Vectors_H__
#define __Vectors_H__
#include "types.H"
#include "Vector.H"
namespace pFlow
{
using int8Vector = Vector<int8>;
using int16Vector = Vector<int16>;
using int32Vector = Vector<int32>;
using int64Vector = Vector<int64>;
using uint32Vector = Vector<uint32>;
using labelVector = Vector<label>;
using realVector = Vector<real> ;
using realx3Vector = Vector<realx3>;
using uint16x3Vector= Vector<uint16x3>;
using uint32x3Vector= Vector<uint32x3>;
using int32x3Vector = Vector<int32x3>;
using int64x3Vector = Vector<int64x3>;
using uint16x3x3Vector = Vector<uint16x3x3>;
using uint32x3x3Vector = Vector<uint32x3x3>;
using int32x3x3Vector = Vector<int32x3x3>;
using realx3x3Vector = Vector<realx3x3>;
using wordVector = Vector<word>;
/*template<>
inline word Vector<label>::TYPENAME() { return "labelVector"; }
typedef Vector<label> labelVector;
template<>
inline word Vector<real>::TYPENAME() { return "realVector"; }
typedef Vector<real> realVector;
template<>
inline word Vector<unit3>::TYPENAME() { return "unit3Vector"; }
typedef Vector<unit3> unit3Vector;
template<>
inline word Vector<real3>::TYPENAME() { return "real3Vector"; }
typedef Vector<real3> real3Vector;
template<>
inline word Vector<real33>::TYPENAME() { return "real33Vector"; }
typedef Vector<real33> real33Vector;
template<>
inline word Vector<bool>::TYPENAME() { return "boolVector"; }
typedef Vector<bool> boolVector;
template<>
inline word Vector<word>::TYPENAME() { return "wordVector"; }
typedef Vector<word> wordVector;
template<>
inline word Vector<sint>::TYPENAME() { return "sintVector"; }
typedef Vector<sint> sintVector;*/
}
#endif //__Vectors_H__

View File

@ -0,0 +1,965 @@
/*------------------------------- 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 __VectorDual_H__
#define __VectorDual_H__
#include "globalSettings.H"
#include "types.H"
#include "typeInfo.H"
#include "Vector.H"
#include "streams.H"
#include "KokkosTypes.H"
#include "ViewAlgorithms.H"
#ifndef __RESERVE__
#define __RESERVE__
struct RESERVE{};
#endif
namespace pFlow
{
template<typename T, typename MemorySpace>
class VectorDual;
template<typename T, typename MemorySpace=void>
class VectorDual
{
public:
using iterator = T*;
using constIterator = const T*;
using reference = T&;
using constReference = const T&;
using valueType = T;
using pointer = T*;
using constPointer = const T*;
using VectorType = VectorDual<T, MemorySpace>;
// dualViewType (view of data host and device)
using dualViewType = Kokkos::DualView<T*, MemorySpace>;
// mirror scape of device view
using hostMirrorSpace = typename dualViewType::host_mirror_space;
// - viewType of data on device
using deviceViewType = typename dualViewType::t_dev;
// - viewType of data on host
using hostViewType = typename dualViewType::t_host;
using deviceType = typename deviceViewType::device_type;
using hostType = typename hostViewType::device_type;
// to be consistent
using viewType = dualViewType;
// we assume device view is the primary side
using memory_space = typename viewType::memory_space;
// we assume device view is the primary side
using execution_space = typename deviceType::execution_space;
protected:
size_t size_ = 0;
size_t capacity_ = 0;
dualViewType dualView_;
mutable deviceViewType deviceSubView_;
mutable hostViewType hostSubView_;
mutable bool subViewsUpdated_ = false;
static const inline real growthFactor_ = vectorGrowthFactor__;
// is host accepsibble from device prespective
static constexpr bool isHostAccessible_ =
Kokkos::SpaceAccessibility<execution_space,Kokkos::HostSpace>::accessible;
// host-device name
static inline const word hdName__ =
word(hostType::memory_space::name())+
word(deviceType::memory_space::name());
constexpr static inline const char* memoerySpaceName()
{
return hdName__.data();
}
static INLINE_FUNCTION_H size_t evalCapacity(size_t n)
{
return static_cast<size_t>(n*growthFactor_+1);
}
// use actualCap = true only for reserve
INLINE_FUNCTION_H void changeSize(size_t n, bool actualCap=false)
{
if(n >= capacity_ )
{
if(actualCap)
capacity_ = n;
else
capacity_ = evalCapacity(n);
dualView_.resize(capacity_);
subViewsUpdated_ = false;
syncViews();
}
if(!actualCap)
{
setSize(n);
}
}
INLINE_FUNCTION_H void setSize(size_t n) {
size_ = n;
subViewsUpdated_ = false;
}
// - seems strange, since we actually are updating values,
// but in fact the content of object is actually const.
INLINE_FUNCTION_H void updateSubViews()const
{
if(subViewsUpdated_)return;
hostSubView_ = Kokkos::subview(dualView_.h_view, Kokkos::make_pair(0,int(size_)));
deviceSubView_ = Kokkos::subview(dualView_.d_view, Kokkos::make_pair(0,int(size_)));
subViewsUpdated_ = true;
}
public:
// - type info
TypeNameTemplateNV2("VectorDual", T, memoerySpaceName());
//// - Constructors
// - empty
VectorDual()
:
VectorDual("VectorDual")
{
}
VectorDual(const word& name)
:
size_(0),
capacity_(2),
dualView_(name,capacity_)
{
changeSize(size_);
}
// - with size n
VectorDual(size_t n)
:
VectorDual("VectorDual",n)
{}
// - with name and size n
VectorDual(const word& name, size_t n)
:
size_(n),
capacity_(evalCapacity(n)),
dualView_(name, capacity_)
{
changeSize(size_);
}
// with size and value, apply on both views
VectorDual(size_t n, const T& val)
:
VectorDual("VectorDual", n , val)
{}
// with name, size and value, apply on both views
VectorDual(const word& name, size_t n, const T& val)
:
VectorDual(name, n)
{
assign(n, val);
}
VectorDual(size_t cap, size_t n, RESERVE )
:
VectorDual("VectorDual", cap, n, RESERVE())
{}
VectorDual(const word& name, size_t cap, size_t n, RESERVE )
:
VectorDual(name)
{
reallocate(cap);
setSize(n);
}
VectorDual(const Vector<T> & src)
:
VectorDual("VectorDual", src)
{}
VectorDual(const word& name, const Vector<T> & src)
:
VectorDual(name)
{
assign(src);
}
// - copy construct (perform deep copy)
// preserve the sync status of the views
VectorDual(const VectorDual& src)
:
VectorDual(src.name(), src.capacity(), src.size(), RESERVE())
{
// transfer the sync status
if(src.hostRequiresSync())
{
modifyOnDevice();
}else if( src.deviceRequiresSync())
{
modifyOnHost();
}else
{
dualView_.clear_sync_state();
}
Kokkos::deep_copy(hostVector(), src.hostVector());
Kokkos::deep_copy(deviceVector(), src.deviceVector());
}
// copy construct with new name
VectorDual(const word& name, const VectorDual& src)
:
VectorDual(name, src.capacity(), src.size(), RESERVE())
{
// transfer the sync status
if(src.hostRequiresSync())
{
modifyOnDevice();
}else if( src.deviceRequiresSync())
{
modifyOnHost();
}else
{
dualView_.clear_sync_state();
}
Kokkos::deep_copy(hostVector(), src.hostVector());
Kokkos::deep_copy(deviceVector(), src.deviceVector());
}
// - copy assignment
VectorDual& operator = (const VectorDual& rhs)
{
if(&rhs == this) return *this;
VectorDual temp(rhs);
capacity_ = temp.capacity();
setSize( temp.size());
dualView_ = temp.dualView_;
return *this;
}
// no move construct
VectorDual(VectorDual&&) = delete;
// no move assignment
VectorDual& operator= (VectorDual&&) = delete;
// - clone as a uniquePtr
INLINE_FUNCTION_H uniquePtr<VectorDual> clone() const
{
return makeUnique<VectorDual>(*this);
}
// - clone as a pointer
INLINE_FUNCTION_H VectorDual* clonePtr()const
{
return new VectorDual(*this);
}
//// - Methods
// - return *this
INLINE_FUNCTION_H
VectorType& VectorField()
{
return *this;
}
// - return *this
INLINE_FUNCTION_H
const VectorType& VectorField()const
{
return *this;
}
// - Device vector
INLINE_FUNCTION_H deviceViewType& deviceVectorAll(){
return dualView_.d_view;
}
// - Device vector
INLINE_FUNCTION_H const deviceViewType& deviceVectorAll() const {
return dualView_.d_view;
}
// - Host vector
INLINE_FUNCTION_H hostViewType& hostVectorAll(){
return dualView_.h_view;
}
// - Host Vector
INLINE_FUNCTION_H const hostViewType& hostVectorAll() const {
return dualView_.h_view;
}
INLINE_FUNCTION_H deviceViewType& deviceVector(){
updateSubViews();
return deviceSubView_;
}
INLINE_FUNCTION_H const deviceViewType& deviceVector() const{
updateSubViews();
return deviceSubView_;
}
INLINE_FUNCTION_H hostViewType& hostVector(){
updateSubViews();
return hostSubView_;
}
INLINE_FUNCTION_H const hostViewType& hostVector()const{
updateSubViews();
return hostSubView_;
}
INLINE_FUNCTION_H
hostViewType hostVector(int32 start, int32 end)const
{
return Kokkos::subview(dualView_.h_view, Kokkos::make_pair(start,end));
}
INLINE_FUNCTION_H
deviceViewType deviceVector(int32 start, int32 end)const
{
return Kokkos::subview(dualView_.d_view, Kokkos::make_pair(start,end));
}
INLINE_FUNCTION_H const word name()const
{
return dualView_.h_view.label();
}
INLINE_FUNCTION_H size_t size()const
{
return size_;
}
INLINE_FUNCTION_H size_t capacity()const
{
return capacity_;
}
INLINE_FUNCTION_H bool empty()const
{
return size_==0;
}
// - reserve capacity for vector
// preserve the content
INLINE_FUNCTION_H void reserve(size_t cap)
{
changeSize(cap, true);
}
// resize the views
// no syncronization occurs
INLINE_FUNCTION_H void resize(size_t n)
{
changeSize(n);
}
INLINE_FUNCTION_H void reallocate(size_t cap)
{
capacity_ = cap;
setSize(0);
dualView_.realloc(cap);
dualView_.clear_sync_state();
}
INLINE_FUNCTION_H void resizeSync(size_t n)
{
changeSize(n);
syncViews();
}
// resize the view and assign value to the most recent view (most updated)
// no syncronization occurs
INLINE_FUNCTION_H void resize(size_t n, const T& val) {
assign(n, val);
}
// resize the view and assign value to the most recent view (most updated)
// and syncronize both views
INLINE_FUNCTION_H void resizeSync(size_t n, const T& val){
assign(n,val);
syncViews();
}
INLINE_FUNCTION_H void clear() {
setSize(0);
dualView_.clear_sync_state();
}
// - fill both views with val
INLINE_FUNCTION_H void fill(const T& val)
{
if(empty())return;
Kokkos::deep_copy(deviceVector(),val);
Kokkos::deep_copy(hostVector(),val);
dualView_.clear_sync_state();
}
INLINE_FUNCTION_H void fillHost(const T& val)
{
if(empty())return;
Kokkos::deep_copy(hostVector(),val);
modifyOnHost();
}
INLINE_FUNCTION_H void fillDevice(const T& val)
{
if(empty())return;
Kokkos::deep_copy(deviceVector(),val);
modifyOnDevice();
}
// - host calls only
// - assign n first elements to val
// resize views
// assign value to both sides (device&host)
FUNCTION_H void assign(size_t n, const T& val)
{
if( n>= capacity_ )
{
reallocate(evalCapacity(n));
}
setSize(n);
fill(val);
}
// - host calls only
// - assign source vector
// resize views
// assign to both sides (device&host)
FUNCTION_H void assign(const Vector<T>& src)
{
auto srcSize = src.size();
if( capacity() < srcSize )
{
reallocate( evalCapacity(srcSize) );
}
setSize(0);
dualView_.clear_sync_state();
for( auto& elem:src )
{
this->push_back(elem);
}
syncViews();
}
// TODO: this part may be implemented in parallel
bool deleteElement
(
const Vector<label>& indices
)
{
if( indices.size() == 0 )return true;
if( *(indices.end()-1) >= size() ) return false;
auto oldSize = this->size();
auto nextInd = indices.begin();
label j = indices[0];
for(label i=indices[0]; i < oldSize; ++i)
{
if( nextInd != indices.end() && i == *nextInd )
{
++nextInd;
}
else
{
dualView_.h_view[j] = dualView_.h_view[i];
++j;
}
}
setSize( oldSize - indices.size() );
modifyOnHost();
// TODO: deep_copy should be changed to a range shorter than the vector size
syncViews();
return true;
}
INLINE_FUNCTION_H
bool insertSetElement(const int32IndexContainer& indices, const T& val)
{
if(indices.size() == 0)return true;
auto maxInd = indices.max();
if(this->empty() || maxInd > size()-1 )
{
resize(maxInd+1);
}
fillSelected(hostVectorAll(), indices.hostView(), indices.size(), val);
auto dIndices = indices.deviceView();
auto dVals = deviceVectorAll();
Kokkos::parallel_for(
"fillSelected",
indices.size(),
LAMBDA_HD(int32 i){
dVals[dIndices[i]]= val;
});
Kokkos::fence();
return true;
}
template<typename side=HostSide>
INLINE_FUNCTION_H
bool insertSetElement
(
const int32IndexContainer& indices,
const Vector<T>& vals
)
{
if(indices.size() == 0)return true;
if(indices.size() != vals.size())return false;
auto maxInd = indices.max();
auto minInd = indices.min();
if(this->empty() || maxInd > size()-1 )
{
resize(maxInd+1);
}
if constexpr (std::is_same<side,HostSide>::value )
{
hostViewType1D<T> hVecVals( const_cast<T*>(vals.data()), vals.size());
//fillSelected(hostVector(), indices.hostView(), hVecVals, indices.size());
pFlow::algorithms::KOKKOS::fillSelected<T, int32, DefaultHostExecutionSpace>(
hostVectorAll().data(),
indices.hostView().data(),
hVecVals.data(),
indices.size());
modifyOnHost();
syncViews(minInd, maxInd+1);
}
else
{
pFlow::hostViewType1D<T> hVecVals( const_cast<T*>(vals.data()), vals.size());
pFlow::deviceViewType1D<T> dVecVals("dVecVals", indices.size());
Kokkos::deep_copy(dVecVals, hVecVals);
//fillSelected(deviceVector(), indices.deviceView(), dVecVals, indices.size());
pFlow::algorithms::KOKKOS::fillSelected<T, int32, execution_space>(
deviceVectorAll().data(),
indices.deviceView().data(),
dVecVals.data(),
indices.size());
modifyOnDevice();
// TODO: deep_copy should be changed to a range shorter than the vector size
syncViews(minInd, maxInd+1);
}
return true;
}
template<typename side=HostSide>
INLINE_FUNCTION_H
bool insertSetElement(const Vector<int32>& indices, const T& val)
{
if(indices.size() == 0)return true;
auto maxInd = max(indices);
auto minInd = min(indices);
if(this->empty() || maxInd > size()-1 )
{
resize(maxInd+1);
}
if constexpr (std::is_same<side,HostSide>::value )
{
hostViewType1D<int32> hVecInd( const_cast<int32*>(indices.data()), indices.size());
fillSelected( hostVectorAll(), hVecInd, indices.size(), val);
modifyOnHost();
syncViews(minInd, maxInd+1);
return true;
}
else
{
hostViewType1D<int32> hVecInd( const_cast<int32*>(indices.data()), indices.size());
deviceViewType1D<int32> dVecInd("dVecInd", indices.size());
Kokkos::deep_copy(dVecInd, hVecInd);
fillSelected(deviceVectorAll(), dVecInd, indices.size(), val);
modifyOnDevice();
// TODO: deep_copy should be changed to a range shorter than the vector size
syncViews(minInd, maxInd+1);
return true;
}
return false;
}
template<typename side=HostSide>
INLINE_FUNCTION_H
bool insertSetElement
(
const Vector<int32>& indices,
const Vector<T>& vals
)
{
if(indices.size() == 0)return true;
if(indices.size() != vals.size())return false;
auto maxInd = max(indices);
auto minInd = min(indices);
if(this->empty() || maxInd > size()-1 )
{
resize(maxInd+1);
}
if constexpr (std::is_same<side,HostSide>::value )
{
hostViewType1D<int32> hVecInd( const_cast<int32*>(indices.data()), indices.size());
hostViewType1D<T> hVecVals( const_cast<T*>(vals.data()), vals.size());
fillSelected(hostVectorAll(), hVecInd, hVecVals, indices.size());
modifyOnHost();
syncViews(minInd, maxInd+1);
}
else
{
pFlow::hostViewType1D<int32> hVecInd( const_cast<int32*>(indices.data()), indices.size());
pFlow::deviceViewType1D<int32> dVecInd("dVecInd", indices.size());
pFlow::hostViewType1D<T> hVecVals( const_cast<T*>(vals.data()), vals.size());
pFlow::deviceViewType1D<T> dVecVals("dVecVals", indices.size());
Kokkos::deep_copy(dVecVals, hVecVals);
Kokkos::deep_copy(dVecInd, hVecInd);
fillSelected(deviceVectorAll(), dVecInd, dVecVals, indices.size());
modifyOnDevice();
// TODO: deep_copy should be changed to a range shorter than the vector size
syncViews(minInd, maxInd+1);
}
return true;
}
// push a new element at the end
// resize if necessary
// first sycn to host side
void push_back(const T& val)
{
syncToHost();
modifyOnHost();
if(size_ == capacity_) changeSize(capacity_);
data()[size_++] = val;
subViewsUpdated_ = false;
}
INLINE_FUNCTION_H pointer data(){
return dualView_.h_view.data();
}
INLINE_FUNCTION_H constPointer data()const{
return dualView_.h_view.data();
}
// host call
// returns begin iterator
INLINE_FUNCTION_H iterator begin(){
return data();
}
// host call
// returns begin iterator
INLINE_FUNCTION_H constIterator begin()const {
return data();
}
// host call
// returns end iterator
INLINE_FUNCTION_H iterator end(){
return size_ > 0 ? data() + size_: data();
}
// host call
// returns end iterator
INLINE_FUNCTION_H constIterator end()const{
return size_ > 0 ? data() + size_: data();
}
INLINE_FUNCTION_H reference operator[](label i){
return dualView_.h_view[i];
}
INLINE_FUNCTION_H constReference operator[](label i)const{
return dualView_.h_view[i];
}
//// - managing sync between views
INLINE_FUNCTION_H void modifyOnHost()
{
dualView_.modify_host();
}
INLINE_FUNCTION_H void modifyOnDevice()
{
dualView_.modify_device();
}
INLINE_FUNCTION_H bool hostRequiresSync()const
{
return dualView_.template need_sync<hostType>();
}
INLINE_FUNCTION_H bool deviceRequiresSync()const
{
return dualView_.template need_sync<deviceType>();
}
INLINE_FUNCTION_H bool areViewsSimilar()const
{
return std::is_same<hostType,deviceType>::value;
}
// - copy from host to device
// set both views to updated
INLINE_FUNCTION_H void copyHostToDevice()
{
if(empty())return;
Kokkos::deep_copy(deviceVector(), hostVector());
dualView_.clear_sync_state();
}
INLINE_FUNCTION_H
void copyHostToDevice(int32 start, int32 end, bool setUpdated = true)
{
if(empty())return;
Kokkos::deep_copy(deviceVector(start, end), hostVector(start, end));
if(setUpdated)
dualView_.clear_sync_state();
}
// - copy from device to host
// set both views to updated
INLINE_FUNCTION_H void copyDeviceToHost()
{
if(empty())return;
Kokkos::deep_copy(hostVector(), deviceVector());
dualView_.clear_sync_state();
}
INLINE_FUNCTION_H
void copyDeviceToHost(int32 start, int32 end, bool setUpdated = true)
{
if(empty())return;
Kokkos::deep_copy(hostVector(start, end), deviceVector(start, end));
if(setUpdated)
dualView_.clear_sync_state();
}
INLINE_FUNCTION_H void syncToHost()
{
if(hostRequiresSync())
{
copyDeviceToHost();
}
}
INLINE_FUNCTION_H void syncToDevice()
{
if(deviceRequiresSync())
{
copyHostToDevice();
}
}
// - check which side requires update and
// apply the update
INLINE_FUNCTION_H void syncViews()
{
if(deviceRequiresSync())
{
copyHostToDevice();
}
else if(hostRequiresSync())
{
copyDeviceToHost();
}
}
INLINE_FUNCTION_H void syncViews(int32 start, int32 end)
{
if(deviceRequiresSync())
{
copyHostToDevice(start, end);
}
else if(hostRequiresSync())
{
copyDeviceToHost(start, end);
}
}
//// - IO operations
FUNCTION_H
bool read(iIstream& is)
{
Vector<T> vecFromFile;
if( !vecFromFile.read(is) ) return false;
this->assign(vecFromFile);
return true;
}
FUNCTION_H
bool write(iOstream& os) const
{
// since the object should be const, no way to syncViews
Vector<T, noConstructAllocator<T>> vecToFile(this->size());
hostViewType1D<T> mirror(vecToFile.data(), vecToFile.size());
if(hostRequiresSync()) // device is updated
{
//const auto dVec = Kokkos::subview(dualView_.d_view, Kokkos::make_pair(0,int(size_)));
Kokkos::deep_copy(mirror,deviceVector());
}
else // either host is updated or both sides are syncronized
{
//const auto hVec = Kokkos::subview(dualView_.h_view, Kokkos::make_pair(0,int(size_)));
Kokkos::deep_copy(mirror,hostVector());
}
return vecToFile.write(os);
}
};
template<typename T, typename memory_space>
inline iIstream& operator >> (iIstream & is, VectorDual<T, memory_space> & ivec )
{
if( !ivec.read(is) )
{
ioErrorInFile (is.name(), is.lineNumber());
fatalExit;
}
return is;
}
template<typename T, typename memory_space>
inline iOstream& operator << (iOstream& os, const VectorDual<T, memory_space>& ovec )
{
if( !ovec.write(os) )
{
ioErrorInFile(os.name(), os.lineNumber());
fatalExit;
}
return os;
}
} // pFlow
#include "VectorDualAlgorithms.H"
#endif //__VectorDual_H__

View File

@ -0,0 +1,113 @@
/*------------------------------- 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 __VectorDualMath_H__
#define __VectorDualMath_H__
#include "baseAlgorithms.H"
namespace pFlow
{
// - select the side (HostSide or DeviceSide)
template<typename side, typename T, typename MemorySpace>
INLINE_FUNCTION_H
int64 count(const VectorDual<T,MemorySpace>& vec, const T& val)
{
if constexpr (std::is_same<side,HostSide>::value)
{
return count( vec.hostVectorAll(), static_cast<size_t>(0), vec.size(), val);
}
else
{
return count( vec.deviceVectorAll(), static_cast<size_t>(0), vec.size(), val);
}
return -1;
}
// default to device side
template<typename T, typename MemorySpace>
INLINE_FUNCTION_H
int64 count(const VectorDual<T,MemorySpace>& vec, const T& val)
{
return count<DeviceSide>( vec, val);
}
template<typename side, typename T, typename MemorySpace>
INLINE_FUNCTION_H
int64 min(const VectorDual<T,MemorySpace>& vec)
{
if constexpr (std::is_same<side,HostSide>::value)
{
return min( vec.hostVectorAll(), static_cast<size_t>(0), vec.size());
}
else
{
return min( vec.deviceVectorAll(), static_cast<size_t>(0), vec.size());
}
return 0.0;
}
// default to device side
template<typename T, typename MemorySpace>
INLINE_FUNCTION_H
int64 min(const VectorDual<T,MemorySpace>& vec)
{
return min<DeviceSide>( vec);
}
template<typename side, typename T, typename MemorySpace>
INLINE_FUNCTION_H
int64 max(const VectorDual<T,MemorySpace>& vec)
{
if constexpr (std::is_same<side,HostSide>::value)
{
return max( vec.hostVectorAll(), static_cast<size_t>(0), vec.size());
}
else
{
return max( vec.deviceVectorAll(), static_cast<size_t>(0), vec.size());
}
return 0.0;
}
// default to device side
template<typename T, typename MemorySpace>
INLINE_FUNCTION_H
int64 max(const VectorDual<T,MemorySpace>& vec)
{
return max<DeviceSide>( vec);
}
} // pFlow
#endif // __VectorSingleMath_H__

View File

@ -0,0 +1,52 @@
/*------------------------------- 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 __VectorDuals_H__
#define __VectorDuals_H__
#include "types.H"
#include "VectorDual.H"
namespace pFlow
{
using int8Vector_HD = VectorDual<int8>;
using int16Vector_HD = VectorDual<int16>;
using int32Vector_HD = VectorDual<int32>;
using int64Vector_HD = VectorDual<int64>;
using uint32Vector_HD = VectorDual<uint32>;
using labelVector_HD = VectorDual<label>;
using realVector_HD = VectorDual<real>;
using realx3Vector_HD = VectorDual<realx3>;
using realx3x3Vector_HD = VectorDual<realx3x3>;
}
#endif

View File

@ -0,0 +1,859 @@
/*------------------------------- 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 __VectorSingle_H__
#define __VectorSingle_H__
#include "globalSettings.H"
#include "types.H"
#include "typeInfo.H"
#include "Vector.H"
#include "indexContainer.H"
#include "KokkosTypes.H"
#include "ViewAlgorithms.H"
#ifndef __RESERVE__
#define __RESERVE__
struct RESERVE{};
#endif
namespace pFlow
{
template<typename T, typename MemorySpace>
class VectorSingle;
template<typename T, typename MemorySpace=void>
class VectorSingle
{
public:
// viewType (view of data host and device)
using VectorType = VectorSingle<T, MemorySpace>;
using iterator = T*;
using constIterator = const T*;
using reference = T&;
using constReference = const T&;
using valueType = T;
using pointer = T*;
using constPointer = const T*;
// type defs related to Kokkos
using viewType = ViewType1D<T, MemorySpace>;
using deviceType = typename viewType::device_type;
using memory_space = typename viewType::memory_space;
using execution_space = typename viewType::execution_space;
protected:
size_t size_ = 0;
size_t capacity_ = 0;
viewType view_;
mutable viewType subView_;
mutable bool subViewUpdated_ = false;
static const inline real growthFactor_ = vectorGrowthFactor__;
static constexpr bool isHostAccessible_ =
Kokkos::SpaceAccessibility<execution_space,Kokkos::HostSpace>::accessible;
constexpr static inline const char* memoerySpaceName()
{
return memory_space::name();
}
static INLINE_FUNCTION_H size_t evalCapacity(size_t n)
{
return static_cast<size_t>(n*growthFactor_+1);
}
// use actualCap = true only for reserve
INLINE_FUNCTION_H void changeSize(size_t n, bool actualCap=false)
{
if(n >= capacity_ )
{
if(actualCap)
capacity_ = n;
else
capacity_ = evalCapacity(n);
Kokkos::resize(view_, capacity_);
subViewUpdated_ = false;
}
if(!actualCap)
{
setSize(n);
}
}
INLINE_FUNCTION_H void setSize(size_t n)
{
size_ = n;
subViewUpdated_ = false;
}
// - update subview
INLINE_FUNCTION_H void updateSubView()const
{
if(subViewUpdated_) return;
subView_ = Kokkos::subview(view_, Kokkos::make_pair(0,int(size_)));
subViewUpdated_ = true;
}
public:
// - type info
TypeNameTemplateNV2("VectorSingle", T, memoerySpaceName());
//// - Constructors
// - empty constructor
VectorSingle()
:
VectorSingle("VectorSingle")
{}
// empty vector with a name
VectorSingle(const word& name)
:
size_(0),
capacity_(2),
view_(name,capacity_)
{
changeSize(size_);
}
// - a vector with size n
VectorSingle(size_t n)
:
VectorSingle("VectorSingle",n)
{}
// - a vector with name and size n
VectorSingle(const word& name, size_t n)
:
size_(n),
capacity_(evalCapacity(n)),
view_(name, capacity_)
{
changeSize(size_);
}
// a vector with size and value
VectorSingle(size_t n, const T& val)
:
VectorSingle("VectorSingle", n , val)
{}
// a vector with name, size and value
VectorSingle(const word& name, size_t n, const T& val)
:
VectorSingle(name, n)
{
assign(n, val);
}
// a vector with name and reserved capacity
VectorSingle(size_t cap, size_t n, RESERVE )
:
VectorSingle("VectorSingle", cap, n, RESERVE())
{}
// a vector with name and reserved capacity
VectorSingle(const word& name, size_t cap, size_t n, RESERVE )
:
VectorSingle(name)
{
reallocate(cap);
size_ = n;
}
// - construct from pFlow::Vector (host memory)
VectorSingle(const Vector<T> & src)
:
VectorSingle("VectorSingle", src)
{}
// - construct from pFlow::Vector and name
VectorSingle(const word& name, const Vector<T> & src)
:
VectorSingle(name)
{
assign(src);
}
// - copy construct (perform deep copy)
VectorSingle(const VectorSingle& src)
:
VectorSingle(src.name(), src.capacity(), src.size(), RESERVE())
{
copy(deviceVectorAll(), src.deviceVectorAll());
////Kokkos::deep_copy(deviceVectorAll(), src.deviceVectorAll());
}
// - copy construct with a new name
VectorSingle(const word& name, const VectorSingle& src)
:
VectorSingle(name, src.capacity(), src.size(), RESERVE())
{
copy(deviceVectorAll(), src.deviceVectorAll());
////Kokkos::deep_copy(deviceVectorAll(), src.deviceVectorAll());
}
// - copy assignment
VectorSingle& operator = (const VectorSingle& rhs)
{
if(&rhs == this) return *this;
VectorSingle temp(rhs);
capacity_ = temp.capacity();
size_ = temp.size();
view_ = temp.view_;
subViewUpdated_ = false;
return *this;
}
// no move construct
VectorSingle(VectorSingle&&) = delete;
// no move assignment
VectorSingle& operator= (VectorSingle&&) = delete;
// - clone as a uniquePtr
INLINE_FUNCTION_H
uniquePtr<VectorSingle> clone() const
{
return makeUnique<VectorSingle>(*this);
}
// - clone as a pointer
INLINE_FUNCTION_H
VectorSingle* clonePtr()const
{
return new VectorSingle(*this);
}
//// - Methods
// - return *this
INLINE_FUNCTION_H
VectorType& VectorField()
{
return *this;
}
// - return *this
INLINE_FUNCTION_H
const VectorType& VectorField()const
{
return *this;
}
// - Device vector range [0,capcity)
INLINE_FUNCTION_H
viewType& deviceVectorAll(){
return view_;
}
// - Device vector range [0,capacity)
INLINE_FUNCTION_H
const viewType& deviceVectorAll() const {
return view_;
}
// - Device vector range [0, size)
INLINE_FUNCTION_H
viewType& deviceVector(){
updateSubView();
return subView_;
}
// - Device vector range [0, size)
INLINE_FUNCTION_H
const viewType& deviceVector()const{
updateSubView();
return subView_;
}
INLINE_FUNCTION_H
const auto hostVectorAll()const
{
auto hView = Kokkos::create_mirror_view(view_);
copy(hView, view_);
return hView;
}
INLINE_FUNCTION_H
auto hostVectorAll()
{
auto hView = Kokkos::create_mirror_view(view_);
copy(hView, view_);
return hView;
}
INLINE_FUNCTION_H
const auto hostVector()const
{
auto hView = Kokkos::create_mirror_view(deviceVector());
copy(hView, deviceVector());
return hView;
}
INLINE_FUNCTION_H
auto hostVector()
{
auto hView = Kokkos::create_mirror_view(deviceVector());
copy(hView, deviceVector());
return hView;
}
// - name of vector
INLINE_FUNCTION_H
const word name()const
{
return view_.label();
}
// - size of vector
INLINE_FUNCTION_H
size_t size()const
{
return size_;
}
// - capcity of vector
INLINE_FUNCTION_H
size_t capacity()const
{
return capacity_;
}
// - if vector is empty
INLINE_FUNCTION_H
bool empty()const
{
return size_==0;
}
// - reserve capacity for vector
// preserve the content
INLINE_FUNCTION_H
void reserve(size_t cap)
{
changeSize(cap, true);
}
// - reallocate memory
INLINE_FUNCTION_H void reallocate(size_t cap)
{
capacity_ = cap;
size_ = 0;
reallocNoInit(view_, capacity_);
subViewUpdated_ = false;
}
INLINE_FUNCTION_H void reallocate(size_t cap, size_t size)
{
capacity_ = cap;
size_ = size;
reallocNoInit(view_, capacity_);
subViewUpdated_ = false;
}
// resize the vector
INLINE_FUNCTION_H
void resize(size_t n){
changeSize(n);
}
// resize the view and assign value to the most recent view (most updated)
INLINE_FUNCTION_H
void resize(size_t n, const T& val) {
assign(n, val);
}
// - clear the vector
INLINE_FUNCTION_H
void clear() {
size_ = 0;
subViewUpdated_ = false;
}
// - fill the range [0,size) with val
INLINE_FUNCTION_H
void fill(const T& val)
{
if(empty())return;
pFlow::fill(deviceVectorAll(),0 ,size_ ,val);
}
// - host calls only
// - assign n first elements to val
// resize view
// assign value to either side (device/host)
INLINE_FUNCTION_H
void assign(size_t n, const T& val)
{
if(capacity()<n)
{
this->reallocate(evalCapacity(n));
}
size_ = n;
this->fill(val);
}
// - host calls only
// - assign source vector
// resize views
// assign to both sides (device&host)
INLINE_FUNCTION_H void assign(const Vector<T>& src)
{
auto srcSize = src.size();
if( capacity() < srcSize )
{
this->reallocate( src.capacity() );
}
size_ = srcSize;
// - unmanaged view in the host
hostViewType1D<const T> temp(src.data(), srcSize );
copy(deviceVector(), temp);
}
//TODO: change it to parallel version
// - delete elements from vector
// similar memory spaces
/*template<class indT, class MSpace>
INLINE_FUNCTION_H
typename std::enable_if<
Kokkos::SpaceAccessibility<
execution_space, typename VectorSingle<indT,MSpace>::memory_space>::accessible,
bool>::type
deleteElement
(
const VectorSingle<indT,MSpace>& sortedIndices
)
{
auto& indices = sortedIndices.deviceVectorAll();
auto& dVec = deviceVectorAll();
indT numInd = sortedIndices.size();
indT oldSize = this->size();
if( numInd == 0 )return true;
// an scalalr
Kokkos::parallel_for(1, LAMBDA_HD(int nn)
{
(void)nn;
indT n = 0;
indT nextInd = indices[0];
indT j = indices[0];
for(label i=indices[0]; i < oldSize; ++i)
{
if( n < numInd && i == nextInd )
{
++n;
nextInd = indices[n];
}
else
{
dVec[j] = dVec[i];
++j;
}
}
});
typename viewType::execution_space().fence();
size_ = oldSize - indices.size();
subViewUpdated_ = false;
return true;
}
// different memory spaces
template<class indT, class MSpace>
INLINE_FUNCTION_H
typename std::enable_if<
! Kokkos::SpaceAccessibility<
execution_space, typename VectorSingle<indT,MSpace>::memory_space>::accessible,
bool>::type
deleteElement
(
const VectorSingle<indT,MSpace>& sortedIndices
)
{
notImplementedFunction;
}*/
INLINE_FUNCTION_H
bool insertSetElement(const int32IndexContainer& indices, const T& val)
{
if(indices.empty()) return true;
auto maxInd = indices.max();
if(this->empty() || maxInd > size()-1 )
{
resize(maxInd+1);
}
if constexpr (isHostAccessible_)
{
fillSelected(deviceVectorAll(), indices.hostView(), indices.size(), val);
return true;
}else
{
fillSelected(deviceVectorAll(), indices.deviceView(), indices.size(), val);
return true;
}
return false;
}
INLINE_FUNCTION_H
bool insertSetElement(const int32IndexContainer& indices, const Vector<T>& vals)
{
if(indices.size() == 0)return true;
if(indices.size() != vals.size())return false;
auto maxInd = indices.max();
if(this->empty() || maxInd > size()-1 )
{
resize(maxInd+1);
}
if constexpr (isHostAccessible_)
{
// TODO: remove const_cast
hostViewType1D<T> dVecVals( const_cast<T*>(vals.data()), vals.size());
pFlow::algorithms::KOKKOS::fillSelected<T, int32, execution_space>(
deviceVectorAll().data(),
indices.hostView().data(),
dVecVals.data(),
indices.size());
return true;
}else
{
// TODO: remove const_cast
hostViewType1D<T> hVecVals( const_cast<T*>(vals.data()), vals.size());
deviceViewType1D<T> dVecVals("dVecVals", indices.size());
copy(dVecVals, hVecVals);
pFlow::algorithms::KOKKOS::fillSelected<T, int32, execution_space>(
deviceVectorAll().data(),
indices.deviceView().data(),
dVecVals.data(),
indices.size());
return true;
}
return false;
}
INLINE_FUNCTION_H
bool insertSetElement(const Vector<int32>& indices, const T& val)
{
if(indices.empty()) return true;
auto maxInd = max(indices);
if(this->empty() || maxInd > size()-1 )
{
resize(maxInd+1);
}
if constexpr (isHostAccessible_)
{
hostViewType1D<int32> hostView(const_cast<int32*>(indices.data()), indices.size());
fillSelected(deviceVectorAll(), hostView, indices.size(), val);
return true;
}else
{
// TODO: remove the const_cast
hostViewType1D<int32> hostView(const_cast<int32*>(indices.data()), indices.size());
deviceViewType1D<int32> dView("dView", indices.size());
copy(dView, hostView);
fillSelected(deviceVectorAll(), dView, indices.size(), val);
return true;
}
return false;
}
INLINE_FUNCTION_H
bool insertSetElement(const Vector<int32>& indices, const Vector<T>& vals)
{
if(indices.size() == 0)return true;
if(indices.size() != vals.size())return false;
auto maxInd = max(indices);
if(this->empty() || maxInd > size()-1 )
{
resize(maxInd+1);
}
if constexpr (isHostAccessible_)
{
// TODO: remove const_cast
hostViewType1D<int32> hVecInd( const_cast<int32*>(indices.data()), indices.size());
hostViewType1D<T> hVecVals( const_cast<T*>(vals.data()), vals.size());
fillSelected(deviceVectorAll(), hVecInd, hVecVals, indices.size());
return true;
}else
{
// TODO: remove const_cast
hostViewType1D<int32> hVecInd( const_cast<int32*>(indices.data()), indices.size());
deviceViewType1D<int32> dVecInd("dVecInd", indices.size());
hostViewType1D<T> hVecVals( const_cast<T*>(vals.data()), vals.size());
deviceViewType1D<T> dVecVals("dVecVals", indices.size());
copy(dVecVals, hVecVals);
copy(dVecInd, hVecInd);
fillSelected(deviceVectorAll(), dVecInd, dVecVals, indices.size());
return true;
}
return false;
}
INLINE_FUNCTION_H
bool append(const deviceViewType1D<T>& dVec, size_t numElems)
{
if(numElems == 0 )return true;
auto oldSize = size_;
auto newSize = size_ + numElems;
if(this->empty() || newSize > capacity() )
{
resize(newSize);
}
else
{
size_ = size_+numElems;
}
auto dSubView = Kokkos::subview(view_, Kokkos::make_pair(oldSize, newSize));
copy(dSubView, dVec);
return true;
}
INLINE_FUNCTION_H
bool append(const VectorSingle& Vec)
{
return append(Vec.deviceVector(), Vec.size());
}
// - host calls only
// push a new element at the end
// resize if necessary
// works on host accessible vector
template<bool Enable = true>
typename std::enable_if<
isHostAccessible_ && Enable,
void>::type
push_back(const T& val)
{
if(size_ == capacity_) changeSize(capacity_);
data()[size_++] = val;
subViewUpdated_ = false;
}
INLINE_FUNCTION_H pointer data(){
return view_.data();
}
INLINE_FUNCTION_H constPointer data()const{
return view_.data();
}
// - host calls only
// works on host accessible vector
// returns begin iterator
template<bool Enable = true>
INLINE_FUNCTION_H
typename std::enable_if_t<
isHostAccessible_ && Enable,
iterator>
begin(){
return data();
}
// - host calls only
// works on host accessible vector
// returns begin iterator
template<bool Enable = true>
INLINE_FUNCTION_H
typename std::enable_if<
isHostAccessible_ && Enable,
constIterator>::type
begin()const {
return data();
}
// - host calls only
// works on host accessible vector
// returns end iterator
template<bool Enable = true>
INLINE_FUNCTION_H
typename std::enable_if<
isHostAccessible_ && Enable,
iterator>::type
end(){
return size_ > 0 ? data() + size_: data();
}
// host call
// returns end iterator
template<bool Enable = true>
INLINE_FUNCTION_H
typename std::enable_if<
isHostAccessible_ && Enable,
constIterator>::type
end()const{
return size_ > 0 ? data() + size_: data();
}
// operator to be used on host side vectors
template<bool Enable = true>
INLINE_FUNCTION_H
typename std::enable_if<
isHostAccessible_ && Enable,
reference>::type
operator[](label i){
return view_[i];
}
template<bool Enable = true>
INLINE_FUNCTION_H
typename std::enable_if<
isHostAccessible_ && Enable,
constReference>::type
operator[](label i)const{
return view_[i];
}
//// - IO operations
FUNCTION_H
bool read(iIstream& is)
{
Vector<T> vecFromFile;
if( !vecFromFile.read(is) ) return false;
this->assign(vecFromFile);
return true;
}
FUNCTION_H
bool write(iOstream& os)const
{
Vector<T, noConstructAllocator<T>> vecToFile(this->size());
const auto dVec = Kokkos::subview(view_, Kokkos::make_pair(0,int(size_)));
hostViewType1D<T> mirror(vecToFile.data(), vecToFile.size());
copy(mirror,dVec);
return vecToFile.write(os);
}
}; // class VectorSingle
template<typename T, typename MemorySpace>
inline iIstream& operator >> (iIstream & is, VectorSingle<T, MemorySpace> & ivec )
{
if( !ivec.read(is) )
{
ioErrorInFile (is.name(), is.lineNumber());
fatalExit;
}
return is;
}
template<typename T, typename MemorySpace>
inline iOstream& operator << (iOstream& os, const VectorSingle<T, MemorySpace>& ovec )
{
if( !ovec.write(os) )
{
ioErrorInFile(os.name(), os.lineNumber());
fatalExit;
}
return os;
}
} // - pFlow
#include "VectorSingleAlgorithms.H"
#endif //__VectorSingle_H__

View File

@ -0,0 +1,61 @@
/*------------------------------- 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 __VectorSingleMath_H__
#define __VectorSingleMath_H__
namespace pFlow
{
template<typename T, typename MemorySpace>
INLINE_FUNCTION_H
size_t count(const VectorSingle<T,MemorySpace>& vec, const T& val)
{
return count( vec.deviceVectorAll(), 0, vec.size(), val);
}
template<class T, class MemorySpace>
INLINE_FUNCTION_H T min( const VectorSingle<T,MemorySpace>& vec)
{
return min(
vec.deviceVectorAll(),
0, vec.size()
);
}
template<class T, class MemorySpace>
INLINE_FUNCTION_H T max( const VectorSingle<T, MemorySpace>& vec)
{
return min(
vec.deviceVectorAll(),
0, vec.size()
);
}
}
#endif // __VectorSingleMath_H__

View File

@ -0,0 +1,86 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
#ifndef __VectorSingles_H__
#define __VectorSingles_H__
#include "types.H"
#include "VectorSingle.H"
namespace pFlow
{
typedef VectorSingle<int8> int8Vector_D;
typedef VectorSingle<int8, HostSpace> int8Vector_H;
typedef VectorSingle<int16> int16Vector_D;
typedef VectorSingle<int16, HostSpace> int16Vector_H;
typedef VectorSingle<int32> int32Vector_D;
typedef VectorSingle<int32, HostSpace> int32Vector_H;
typedef VectorSingle<int64> int64Vector_D;
typedef VectorSingle<int64, HostSpace> int64Vector_H;
typedef VectorSingle<uint32> uint32Vector_D;
typedef VectorSingle<uint32, HostSpace> uint32Vector_H;
typedef VectorSingle<label> labelVector_D;
typedef VectorSingle<label, HostSpace> labelVector_H;
typedef VectorSingle<real> realVector_D;
typedef VectorSingle<real, HostSpace> realVector_H;
typedef VectorSingle<realx3> realx3Vector_D;
typedef VectorSingle<realx3, HostSpace> realx3Vector_H;
typedef VectorSingle<uint16x3> uint16x3Vector_D;
typedef VectorSingle<uint16x3, HostSpace> uint16x3Vector_H;
typedef VectorSingle<uint32x3> uint32x3Vector_D;
typedef VectorSingle<uint32x3, HostSpace> uint32x3Vector_H;
typedef VectorSingle<int32x3> int32x3Vector_D;
typedef VectorSingle<int32x3, HostSpace> int32x3Vector_H;
typedef VectorSingle<int64x3> int64x3Vector_D;
typedef VectorSingle<int64x3, HostSpace> int64x3Vector_H;
typedef VectorSingle<realx3x3> realx3x3Vector_D;
typedef VectorSingle<realx3x3, HostSpace> realx3x3Vector_H;
}
#endif

View File

@ -0,0 +1,223 @@
/*------------------------------- 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 __bitsetHD_H__
#define __bitsetHD_H__
#include "KokkosTypes.H"
#include "types.H"
// a lightweight container for holding bits on host or device
// it is NOT concurrent and it does not used atommic operation on memory
namespace pFlow
{
template<typename blockType, typename MemorySpace=void>
class bitsetHD
{
public:
using BlockType = blockType;
using blockViewType = Kokkos::View<BlockType*, Kokkos::LayoutLeft, MemorySpace>;
using deviceType = typename blockViewType::device_type;
using memory_space = typename blockViewType::memory_space;
using execution_space = typename blockViewType::execution_space;
protected:
int32 numBlocks_;
int32 numBits_;
blockViewType blocks_;
const static inline
int32 bitsPerBlock_ = std::numeric_limits<BlockType>::digits;
const static inline
int32 blockMask_ = bitsPerBlock_ - 1;
static INLINE_FUNCTION_HD
int32 blockIndex(int32 pos)
{
return pos/bitsPerBlock_;
}
static INLINE_FUNCTION_HD
BlockType bitIndex(int32 pos)
{
return static_cast<BlockType>(pos%bitsPerBlock_);
}
static INLINE_FUNCTION_HD
BlockType blockMask(int32 pos)
{
return static_cast<BlockType> (1 <<(pos & blockMask_));
}
static INLINE_FUNCTION_HD
int32 calculateBlockSize(int32 numBits)
{
return numBits/bitsPerBlock_ + 1;
}
public:
bitsetHD(const word& name, int32 numBits)
:
numBlocks_(calculateBlockSize(numBits)),
numBits_(numBits),
blocks_(name, numBlocks_)
{
}
bitsetHD(const bitsetHD&) = default;
bitsetHD(bitsetHD&&) = default;
bitsetHD& operator=(const bitsetHD&) = default;
bitsetHD& operator=(bitsetHD&&) = default;
void set()
{
Kokkos::deep_copy(blocks_, ~0);
}
void reset()
{
Kokkos::deep_copy( blocks_ , static_cast<BlockType>(0));
}
void clear()
{
Kokkos::deep_copy( blocks_ , static_cast<BlockType>(0));
}
INLINE_FUNCTION_HD
void set(int32 pos) const
{
BlockType& block = blocks_[blockIndex(pos)];
block |= blockMask(pos);
}
INLINE_FUNCTION_HD
void unset(int32 pos)const
{
BlockType& block = blocks_[blockIndex(pos)];
block &= (~blockMask(pos));
}
INLINE_FUNCTION_HD
void reset(int32 pos)const
{
unset(pos);
}
INLINE_FUNCTION_HD
void flip(int32 pos)const
{
BlockType& block = blocks_[blockIndex(pos)];
block ^= blockMask(pos);
}
INLINE_FUNCTION_HD
bool isSet(int32 pos)const
{
BlockType& block = blocks_[blockIndex(pos)];
return block & blockMask(pos);
}
INLINE_FUNCTION_HD
bool isUnset(int32 pos)const
{
return !isSet(pos);
}
INLINE_FUNCTION_HD
bool isSetReset(int32 pos)const
{
BlockType& block = blocks_[blockIndex(pos)];
auto mask = blockMask(pos);
bool is_set = block & mask;
block &= (~mask);
return is_set;
}
INLINE_FUNCTION_HD
int32 numBlocks()const
{
return numBlocks_;
}
INLINE_FUNCTION_HD
int32 numBits()const
{
return numBits_;
}
INLINE_FUNCTION_HD
int32 size()const
{
return numBits_;
}
INLINE_FUNCTION_HD
int32 capacity()const
{
return numBlocks_*bitsPerBlock_;
}
INLINE_FUNCTION_H
void realloc(int32 numBits)
{
numBlocks_ = calculateBlockSize(numBits);
numBits_ = numBits;
Kokkos::realloc(blocks_, numBlocks_);
}
};
using bitset32_D = bitsetHD<unsigned>;
using bitset32_H = bitsetHD<unsigned, HostSpace>;
using bitset64_D = bitsetHD<unsigned long>;
using bitset64_H = bitsetHD<unsigned long, HostSpace>;
} // namespace pFlow
#endif //__bitsetHD_H__

View File

@ -0,0 +1,27 @@
/*------------------------------- 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 "bitsetHD.H"
template class pFlow::bitsetHD<unsigned>;

View File

@ -0,0 +1,21 @@
/*------------------------------- 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 "indexContainer.H"

View File

@ -0,0 +1,171 @@
/*------------------------------- 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 __indexContainer_H__
#define __indexContainer_H__
#include "span.H"
#include "KokkosTypes.H"
#include "KokkosUtilities.H"
#include "ViewAlgorithms.H"
namespace pFlow
{
template<typename IndexType>
class indexContainer
{
public:
using DualViewType = Kokkos::DualView<IndexType*>;
// - viewType of data on device
using DeviceViewType = typename DualViewType::t_dev;
// - viewType of data on host
using HostViewType = typename DualViewType::t_host;
template<typename ViewType>
class IndexAccessor
{
protected:
ViewType view_;
public:
IndexAccessor(ViewType v):
view_(v){}
INLINE_FUNCTION_HD
IndexType operator()(int32 i)const
{
return view_[i];
}
};
protected:
int32 min_ = 0;
int32 max_ = 0;
size_t size_ = 0;
DualViewType views_;
public:
indexContainer(){}
// half open [begin,end)
indexContainer(IndexType begin, IndexType end)
:
min_(begin),
max_(end-1),
size_(end-begin),
views_("indexContainer", size_)
{
pFlow::fillSequence(views_.d_view, 0, size_, min_);
copy(views_.h_view, views_.d_view);
}
indexContainer(IndexType* data, int32 numElems)
:
size_(numElems),
views_("indexContainer", numElems)
{
HostViewType hData(data, numElems);
copy(views_.h_view, hData);
copy(views_.d_view, views_.h_view);
min_ = pFlow::min(views_.d_view, 0, numElems);
max_ = pFlow::max(views_.d_view, 0, numElems);
}
indexContainer(const indexContainer&) = default;
indexContainer& operator = (const indexContainer&) = default;
~indexContainer() = default;
INLINE_FUNCTION_HD
size_t size()const
{
return size_;
}
INLINE_FUNCTION_HD
size_t empty()const
{
return size_==0;
}
INLINE_FUNCTION_HD
IndexType min()const
{
return min_;
}
INLINE_FUNCTION_HD
IndexType max()const
{
return max_;
}
template<typename executionSpace>
INLINE_FUNCTION_HD
IndexType operator()(selectSide<executionSpace>,int32 i)const
{
if constexpr (isHostAccessible<executionSpace>())
{
return views_.h_view(i);
}else
{
return views_.d_view(i);
}
}
const HostViewType& hostView()const
{
return views_.h_view;
}
const DeviceViewType& deviceView()const
{
return views_.d_view;
}
auto indicesHost()const
{
return IndexAccessor<HostViewType>(views_.h_view);
}
auto indicesDevice()const
{
return IndexAccessor<DeviceViewType>(views_.d_veiw);
}
};
using int32IndexContainer = indexContainer<int32>;
using int64IndexContainer = indexContainer<int64>;
}
#endif

View File

@ -0,0 +1,129 @@
/*------------------------------- 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<template<class, class> class VectorField, class T, class MemorySpace>
bool pFlow::pointField<VectorField, T, MemorySpace>::readPointField
(
iIstream& is
)
{
return FieldType::readField(is, pStruct_.size(), false);
}
template<template<class, class> class VectorField, class T, class MemorySpace>
bool pFlow::pointField<VectorField, T, MemorySpace>::writePointField
(
iOstream& os
)const
{
return FieldType::write(os);
}
template<template<class, class> class VectorField, class T, class MemorySpace>
pFlow::pointField<VectorField, T, MemorySpace>::pointField
(
const pointStructure& pStruct,
const T& defVal,
bool subscribe
)
:
eventObserver(pStruct, subscribe),
FieldType(pStruct.capacity(), pStruct.size(), RESERVE()),
pStruct_(pStruct),
defaultValue_(defVal)
{
// set value
this->fill(defVal);
}
template<template<class, class> class VectorField, class T, class MemorySpace>
pFlow::pointField<VectorField, T, MemorySpace>::pointField
(
const pointStructure& pStruct,
const T& val,
const T& defVal,
bool subscribe
)
:
eventObserver(pStruct, subscribe),
FieldType(pStruct.capacity(), pStruct.size(), RESERVE()),
pStruct_(pStruct),
defaultValue_(defVal)
{
this->fill(val);
}
template<template<class, class> class VectorField, class T, class MemorySpace>
pFlow::pointField<VectorField, T, MemorySpace>::pointField
(
const pointField& src,
bool subscribe
)
:
eventObserver(src.pStruct(), subscribe),
FieldType(src),
pStruct_(src.pStruct()),
defaultValue_(src.defaultValue_)
{}
template<template<class, class> class VectorField, class T, class MemorySpace>
pFlow::pointField<VectorField, T, MemorySpace>::pointField(const pointField& src)
:
pointField<VectorField, T, MemorySpace>(src, src.subscribed())
{}
template<template<class, class> class VectorField, class T, class MemorySpace>
pFlow::pointField<VectorField, T, MemorySpace>& pFlow::pointField<VectorField, T, MemorySpace>::operator =
(
const pointField& rhs
)
{
if(this == &rhs) return *this;
this->VectorField() = rhs.VectorField();
return *this;
}
template<template<class, class> class VectorField, class T, class MemorySpace>
bool pFlow::pointField<VectorField, T, MemorySpace>::update(const eventMessage& msg)
{
if( msg.isDeleted() )
{
/*const auto& dp = pStruct_.markedDeletePoints();
return this->deleteElement(dp);
notImplementedFunction;*/
}
else if( msg.isInsert())
{
const auto newElems = pStruct().insertedPointIndex();
//Vector<T> vals( newElems.size(), defaultValue_);
return this->insertSetElement(newElems, defaultValue_);
}
return true;
}

View File

@ -0,0 +1,196 @@
/*------------------------------- 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 __pointField_H__
#define __pointField_H__
#include "Field.H"
#include "pointStructure.H"
#include "error.H"
namespace pFlow
{
template<template<class, class> class VectorField, class T, class MemorySpace=void>
class pointField
:
public eventObserver,
public Field<VectorField, T, MemorySpace>
{
public:
using pointFieldType = pointField<VectorField, T, MemorySpace>;
using FieldType = Field<VectorField, T, MemorySpace>;
using VectorType = typename FieldType::VectorType;
using iterator = typename FieldType::iterator;
using constIterator = typename FieldType::constIterator;
using reference = typename FieldType::reference;
using constReference = typename FieldType::constReference;
using valueType = typename FieldType::valueType;
using pointer = typename FieldType::pointer;
using constPointer = typename FieldType::constPointer;
protected:
////- data members
const pointStructure& pStruct_;
// - value when a new item is added to field
T defaultValue_;
public:
// - type info
TypeNameTemplateNV2("pointField", T, VectorType::memoerySpaceName());
//// - Constructors
// - construct a field from pointStructure and set defaultValue_ and field value to defVal
pointField( const pointStructure& pStruct, const T& defVal, bool subscribe = true);
// - construct from iIOEntity, pointStructure and a value
pointField( const pointStructure& pStruct, const T& val, const T& defVal, bool subscribe = true);
// - construct from another pointField
// subscribe to events if true
pointField( const pointField& src, bool subscribe);
// - copy construct
pointField(const pointField& src);
// - no move construct
pointField(pointField&& src) = delete;
// assignment, only assign the VectorField and preserve other parts of this
pointField& operator = (const pointField& rhs);
// no move assignment
pointField& operator = (pointField&&) = delete;
inline uniquePtr<pointFieldType> clone() const
{
return makeUnique<pointFieldType>(*this);
}
inline pointFieldType* clonePtr()const
{
return new pointFieldType(*this);
}
//// - Methods
// - reference to pointStructure
inline const pointStructure& pStruct()const {
return pStruct_;
}
// if all points are active
INLINE_FUNCTION_H
bool allActive()const {
return pStruct_.allActive();
}
INLINE_FUNCTION_H
bool isActive(label i)const {
return pStruct_.isActive(i);
}
const auto& pointFlag()const
{
return pStruct_.pointFlag();
}
range activeRange()const
{
return pStruct_.activeRange();
}
// - update the field if any changes occure in pStruct
// for now it checks for deleted points
bool update(const eventMessage& msg);
//// - IO operations
bool readPointField(iIstream& is);
bool writePointField(iOstream& os)const;
bool read(iIstream& is)
{
return readPointField(is);
}
bool write(iOstream& os)const
{
return writePointField(os);
}
};
template<template<class, class> class VectorField, class T, class MemorySpace>
iIstream& operator >> (iIstream & is, pointField<VectorField, T, MemorySpace> & pF )
{
if( !pF.read(is))
{
ioErrorInFile( is.name(), is.lineNumber() ) <<
"error in reading pointField from file. \n";
fatalExit;
}
return is;
}
template<template<class, class> class VectorField, class T, class MemorySpace>
iOstream& operator << (iOstream& os, const pointField<VectorField, T, MemorySpace>& pF )
{
if(! pF.write(os) )
{
ioErrorInFile( os.name(), os.lineNumber() )<<
"error in writing pointField into file. \n";
fatalExit;
}
return os;
}
}
#include "pointField.C"
#include "pointFieldAlgorithms.H"
#endif // __pointField_H__

View File

@ -0,0 +1,269 @@
/*------------------------------- 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.
-----------------------------------------------------------------------------*/
namespace pFlow
{
const inline auto ActivePoint = pointStructure::ACTIVE;
template<class T, typename... properties>
T maxActive_serial(
const Kokkos::View<T*, properties...>& view,
const Kokkos::View<int8*, Kokkos::LayoutLeft, Kokkos::HostSpace>& flag,
size_t start,
size_t end
)
{
T maxValue = largestNegative<T>();
for(label i=start; i<end; ++i)
{
if(flag[i] == ActivePoint )maxValue = max(maxValue, view[i]);
}
return maxValue;
}
// to be executed on host
template<typename T, typename... properties>
INLINE_FUNCTION_H
T maxActiveH(
const Kokkos::View<T*, properties...>& view,
const Kokkos::View<int8*, Kokkos::LayoutLeft, Kokkos::HostSpace>& flag,
size_t start,
size_t end
)
{
T maxValue = largestNegative<T>();
auto RP = Kokkos::RangePolicy<
Kokkos::IndexType<size_t>,
typename Kokkos::View<T, properties...>::execution_space >(start, end);
Kokkos::parallel_reduce("pointFieldAlgorithms-maxActive",
RP,
LAMBDA_HD(label i, T& valueToUpdate){
if(flag[i] == ActivePoint) valueToUpdate = max(view[i],valueToUpdate);
},
Kokkos::Max<T>( maxValue )
);
return maxValue;
}
// to be executed on device
template<typename T, typename... properties>
INLINE_FUNCTION_H
T maxActiveD(
const Kokkos::View<T*, properties...>& view,
const Kokkos::View<int8*, Kokkos::LayoutLeft>& flag,
size_t start,
size_t end
)
{
T maxValue = largestNegative<T>();
auto RP = Kokkos::RangePolicy<
Kokkos::IndexType<size_t>,
typename Kokkos::View<T, properties...>::execution_space >(start, end);
Kokkos::parallel_reduce("pointFieldAlgorithms-maxActive",
RP,
LAMBDA_HD(label i, T& valueToUpdate){
if(flag[i] == ActivePoint) valueToUpdate = max(view[i],valueToUpdate);
},
Kokkos::Max<T>( maxValue )
);
return maxValue;
}
template<class T, class MemorySpace>
T maxActive(const pointField<VectorSingle, T, MemorySpace>& pField)
{
// if all points are active, perfrom a simple max
if( pField.allActive() )
return max(pField.VectorField());
const auto len = pField.size();
if constexpr ( pField.isHostAccessible())
{
if(len < sizeToSerial__ ) // serial execution instead of lunching parallel execution
return maxActive_serial(
pField.deviceVectorAll(),
pField.pointFlag().hostVectorAll(),
static_cast<size_t>(0),
len
);
else
return maxActiveH(
pField.deviceVectorAll(),
pField.pointFlag().hostVectorAll(),
static_cast<size_t>(0),
len
);
}
else
{
return maxActiveD(
pField.deviceVectorAll(),
pField.pointFlag().deviceVectorAll(),
static_cast<size_t>(0),
len
);
}
// to remove the warning of CUDAC++ compiler when dealing with constexpr
return 0;
}
template<class side, class T, class MemorySpace=void>
T maxActive(const pointField<VectorDual, T, MemorySpace>& pField)
{
if( pField.allActive() )
return max(pField.VectorField());
auto len = pField.size();
if constexpr (std::is_same<side,HostSide>::value)
{
if( len < sizeToSerial__)
return maxActive_serial(
pField.hostVectorAll(),
pField.pointFlag().hostVectorAll(),
static_cast<size_t>(0),
len
);
else
return maxActiveH(
pField.hostVectorAll(),
pField.pointFlag().hostVectorAll(),
static_cast<size_t>(0),
len
);
}else
{
return maxActiveD(
pField.deviceVectorAll(),
pField.pointFlag().deviceVectorAll(),
static_cast<size_t>(0),
len
);
}
return 0;
}
/*template<typename T>
void inline fillActive(pointField<T>& field, const T& val)
{
if(field.pStruct().allActive)
{
fill_n(field, field.size(), val);
return;
}
forAll(i, field)
{
if(field.pStruct().isActive(i)) field[i] = val;
}
}
template<typename T>
void inline fillMarkedDelete( pointField<T>& field, const T& val)
{
if(field.pStruct().allActive())return;
forAll(i,field)
{
if(!field.pStruct().isActive(i)) field[i] = val;
}
}
template<typename T>
inline auto countActive(const pointField<T>& field, const T& val)
{
if(field.pStruct().allActive())
{
return count(field, val);
}
else
{
return count(field, val, [&](label i){return field.pointField().isActive(i);});
}
}
template<typename T, typename UnaryPredicate>
inline auto for_eachActive(pointField<T>& field, UnaryPredicate func)
{
if(field.pStruct().allActive())
{
forAll(i,field)
{
func(i);
}
}
else
{
forAll(i, field)
{
if(field.pStruct().isActive(i)) func(i);
}
}
return func;
}
template<typename T, typename UnaryPredicate>
inline bool for_eachActiveBreak(pointField<T>& field, UnaryPredicate func)
{
if(field.pStruct().allActive())
{
forAll(i,field)
{
if(!func(i))return false;
}
}
else
{
forAll(i, field)
{
if(field.pStruct().isActive(i))
{
if(!func(i)) return false;
}
}
}
return true;
}
template<typename T, typename UnaryPredicate>
inline auto for_eachMarkedDelete(pointField<T>& field, UnaryPredicate func)
{
if(field.pStruct().allActive()) return func;
forAll(i, field)
{
if(!field.pStruct().isActive(i)) func(i);
}
return func;
}*/
}

View File

@ -0,0 +1,58 @@
/*------------------------------- 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 "pointFields.H"
template class pFlow::pointField<pFlow::VectorSingle, pFlow::int8>;
template class pFlow::pointField<pFlow::VectorSingle, pFlow::int8, pFlow::HostSpace>;
template class pFlow::pointField<pFlow::VectorSingle, pFlow::int16>;
template class pFlow::pointField<pFlow::VectorSingle, pFlow::int16, pFlow::HostSpace>;
template class pFlow::pointField<pFlow::VectorSingle, pFlow::int32>;
template class pFlow::pointField<pFlow::VectorSingle, pFlow::int32, pFlow::HostSpace>;
template class pFlow::pointField<pFlow::VectorSingle, pFlow::int64>;
template class pFlow::pointField<pFlow::VectorSingle, pFlow::int64, pFlow::HostSpace>;
template class pFlow::pointField<pFlow::VectorSingle, pFlow::uint32>;
template class pFlow::pointField<pFlow::VectorSingle, pFlow::uint32, pFlow::HostSpace>;
template class pFlow::pointField<pFlow::VectorSingle, pFlow::label>;
template class pFlow::pointField<pFlow::VectorSingle, pFlow::label, pFlow::HostSpace>;
template class pFlow::pointField<pFlow::VectorSingle, pFlow::real>;
template class pFlow::pointField<pFlow::VectorSingle, pFlow::real, pFlow::HostSpace>;
template class pFlow::pointField<pFlow::VectorSingle, pFlow::realx3>;
template class pFlow::pointField<pFlow::VectorSingle, pFlow::realx3, pFlow::HostSpace>;

View File

@ -0,0 +1,88 @@
/*------------------------------- 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 __pointFields_H__
#define __pointFields_H__
#include "VectorSingle.H"
#include "pointField.H"
#include "types.H"
namespace pFlow
{
using int8PointField_D = pointField<VectorSingle, int8>;
using int8PointField_H = pointField<VectorSingle, int8, HostSpace>;
using int16PointField_D = pointField<VectorSingle, int16>;
using int16PointField_H = pointField<VectorSingle, int16, HostSpace>;
using int32PointField_D = pointField<VectorSingle, int32>;
using int32PointField_H = pointField<VectorSingle, int32, HostSpace>;
using int64PointField_D = pointField<VectorSingle, int64>;
using int64PointField_H = pointField<VectorSingle, int64, HostSpace>;
using uint32PointField_D = pointField<VectorSingle, uint32>;
using uint32PointField_H = pointField<VectorSingle, uint32, HostSpace>;
using labelPointField_D = pointField<VectorSingle, label>;
using labelPointField_H = pointField<VectorSingle, label, HostSpace>;
using realPointField_D = pointField<VectorSingle, real>;
using realPointField_H = pointField<VectorSingle, real, HostSpace>;
using realx3PointField_D = pointField<VectorSingle, realx3> ;
using realx3PointField_H = pointField<VectorSingle, realx3, HostSpace>;
using wordPointField_H = pointField<VectorSingle, word, HostSpace>;
using int8PointField_HD = pointField<VectorDual, int8>;
using int16PointField_HD = pointField<VectorDual, int16>;
using int32PointField_HD = pointField<VectorDual, int32>;
using int64PointField_HD = pointField<VectorDual, int64>;
using uint32PointField_HD = pointField<VectorDual, uint32>;
using labelPointField_HD = pointField<VectorDual, label>;
using realPointField_HD = pointField<VectorDual, real>;
using realx3PointField_HD = pointField<VectorDual, realx3>;
using wordPointField = pointField<Vector, word, vecAllocator<word>>;
}
#endif

View File

@ -0,0 +1,161 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
#ifndef __span_H__
#define __span_H__
#include "types.H"
namespace pFlow {
template<typename T>
class span
{
public:
using iterator = T*;
using constIterator = const T*;
using reference = T&;
using constReference = const T&;
using valueType = T;
using pointer = T*;
using constPointer = const T*;
protected:
T* data_ = nullptr;
label size_ = 0;
public:
TypeNameTemplateNV("span", T);
/// Constructor
INLINE_FUNCTION_HD
span() = default;
INLINE_FUNCTION_HD
span(T* data, label size)
: data_(data), size_(size)
{}
/// copy
INLINE_FUNCTION_HD
span(const span&) = default;
/// assignment
INLINE_FUNCTION_HD
span& operator=(const span&) = default;
/// move
INLINE_FUNCTION_HD
span(span&&) = delete;
/// assignment
INLINE_FUNCTION_HD
span& operator=(span&) = delete;
INLINE_FUNCTION_HD
bool empty() const
{
return size_ == 0;
}
INLINE_FUNCTION_HD
T* data() const
{
return data_;
}
/// Returns the number of elements in the span
INLINE_FUNCTION_HD
label size() const
{
return size_;
}
/// Returns an iterator to the beginning of the span
INLINE_FUNCTION_HD
constIterator begin() const
{
return data_;
}
/// Returns an iterator to the beginning of the span
INLINE_FUNCTION_HD
constIterator cbegin() const
{
return data_;
}
/// Returns an iterator to one past the end of the span
INLINE_FUNCTION_HD
constIterator end() const
{
return data_ + size_;
}
/// Returns an iterator to one past the end of the span
INLINE_FUNCTION_HD
constIterator cend() const
{
return data_ + size_;
}
INLINE_FUNCTION_HD
T& operator[](int32 i)
{
data_[i];
}
INLINE_FUNCTION_HD
const T& operator[](int32 i)const
{
data_[i];
}
INLINE_FUNCTION_HD
T& operator[](label i)
{
data_[i];
}
INLINE_FUNCTION_HD
const T& operator[](label i)const
{
data_[i];
}
};
} // pFlow
#endif //__span_H__

View File

@ -0,0 +1,278 @@
/*------------------------------- 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 __symArray_H__
#define __symArray_H__
#include "KokkosTypes.H"
#include "types.H"
#include "typeInfo.H"
#include "Vector.H"
/*
stores the elemnt of a symetric array in the following order in a 1D vector
0 1 2 3
4 5 6
7 8
9
*/
namespace pFlow
{
template<typename Type>
INLINE_FUNCTION_HD
void SWAP(Type &x, Type& y)
{
auto temp = y;
y = x;
x = temp;
}
template<typename T, typename MemorySpace=void>
class symArray
{
using SymArrayType = symArray<T, MemorySpace>;
using iterator = T*;
using constIterator = const T*;
using reference = T&;
using constReference = const T&;
using valueType = T;
using pointer = T*;
using constPointer = const T*;
// type defs related to Kokkos
using ViewType = ViewType1D<T,MemorySpace>;
using deviceType = typename ViewType::device_type;
using memory_space = typename ViewType::memory_space;
using execution_space = typename ViewType::execution_space;
protected:
uint32 n_=0;
ViewType view_;
constexpr static inline const char* memoerySpaceName()
{
return memory_space::name();
}
public:
// - type info
TypeNameTemplateNV2("symArray", T, memoerySpaceName());
//// constructors
INLINE_FUNCTION_H
symArray();
INLINE_FUNCTION_H
symArray(uint32 n)
:
symArray("symArray",n)
{}
INLINE_FUNCTION_H
symArray(word name, uint32 n)
:
n_(n),
view_(name, numElem(n))
{}
INLINE_FUNCTION_H
symArray(word name, uint32 n , const T& val)
:
symArray(name, n)
{
this->fill(val);
}
INLINE_FUNCTION_H
symArray(word name, Vector<T> src)
:
view_(name)
{
if( !assign(src))
{
fatalErrorInFunction<<
"error in creating symArray " << name << endl;
fatalExit;
}
}
INLINE_FUNCTION_H
symArray(const symArray&) = default;
INLINE_FUNCTION_H
symArray& operator=(const symArray&) = default;
INLINE_FUNCTION_H
symArray(symArray&&) = delete;
INLINE_FUNCTION_H
symArray& operator=(symArray&&) = delete;
INLINE_FUNCTION_H
~symArray()=default;
//// - Methods
void fill(const T& val)
{
if(n_==0)return;
Kokkos::deep_copy(view_, val);
}
INLINE_FUNCTION_HD
T& operator()(uint32 i, uint32 j)
{
if(i>j) SWAP(i,j);
return view_(j+i*n_-numElem(i));
}
INLINE_FUNCTION_HD
const T& operator()(uint32 i, uint32 j)const
{
if(i>j) SWAP(i,j);
return view_(j+i*n_-numElem(i));
}
bool assign(const Vector<T> src)
{
uint32 nElem = src.size();
uint32 n;
if( !getN(nElem,n))
{
fatalErrorInFunction<<
"size of input vector do not match a symetric array "<< nElem<<endl;
return false;
}
if(n == 0 )
{
n_ = 0;
return true;
}
if( n > n_ )
Kokkos::realloc(view_, nElem );
n_ = n;
hostViewType1D<const T> temp(src.data(), nElem );
Kokkos::deep_copy(view_, temp);
return true;
}
//// IO operations
FUNCTION_H
bool read(iIstream& is)
{
Vector<T> vecFromFile;
if( !vecFromFile.read(is) ) return false;
this->assign(vecFromFile);
return true;
}
FUNCTION_H
bool write(iOstream& os)const
{
int32 s = numElem(n_);
Vector<T, noConstructAllocator<T>> vecToFile(s);
const auto dVec = Kokkos::subview(view_, kPair<int32,int32>(0, s));
hostViewType1D<T> mirror(vecToFile.data(), vecToFile.size());
Kokkos::deep_copy(mirror,dVec);
return vecToFile.write(os);
}
INLINE_FUNCTION_HD
static uint32 numElem(uint32 n)
{
if(n==0)return 0;
return n*(n+1)/2;
}
static bool getN(uint32 nElem, uint32& n)
{
real nr = 0.5*(sqrt(8.0*nElem+1)-1);
n = static_cast<uint32>(nr);
if( equal(nr-static_cast<real>(n) , 0.0) ) return true;
return false;
}
};
template<typename T, typename MemorySpace>
inline iIstream& operator >> (iIstream & is, symArray<T, MemorySpace> & iArr )
{
if( !iArr.read(is) )
{
ioErrorInFile (is.name(), is.lineNumber());
fatalExit;
}
return is;
}
template<typename T, typename MemorySpace>
inline iOstream& operator << (iOstream& os, const symArray<T, MemorySpace>& oArr )
{
if( !oArr.write(os) )
{
ioErrorInFile(os.name(), os.lineNumber());
fatalExit;
}
return os;
}
}
#endif //__symArray_H__

View File

@ -0,0 +1,29 @@
/*------------------------------- 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 "symArrays.H"
template class pFlow::symArray<pFlow::real>;
template class pFlow::symArray<pFlow::real, pFlow::HostSpace>;
template class pFlow::symArray<pFlow::realx3>;
template class pFlow::symArray<pFlow::realx3, pFlow::HostSpace>;

View File

@ -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.
-----------------------------------------------------------------------------*/
#include "symArrayHD.H"
namespace pFlow
{
using realSymArray_D = symArray<real>;
using realSymArray_H = symArray<real, HostSpace>;
using realx3SymArray_D = symArray<realx3>;
using realx3SymArray_H = symArray<realx3, HostSpace>;
}

View File

@ -0,0 +1,119 @@
/*------------------------------- 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<template<class, class> class VectorField, class T, class MemorySpace>
pFlow::triSurfaceField<VectorField, T, MemorySpace>::triSurfaceField
(
const triSurface& surface,
const T& defVal,
bool subscribe
)
:
eventObserver(surface, subscribe),
FieldType(surface.capacity(), surface.size(), RESERVE()),
surface_(surface),
defaultValue_(defVal)
{
this->fill(defVal);
}
template<template<class, class> class VectorField, class T, class MemorySpace>
pFlow::triSurfaceField<VectorField, T, MemorySpace>::triSurfaceField
(
const triSurface& surface,
const T& val,
const T& defVal,
bool subscribe
)
:
eventObserver(surface, subscribe),
FieldType(surface.capacity(), surface.size(), RESERVE()),
surface_(surface),
defaultValue_(defVal)
{
this->fill(val);
}
template<template<class, class> class VectorField, class T, class MemorySpace>
pFlow::triSurfaceField<VectorField, T, MemorySpace>::triSurfaceField
(
const triSurfaceField& src,
bool subscribe
)
:
eventObserver(src.surface(), subscribe),
FieldType(src),
surface_(src.surface()),
defaultValue_(src.defaultValue_)
{
}
template<template<class, class> class VectorField, class T, class MemorySpace>
pFlow::triSurfaceField<VectorField, T, MemorySpace>::triSurfaceField
(
const triSurfaceField& src
)
:
triSurfaceField<VectorField, T, MemorySpace>(src, src.subscribed())
{}
template<template<class, class> class VectorField, class T, class MemorySpace>
pFlow::triSurfaceField<VectorField, T, MemorySpace>&
pFlow::triSurfaceField<VectorField, T, MemorySpace>::operator=
(
const triSurfaceField& rhs
)
{
if(this == &rhs) return *this;
this->VectorField() = rhs.VectorField();
return *this;
}
template<template<class, class> class VectorField, class T, class MemorySpace>
bool pFlow::triSurfaceField<VectorField, T, MemorySpace>::update
(
const eventMessage& msg
)
{
notImplementedFunction;
return true;
}
template<template<class, class> class VectorField, class T, class MemorySpace>
bool pFlow::triSurfaceField<VectorField, T, MemorySpace>::readTriSurfacceField
(
iIstream& is
)
{
return FieldType::readField(is, surface_.size(), false);
}
template<template<class, class> class VectorField, class T, class MemorySpace>
bool pFlow::triSurfaceField<VectorField, T, MemorySpace>::writeTriSurfaceField
(
iOstream& os
)const
{
return FieldType::write(os);
}

View File

@ -0,0 +1,177 @@
/*------------------------------- 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 __trieSurfaceField_H__
#define __trieSurfaceField_H__
#include "Field.H"
#include "triSurface.H"
#include "error.H"
namespace pFlow
{
template<template<class, class> class VectorField, class T, class MemorySpace=void>
class triSurfaceField
:
public eventObserver,
public Field<VectorField, T, MemorySpace>
{
public:
using triSurfaceFieldType = triSurfaceField<VectorField, T, MemorySpace>;
using FieldType = Field<VectorField, T, MemorySpace>;
using VectorType = typename FieldType::VectorType;
using iterator = typename FieldType::iterator;
using constIterator = typename FieldType::constIterator;
using reference = typename FieldType::reference;
using constReference = typename FieldType::constReference;
using valueType = typename FieldType::valueType;
using pointer = typename FieldType::pointer;
using constPointer = typename FieldType::constPointer;
protected:
////- data members
const triSurface& surface_;
// - value when a new item is added to field
T defaultValue_;
public:
// - type info
TypeNameTemplateNV2("triSurfaceField", T, VectorType::memoerySpaceName());
//// CONSTRUCTORS
// - construct a field from tirSurface and set defaultValue_ and field value to defVal
triSurfaceField( const triSurface& surface, const T& defVal, bool subscribe = true);
// - construct from iIOEntity, tirSurface and a value
triSurfaceField( const triSurface& surface, const T& val, const T& defVal, bool subscribe = true);
// - construct from another triSurfaceField
// subscribe to events if true
triSurfaceField( const triSurfaceField& src, bool subscribe);
// - copy construct
triSurfaceField(const triSurfaceField& src);
// - no move construct
triSurfaceField(triSurfaceField&& src) = delete;
// assignment, only assign the VectorField and preserve other parts of this
triSurfaceField& operator = (const triSurfaceField& rhs);
// no move assignment
triSurfaceField& operator = (triSurfaceField&&) = delete;
inline uniquePtr<triSurfaceFieldType> clone() const
{
return makeUnique<triSurfaceFieldType>(*this);
}
inline triSurfaceFieldType* clonePtr()const
{
return new triSurfaceFieldType(*this);
}
//// - Methods
inline const triSurface& surface()const {
return surface_;
}
auto getTriangleAccessor()const
{
return surface_.getTriangleAccessor();
}
bool update(const eventMessage& msg);
//// - IO operations
bool readTriSurfacceField(iIstream& is);
bool writeTriSurfaceField(iOstream& os)const;
bool read(iIstream& is)
{
return readTriSurfacceField(is);
}
bool write(iOstream& os)const
{
return writeTriSurfaceField(os);
}
};
template<template<class, class> class VectorField, class T, class MemorySpace>
iIstream& operator >> (iIstream & is, triSurfaceField<VectorField, T, MemorySpace> & tsF )
{
if( !tsF.read(is))
{
ioErrorInFile( is.name(), is.lineNumber() ) <<
"error in reading triSurfaceField from file. \n"<<
"field name: "<< tsF.name()<<endl;
fatalExit;
}
return is;
}
template<template<class, class> class VectorField, class T, class MemorySpace>
iOstream& operator << (iOstream& os, const triSurfaceField<VectorField, T, MemorySpace>& tsF )
{
if(! tsF.write(os) )
{
ioErrorInFile( os.name(), os.lineNumber() )<<
"error in writing triSurfaceField into file. \n"<<
"field name: "<< tsF.name()<<endl;
fatalExit;
}
return os;
}
}
#include "triSurfaceField.C"
#endif //__trieSurfaceField_H__

View File

@ -0,0 +1,34 @@
/*------------------------------- 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 "triSurfaceFields.H"
template class pFlow::triSurfaceField<pFlow::VectorSingle, pFlow::real>;
template class pFlow::triSurfaceField<pFlow::VectorSingle, pFlow::real, pFlow::HostSpace>;
template class pFlow::triSurfaceField<pFlow::VectorSingle, pFlow::realx3>;
template class pFlow::triSurfaceField<pFlow::VectorSingle, pFlow::realx3, pFlow::HostSpace>;
template class pFlow::triSurfaceField<pFlow::VectorDual, pFlow::real>;
template class pFlow::triSurfaceField<pFlow::VectorDual, pFlow::realx3>;

View File

@ -0,0 +1,59 @@
/*------------------------------- 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 __triSurfaceFields_H__
#define __triSurfaceFields_H__
#include "VectorSingle.H"
#include "VectorDual.H"
#include "triSurfaceField.H"
#include "types.H"
namespace pFlow
{
using realTriSurfaceField_D = triSurfaceField<VectorSingle, real> ;
using realTriSurfaceField_H = triSurfaceField<VectorSingle, real, HostSpace> ;
using realx3TriSurfaceField_D = triSurfaceField<VectorSingle, realx3> ;
using realx3TriSurfaceField_H = triSurfaceField<VectorSingle, realx3, HostSpace> ;
using realTriSurfaceField_HD = triSurfaceField<VectorDual, real> ;
using realx3TriSurfaceField_HD = triSurfaceField<VectorDual, realx3> ;
using realTriSurfaceField = triSurfaceField<Vector, real, vecAllocator<real>> ;
using realx3TriSurfaceField = triSurfaceField<Vector, realx3, vecAllocator<realx3>> ;
using int8TriSurfaceField_D = triSurfaceField<VectorSingle, int8> ;
using int8TriSurfaceField_H = triSurfaceField<VectorSingle, int8, HostSpace> ;
using int8TriSurfaceField_HD = triSurfaceField<VectorDual, int8> ;
using int8TriSurfaceField = triSurfaceField<Vector, int8, vecAllocator<real>> ;
}
#endif //__trieSurfaceField_H__

View File

@ -0,0 +1,819 @@
/*------------------------------- 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.
-----------------------------------------------------------------------------*/
// based on OpenFOAM dictionary, with some modifications/simplifications
// to be tailored to our needs
#include "dictionary.H"
#include "uniquePtr.H"
#include "error.H"
#include "streams.H"
pFlow::dictionary pFlow::dictionary::nullDict;
// better to move it to the abstract class
// with an static member function.
bool pFlow::dictionary::readDictionary
(
iIstream & is
)
{
// ensure that the entry list of new the dicrionary is empty
entries_.clear();
// empty dictionary
if (is.eof())
{
return true;
}
if (!is.good())
{
ioErrorInFile( is.name(), is.lineNumber() )<<
"iIstream is not good for reading tokens .... \n";
return false;
}
// reads tokens one-by-one
token nextTok(is);
if( nextTok == token::END_BLOCK)
{
ioErrorInFile( is.name(), is.lineNumber() )<<
"Not expecting a } for the start of a dictionray \n";
return false;
}
bool hasBlockToken = true;
// this is a sub-dict, so it should start with {
if(nextTok != token::BEGIN_BLOCK)
{
hasBlockToken = false;
is.putBack(nextTok);
}
//read all entries in ths dictionary
while ( !is.eof() && iEntry::createEntry(*this, is, hasBlockToken) )
{}
return true;
}
bool pFlow::dictionary::writeDictionary
(
iOstream& os,
bool withBlock
)const
{
if(withBlock) os.beginBlock(keyword());
for( const auto& e:orderedEntries_)
{
if(e != nullptr )
e->write(os);
}
if(withBlock) os.endBlock();
return true;
}
pFlow::iEntry* pFlow::dictionary::findEntry
(
const word& keyword
)
{
if( auto [ptr, exist] = entries_.find(keyword); exist)
{
return ptr;
}
return nullptr;
}
pFlow::iEntry* pFlow::dictionary::findEntry
(
const word& keyword
)const
{
if( auto [ptr, exist] = entries_.find(keyword); exist)
{
return const_cast<iEntry*> (ptr);
}
return nullptr;
}
pFlow::dictionary::dictionary
()
:
iEntry("NULL_DICT"),
name_("NULL_DICT"),
entries_(),
orderedEntries_(),
parDict_(dictionary::nullDict),
isGlobal_(false)
{}
pFlow::dictionary::dictionary
(
const word& keyword
)
:
iEntry(keyword),
name_(keyword),
entries_(),
orderedEntries_(),
parDict_(dictionary::nullDict),
isGlobal_(false)
{}
pFlow::dictionary::dictionary
(
const word& keyword,
bool global
)
:
iEntry(keyword),
name_(keyword),
entries_(),
orderedEntries_(),
parDict_(dictionary::nullDict),
isGlobal_(global)
{
}
pFlow::dictionary::dictionary
(
const word& keyword,
const fileSystem& file
)
:
iEntry(keyword),
name_(file.wordPath()),
entries_(),
orderedEntries_(),
parDict_(dictionary::nullDict),
isGlobal_(true)
{
iFstream dictStream(file);
if(!read(dictStream))
{
ioErrorInFile(dictStream.name(), dictStream.lineNumber())<<
"error in reading dictionary from file "<< file <<endl;
fatalExit;
}
}
pFlow::dictionary::dictionary
(
const word& keyword,
const dictionary& parDict
)
:
iEntry(keyword),
name_(groupNames(parDict.globalName(), keyword)),
entries_(),
orderedEntries_(),
parDict_(parDict),
isGlobal_(false)
{
}
pFlow::dictionary::dictionary
(
const word& keyword,
const dictionary& parDict,
iIstream& is
)
:
iEntry(keyword),
name_(groupNames(parDict.globalName(), keyword)),
entries_(),
orderedEntries_(),
parDict_(parDict),
isGlobal_(false)
{
if( !readDictionary(is) )
{
ioErrorInFile(is.name(), is.lineNumber()) <<
"error in reading dictionary " << name_ <<endl;
fatalExit;
}
}
pFlow::dictionary::dictionary
(
const word& keyword,
const dictionary& parDict,
const dictionary& dict
)
:
iEntry(keyword),
name_(groupNames(parDict.globalName(),keyword)),
entries_(),
orderedEntries_(),
parDict_(parDict),
isGlobal_(false)
{
for( auto& entry : dict.orderedEntries_ )
{
if(entry)
{
auto ptr = entry->clone(*this);
auto key = entry->name();
if( !addPtr(key, ptr) )
{
fatalErrorInFunction <<
" error in cloning dicrionary / dataEntry " << entry->globalName() <<endl;
fatalExit;
}
}
}
}
pFlow::dictionary::dictionary
(
const dictionary& src
)
:
iEntry(src.keyword()),
name_(src.keyword()),
entries_(),
orderedEntries_(),
parDict_(dictionary::nullDict),
isGlobal_(src.isGlobal_)
{
for( auto& entry: src.orderedEntries_)
{
if(entry)
{
auto ptr = entry->clone(*this);
auto key = entry->name();
if( !addPtr(key, ptr) )
{
fatalErrorInFunction <<
" error in cloning dicrionary / dataEntry " << entry->globalName() <<endl;
fatalExit;
}
}
}
}
pFlow::dictionary& pFlow::dictionary::operator=
(
const dictionary& rhs
)
{
if( &rhs == this)return *this;
clear();
for( auto& entry: rhs.orderedEntries_)
{
if(entry)
{
auto ptr = entry->clone(*this);
auto key = entry->name();
if( !addPtr(key, ptr) )
{
fatalErrorInFunction <<
" error in cloning dicrionary / dataEntry " << entry->globalName() <<endl;
fatalExit;
}
}
}
return *this;
}
pFlow::dictionary* pFlow::dictionary::dictPtr()
{
return this;
}
const pFlow::dictionary* pFlow::dictionary::dictPtr() const
{
return this;
}
bool pFlow::dictionary::isDictionary() const
{
return true;
}
pFlow::word pFlow::dictionary::globalName()const
{
return name_;
}
const pFlow::dictionary& pFlow::dictionary::parrentDict() const
{
return parDict_;
}
pFlow::dictionary& pFlow::dictionary::dict()
{
return *this;
}
const pFlow::dictionary& pFlow::dictionary::dict() const
{
return *this;
}
bool pFlow::dictionary::isFileDict()const
{
return isGlobal_;
}
bool pFlow::dictionary::addPtr
(
const word& keyword,
uniquePtr<iEntry>& entry
)
{
if(entry == nullptr) return false;
iEntry* oldEntryPtr = nullptr;
iEntry* newEntryPtr = entry.get();
// search all entries for repeated keyword
if(auto [ptr, exist] = entries_.find(keyword); exist )
{
warningInFunction <<
"keyword " << keyword << " already exists in the dicrionary " <<
this->globalName() << ". The old entry will be replaced by the new one. \n";
// store the old pointer to entry
oldEntryPtr = ptr;
}
if( entries_.insertReplace(keyword, entry) )
{
if(oldEntryPtr)
{
// this should be replaced
auto oIter = orderedEntries_.find(oldEntryPtr);
*oIter = newEntryPtr;
}
else
{
orderedEntries_.push_back(newEntryPtr);
}
return true;
}else
{
return false;
}
}
bool pFlow::dictionary::add
(
const word& keyword,
const float& v
)
{
uniquePtr<iEntry> ptr = makeUnique<dataEntry>(keyword, *this, token(v));
return addPtr(keyword, ptr);
}
bool pFlow::dictionary::add
(
const word& keyword,
const double& v
)
{
uniquePtr<iEntry> ptr = makeUnique<dataEntry>(keyword, *this, token(v));
return addPtr(keyword, ptr);
}
bool pFlow::dictionary::add
(
const word& keyword,
const word& v
)
{
uniquePtr<iEntry> ptr = makeUnique<dataEntry>(keyword, *this, token(v));
return addPtr(keyword, ptr);
}
bool pFlow::dictionary::add
(
const word& keyword,
const int64& v
)
{
uniquePtr<iEntry> ptr = makeUnique<dataEntry>(keyword, *this, token(v));
return addPtr(keyword, ptr);
}
bool pFlow::dictionary::add
(
const word& keyword,
const int32& v
)
{
uniquePtr<iEntry> ptr = makeUnique<dataEntry>(keyword, *this, token(v));
return addPtr(keyword, ptr);
}
bool pFlow::dictionary::add
(
const word& keyword,
const int16& v
)
{
uniquePtr<iEntry> ptr = makeUnique<dataEntry>(keyword, *this, token(v));
return addPtr(keyword, ptr);
}
bool pFlow::dictionary::add
(
const word& keyword,
const int8& v
)
{
uniquePtr<iEntry> ptr = makeUnique<dataEntry>(keyword, *this, token(v));
return addPtr(keyword, ptr);
}
bool pFlow::dictionary::add
(
const word& keyword,
const label& v
)
{
uniquePtr<iEntry> ptr = makeUnique<dataEntry>(keyword, *this, token(v));
return addPtr(keyword, ptr);
}
bool pFlow::dictionary::add
(
const word& keyword,
const uint32& v
)
{
uniquePtr<iEntry> ptr = makeUnique<dataEntry>(keyword, *this, token(v));
return addPtr(keyword, ptr);
}
bool pFlow::dictionary::addDict
(
const word& keyword,
const dictionary& dict
)
{
uniquePtr<iEntry> ptr = makeUnique<dictionary>(keyword, *this, dict);
return addPtr(keyword, ptr);
}
void pFlow::dictionary::clear()
{
orderedEntries_.clear();
entries_.clear();
}
pFlow::dictionary* pFlow::dictionary::subDictPtr
(
const word& keyword
)
{
if( auto entry = findEntry(keyword); entry!= nullptr && entry->isDictionary() )
{
return dynamic_cast<dictionary*>(entry);
}
else
{
fatalErrorInFunction<<
"keyword " << keyword<< " is not an sub-dictionary of " << this->globalName()<<endl;
fatalExit;
return this;
}
}
pFlow::dictionary& pFlow::dictionary::subDict
(
const word& keyword
)
{
if( auto entry = findEntry(keyword); entry!= nullptr && entry->isDictionary() )
{
return dynamic_cast<dictionary&>(*entry);
}
else
{
fatalErrorInFunction<<
"keyword " << keyword<< " is not an sub-dictionary of " << this->globalName()<<endl;
fatalExit;
return *this;
}
}
const pFlow::dictionary& pFlow::dictionary::subDict
(
const word& keyword
) const
{
if( auto entry = findEntry(keyword); entry!= nullptr && entry->isDictionary() )
{
return dynamic_cast<dictionary&>(*entry);
}
else
{
fatalErrorInFunction<<
"keyword " << keyword<< " is not an sub-dictionary of " << this->globalName()<<endl;
fatalExit;
return *this;
}
}
pFlow::dataEntry* pFlow::dictionary::dataEntryPtr(const word& keyword)
{
if( auto entry = findEntry(keyword); entry && !entry->isDictionary() )
{
return dynamic_cast<dataEntry*>(entry);
}
else
{
fatalErrorInFunction<<
"keyword " << keyword<< " is not a dataEntry of " << this->globalName()<<endl;
fatalExit;
return nullptr;
}
}
pFlow::dataEntry& pFlow::dictionary::dataEntryRef(const word& keyword)
{
if( auto entry = findEntry(keyword); entry && !entry->isDictionary() )
{
return dynamic_cast<dataEntry&>(*entry);
}
else
{
fatalErrorInFunction<<
"keyword " << keyword<< " is not a dataEntry of " << this->globalName()<<endl;
fatalExit;
return dataEntry::nullDataEntry;
}
}
const pFlow::dataEntry& pFlow::dictionary::dataEntryRef
(
const word& keyword
)const
{
if( auto entry = findEntry(keyword); entry && !entry->isDictionary() )
{
return dynamic_cast<dataEntry&>(*entry);
}
else
{
fatalErrorInFunction<<
"keyword " << keyword<< " is not a dataEntry of " << this->globalName()<<endl;
fatalExit;
return dataEntry::nullDataEntry;
}
}
pFlow::dictionary& pFlow::dictionary::subDictOrCreate
(
const word& keyword
)
{
if( auto entry = findEntry(keyword); entry!= nullptr && entry->isDictionary() )
{
return dynamic_cast<dictionary&>(*entry);
}
else
{
uniquePtr<iEntry> ptr = makeUnique<dictionary>(keyword, *this);
if( addPtr
(
keyword,
ptr
)
)
{
return subDictOrCreate(keyword);
}
else
{
fatalErrorInFunction<<
"Unable to create sub-dictionary "<< keyword << " in dictionary " << globalName() <<endl;
fatalExit;
}
}
return *this;
}
size_t pFlow::dictionary::numEntries()const
{
return entries_.size();
}
size_t pFlow::dictionary::numDataEntries()const
{
size_t num = 0;
for(auto& e:entries_)
{
if( e.second && !e.second->isDictionary())
{
num++;
}
}
return num;
}
size_t pFlow::dictionary::numDictionaries()const
{
size_t num = 0;
for(auto& e:entries_)
{
if( e.second && e.second->isDictionary())
{
num++;
}
}
return num;
}
pFlow::wordList pFlow::dictionary::allKeywords()const
{
wordList wl;
for(auto oe:orderedEntries_)
{
if(oe) wl.push_back( oe->keyword() );
}
return wl;
}
pFlow::wordList pFlow::dictionary::dataEntryKeywords()const
{
wordList wl;
for(auto oe:orderedEntries_)
{
if( oe && !oe->isDictionary())
{
wl.push_back(oe->keyword());
}
}
return wl;
}
// return a list of all dictionary keywords
pFlow::wordList pFlow::dictionary::dictionaryKeywords()const
{
wordList wl;
for(auto& oe:orderedEntries_)
{
if( oe && oe->isDictionary())
{
wl.push_back(oe->keyword());
}
}
return wl;
}
bool pFlow::dictionary::containsDictionay
(
const word& name
)const
{
if( auto ptr = findEntry(name); ptr)
{
return ptr->isDictionary();
}
return false;
}
bool pFlow::dictionary::containsDataEntry
(
const word& name
)const
{
if( auto ptr = findEntry(name); ptr)
{
return !ptr->isDictionary();
}
return false;
}
bool pFlow::dictionary::read(iIstream& is)
{
token tok;
if(!isFileDict() && !readKeyword(is, keyword_, tok))
{
ioErrorInFile(is.name(), is.lineNumber()) <<
"expected a valid keyword for dictionary but found " << tok <<endl;
fatalExit;
}
if( !readDictionary(is) )
{
ioErrorInFile(is.name(), is.lineNumber()) <<
"error in reading dictionary " << keyword_ <<endl;
fatalExit;
}
return true;
}
bool pFlow::dictionary::write(iOstream& os) const
{
if(! writeDictionary(os, !isFileDict()) )
{
ioErrorInFile( os.name(), os.lineNumber());
fatalExit;
}
return true;
}
pFlow::uniquePtr<pFlow::iEntry> pFlow::dictionary::clone() const
{
return makeUnique<dictionary>(*this);
}
pFlow::iEntry* pFlow::dictionary::clonePtr() const
{
auto ptr = makeUnique<dictionary>(*this);
return ptr.release();
}
pFlow::uniquePtr<pFlow::iEntry> pFlow::dictionary::clone
(
const dictionary& parDict
) const
{
return makeUnique<dictionary>(this->keyword(), parDict, *this);
}
pFlow::iEntry* pFlow::dictionary::clonePtr
(
const dictionary& parDict
) const
{
auto ptr = makeUnique<dictionary>(this->keyword(), parDict, *this);
return ptr.release();
}

View File

@ -0,0 +1,344 @@
/*------------------------------- 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.
-----------------------------------------------------------------------------*/
// based on OpenFOAM dictionary, with some modifications/simplifications
// to be tailored to our needs
#ifndef __dictionary_H__
#define __dictionary_H__
#include "types.H"
#include "iEntry.H"
#include "dataEntry.H"
#include "MapPtr.H"
#include "List.H"
#include "fileSystem.H"
namespace pFlow
{
class dictionary
:
public iEntry
{
protected:
//// - Data members
// global name of dictionary, separated with dots
word name_;
// all the entries (data and dictionary) of the current dictionary
wordOrderedMapPtr<iEntry> entries_;
// entries in order of insertion
List<iEntry*> orderedEntries_;
// - ref to parrent dictionary
const dictionary& parDict_;
bool isGlobal_;
//// - protected methods
// - find an entry based on keyword
// return nullptr if not found
iEntry* findEntry(const word& keyword);
// - find and entry based on keyword
// return nullptr if not found
iEntry* findEntry(const word& keyword)const;
// - reads a dataEntry with keyword from dictionary
template<typename T>
bool readDataEntry( const word& keyword, T& val)const;
// - read dictionary from stream - without keyword
bool readDictionary(iIstream & is);
// - write dictionary to stream - with keyword
bool writeDictionary(iOstream& os, bool withBlock = true)const;
public:
// null dictionary object, to be used for references
static dictionary nullDict;
TypeName("dictionary");
//// - Constructors
// - cunstructs a null dictionary
dictionary();
// - construct an empty dictionary with keyword
dictionary(const word& keyword);
// - construct an empty dictionary with keyword and make it global/fileDictionary (if true)
dictionary(const word& keyword, bool global);
// - construct a dictionary with name and read it from file
dictionary(const word& keyword, const fileSystem& file);
// - cunstruct an empty dictionary with keyword and parDict
dictionary(const word& keyword, const dictionary& parDict);
// - cunstruct a dictionary with keyword and parDict and from stream
dictionary( const word& keyword, const dictionary& parDict, iIstream& is);
// - copy construct with keyword and new parrent dict
// discard the keyword and parDict of dict
dictionary(const word& keyword, const dictionary& parDict, const dictionary& dict);
// - copy construct as default behavior
// entries_ are copied smoothly. set parrent dict to nullDict
dictionary(const dictionary& );
// - assignment preserve name of this dictionary
// - only entries are transfered with ownership
dictionary& operator=(const dictionary& rhs);
//// - Methods
// - pointer to this dictionary
virtual dictionary* dictPtr();
// - pointer to this dictionary
virtual const dictionary* dictPtr() const;
// - if this is a dictionary
virtual bool isDictionary() const;
// - global name of entry, separated with dots
virtual word globalName()const;
// - const ref to parrent dictionary
virtual const dictionary& parrentDict() const;
// - ref to this dictionary, if it is a dictionary
virtual dictionary& dict();
// - const ref to this dictionary, if it is a dictionary
virtual const dictionary& dict() const;
// - if dictionary is file dictionary, return false
virtual bool isFileDict()const;
// - add a pointer entry (dictionary/dataEntry)
// replaces this entry with existing one
bool addPtr(const word& keyword, uniquePtr<iEntry>& etry );
// - add a float dataEntry
bool add(const word& keyword, const float& v);
// - add a double dataEntry
bool add(const word& keyword, const double& v);
// - add a word dataEntry
bool add(const word& keyword, const word& v);
// - add a int64 dataEntry
bool add(const word& keyword, const int64& v);
// - add a int32 dataEntry
bool add(const word& keyword, const int32& v);
// - add a int16 dataEntry
bool add(const word& keyword, const int16& v);
// - add a int8 dataEntry
bool add(const word& keyword, const int8& v);
// - add a label dataEntry
bool add(const word& keyword, const label& v);
// - add a uint32 dataEntry
bool add(const word& keyword, const uint32& v);
// add a dictionary with the specifiedd keyword
bool addDict(const word& keyword, const dictionary& dict);
// - add a dataEntry of type T
template<typename T>
bool add(const word& keyword, const T& v );
void clear();
// - pointer to a subdictionary
// fatalExit if not found
dictionary* subDictPtr(const word& keyword);
// - ref to a subdictioanry
// fatalExit if not found
dictionary& subDict(const word& keyword);
// - const ref to a subdictioanry
// fatalExit if not found
const dictionary& subDict(const word& keyword) const;
// - pointer to a dataEntry
// fatalExit if not found/not a dataEntry
dataEntry* dataEntryPtr(const word& keyword);
// - ref to a subdictioanry
// fatalExit if not found/not a dataEntry
dataEntry& dataEntryRef(const word& keyword);
// - const ref to a subdictioanry
// fatalExit if not found/not a dataEntry
const dataEntry& dataEntryRef(const word& keyword)const;
// - search for a sub-dict with keyword
// create a new sub-dict if not found and return a ref to it
// fatalExit if fails
dictionary& subDictOrCreate(const word& keyword);
// - get the value of data entry
template<typename T>
T getVal(const word& keyword) const;
// - get the value of data entry or
// if not found, set the value to setVal
template<typename T>
T getValOrSet(const word& keyword, const T& setVal)const;
// return number of entris in this dictionary
size_t numEntries()const;
// return number of non-nullptr dataEntries
size_t numDataEntries()const;
// return number of non-nullptr dictionaries
size_t numDictionaries()const;
// return all keywords (non-nullptr) in this dictionary
wordList allKeywords()const;
// return a list of all dataEntries (non-nullptr) keywords
wordList dataEntryKeywords()const;
// return a list of all dictionary (non-null) keywords
wordList dictionaryKeywords()const;
// check if a sub-dictionary exists
bool containsDictionay(const word& name)const;
// check if a data entry exist
bool containsDataEntry(const word& name)const;
// clone polymorphic object (here dictionary)
virtual uniquePtr<iEntry> clone() const;
virtual iEntry* clonePtr() const;
// - clone the polymorhpic object with parDict as the new parrent dictionary
virtual uniquePtr<iEntry> clone(const dictionary& parDict)const;
virtual iEntry* clonePtr(const dictionary& parDict) const;
//// IO operations
// - read from stream
virtual bool read(iIstream& is);
// - write to stream
virtual bool write(iOstream& os) const;
};
template<typename T>
bool dictionary::add(const word& keyword, const T& v )
{
uniquePtr<iEntry> ptr = makeUnique<dataEntry>(keyword, *this ,v);
return addPtr(keyword, ptr);
}
template<typename T>
bool dictionary::readDataEntry
(
const word& keyword,
T& val
)const
{
if( auto entry = findEntry(keyword); entry!= nullptr && !entry->isDictionary() )
{
iTstream& is = dynamic_cast<dataEntry&>(*entry).stream();
is >> val;
return true;
}
else
{
return false;
}
}
template<typename T>
T dictionary::getVal
(
const word& keyword
)const
{
T val{};
if(!readDataEntry(keyword, val))
{
fatalErrorInFunction <<
"cannot find dataEntry "<< keyword <<" in dictionary "<< globalName()<<endl;
fatalExit;
}
return val;
}
template<typename T>
T dictionary::getValOrSet
(
const word& keyword,
const T& setVal
)const
{
T val{};
if( readDataEntry(keyword, val) )
{
return val;
}
else
{
return setVal;
}
}
}
#endif // __dictionary_H__

View File

@ -0,0 +1,375 @@
/*------------------------------- 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.
-----------------------------------------------------------------------------*/
// based on OpenFOAM dictionary, with some modifications/simplifications
// to be tailored to our needs
#include "dataEntry.H"
#include "dictionary.H"
#include "error.H"
#include "iIstream.H"
#include "iOstream.H"
#include "iTstream.H"
#include "oTstream.H"
pFlow::dataEntry pFlow::dataEntry::nullDataEntry;
bool pFlow::dataEntry::readDataEntry
(
iIstream& is
)
{
// reset the stream (only tokens)
tokenStream_.reset();
int32 level = 0;
token nextTok;
while
(
!is.read(nextTok).bad() && nextTok.good() &&
!(level == 0 && nextTok == token::END_STATEMENT)
)
{
if( nextTok.isPunctuation() )
{
auto t = nextTok.pToken();
if( t == token::BEGIN_LIST ||
t == token::BEGIN_BLOCK ||
t == token::BEGIN_SQR
)
{
level ++;
}
else if (
t == token::END_LIST ||
t == token::END_BLOCK ||
t == token::END_SQR )
{
level--;
}
}
// checks if there are imbalance (, { or [
if( level < 0 )
{
ioErrorInFile(is.name(), is.lineNumber()) <<
"number of opening and closing ( or, [ or { does not match, closing is greater than opening \n";
fatalExit;
}
// add token to tokenStream
// iTstream will take care of invalid tokens (space, tab, new line and null)
tokenStream_.appendToken(nextTok);
}
if( level )
{
ioErrorInFile(is.name(), is.lineNumber()) <<
"imbalance number of ( or { or [ \n";
fatalExit;
}
is.fatalCheck(FUNCTION_NAME);
return nextTok.good();
}
bool pFlow::dataEntry::writeDataEntry
(
iOstream& os
)const
{
writeKeyword(os);
auto lastPuncBegin = false;
auto lastPuncEnd = false;
auto applySpace = false;
const tokenList& tokens = tokenStream_.tokens();
for(auto tok = tokens.cbegin(); tok != tokens.cend(); tok++)
{
if(*tok == endStatementToken()) continue;
if(isBeginToken(*tok))
{
if(lastPuncEnd)
{
os<<spaceToken();
os << *tok;
}
else
{
os << *tok;
}
lastPuncBegin = true;
lastPuncEnd = false;
}
else if(isEndToken(*tok))
{
if(lastPuncBegin)
{
os<<spaceToken();
os << *tok;
}
else
os << *tok;
lastPuncEnd = true;
lastPuncBegin = false;
}
else
{
if(!lastPuncBegin&&applySpace) os<<spaceToken();
os << *tok;
lastPuncEnd = false;
lastPuncBegin = false;
applySpace = true;
}
}
os.endEntry();
return true;
}
pFlow::dataEntry::dataEntry()
:
iEntry("NULL_DATAENTRY"),
parDict_(dictionary::nullDict),
tokenStream_(parDict_.globalName())
{}
pFlow::dataEntry::dataEntry
(
const word& keyword,
const dictionary& parDict
)
:
iEntry(keyword),
parDict_(parDict),
tokenStream_
(
groupNames(parDict.globalName(), keyword)
)
{
}
pFlow::dataEntry::dataEntry
(
const word& keyWord,
const dictionary& parDict,
const iTstream& is
)
:
iEntry(keyWord),
parDict_(parDict),
tokenStream_
(
groupNames(parDict.globalName(), keyWord),
is.tokens()
)
{
tokenStream_.rewind();
}
pFlow::dataEntry::dataEntry
(
const word& keyWord,
const dictionary& parDict,
iIstream& is
)
:
iEntry(keyWord),
parDict_(parDict),
tokenStream_
(
groupNames(parDict.globalName(),keyWord)
)
{
// reads the entry
if( !readDataEntry(is) )
{
ioErrorInFile(is.name(), is.lineNumber() ) <<
"error in reading data entry from file \n";
fatalExit;
}
tokenStream_.rewind();
}
pFlow::dataEntry::dataEntry
(
const word& keyword,
const dictionary& parDict,
const token& tok
)
:
iEntry(keyword),
parDict_(parDict),
tokenStream_
(
groupNames(parDict.globalName(),keyword)
)
{
tokenStream_.appendToken(tok);
tokenStream_.rewind();
}
pFlow::dataEntry::dataEntry
(
const word& keyword,
const dictionary& parDict,
const dataEntry& entry
)
:
dataEntry(keyword, parDict)
{
tokenStream_ = entry.tokenStream_.tokens();
tokenStream_.rewind();
}
pFlow::iTstream& pFlow::dataEntry::stream
(
)
{
tokenStream_.rewind();
return tokenStream_;
}
pFlow::dictionary* pFlow::dataEntry::dictPtr()
{
fatalErrorInFunction<<
"Request for an entry that is not a dictionray. Entry name is " << globalName() << endl;
fatalExit;
return nullptr;
}
const pFlow::dictionary* pFlow::dataEntry::dictPtr() const
{
fatalErrorInFunction<<
"Request for an entry that is not a dictionray. Entry name is " << globalName() << endl;
fatalExit;
return nullptr;
}
bool pFlow::dataEntry::isDictionary()const
{
return false;
}
pFlow::word pFlow::dataEntry::globalName()const
{
return tokenStream_.name();
}
const pFlow::dictionary& pFlow::dataEntry::parrentDict() const
{
return parDict_;
}
pFlow::dictionary& pFlow::dataEntry::dict()
{
fatalErrorInFunction<<
"Request for an entry that is not a dictionray. Entry name is " << globalName() << endl;
fatalExit;
return const_cast<dictionary&>(parDict_);
}
const pFlow::dictionary& pFlow::dataEntry::dict() const
{
fatalErrorInFunction<<
"Request for an entry that is not a dictionray. Entry name is " << globalName() << endl;
fatalExit;
return parDict_;
}
pFlow::uniquePtr<pFlow::iEntry> pFlow::dataEntry::clone() const
{
return makeUnique<dataEntry>(*this);
}
pFlow::iEntry* pFlow::dataEntry::clonePtr() const
{
auto ptr = makeUnique<dataEntry>(*this);
return ptr.release();
}
pFlow::uniquePtr<pFlow::iEntry> pFlow::dataEntry::clone(const dictionary& parDict) const
{
return makeUnique<dataEntry>(this->keyword(), parDict, *this);
}
pFlow::iEntry* pFlow::dataEntry::clonePtr(const dictionary& parDict) const
{
auto ptr = makeUnique<dataEntry>(this->keyword(), parDict, *this);
return ptr.release();
}
///
bool pFlow::dataEntry::read(iIstream& is)
{
token tok;
if(!readKeyword(is, keyword_, tok))
{
ioErrorInFile(is.name(), is.lineNumber()) <<
"expected a valid keyword for dataEntry but found " << tok <<endl;
fatalExit;
}
if(!readDataEntry(is) )
{
fatalErrorInFunction<<
"unsucceful in reading dataEntry from " << is.name() <<endl;
fatalExit;
}
return true;
}
bool pFlow::dataEntry::write(iOstream& os) const
{
if( !writeDataEntry(os) )
{
ioErrorInFile( os.name(), os.lineNumber() );
fatalExit;
}
return true;
}

View File

@ -0,0 +1,163 @@
/*------------------------------- 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.
-----------------------------------------------------------------------------*/
// based on OpenFOAM dictionary, with some modifications/simplifications
// to be tailored to our needs
#ifndef __dataEntry_H__
#define __dataEntry_H__
#include "iEntry.H"
#include "iTstream.H"
#include "oTstream.H"
namespace pFlow
{
class dictionary;
class dataEntry
:
public iEntry
{
protected:
//// - data memebers
// - ref to parrent dictionary
const dictionary& parDict_;
// - list the tokens as input token stream
iTstream tokenStream_;
//// - protected member functions
// - read dataEntry from stream
bool readDataEntry(iIstream& is);
// - write dataEntry to stream
bool writeDataEntry(iOstream& os) const;
public:
static dataEntry nullDataEntry;
//// - constructors
// - construct null dataEntry
dataEntry();
// - construct from keyword and parDict, empty dataEntry
dataEntry(const word& keyword, const dictionary& parDict);
// - construct from keyword, parDict and input token stream
dataEntry(const word& keyWord, const dictionary& parDict, const iTstream& is);
//- construct from keyword, parDict and input stream
dataEntry(const word& keyWord, const dictionary& parDict, iIstream& is);
// - construct from keyword, parDict and a single token
dataEntry(const word& keyword, const dictionary& parDict, const token& tok);
// - construct from keyword, parDict, and data of type T
template<typename T>
dataEntry(const word& keyword, const dictionary& parDict, const T& v);
// - copy construct with new keyword and parDict
dataEntry(const word& keyword, const dictionary& parDict, const dataEntry& entry );
// - copy construct
dataEntry(const dataEntry& src )= default;
//// - Methods
// - global name of entry, separated with dots
virtual word globalName()const;
// - access to token stream
virtual iTstream& stream();
// - not permited to be called
virtual dictionary* dictPtr();
// - not permited to be called
virtual const dictionary* dictPtr() const;
// - should returen false;
virtual bool isDictionary()const;
// - const ref to parrent dictionary
virtual const dictionary& parrentDict() const;
// - not permited to be called
virtual dictionary& dict();
// - not permited to be called
virtual const dictionary& dict() const;
// clone the object
virtual iEntry* clonePtr() const;
virtual uniquePtr<iEntry> clone() const;
// clone the object and change its ownership to parDict
virtual iEntry* clonePtr(const dictionary& parDict) const;
virtual uniquePtr<iEntry> clone(const dictionary& parDict)const;
//// - IO operations
// - read from stream
virtual bool read(iIstream& is);
// - write to stream
virtual bool write(iOstream& os) const;
};
template<typename T>
dataEntry::dataEntry(const word& keyword, const dictionary& parDict, const T& v)
:
dataEntry(keyword, parDict)
{
oTstream os("oTStream for " + globalName());
os<< v << endStatementToken();
tokenStream_ = std::move(os.tokens());
}
} // pFlow
#endif //__dataEntry_H__

View File

@ -0,0 +1,185 @@
/*------------------------------- 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.
-----------------------------------------------------------------------------*/
// based on OpenFOAM dictionary, with some modifications/simplifications
// to be tailored to our needs
#include "iEntry.H"
#include "dictionary.H"
#include "dataEntry.H"
#include "error.H"
#include "iOstream.H"
#include "iIstream.H"
bool pFlow::iEntry::readKeyword
(
iIstream &is,
word& keyword,
token& tok
)
{
while
(
!is.read(tok).bad() &&
!is.eof() &&
tok.good()
)
{
if(tok == token::END_STATEMENT) continue;
if( tok.isWord())
{
keyword = tok.wordToken();
return true;
}
else
{
return false;
}
}
return false;
}
bool pFlow::iEntry::createEntry
(
dictionary& parDict,
iIstream& is,
bool hasBlockToken
)
{
is.fatalCheck(FUNCTION_NAME);
// reads tokens one-by-one
word key;
token nextTok;
if( auto isKey = iEntry::readKeyword(is, key, nextTok ); isKey )
{
//output<< key << " "<<nextTok <<endl;
is.read(nextTok);
if( is.eof() || is.bad() || !nextTok.good() )
{
ioErrorInFile(is.name(), is.lineNumber())<<
"expecting a valid token after keyword " << key << endl;
fatalExit;
}
// output<< nextTok<<endl;
is.putBack(nextTok);
if( nextTok == token::BEGIN_BLOCK )
{
uniquePtr<iEntry> ptr = makeUnique<dictionary>(key, parDict, is);
if( !parDict.addPtr(key, ptr ))
{
fatalErrorInFunction <<
"unable to add dicrionary " << key <<
" to dictionary " << parDict.globalName() <<endl;
fatalExit;
}
}
else
{
uniquePtr<iEntry> ptr = makeUnique<dataEntry>(key, parDict, is);
if( !parDict.addPtr(key, ptr ) )
{
fatalErrorInFunction <<
"unable to add dataEntry " << key <<
" to dictionary " << parDict.globalName() <<endl;
fatalExit;
}
}
}
else
{
if( nextTok.good() )
{
if(hasBlockToken)
{
if(nextTok != token::END_BLOCK )
{
ioErrorInFile(is.name(), is.lineNumber())<<
"expecting a } but found "<< nextTok <<endl;
fatalExit;
}else
{
return false;
}
}else
{
ioErrorInFile(is.name(), is.lineNumber())<<
"not expecting " << nextTok <<endl;
return false;
}
}
else if( !is.eof())
{
ioErrorInFile(is.name(), is.lineNumber())<<
"error in reading next token. \n";
fatalExit;
}
}
return true;
}
bool pFlow::iEntry::writeKeyword
(
iOstream& os
)const
{
os.writeWordKeyword(keyword_);
os.fatalCheck("pFlow::iEntry::writeKeyword");
return true;
}
pFlow::iOstream& pFlow::operator << (iOstream& os, const iEntry& e)
{
if(!e.write(os))
{
ioErrorInFile(os.name(), os.lineNumber())<<
"Error in wrting to file \n";
fatalExit;
}
return os;
}
pFlow::iIstream& pFlow::operator >> (iIstream& is, iEntry& e)
{
if( !e.read(is))
{
ioErrorInFile(is.name(), is.lineNumber())<<
"Error in reading from file \n";
fatalExit;
}
return is;
}

View File

@ -0,0 +1,160 @@
/*------------------------------- 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.
-----------------------------------------------------------------------------*/
// based on OpenFOAM dictionary, with some modifications/simplifications
// to be tailored to our needs
#ifndef __iEntry_H__
#define __iEntry_H__
#include "types.H"
#include "typeInfo.H"
#include "uniquePtr.H"
namespace pFlow
{
class dictionary;
class iEntry
{
public:
//// - public static methods
// - read a keyword from stream
static bool readKeyword(iIstream &is, word& keyword, token& tok );
// - create an entry (dataEntry or dictionary) from stream
static bool createEntry(dictionary& parDict, iIstream& is, bool hasBlockToken = false);
protected:
// keyWord of entry
word keyword_;
bool writeKeyword(iOstream& os)const;
public:
TypeName("iEntry");
//// - Constructors
// - empty constructor
iEntry()
{}
// - construct with a keyword
iEntry(const word& key)
{
// this moved here due to a very strange core dumped error!
keyword_ = key;
}
// - destructor
virtual ~iEntry()
{}
//// - Methods
// - return keyword
virtual const word& keyword() const
{
return keyword_;
}
// - return keyword
virtual word& keyword()
{
return keyword_;
}
virtual word name()const
{
return keyword();
}
// global name of entry, separated with dots
virtual word globalName()const = 0;
// - pointer to this dictionary
virtual dictionary* dictPtr()
{
return nullptr;
}
// - const pointer to this dictionary
virtual const dictionary* dictPtr() const
{
return nullptr;
}
// - if this is a dictionary
virtual bool isDictionary() const
{
return false;
}
// - const ref to parrent dictionary
virtual const dictionary& parrentDict() const = 0;
// - ref to this dictionary, if it is a dictionary
virtual dictionary& dict() = 0;
// - const ref to this dictionary, if it is a dicrionary
virtual const dictionary& dict() const = 0;
// clone the object
virtual iEntry* clonePtr() const = 0;
virtual uniquePtr<iEntry> clone() const = 0;
// clone the object and change its ownership to parDict
virtual iEntry* clonePtr(const dictionary& parDict) const = 0;
virtual uniquePtr<iEntry> clone(const dictionary& parDict)const = 0;
//// - IO operatoins
// read from stream
virtual bool read(iIstream& is) = 0;
// write to stream
virtual bool write(iOstream& os) const =0;
};
iOstream& operator << (iOstream& os, const iEntry& e);
iIstream& operator >> (iIstream& is, iEntry& e);
}
#endif //__iEntry_H__

View File

@ -0,0 +1,48 @@
/*------------------------------- 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.
-----------------------------------------------------------------------------*/
// based on OpenFOAM dictionary, with some modifications/simplifications
// to be tailored to our needs
#include "twoPartEntry.H"
pFlow::twoPartEntry::twoPartEntry
(
dataEntry entry
)
:
keyword_(entry.keyword()),
secondPart_(keyword_)
{
iTstream& iT = entry.stream();
iT >> firstPart_;
token t;
while(true)
{
iT.read(t);
secondPart_.appendToken(t);
if(iT.eof())break;
}
}

View File

@ -0,0 +1,70 @@
/*------------------------------- 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.
-----------------------------------------------------------------------------*/
// based on OpenFOAM dictionary, with some modifications/simplifications
// to be tailored to our needs
#ifndef __twoPartEntry_H__
#define __twoPartEntry_H__
#include "dataEntry.H"
namespace pFlow
{
class twoPartEntry
{
protected:
word keyword_;
word firstPart_;
mutable iTstream secondPart_;
public:
twoPartEntry(dataEntry entry);
const word& keyword()const
{
return keyword_;
}
const word& firstPart()const
{
return firstPart_;
}
template<typename T>
T secondPartVal()const
{
T val;
secondPart_.rewind();
secondPart_ >> val;
return val;
}
};
}
#endif

View File

@ -0,0 +1,116 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
#ifndef __eventMessage_H__
#define __eventMessage_H__
namespace pFlow
{
class eventMessage
{
public:
enum event : unsigned int
{
DELETE = 1,
INSERT = 2,
REARRANGE = 4,
SIZE_CHANGED = 8,
CAP_CHANGED = 16,
RANGE_CHANGED = 32
};
protected:
unsigned int message_;
public:
eventMessage()
:
message_(0)
{}
eventMessage(unsigned int msg)
:
message_(msg)
{}
inline unsigned int get()const
{
return message_;
}
inline void set(unsigned int msg)
{
message_= msg;
}
inline void add(unsigned int msg)
{
message_ = message_+ msg;
}
inline bool equivalentTo( const event& evt )const
{
return (message_ & evt) == evt;
}
inline bool isNull()const
{
return message_ == 0u;
}
inline bool isDeleted()const
{
return equivalentTo(event::DELETE);
}
inline bool isInsert()const
{
return equivalentTo(event::INSERT);
}
inline bool isRearranged()const
{
return equivalentTo(event::REARRANGE);
}
inline bool isSizeChanged()const
{
return equivalentTo(event::SIZE_CHANGED);
}
inline bool isCapacityChanged()const
{
return equivalentTo(event::CAP_CHANGED);
}
inline bool isRangeChanged()const
{
return equivalentTo(event::RANGE_CHANGED);
}
};
}
#endif // __eventMessage_H__

View File

@ -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 "eventObserver.H"
#include "eventSubscriber.H"
pFlow::eventObserver::eventObserver():
subscriber_(nullptr),
subscribed_(false)
{}
pFlow::eventObserver::eventObserver
(
const eventSubscriber& subscriber,
bool subscribe
)
:
subscriber_(&subscriber),
subscribed_(false)
{
if(subscribe && subscriber_)
{
subscribed_ = subscriber_->subscribe(this);
}
}
pFlow::eventObserver::~eventObserver()
{
if(subscribed_ && subscriber_)
subscriber_->unsubscribe(this);
}
bool pFlow::eventObserver::subscribe(const eventSubscriber& subscriber)
{
subscriber_ = &subscriber;
subscribed_ = subscriber_->subscribe(this);
return subscribed_;
}

View File

@ -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 __eventObserver_H__
#define __eventObserver_H__
#include "eventMessage.H"
namespace pFlow
{
class eventSubscriber;
class eventObserver
{
protected:
const eventSubscriber* subscriber_ = nullptr;
// if this object is linked to subscriber
bool subscribed_ = false;
public:
eventObserver();
eventObserver(const eventSubscriber& subscriber, bool subscribe = true );
virtual ~eventObserver();
inline bool subscribed()const {return subscribed_;}
bool subscribe(const eventSubscriber& subscriber);
inline void invalidateSubscriber()
{
subscribed_ = false;
}
virtual bool update(const eventMessage& msg)=0;
};
} // pFlow
#endif // __eventObserver_H__

View File

@ -0,0 +1,92 @@
/*------------------------------- 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 "eventSubscriber.H"
#include "Set.H"
pFlow::eventSubscriber::~eventSubscriber()
{
for(auto& observer:observerList_)
{
observer->invalidateSubscriber();
}
}
bool pFlow::eventSubscriber::subscribe
(
eventObserver* observer
)const
{
if(observer)
{
observerList_.push_back(observer);
return true;
}
else
{
return false;
}
}
bool pFlow::eventSubscriber::unsubscribe
(
eventObserver* observer
)const
{
if(observer)
{
observerList_.remove(observer);
}
return true;
}
bool pFlow::eventSubscriber::notify
(
const eventMessage &msg
)
{
for ( auto& observer:observerList_ )
{
if(observer)
if( !observer->update(msg) ) return false;
}
return true;
}
bool pFlow::eventSubscriber::notify
(
const eventMessage& msg,
const List<eventObserver*>& exclutionList
)
{
Set<eventObserver*> sortedExcList(exclutionList.begin(),exclutionList.end());
for(auto& observer:observerList_)
{
if( observer && sortedExcList.count(observer) == 0 )
{
if(!observer->update(msg)) return false;
}
}
return true;
}

View File

@ -0,0 +1,64 @@
/*------------------------------- 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 __eventSubscriber_H__
#define __eventSubscriber_H__
#include "List.H"
#include "eventObserver.H"
#include "eventMessage.H"
namespace pFlow
{
class eventSubscriber
{
protected:
// - list of subsribed objectd that recieve updage messages
mutable List<eventObserver*> observerList_;
public:
eventSubscriber()
{}
virtual ~eventSubscriber();
virtual bool subscribe(eventObserver* observer)const;
virtual bool unsubscribe(eventObserver* observer)const;
bool notify(const eventMessage& msg);
bool notify(const eventMessage& msg, const List<eventObserver*>& exclutionList );
};
} // pFlow
#endif // __eventSubscriber_H__

View File

@ -0,0 +1,96 @@
/*------------------------------- 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 <iostream>
#include <stdlib.h>
#include "error.H"
#include "streams.H"
static pFlow::Ostream& errorStream = pFlow::errReport;
pFlow::iOstream& fatalErrorMessage(const char* fileName, int linNumber )
{
errorStream<<"\n>>> Fatal error in phasicFlow\n" <<
"Error occured in source file "<< redText(fileName) <<
" at line "<<redText(linNumber)<<'\n';
return errorStream;
}
pFlow::iOstream& fatalErrorInMessage(const char* fnName, const char* fileName, int linNumber )
{
errorStream<<"\n>>> Fatal error in phasicFlow\n" <<
" Error is issued in function " << redText(fnName)<<
", located in file "<< redText(fileName) <<
" at line "<< redText(linNumber) << '\n';
return errorStream;
}
pFlow::iOstream& notImplementedErrorMessage(const char*fnName, const char* fileName, int lineNumber)
{
errorStream<<"\n>>> Fatal error in phasicFlow\n";
errorStream<<" Function "<< redText(fnName) << " has not implmented yet!\n" <<
" Function definition is in source file "<< redText(fileName) <<
" at line "<< redText(lineNumber) <<'\n';
return errorStream;
}
pFlow::iOstream& ioErrorMessage(const char* fileName, int fileLineNumber, const char* fnName, const char* fName, int lNumber)
{
errorStream<<"\n>>> Fatal IO file error\n"<<
" IO error at number "<<redText(fileLineNumber)<<
" of file " << redText(fileName)<<'\n';
errorStream<<" IO operation is peformed from function "<<redText(fnName) <<
" in file "<< redText(fName)<< " at line "<< redText(lNumber) <<'\n';
return errorStream;
}
pFlow::iOstream& ioErrorMessage(const pFlow::word& fileName, int fileLineNumber, const char* fnName, const char* fName, int lNumber)
{
return ioErrorMessage( fileName.c_str(), fileLineNumber, fnName, fName, lNumber);
}
pFlow::iOstream& warningMessage(const char* fnName, const char* fileName, int linNumber )
{
errorStream<<"\n>>> Warning in phasicFlow\n"<<
" Warning is issued in function " << yellowText(fnName)<<
" in source file "<< yellowText(fileName) <<
" at line "<< yellowText(linNumber) <<'\n';
return errorStream;
}
pFlow::iOstream& reportAndExit()
{
errorStream<<"\n>>> phasicFlow is exiting . . ." << pFlow::endl;
exit(EXIT_FAILURE);
return errorStream;
}

View File

@ -0,0 +1,68 @@
/*------------------------------- 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 __error_H__
#define __error_H__
#include "builtinTypes.H"
namespace pFlow
{
class iOstream;
}
// reports a fatal error and exit the applicaiton
#define fatalError \
fatalErrorMessage(__FILE__, __LINE__)
#define fatalErrorIn( functionName ) \
fatalErrorInMessage((functionName), __FILE__, __LINE__ )
#define fatalErrorInFunction fatalErrorIn(FUNCTION_NAME)
#define notImplemented(functionName) \
notImplementedErrorMessage ((functionName), __FILE__, __LINE__ )
#define notImplementedFunction notImplemented(FUNCTION_NAME);
#define ioErrorInFile( fileName, lineNumber) \
ioErrorMessage( fileName, lineNumber, FUNCTION_NAME, __FILE__, __LINE__ )
#define warningIn( functionName ) \
warningMessage((functionName), __FILE__, __LINE__ )
#define warningInFunction warningIn(FUNCTION_NAME)
#define fatalExit \
reportAndExit()
pFlow::iOstream& fatalErrorMessage(const char* fileName, int linNumber );
pFlow::iOstream& fatalErrorInMessage(const char* fnName, const char* fileName, int linNumber );
pFlow::iOstream& notImplementedErrorMessage(const char*fnName, const char* fileName, int lineNumber);
pFlow::iOstream& ioErrorMessage(const pFlow::word& fileName, int fileLineNumber, const char* fnName, const char* fName, int lNumber);
pFlow::iOstream& ioErrorMessage(const char* fileName, int fileLineNumber, const char* fnName, const char* fName, int lNumber);
pFlow::iOstream& warningMessage(const char* fnName, const char* fileName, int linNumber );
pFlow::iOstream& reportAndExit();
#endif

View File

@ -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 __globalSettings_H__
#define __globalSettings_H__
namespace pFlow
{
const inline double vectorGrowthFactor__ = 1.1;
}
#endif // __globalSettings_H__

View File

@ -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 __pFlowMacros_H__
#define __pFlowMacros_H__
#include "phasicFlowConfig.H"
#ifdef __GNUC__
#define FUNCTION_NAME __PRETTY_FUNCTION__
#else
#define FUNCTION_NAME __func__
#endif
#ifdef __GNUC__
# define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
#else
# define UNUSED(x) UNUSED_ ## x
#endif
#define CONSUME_PARAM(x) (void)(x);
#ifdef __CUDACC__
#define INLINE_FUNCTION_HD inline __host__ __device__
#define INLINE_FUNCTION_D inline __device__
#define INLINE_FUNCTION_H inline __host__
#define LAMBDA_HD [=] __host__ __device__
#define LAMBDA_D [=] __device__
#define CLASS_LAMBDA_HD [=,*this] __host__ __device__
#define FUNCTION_HD __host__ __device__
#define FUNCTION_H __host__
#define FUNCTION_D __device__
#else
#define INLINE_FUNCTION_HD inline
#define INLINE_FUNCTION_D inline
#define INLINE_FUNCTION_H inline
#define LAMBDA_HD [=]
#define LAMBDA_D [=]
#define CLASS_LAMBDA_HD [=,*this]
#define FUNCTION_HD
#define FUNCTION_H
#define FUNCTION_D
#endif
#define INLINE_FUNCTION inline
#ifdef BUILD_SHARED_LIBS
#define USE_INSTANTIATION 1
#else
#define USE_INSTANTIATION 0
#endif
#define forAll(i, container) for(auto i=0; i < container.size(); ++i)
#ifdef USE_STD_PARALLEL_ALG
static inline const bool useStdParallel__ = true;
#else
static inline const bool useStdParallel__ = false;
#endif
#endif //__pFlowMacros_H__

58
src/phasicFlow/globals/vocabs.H Executable file
View File

@ -0,0 +1,58 @@
/*------------------------------- 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 __vocabs_H__
#define __vocabs_H__
namespace pFlow
{
// folders / repositories
const inline char* settingsFolder__ = "settings";
const inline char* settingsRepository__ = "settings";
const inline char* caseSetupFolder__ = "caseSetup";
const inline char* caseSetupRepository__ = "caseSetup";
const inline char* geometryFolder__ = "geometry";
const inline char* geometryRepository_ = "geometry";
const inline char* integrationRepository__ = "integration";
const inline char* integrationFolder__ = "integration";
// file names
const inline char* settingsFile__ = "settingsDict";
const inline char* insertionFile__ = "particleInsertion";
const inline char* sphereShapeFile__ = "sphereShape";
const inline char* pointStructureFile__ = "pStructure";
const inline char* triSurfaceFile__ = "triSurface";
const inline char* createParticles__ = "createParticles";
const inline char* motionModelFile__ = "motionModel";
const inline char* contactSearchFile__ = "contactSearch";
const inline char* propertyFile__ = "interaction";
const inline char* interactionFile__ = "interaction";
const inline char* uniform__ = "uniform";
const inline char* nonUniform__ = "nonUniform";
}
#endif // __vocabs_H__

View File

@ -0,0 +1,53 @@
/*------------------------------- 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 "RandomReal.H"
template<typename DistributionType>
pFlow::RandomReal<DistributionType>::RandomReal
(
word distribution
)
:
randomReal(distribution),
distribution_()
{
}
template<typename DistributionType>
pFlow::real pFlow::RandomReal<DistributionType>::randomNumber
(
real a, real b
)
{
return distribution_.randomNumber(a,b);
}
template<typename DistributionType>
pFlow::realx3 pFlow::RandomReal<DistributionType>::randomNumber
(
realx3 a,
realx3 b
)
{
return distribution_.randomNumber(a,b);
}

View File

@ -0,0 +1,73 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
#ifndef __RandomReal_H__
#define __RandomReal_H__
//#include <random>
#include "randomReal.H"
#include "uniformRandomReal.H"
namespace pFlow
{
template<typename DistributionType>
class RandomReal
:
public randomReal
{
protected:
DistributionType distribution_;
public:
// type info
TypeNameTemplate("randomReal", DistributionType);
RandomReal(word distribution);
add_vCtor
(
randomReal,
RandomReal,
word
);
virtual ~RandomReal()= default;
virtual real randomNumber(real a, real b)override;
virtual realx3 randomNumber(realx3 a, realx3 b)override;
};
}
#include "RandomReal.C"
#endif

View File

@ -0,0 +1,51 @@
/*------------------------------- 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 "randomReal.H"
pFlow::uniquePtr<pFlow::randomReal> pFlow::randomReal::create
(
word distribution
)
{
word dist = angleBracketsNames("randomReal", distribution);
if( wordvCtorSelector_.search(dist) )
{
return wordvCtorSelector_[dist] (distribution);
}
else
{
printKeys
(
fatalError << "Ctor Selector "<< dist << " dose not exist. \n"
<<"Avaiable ones are: \n\n"
,
wordvCtorSelector_
);
fatalExit();
}
return nullptr;
}

Some files were not shown because too many files have changed in this diff Show More