mirror of
https://github.com/PhasicFlow/phasicFlow.git
synced 2025-06-12 16:26:23 +00:00
added phasicFlow
This commit is contained in:
135
src/phasicFlow/Kokkos/KokkosTypes.H
Normal file
135
src/phasicFlow/Kokkos/KokkosTypes.H
Normal 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__
|
92
src/phasicFlow/Kokkos/KokkosUtilities.H
Normal file
92
src/phasicFlow/Kokkos/KokkosUtilities.H
Normal 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__
|
593
src/phasicFlow/Kokkos/ViewAlgorithms.H
Normal file
593
src/phasicFlow/Kokkos/ViewAlgorithms.H
Normal 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
|
245
src/phasicFlow/Kokkos/baseAlgorithms.H
Normal file
245
src/phasicFlow/Kokkos/baseAlgorithms.H
Normal 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__
|
51
src/phasicFlow/Kokkos/baseAlgorithmsFwd.H
Normal file
51
src/phasicFlow/Kokkos/baseAlgorithmsFwd.H
Normal 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
|
||||
);
|
97
src/phasicFlow/Timer/Timer.C
Normal file
97
src/phasicFlow/Timer/Timer.C
Normal 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;
|
||||
}
|
163
src/phasicFlow/Timer/Timer.H
Normal file
163
src/phasicFlow/Timer/Timer.H
Normal 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__
|
40
src/phasicFlow/Timer/Timers.C
Normal file
40
src/phasicFlow/Timer/Timers.C
Normal 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;
|
||||
}
|
120
src/phasicFlow/Timer/Timers.H
Normal file
120
src/phasicFlow/Timer/Timers.H
Normal 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__
|
96
src/phasicFlow/algorithms/algorithmFunctions.H
Normal file
96
src/phasicFlow/algorithms/algorithmFunctions.H
Normal 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__
|
182
src/phasicFlow/algorithms/cudaAlgorithms.H
Normal file
182
src/phasicFlow/algorithms/cudaAlgorithms.H
Normal 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__
|
188
src/phasicFlow/algorithms/kokkosAlgorithms.H
Normal file
188
src/phasicFlow/algorithms/kokkosAlgorithms.H
Normal 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__
|
243
src/phasicFlow/algorithms/stdAlgorithms.H
Normal file
243
src/phasicFlow/algorithms/stdAlgorithms.H
Normal 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__
|
3201
src/phasicFlow/commandLine/CLI/App.hpp
Normal file
3201
src/phasicFlow/commandLine/CLI/App.hpp
Normal file
File diff suppressed because it is too large
Load Diff
36
src/phasicFlow/commandLine/CLI/CLI.hpp
Normal file
36
src/phasicFlow/commandLine/CLI/CLI.hpp
Normal 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"
|
396
src/phasicFlow/commandLine/CLI/Config.hpp
Normal file
396
src/phasicFlow/commandLine/CLI/Config.hpp
Normal 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 §ion, 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 ¤tSection, 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
|
182
src/phasicFlow/commandLine/CLI/ConfigFwd.hpp
Normal file
182
src/phasicFlow/commandLine/CLI/ConfigFwd.hpp
Normal 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 §ionRef() { return configSection; }
|
||||
/// get the section
|
||||
const std::string §ion() const { return configSection; }
|
||||
/// specify a particular section of the configuration file to use
|
||||
ConfigBase *section(const std::string §ionName) {
|
||||
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
|
351
src/phasicFlow/commandLine/CLI/Error.hpp
Normal file
351
src/phasicFlow/commandLine/CLI/Error.hpp
Normal 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
|
292
src/phasicFlow/commandLine/CLI/Formatter.hpp
Normal file
292
src/phasicFlow/commandLine/CLI/Formatter.hpp
Normal 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
|
184
src/phasicFlow/commandLine/CLI/FormatterFwd.hpp
Normal file
184
src/phasicFlow/commandLine/CLI/FormatterFwd.hpp
Normal 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
|
25
src/phasicFlow/commandLine/CLI/LICENSE
Normal file
25
src/phasicFlow/commandLine/CLI/LICENSE
Normal 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.
|
44
src/phasicFlow/commandLine/CLI/Macros.hpp
Normal file
44
src/phasicFlow/commandLine/CLI/Macros.hpp
Normal 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]
|
1348
src/phasicFlow/commandLine/CLI/Option.hpp
Normal file
1348
src/phasicFlow/commandLine/CLI/Option.hpp
Normal file
File diff suppressed because it is too large
Load Diff
143
src/phasicFlow/commandLine/CLI/Split.hpp
Normal file
143
src/phasicFlow/commandLine/CLI/Split.hpp
Normal 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 ¤t, 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 ¤t, 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 ¤t, 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
|
430
src/phasicFlow/commandLine/CLI/StringTools.hpp
Normal file
430
src/phasicFlow/commandLine/CLI/StringTools.hpp
Normal 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 <rim(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 <rim(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
|
134
src/phasicFlow/commandLine/CLI/Timer.hpp
Normal file
134
src/phasicFlow/commandLine/CLI/Timer.hpp
Normal 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(); }
|
1548
src/phasicFlow/commandLine/CLI/TypeTools.hpp
Normal file
1548
src/phasicFlow/commandLine/CLI/TypeTools.hpp
Normal file
File diff suppressed because it is too large
Load Diff
1142
src/phasicFlow/commandLine/CLI/Validators.hpp
Normal file
1142
src/phasicFlow/commandLine/CLI/Validators.hpp
Normal file
File diff suppressed because it is too large
Load Diff
16
src/phasicFlow/commandLine/CLI/Version.hpp
Normal file
16
src/phasicFlow/commandLine/CLI/Version.hpp
Normal 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]
|
63
src/phasicFlow/commandLine/commandLine.C
Normal file
63
src/phasicFlow/commandLine/commandLine.C
Normal 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()
|
||||
}
|
140
src/phasicFlow/commandLine/commandLine.H
Normal file
140
src/phasicFlow/commandLine/commandLine.H
Normal 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
|
||||
|
170
src/phasicFlow/containers/Field/Field.C
Normal file
170
src/phasicFlow/containers/Field/Field.C
Normal 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;
|
||||
}
|
270
src/phasicFlow/containers/Field/Field.H
Normal file
270
src/phasicFlow/containers/Field/Field.H
Normal 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__
|
81
src/phasicFlow/containers/Field/Fields.C
Normal file
81
src/phasicFlow/containers/Field/Fields.C
Normal 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>>;
|
||||
|
||||
|
126
src/phasicFlow/containers/Field/Fields.H
Normal file
126
src/phasicFlow/containers/Field/Fields.H
Normal 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__
|
250
src/phasicFlow/containers/List/List/List.H
Normal file
250
src/phasicFlow/containers/List/List/List.H
Normal 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__
|
257
src/phasicFlow/containers/List/List/ListI.H
Normal file
257
src/phasicFlow/containers/List/List/ListI.H
Normal 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;
|
||||
}
|
197
src/phasicFlow/containers/List/ListPtr/ListPtr.H
Normal file
197
src/phasicFlow/containers/List/ListPtr/ListPtr.H
Normal 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
|
301
src/phasicFlow/containers/List/ListPtr/ListPtrI.H
Normal file
301
src/phasicFlow/containers/List/ListPtr/ListPtrI.H
Normal 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));
|
||||
}
|
||||
}
|
35
src/phasicFlow/containers/List/Lists.H
Normal file
35
src/phasicFlow/containers/List/Lists.H
Normal 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__
|
174
src/phasicFlow/containers/Map/Map/Map.H
Normal file
174
src/phasicFlow/containers/Map/Map/Map.H
Normal 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
|
134
src/phasicFlow/containers/Map/Map/MapI.H
Normal file
134
src/phasicFlow/containers/Map/Map/MapI.H
Normal 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;
|
||||
}
|
274
src/phasicFlow/containers/Map/MapPtr/MapPtr.H
Normal file
274
src/phasicFlow/containers/Map/MapPtr/MapPtr.H
Normal 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
|
333
src/phasicFlow/containers/Map/MapPtr/MapPtrI.H
Normal file
333
src/phasicFlow/containers/Map/MapPtr/MapPtrI.H
Normal 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();
|
||||
}
|
||||
|
||||
|
30
src/phasicFlow/containers/Map/Maps.H
Normal file
30
src/phasicFlow/containers/Map/Maps.H
Normal 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
|
174
src/phasicFlow/containers/Map/hashMap/hashMap.H
Normal file
174
src/phasicFlow/containers/Map/hashMap/hashMap.H
Normal 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
|
137
src/phasicFlow/containers/Map/hashMap/hashMapI.H
Normal file
137
src/phasicFlow/containers/Map/hashMap/hashMapI.H
Normal 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;
|
||||
}
|
35
src/phasicFlow/containers/Set/Set.H
Normal file
35
src/phasicFlow/containers/Set/Set.H
Normal 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
|
352
src/phasicFlow/containers/Vector/Vector.C
Normal file
352
src/phasicFlow/containers/Vector/Vector.C
Normal 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;
|
||||
}
|
425
src/phasicFlow/containers/Vector/Vector.H
Normal file
425
src/phasicFlow/containers/Vector/Vector.H
Normal 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
|
80
src/phasicFlow/containers/Vector/VectorAlgorithm.H
Normal file
80
src/phasicFlow/containers/Vector/VectorAlgorithm.H
Normal 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
|
||||
|
80
src/phasicFlow/containers/Vector/VectorFwd.H
Normal file
80
src/phasicFlow/containers/Vector/VectorFwd.H
Normal 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);
|
302
src/phasicFlow/containers/Vector/VectorI.H
Normal file
302
src/phasicFlow/containers/Vector/VectorI.H
Normal 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;
|
||||
}
|
212
src/phasicFlow/containers/Vector/VectorMath.H
Normal file
212
src/phasicFlow/containers/Vector/VectorMath.H
Normal 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;
|
||||
}
|
||||
|
||||
}
|
46
src/phasicFlow/containers/Vector/Vectors.C
Normal file
46
src/phasicFlow/containers/Vector/Vectors.C
Normal 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>;
|
||||
|
||||
|
||||
|
||||
|
101
src/phasicFlow/containers/Vector/Vectors.H
Normal file
101
src/phasicFlow/containers/Vector/Vectors.H
Normal 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__
|
965
src/phasicFlow/containers/VectorHD/VectorDual.H
Normal file
965
src/phasicFlow/containers/VectorHD/VectorDual.H
Normal 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__
|
||||
|
113
src/phasicFlow/containers/VectorHD/VectorDualAlgorithms.H
Normal file
113
src/phasicFlow/containers/VectorHD/VectorDualAlgorithms.H
Normal 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__
|
52
src/phasicFlow/containers/VectorHD/VectorDuals.H
Normal file
52
src/phasicFlow/containers/VectorHD/VectorDuals.H
Normal 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
|
859
src/phasicFlow/containers/VectorHD/VectorSingle.H
Normal file
859
src/phasicFlow/containers/VectorHD/VectorSingle.H
Normal 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__
|
||||
|
61
src/phasicFlow/containers/VectorHD/VectorSingleAlgorithms.H
Normal file
61
src/phasicFlow/containers/VectorHD/VectorSingleAlgorithms.H
Normal 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__
|
86
src/phasicFlow/containers/VectorHD/VectorSingles.H
Normal file
86
src/phasicFlow/containers/VectorHD/VectorSingles.H
Normal 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
|
223
src/phasicFlow/containers/bitsetHD/bitsetHD.H
Normal file
223
src/phasicFlow/containers/bitsetHD/bitsetHD.H
Normal 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__
|
27
src/phasicFlow/containers/bitsetHD/bitsetHDs.C
Normal file
27
src/phasicFlow/containers/bitsetHD/bitsetHDs.C
Normal 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>;
|
||||
|
21
src/phasicFlow/containers/indexContainer/indexContainer.C
Normal file
21
src/phasicFlow/containers/indexContainer/indexContainer.C
Normal 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"
|
171
src/phasicFlow/containers/indexContainer/indexContainer.H
Normal file
171
src/phasicFlow/containers/indexContainer/indexContainer.H
Normal 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
|
129
src/phasicFlow/containers/pointField/pointField.C
Normal file
129
src/phasicFlow/containers/pointField/pointField.C
Normal 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;
|
||||
}
|
||||
|
196
src/phasicFlow/containers/pointField/pointField.H
Normal file
196
src/phasicFlow/containers/pointField/pointField.H
Normal 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__
|
269
src/phasicFlow/containers/pointField/pointFieldAlgorithms.H
Normal file
269
src/phasicFlow/containers/pointField/pointFieldAlgorithms.H
Normal 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;
|
||||
}*/
|
||||
|
||||
|
||||
}
|
58
src/phasicFlow/containers/pointField/pointFields.C
Normal file
58
src/phasicFlow/containers/pointField/pointFields.C
Normal 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>;
|
||||
|
||||
|
||||
|
88
src/phasicFlow/containers/pointField/pointFields.H
Normal file
88
src/phasicFlow/containers/pointField/pointFields.H
Normal 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
|
161
src/phasicFlow/containers/span/span.H
Normal file
161
src/phasicFlow/containers/span/span.H
Normal 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__
|
278
src/phasicFlow/containers/symArrayHD/symArrayHD.H
Normal file
278
src/phasicFlow/containers/symArrayHD/symArrayHD.H
Normal 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__
|
29
src/phasicFlow/containers/symArrayHD/symArrays.C
Normal file
29
src/phasicFlow/containers/symArrayHD/symArrays.C
Normal 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>;
|
35
src/phasicFlow/containers/symArrayHD/symArrays.H
Normal file
35
src/phasicFlow/containers/symArrayHD/symArrays.H
Normal 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>;
|
||||
|
||||
}
|
119
src/phasicFlow/containers/triSurfaceField/triSurfaceField.C
Normal file
119
src/phasicFlow/containers/triSurfaceField/triSurfaceField.C
Normal 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);
|
||||
}
|
177
src/phasicFlow/containers/triSurfaceField/triSurfaceField.H
Normal file
177
src/phasicFlow/containers/triSurfaceField/triSurfaceField.H
Normal 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__
|
34
src/phasicFlow/containers/triSurfaceField/triSurfaceFields.C
Normal file
34
src/phasicFlow/containers/triSurfaceField/triSurfaceFields.C
Normal 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>;
|
59
src/phasicFlow/containers/triSurfaceField/triSurfaceFields.H
Normal file
59
src/phasicFlow/containers/triSurfaceField/triSurfaceFields.H
Normal 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__
|
819
src/phasicFlow/dictionary/dictionary.C
Normal file
819
src/phasicFlow/dictionary/dictionary.C
Normal 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();
|
||||
}
|
344
src/phasicFlow/dictionary/dictionary.H
Normal file
344
src/phasicFlow/dictionary/dictionary.H
Normal 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__
|
375
src/phasicFlow/dictionary/entry/dataEntry.C
Normal file
375
src/phasicFlow/dictionary/entry/dataEntry.C
Normal 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;
|
||||
}
|
163
src/phasicFlow/dictionary/entry/dataEntry.H
Normal file
163
src/phasicFlow/dictionary/entry/dataEntry.H
Normal 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__
|
185
src/phasicFlow/dictionary/entry/iEntry.C
Normal file
185
src/phasicFlow/dictionary/entry/iEntry.C
Normal 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;
|
||||
}
|
160
src/phasicFlow/dictionary/entry/iEntry.H
Normal file
160
src/phasicFlow/dictionary/entry/iEntry.H
Normal 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__
|
48
src/phasicFlow/dictionary/twoPartEntry/twoPartEntry.C
Normal file
48
src/phasicFlow/dictionary/twoPartEntry/twoPartEntry.C
Normal 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;
|
||||
}
|
||||
|
||||
}
|
70
src/phasicFlow/dictionary/twoPartEntry/twoPartEntry.H
Normal file
70
src/phasicFlow/dictionary/twoPartEntry/twoPartEntry.H
Normal 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
|
116
src/phasicFlow/eventSubscriber/eventMessage.H
Normal file
116
src/phasicFlow/eventSubscriber/eventMessage.H
Normal 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__
|
56
src/phasicFlow/eventSubscriber/eventObserver.C
Normal file
56
src/phasicFlow/eventSubscriber/eventObserver.C
Normal 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_;
|
||||
}
|
||||
|
65
src/phasicFlow/eventSubscriber/eventObserver.H
Normal file
65
src/phasicFlow/eventSubscriber/eventObserver.H
Normal 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__
|
92
src/phasicFlow/eventSubscriber/eventSubscriber.C
Normal file
92
src/phasicFlow/eventSubscriber/eventSubscriber.C
Normal 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;
|
||||
}
|
64
src/phasicFlow/eventSubscriber/eventSubscriber.H
Normal file
64
src/phasicFlow/eventSubscriber/eventSubscriber.H
Normal 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__
|
96
src/phasicFlow/globals/error.C
Normal file
96
src/phasicFlow/globals/error.C
Normal 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;
|
||||
}
|
||||
|
||||
|
68
src/phasicFlow/globals/error.H
Normal file
68
src/phasicFlow/globals/error.H
Normal 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
|
35
src/phasicFlow/globals/globalSettings.H
Executable file
35
src/phasicFlow/globals/globalSettings.H
Executable 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__
|
80
src/phasicFlow/globals/pFlowMacros.H
Executable file
80
src/phasicFlow/globals/pFlowMacros.H
Executable 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
58
src/phasicFlow/globals/vocabs.H
Executable 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__
|
53
src/phasicFlow/random/randomReal/RandomReal.C
Normal file
53
src/phasicFlow/random/randomReal/RandomReal.C
Normal 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);
|
||||
}
|
73
src/phasicFlow/random/randomReal/RandomReal.H
Normal file
73
src/phasicFlow/random/randomReal/RandomReal.H
Normal 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
|
51
src/phasicFlow/random/randomReal/randomReal.C
Normal file
51
src/phasicFlow/random/randomReal/randomReal.C
Normal 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
Reference in New Issue
Block a user