Field class and pointStructure modified and tested
This commit is contained in:
parent
90a1ac8f16
commit
0096856c98
|
@ -35,9 +35,10 @@ dictionary/entry/dataEntry.cpp
|
|||
dictionary/twoPartEntry/twoPartEntry.cpp
|
||||
|
||||
containers/Vector/Vectors.cpp
|
||||
containers/VectorHD/VectorSingles.cpp
|
||||
containers/Field/Fields.cpp
|
||||
containers/List/anyList/anyList.cpp
|
||||
containers/pointField/pointFields.cpp
|
||||
#containers/pointField/pointFields.cpp
|
||||
|
||||
#setFieldList/setFieldList.cpp
|
||||
#setFieldList/setFieldEntry.cpp
|
||||
|
|
|
@ -26,6 +26,7 @@ Licence:
|
|||
#include "pFlowMacros.hpp"
|
||||
#include "types.hpp"
|
||||
#include "span.hpp"
|
||||
#include "dataIO.hpp"
|
||||
#include "iOstream.hpp"
|
||||
|
||||
namespace pFlow
|
||||
|
|
|
@ -18,6 +18,116 @@ Licence:
|
|||
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
template<class T, class MemorySpace>
|
||||
bool pFlow::Field<T, MemorySpace>::read
|
||||
(
|
||||
iIstream& is
|
||||
)
|
||||
{
|
||||
|
||||
bool tokenFound = true;
|
||||
|
||||
tokenFound = is.findToken(fieldKey_);
|
||||
|
||||
if( !tokenFound )
|
||||
{
|
||||
ioErrorInFile( is.name(), is.lineNumber() ) <<
|
||||
" error in searching for filedkey " << fieldKey_<<endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !VectorType::read(is) )
|
||||
{
|
||||
ioErrorInFile(is.name(), is.lineNumber())<<
|
||||
"error in reading field data from field "<< this->name()<<endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
is.readEndStatement("Field::read");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class MemorySpace>
|
||||
bool pFlow::Field<T, MemorySpace>::read
|
||||
(
|
||||
iIstream& is,
|
||||
const IOPattern& iop
|
||||
)
|
||||
{
|
||||
|
||||
bool tokenFound = true;
|
||||
|
||||
if(iop.thisProcReadData())
|
||||
tokenFound = is.findToken(fieldKey_);
|
||||
|
||||
if( !tokenFound )
|
||||
{
|
||||
ioErrorInFile( is.name(), is.lineNumber() ) <<
|
||||
" error in searching for filedkey " << fieldKey_<<endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !VectorType::read(is, iop) )
|
||||
{
|
||||
ioErrorInFile(is.name(), is.lineNumber())<<
|
||||
"error in reading field data from field "<< this->name()<<endl;
|
||||
return false;
|
||||
}
|
||||
if(iop.thisProcReadData())
|
||||
is.readEndStatement("Field::read");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T, class MemorySpace>
|
||||
bool pFlow::Field<T, MemorySpace>::write
|
||||
(
|
||||
iOstream& os
|
||||
)const
|
||||
{
|
||||
|
||||
os.writeWordKeyword(fieldKey_)<<endl;
|
||||
|
||||
if(!os.check(FUNCTION_NAME))return false;
|
||||
|
||||
if(!VectorType::write(os)) return false;
|
||||
|
||||
os.endEntry();
|
||||
if(!os.check(FUNCTION_NAME))return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class T, class MemorySpace>
|
||||
bool pFlow::Field<T, MemorySpace>::write
|
||||
(
|
||||
iOstream& os,
|
||||
const IOPattern& iop
|
||||
)const
|
||||
{
|
||||
|
||||
if(iop.thisProcWriteData())
|
||||
os.writeWordKeyword(fieldKey_)<<endl;
|
||||
|
||||
if(!os.check(FUNCTION_NAME))return false;
|
||||
|
||||
if(!VectorType::write(os, iop)) return false;
|
||||
|
||||
if(iop.thisProcWriteData())
|
||||
os.endEntry();
|
||||
|
||||
if(!os.check(FUNCTION_NAME))return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*template<template<class, class> class VectorField, class T, class PropType>
|
||||
bool pFlow::Field<VectorField, T, PropType>::readUniform
|
||||
(
|
||||
|
@ -179,55 +289,3 @@ bool pFlow::Field<VectorField, T, PropType>::writeField(iOstream& os)const
|
|||
|
||||
return true;
|
||||
}*/
|
||||
|
||||
|
||||
template<template<class, class> class VectorField, class T, class PropType>
|
||||
bool pFlow::Field<VectorField, T, PropType>::read
|
||||
(
|
||||
iIstream& is,
|
||||
const IOPattern& iop
|
||||
)
|
||||
{
|
||||
|
||||
bool tokenFound = true;
|
||||
|
||||
if(iop.thisProcReadData())
|
||||
tokenFound = is.findToken(fieldKey_);
|
||||
|
||||
if( !tokenFound )
|
||||
{
|
||||
ioErrorInFile( is.name(), is.lineNumber() ) <<
|
||||
" error in searching for filedkey " << fieldKey_<<endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !VectorType::read(is, iop) )
|
||||
{
|
||||
ioErrorInFile(is.name(), is.lineNumber())<<
|
||||
"error in reading field data from field "<< this->name()<<endl;
|
||||
}
|
||||
if(iop.thisProcReadData())
|
||||
is.readEndStatement("Field::read");
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<template<class, class> class VectorField, class T, class PropType>
|
||||
bool pFlow::Field<VectorField, T, PropType>::write(
|
||||
iOstream& os,
|
||||
const IOPattern& iop)const
|
||||
{
|
||||
|
||||
os.writeWordKeyword(fieldKey_)<<endl;
|
||||
|
||||
if(!os.check(FUNCTION_NAME))return false;
|
||||
|
||||
if(!VectorType::write(os, iop)) return false;
|
||||
|
||||
os.endEntry();
|
||||
if(!os.check(FUNCTION_NAME))return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,11 +21,9 @@ Licence:
|
|||
#ifndef __Field_hpp__
|
||||
#define __Field_hpp__
|
||||
|
||||
//#include "VectorSingle.hpp"
|
||||
//#include "vocabs.hpp"
|
||||
|
||||
|
||||
#include "types.hpp"
|
||||
#include "VectorSingle.hpp"
|
||||
#include "Vector.hpp"
|
||||
#include "streams.hpp"
|
||||
|
||||
|
@ -33,44 +31,44 @@ namespace pFlow
|
|||
{
|
||||
|
||||
|
||||
|
||||
template<template<class, class> class VectorField, class T, class PropType=void>
|
||||
template<class T, class MemorySpace = void>
|
||||
class Field
|
||||
:
|
||||
public VectorField<T, PropType>
|
||||
public VectorSingle<T, MemorySpace>
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
using VectorType = VectorField<T,PropType>;
|
||||
using VectorType = VectorSingle<T,MemorySpace>;
|
||||
|
||||
using FieldType = Field<VectorField, T, PropType>;
|
||||
using FieldType = Field<T, MemorySpace>;
|
||||
|
||||
using iterator = typename VectorType::iterator;
|
||||
using FieldTypeHost = Field<T, HostSpace>;
|
||||
|
||||
using const_iterator = typename VectorType::const_iterator;
|
||||
using memory_space = typename VectorType::memory_space;
|
||||
|
||||
using reference = typename VectorType::reference;
|
||||
using execution_space = typename VectorType::execution_space;
|
||||
|
||||
using iterator = typename VectorType::iterator;
|
||||
|
||||
using const_iterator = typename VectorType::const_iterator;
|
||||
|
||||
using reference = typename VectorType::reference;
|
||||
|
||||
using const_reference = typename VectorType::const_reference;
|
||||
using const_reference = typename VectorType::const_reference;
|
||||
|
||||
using value_type = typename VectorType::value_type;
|
||||
using value_type = typename VectorType::value_type;
|
||||
|
||||
using pointer = typename VectorType::pointer;
|
||||
using pointer = typename VectorType::pointer;
|
||||
|
||||
using const_pointer = typename VectorType::const_pointer;
|
||||
using const_pointer = typename VectorType::const_pointer;
|
||||
|
||||
|
||||
protected:
|
||||
private:
|
||||
|
||||
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
|
||||
|
@ -91,7 +89,6 @@ public:
|
|||
VectorType(name),
|
||||
fieldKey_(fieldKey)
|
||||
{}
|
||||
|
||||
|
||||
/// Construct a field with name and fieldKey and specified len
|
||||
Field(const word& name, const word& fieldKey, size_t len)
|
||||
|
@ -189,15 +186,12 @@ public:
|
|||
}
|
||||
|
||||
//// - IO operations
|
||||
/*bool readField(iIstream& is, const size_t len, bool resume, bool readLength = true);
|
||||
|
||||
bool read(iIstream& is);
|
||||
|
||||
bool readField(iIstream& is, bool resume );
|
||||
bool write(iOstream& os)const;
|
||||
|
||||
|
||||
bool writeField(iOstream& os)const;*/
|
||||
|
||||
|
||||
bool read(iIstream& is, const IOPattern& iop);
|
||||
|
||||
|
||||
|
@ -206,8 +200,8 @@ public:
|
|||
};
|
||||
|
||||
|
||||
template<template<class, class> class VectorField, class T, class PropType>
|
||||
inline iIstream& operator >> (iIstream & is, Field<VectorField, T, PropType> & ifld )
|
||||
template<class T, class MemorySpace>
|
||||
inline iIstream& operator >> (iIstream & is, Field<T, MemorySpace> & ifld )
|
||||
{
|
||||
if( !ifld.read(is, IOPattern::MasterProcessorOnly) )
|
||||
{
|
||||
|
@ -217,8 +211,8 @@ inline iIstream& operator >> (iIstream & is, Field<VectorField, T, PropType> & i
|
|||
return is;
|
||||
}
|
||||
|
||||
template<template<class, class> class VectorField, class T, class PropType>
|
||||
inline iOstream& operator << (iOstream& os, const Field<VectorField, T, PropType>& ofld )
|
||||
template<typename T, typename MemorySpace>
|
||||
inline iOstream& operator << (iOstream& os, const Field<T, MemorySpace>& ofld )
|
||||
{
|
||||
|
||||
if( !ofld.write(os, IOPattern::AllProcessorsDifferent) )
|
||||
|
|
|
@ -21,61 +21,17 @@ Licence:
|
|||
#include "Fields.hpp"
|
||||
|
||||
|
||||
template class pFlow::Field<pFlow::VectorSingle, pFlow::int8>;
|
||||
template class pFlow::Field<pFlow::int8>;
|
||||
|
||||
/*template class pFlow::Field<pFlow::VectorSingle, pFlow::int8, pFlow::HostSpace>;
|
||||
template class pFlow::Field<pFlow::uint8>;
|
||||
|
||||
template class pFlow::Field<pFlow::VectorSingle, pFlow::int16>;
|
||||
template class pFlow::Field<pFlow::int32>;
|
||||
|
||||
template class pFlow::Field<pFlow::VectorSingle, pFlow::int16, pFlow::HostSpace>;
|
||||
template class pFlow::Field<pFlow::uint32>;
|
||||
|
||||
template class pFlow::Field<pFlow::VectorSingle, pFlow::int32>;
|
||||
template class pFlow::Field<pFlow::real>;
|
||||
|
||||
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::realx3>;
|
||||
|
||||
|
||||
template class pFlow::Field<pFlow::Vector, pFlow::word, pFlow::vecAllocator<pFlow::word>>;*/
|
||||
|
||||
|
||||
|
|
|
@ -30,44 +30,44 @@ Licence:
|
|||
namespace pFlow
|
||||
{
|
||||
|
||||
using int8Field_D = Field<VectorSingle, int8>;
|
||||
using int8Field_D = Field<int8>;
|
||||
|
||||
using int8Field_H = Field<VectorSingle, int8, HostSpace>;
|
||||
using int8Field_H = Field<int8, HostSpace>;
|
||||
|
||||
using int32Field_D = Field<VectorSingle, int32>;
|
||||
using int32Field_D = Field<int32>;
|
||||
|
||||
using int32Field_H = Field<VectorSingle, int32, HostSpace>;
|
||||
using int32Field_H = Field<int32, HostSpace>;
|
||||
|
||||
using int64Field_D = Field<VectorSingle, int64>;
|
||||
using int64Field_D = Field<int64>;
|
||||
|
||||
using int64Field_H = Field<VectorSingle, int64, HostSpace>;
|
||||
using int64Field_H = Field<int64, HostSpace>;
|
||||
|
||||
using uint8Field_D = Field<VectorSingle, uint8>;
|
||||
using uint8Field_D = Field<uint8>;
|
||||
|
||||
using uint8Field_H = Field<VectorSingle, uint8, HostSpace>;
|
||||
using uint8Field_H = Field<uint8, HostSpace>;
|
||||
|
||||
using uint32Field_D = Field<VectorSingle, uint32>;
|
||||
using uint32Field_D = Field<uint32>;
|
||||
|
||||
using uint32Field_H = Field<VectorSingle, uint32, HostSpace>;
|
||||
using uint32Field_H = Field<uint32, HostSpace>;
|
||||
|
||||
using uint64Field_D = Field<VectorSingle, uint64>;
|
||||
using uint64Field_D = Field<uint64>;
|
||||
|
||||
using uint64Field_H = Field<VectorSingle, uint64, HostSpace> ;
|
||||
using uint64Field_H = Field<uint64, HostSpace> ;
|
||||
|
||||
using realField_D = Field<VectorSingle, real>;
|
||||
using realField_D = Field<real>;
|
||||
|
||||
using realField_H = Field<VectorSingle, real, HostSpace> ;
|
||||
using realField_H = Field<real, HostSpace> ;
|
||||
|
||||
using realx3Field_D = Field<VectorSingle, realx3>;
|
||||
using realx3Field_D = Field<realx3>;
|
||||
|
||||
using realx3Field_H = Field<VectorSingle, realx3, HostSpace>;
|
||||
using realx3Field_H = Field<realx3, HostSpace>;
|
||||
|
||||
using realx3x3Field_D = Field<VectorSingle, realx3x3>;
|
||||
using realx3x3Field_D = Field<realx3x3>;
|
||||
|
||||
using realx3x3Field_H = Field<VectorSingle, realx3x3, HostSpace>;
|
||||
using realx3x3Field_H = Field<realx3x3, HostSpace>;
|
||||
|
||||
// - no typedef on device (since word does not compile on CUDA)
|
||||
using wordField_H = Field<VectorSingle, word, HostSpace>;
|
||||
using wordField_H = Field<word, HostSpace>;
|
||||
|
||||
|
||||
// host device fields
|
||||
|
@ -93,11 +93,6 @@ using int64x3Field_HD = Field<VectorDual, int64x3>;
|
|||
|
||||
using realx3x3Field_HD = Field<VectorDual, realx3x3>;*/
|
||||
|
||||
|
||||
using wordField = Field<Vector, word , vecAllocator<word>>;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ Licence:
|
|||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
template<typename T, typename Allocator>
|
||||
/*template<typename T, typename Allocator>
|
||||
bool pFlow::Vector<T, Allocator>::readVector
|
||||
(
|
||||
iIstream& is,
|
||||
|
@ -38,7 +38,7 @@ bool pFlow::Vector<T, Allocator>::writeVector
|
|||
) const
|
||||
{
|
||||
return writeStdVector(os, vectorField(), iop);
|
||||
}
|
||||
}*/
|
||||
|
||||
/*template<typename T, typename Allocator>
|
||||
bool pFlow::Vector<T, Allocator>::deleteElement_sorted
|
||||
|
|
|
@ -59,27 +59,27 @@ class Vector
|
|||
{
|
||||
public:
|
||||
|
||||
typedef Vector<T, Allocator> VectorType;
|
||||
using VectorType = Vector<T, Allocator>;
|
||||
|
||||
typedef typename std::vector<T, Allocator> vectorType;
|
||||
using vectorType = typename std::vector<T, Allocator>;
|
||||
|
||||
typedef typename vectorType::iterator iterator;
|
||||
using iterator = typename vectorType::iterator;
|
||||
|
||||
typedef typename vectorType::const_iterator const_iterator;
|
||||
using const_iterator = typename vectorType::const_iterator;
|
||||
|
||||
typedef typename vectorType::reference reference;
|
||||
using reference = typename vectorType::reference;
|
||||
|
||||
typedef typename vectorType::const_reference const_reference;
|
||||
using const_reference = typename vectorType::const_reference;
|
||||
|
||||
typedef T value_type;
|
||||
using value_type = T;
|
||||
|
||||
typedef T* pointer;
|
||||
using pointer = T *;
|
||||
|
||||
typedef const T* const_pointer;
|
||||
using const_pointer = const T *;
|
||||
|
||||
typedef typename std::initializer_list<T> init_list;
|
||||
using init_list = typename std::initializer_list<T>;
|
||||
|
||||
protected:
|
||||
private:
|
||||
|
||||
// - name of the vector
|
||||
word name_;
|
||||
|
@ -105,21 +105,24 @@ public:
|
|||
|
||||
|
||||
/// Empty Vector with a name
|
||||
inline Vector(const word& name)
|
||||
inline
|
||||
explicit Vector(const word& name)
|
||||
:
|
||||
name_(name)
|
||||
{}
|
||||
|
||||
|
||||
/// Vector with specified length and name
|
||||
inline Vector(const word& name, size_t len)
|
||||
inline
|
||||
Vector(const word& name, size_t len)
|
||||
:
|
||||
vectorType(len),
|
||||
name_(name)
|
||||
{}
|
||||
|
||||
/// Vector with name, length and value
|
||||
inline Vector(const word& name, size_t len, const T& val)
|
||||
inline
|
||||
Vector(const word& name, size_t len, const T& val)
|
||||
:
|
||||
Vector(name, len)
|
||||
{
|
||||
|
@ -136,7 +139,8 @@ public:
|
|||
|
||||
|
||||
/// Vector from name and initializer list
|
||||
inline Vector(const word& name, const init_list &l)
|
||||
inline
|
||||
Vector(const word& name, const init_list &l)
|
||||
:
|
||||
vectorType(l),
|
||||
name_(name)
|
||||
|
@ -162,7 +166,7 @@ public:
|
|||
inline Vector(const VectorType& src) = default;
|
||||
|
||||
/// Copy from src with a new name
|
||||
inline Vector(const word name, const Vector<T>& src):
|
||||
inline Vector(const word& name, const Vector<T>& src):
|
||||
vectorType(src),
|
||||
name_(name)
|
||||
{}
|
||||
|
@ -178,10 +182,10 @@ public:
|
|||
}
|
||||
|
||||
/// Move construct
|
||||
inline Vector( VectorType && mv) = default;
|
||||
Vector( VectorType && mv) noexcept= default;
|
||||
|
||||
/// Move assignment
|
||||
inline VectorType& operator=( VectorType && mv) = default;
|
||||
VectorType& operator=( VectorType && mv)noexcept = default;
|
||||
|
||||
/// Scalar assignment
|
||||
inline void operator=(const T& val)
|
||||
|
@ -190,10 +194,8 @@ public:
|
|||
}
|
||||
|
||||
/// Destructor
|
||||
inline ~Vector()
|
||||
{
|
||||
vectorType::clear();
|
||||
}
|
||||
~Vector() = default;
|
||||
|
||||
|
||||
/// Clone as a uniquePtr
|
||||
inline uniquePtr<VectorType> clone() const
|
||||
|
@ -204,7 +206,8 @@ public:
|
|||
/// Clone as a pointer
|
||||
inline VectorType* clonePtr()const
|
||||
{
|
||||
return new VectorType(*this);
|
||||
uniquePtr<VectorType> Ptr = makeUnique<VectorType>(*this);
|
||||
return Ptr.release();
|
||||
}
|
||||
|
||||
|
||||
|
@ -283,6 +286,99 @@ public:
|
|||
vectorType::reserve(cap);
|
||||
}
|
||||
|
||||
// - fill the whole content of vector, [begin, end), with val
|
||||
void fill( const T& val);
|
||||
|
||||
inline
|
||||
auto getSpan()
|
||||
{
|
||||
return span<T>(this->data(), this->size());
|
||||
}
|
||||
|
||||
inline
|
||||
auto getSpan()const
|
||||
{
|
||||
return span<T>(const_cast<T*>(this->data()), this->size());
|
||||
}
|
||||
|
||||
static constexpr bool isHostAccessible()
|
||||
{
|
||||
return isHostAccessible_;
|
||||
}
|
||||
|
||||
void operator +=( const T& val);
|
||||
void operator -=( const T& val);
|
||||
void operator *=( const T& val);
|
||||
void operator /=( const T& val);
|
||||
|
||||
void operator +=( const VectorType& v );
|
||||
void operator -=( const VectorType& v );
|
||||
void operator /=( const VectorType& v );
|
||||
void operator *=( const VectorType& v );
|
||||
|
||||
VectorType operator -()const;
|
||||
|
||||
bool read(iIstream& is)
|
||||
{
|
||||
return readStdVector(is, vectorField());
|
||||
}
|
||||
bool write(iOstream& os)
|
||||
{
|
||||
return writeStdVector(os, vectorField());
|
||||
}
|
||||
|
||||
bool read(iIstream& is, const IOPattern& iop)
|
||||
{
|
||||
return readStdVector(is, vectorField(), iop);
|
||||
}
|
||||
|
||||
bool write(iOstream& os, const IOPattern& iop)const
|
||||
{
|
||||
return writeStdVector(os, vectorField(), iop);
|
||||
}
|
||||
|
||||
static
|
||||
constexpr const char* memoerySpaceName()
|
||||
{
|
||||
return "std";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename T, typename Allocator>
|
||||
inline iIstream& operator >> (iIstream & is, Vector<T, Allocator> & ivec )
|
||||
{
|
||||
if( !ivec.read(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.write(os) )
|
||||
{
|
||||
ioErrorInFile(os.name(), os.lineNumber());
|
||||
fatalExit;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
} // pFlow
|
||||
|
||||
|
||||
#include "VectorI.hpp"
|
||||
#include "Vector.cpp"
|
||||
#include "VectorMath.hpp"
|
||||
#include "VectorAlgorithm.hpp"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*// - delete elemens of vector based on sorted indices
|
||||
// return false if out of range
|
||||
|
@ -317,94 +413,4 @@ public:
|
|||
|
||||
// - 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);
|
||||
|
||||
inline
|
||||
auto getSpan()
|
||||
{
|
||||
return span<T>(this->data(), this->size());
|
||||
}
|
||||
|
||||
inline
|
||||
auto getSpan()const
|
||||
{
|
||||
return span<T>(const_cast<T*>(this->data()), this->size());
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/// Read vector (assume ASCII in input)
|
||||
bool readVector(iIstream& is, const IOPattern& iop);
|
||||
|
||||
/// write vector
|
||||
bool writeVector(iOstream& os, const IOPattern& iop) const;
|
||||
|
||||
bool read(iIstream& is, const IOPattern& iop)
|
||||
{
|
||||
return readVector(is, iop);
|
||||
}
|
||||
|
||||
bool write(iOstream& os, const IOPattern& iop)const
|
||||
{
|
||||
return writeVector(os, iop);
|
||||
}
|
||||
|
||||
constexpr static inline const char* memoerySpaceName()
|
||||
{
|
||||
return "std";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename T, typename Allocator>
|
||||
inline iIstream& operator >> (iIstream & is, Vector<T, Allocator> & ivec )
|
||||
{
|
||||
if( !ivec.readVector(is, IOPattern::MasterProcessorOnly) )
|
||||
{
|
||||
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, IOPattern::AllProcessorsDifferent) )
|
||||
{
|
||||
ioErrorInFile(os.name(), os.lineNumber());
|
||||
fatalExit;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
} // pFlow
|
||||
|
||||
|
||||
#include "VectorI.hpp"
|
||||
#include "Vector.cpp"
|
||||
#include "VectorMath.hpp"
|
||||
#include "VectorAlgorithm.hpp"
|
||||
|
||||
#endif
|
||||
inline bool insertSetElement(int32 idx, const T& val);*/
|
|
@ -20,22 +20,4 @@ Licence:
|
|||
|
||||
#include "Vectors.hpp"
|
||||
|
||||
// instantiation just for numeral types
|
||||
|
||||
/*template class pFlow::Vector<pFlow::int8>;
|
||||
|
||||
template class pFlow::Vector<pFlow::int32>;
|
||||
|
||||
template class pFlow::Vector<pFlow::uint32>;
|
||||
|
||||
template class pFlow::Vector<pFlow::real>;
|
||||
|
||||
template class pFlow::Vector<pFlow::realx3>;
|
||||
|
||||
template class pFlow::Vector<pFlow::realx3x3>;*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -48,12 +48,20 @@ public:
|
|||
template<typename T>
|
||||
using vecAllocator = std::allocator<T>;
|
||||
|
||||
template<typename T>
|
||||
inline
|
||||
bool writeSpan(
|
||||
iOstream& os,
|
||||
span<T> sp)
|
||||
{
|
||||
return writeDataAsciiBinary(os, sp);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline
|
||||
bool writeSpan(
|
||||
iOstream& os,
|
||||
const span<T>& sp,
|
||||
span<T> sp,
|
||||
const IOPattern& iop)
|
||||
{
|
||||
|
||||
|
@ -73,6 +81,17 @@ bool writeSpan(
|
|||
return true;
|
||||
}
|
||||
|
||||
template<typename T, typename Allocator>
|
||||
bool writeStdVector
|
||||
(
|
||||
iOstream& os,
|
||||
const std::vector<T,Allocator>& vec
|
||||
)
|
||||
{
|
||||
auto sp = makeSpan(vec);
|
||||
return writeSpan(os, sp);
|
||||
}
|
||||
|
||||
template<typename T, typename Allocator>
|
||||
bool writeStdVector
|
||||
(
|
||||
|
@ -85,6 +104,18 @@ bool writeStdVector
|
|||
return writeSpan(os, sp, iop);
|
||||
}
|
||||
|
||||
template<typename T, typename Allocator>
|
||||
bool readStdVector
|
||||
(
|
||||
iIstream& is,
|
||||
std::vector<T,Allocator>& vec
|
||||
)
|
||||
{
|
||||
|
||||
return readDataAsciiBinary(is, vec);
|
||||
|
||||
}
|
||||
|
||||
template<typename T, typename Allocator>
|
||||
bool readStdVector
|
||||
(
|
||||
|
@ -113,7 +144,7 @@ bool readStdVector
|
|||
template<typename T, typename Allocator>
|
||||
iOstream& operator<<( iOstream& os, const std::vector<T,Allocator>& vec)
|
||||
{
|
||||
if(!writeStdVector(os, vec, IOPattern::AllProcessorsDifferent))
|
||||
if(!writeStdVector(os, vec))
|
||||
{
|
||||
fatalErrorInFunction;
|
||||
fatalExit;
|
||||
|
@ -125,7 +156,7 @@ iOstream& operator<<( iOstream& os, const std::vector<T,Allocator>& vec)
|
|||
template<typename T, typename Allocator>
|
||||
iIstream& operator>>(iIstream& is, std::vector<T,Allocator>& vec)
|
||||
{
|
||||
if( !readStdVector(is,vec, IOPattern::MasterProcessorOnly))
|
||||
if( !readStdVector(is,vec))
|
||||
{
|
||||
fatalErrorInFunction;
|
||||
fatalExit;
|
||||
|
|
|
@ -403,6 +403,23 @@ void pFlow::VectorSingle<T,MemorySpace>::assign
|
|||
{
|
||||
assign(src, src.capacity());
|
||||
}
|
||||
template<typename T, typename MemorySpace>
|
||||
INLINE_FUNCTION_H
|
||||
void pFlow::VectorSingle<T,MemorySpace>::assign(const VectorTypeHost& src)
|
||||
{
|
||||
uint32 srcSize = src.size();
|
||||
uint32 srcCap = src.capacity();
|
||||
|
||||
if(srcCap != capacity())
|
||||
{
|
||||
reallocateCapacitySize(srcCap, srcSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
setSize(srcSize);
|
||||
}
|
||||
copy(deviceVector(), src.hostVector());
|
||||
}
|
||||
|
||||
template<typename T, typename MemorySpace>
|
||||
INLINE_FUNCTION_H
|
||||
|
|
|
@ -24,12 +24,11 @@ Licence:
|
|||
|
||||
#include "globalSettings.hpp"
|
||||
#include "phasicFlowKokkos.hpp"
|
||||
#include "types.hpp"
|
||||
#include "stdVectorHelper.hpp"
|
||||
#include "error.hpp"
|
||||
#include "indexContainer.hpp"
|
||||
#include "streams.hpp"
|
||||
#include "span.hpp"
|
||||
#include "dataIO.hpp"
|
||||
|
||||
|
||||
|
||||
#ifndef __RESERVE__
|
||||
|
@ -53,6 +52,8 @@ public:
|
|||
|
||||
using VectorType = VectorSingle<T, MemorySpace>;
|
||||
|
||||
using VectorTypeHost = VectorSingle<T, HostSpace>;
|
||||
|
||||
using iterator = T*;
|
||||
|
||||
using const_iterator = const T*;
|
||||
|
@ -77,7 +78,7 @@ public:
|
|||
|
||||
using execution_space = typename viewType::execution_space;
|
||||
|
||||
protected:
|
||||
private:
|
||||
|
||||
// - Data members
|
||||
|
||||
|
@ -136,7 +137,7 @@ public:
|
|||
VectorSingle();
|
||||
|
||||
/// Empty vector with a name (capacity = 2)
|
||||
VectorSingle(const word& name);
|
||||
explicit VectorSingle(const word& name);
|
||||
|
||||
/// Vector with name and size n
|
||||
VectorSingle(const word& name, uint32 n);
|
||||
|
@ -271,6 +272,12 @@ public:
|
|||
/// The capacity of *this becomes the capacity of src.
|
||||
INLINE_FUNCTION_H
|
||||
void assign(const std::vector<T>& src);
|
||||
|
||||
/// Assign source vector from host side.
|
||||
/// The size of *this becomes the size of src.
|
||||
/// The capacity of *this becomes the capacity of src.
|
||||
INLINE_FUNCTION_H
|
||||
void assign(const VectorTypeHost& src);
|
||||
|
||||
INLINE_FUNCTION_H
|
||||
auto getSpan();
|
||||
|
@ -291,7 +298,7 @@ public:
|
|||
/// resize if necessary and works on host accessible vector.
|
||||
template<bool Enable = true>
|
||||
INLINE_FUNCTION_H
|
||||
typename std::enable_if<isHostAccessible_ && Enable, void>::type
|
||||
typename std::enable_if_t<isHostAccessible_ && Enable, void>
|
||||
push_back(const T& val)
|
||||
{
|
||||
auto n = changeSize(size_+1);
|
||||
|
@ -360,7 +367,19 @@ public:
|
|||
|
||||
//// - IO operations
|
||||
|
||||
/// Read vector from stream (ASCII)
|
||||
/// Read vector from stream
|
||||
FUNCTION_H
|
||||
bool read(iIstream& is)
|
||||
{
|
||||
std::vector<T> vecFromFile;
|
||||
if(! readStdVector(is, vecFromFile)) return false;
|
||||
|
||||
this->assign(vecFromFile);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Read vector from stream
|
||||
FUNCTION_H
|
||||
bool read(iIstream& is, const IOPattern& iop)
|
||||
{
|
||||
|
@ -383,6 +402,16 @@ public:
|
|||
|
||||
}
|
||||
|
||||
FUNCTION_H
|
||||
bool write(iOstream& os)const
|
||||
{
|
||||
auto hVec = hostVector();
|
||||
auto sp = span<T>( const_cast<T*>(hVec.data()), hVec.size());
|
||||
|
||||
return writeSpan(os, sp);
|
||||
|
||||
}
|
||||
|
||||
template<typename HostMask>
|
||||
FUNCTION_H
|
||||
bool write(iOstream& os, const IOPattern& iop, const HostMask& mask)const
|
||||
|
@ -408,19 +437,21 @@ public:
|
|||
return writeSpan(os, sp, iop);
|
||||
|
||||
}
|
||||
/// Name of the memory space
|
||||
constexpr static inline
|
||||
const char* memoerySpaceName()
|
||||
{
|
||||
return memory_space::name();
|
||||
}
|
||||
|
||||
|
||||
/// Name of the memory space
|
||||
static
|
||||
constexpr const char* memoerySpaceName()
|
||||
{
|
||||
return memory_space::name();
|
||||
}
|
||||
|
||||
}; // class VectorSingle
|
||||
|
||||
template<typename T, typename MemorySpace>
|
||||
inline iIstream& operator >> (iIstream & is, VectorSingle<T, MemorySpace> & ivec )
|
||||
{
|
||||
if( !ivec.read(is, IOPattern::MasterProcessorOnly ) )
|
||||
if( !ivec.read(is) )
|
||||
{
|
||||
ioErrorInFile (is.name(), is.lineNumber());
|
||||
fatalExit;
|
||||
|
@ -432,7 +463,7 @@ template<typename T, typename MemorySpace>
|
|||
inline iOstream& operator << (iOstream& os, const VectorSingle<T, MemorySpace>& ovec )
|
||||
{
|
||||
|
||||
if( !ovec.write(os, IOPattern::AllProcessorsDifferent) )
|
||||
if( !ovec.write(os) )
|
||||
{
|
||||
ioErrorInFile(os.name(), os.lineNumber());
|
||||
fatalExit;
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*------------------------------- 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 "VectorSingles.hpp"
|
||||
|
||||
|
||||
template class Kokkos::View<pFlow::uint8*>;
|
||||
template class pFlow::VectorSingle<pFlow::uint8>;
|
||||
|
||||
template class Kokkos::View<pFlow::int32*>;
|
||||
template class pFlow::VectorSingle<pFlow::int32>;
|
||||
|
||||
template class Kokkos::View<pFlow::uint32*>;
|
||||
template class pFlow::VectorSingle<pFlow::uint32>;
|
||||
|
||||
template class Kokkos::View<pFlow::real*>;
|
||||
template class pFlow::VectorSingle<pFlow::real>;
|
||||
|
||||
template class Kokkos::View<pFlow::realx3*>;
|
||||
template class pFlow::VectorSingle<pFlow::realx3>;
|
||||
|
|
@ -28,7 +28,7 @@ pFlow::internalField<VectorField, T, MemorySpace>::internalField
|
|||
observer
|
||||
(
|
||||
&internal,
|
||||
message::CAP_CHANGED+message::ITEM_INSERT+message::ITEM_REARRANGE+message::ITEM_DELETE
|
||||
defaultMessage_
|
||||
),
|
||||
field_
|
||||
(
|
||||
|
@ -41,10 +41,36 @@ pFlow::internalField<VectorField, T, MemorySpace>::internalField
|
|||
internalPoints_(internal)
|
||||
{}
|
||||
|
||||
|
||||
template<template<class, class> class VectorField, class T, class MemorySpace>
|
||||
pFlow::hostViewType1D<T>
|
||||
pFlow::internalField<VectorField, T, MemorySpace>::activeValuesHost()const
|
||||
pFlow::internalField<VectorField, T, MemorySpace>::internalField
|
||||
(
|
||||
const word &name,
|
||||
const internalPoints &internal,
|
||||
const T &val
|
||||
)
|
||||
:
|
||||
observer
|
||||
(
|
||||
&internal,
|
||||
defaultMessage_
|
||||
),
|
||||
field_
|
||||
(
|
||||
name,
|
||||
"ineternalField",
|
||||
internal.capacity(),
|
||||
internal.size(),
|
||||
RESERVE()
|
||||
),
|
||||
internalPoints_(internal)
|
||||
{
|
||||
field_.fill(val);
|
||||
}
|
||||
|
||||
|
||||
template <template <class, class> class VectorField, class T, class MemorySpace>
|
||||
pFlow::hostViewType1D<T>
|
||||
pFlow::internalField<VectorField, T, MemorySpace>::activeValuesHost() const
|
||||
{
|
||||
auto maskH = internalPoints_.activePointsMaskHost();
|
||||
auto fieldH = field_.hostVector();
|
||||
|
|
|
@ -50,12 +50,26 @@ protected:
|
|||
|
||||
const internalPoints& internalPoints_;
|
||||
|
||||
static inline
|
||||
const message defaultMessage_ =
|
||||
(
|
||||
message::CAP_CHANGED+
|
||||
message::ITEM_INSERT+
|
||||
message::ITEM_REARRANGE+
|
||||
message::ITEM_DELETE
|
||||
);
|
||||
|
||||
public:
|
||||
|
||||
internalField(
|
||||
const word& name,
|
||||
const internalPoints& internal);
|
||||
|
||||
internalField(
|
||||
const word& name,
|
||||
const internalPoints& internal,
|
||||
const T& val);
|
||||
|
||||
|
||||
auto fieldDevice()const
|
||||
{
|
||||
|
@ -105,28 +119,34 @@ public:
|
|||
return internalPoints_.isAllActive();
|
||||
}
|
||||
|
||||
bool hearChanges(const message& msg, const anyList& varList) override
|
||||
{
|
||||
notImplementedFunction;
|
||||
return false;
|
||||
}
|
||||
|
||||
//// - IO
|
||||
|
||||
bool write(iOstream& os, const IOPattern& iop)const;
|
||||
|
||||
};
|
||||
|
||||
/*template<template<class, class> class VectorField, class T, class MemorySpace>
|
||||
template<template<class, class> class VectorField, class T, class MemorySpace>
|
||||
inline
|
||||
iOstream& operator<<
|
||||
(
|
||||
iOstream& os,
|
||||
const internalField<VectorField, T, MemorySpace>& if
|
||||
const internalField<VectorField, T, MemorySpace>& ifeild
|
||||
)
|
||||
{
|
||||
if( !if.write(os, IOPattern::AllProcessorsDifferent) )
|
||||
if( !ifeild.write(os, IOPattern::AllProcessorsDifferent) )
|
||||
{
|
||||
ioErrorInFile(os.name(), os.lineNumber());
|
||||
fatalExit;
|
||||
}
|
||||
|
||||
return os;
|
||||
}*/
|
||||
}
|
||||
|
||||
} // pFlow
|
||||
|
||||
|
|
|
@ -44,109 +44,139 @@ pFlow::pointField<VectorField, T, MemorySpace>::pointField
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
|
||||
|
||||
template<template<class, class> class VectorField, class T, class MemorySpace>
|
||||
pFlow::pointField<VectorField, T, MemorySpace>::pointField
|
||||
(
|
||||
const pointStructure& pStruct,
|
||||
const objectFile &objf,
|
||||
pointStructure &pStruct,
|
||||
const T& defVal,
|
||||
bool subscribe
|
||||
const T& val
|
||||
)
|
||||
:
|
||||
eventObserver(pStruct, subscribe),
|
||||
FieldType(pStruct.capacity(), pStruct.size(), RESERVE()),
|
||||
IOobject
|
||||
(
|
||||
objectFile
|
||||
(
|
||||
objf.name(),
|
||||
objf.localPath(),
|
||||
objectFile::READ_NEVER,
|
||||
objf.wFlag()
|
||||
),
|
||||
pStruct.ioPattern(),
|
||||
pStruct.owner()
|
||||
),
|
||||
InternalFieldType
|
||||
(
|
||||
objf.name(),
|
||||
pStruct,
|
||||
val
|
||||
),
|
||||
boundaryFieldList_(pStruct.boundaries(), *this),
|
||||
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() )
|
||||
{
|
||||
|
||||
}
|
||||
else if( msg.isInsert())
|
||||
{
|
||||
const auto newElems = pStruct().insertedPointIndex();
|
||||
//Vector<T> vals( newElems.size(), defaultValue_);
|
||||
return this->insertSetElement(newElems, defaultValue_);
|
||||
}
|
||||
|
||||
if(msg.isRearranged())
|
||||
{
|
||||
auto sortedIndex = pStruct().mortonSortedIndex();
|
||||
this->sortItems(sortedIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}*/
|
||||
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>
|
||||
bool pFlow::pointField<VectorField, T, MemorySpace>::readPointField
|
||||
(
|
||||
iIstream& is,
|
||||
const IOPattern& iop
|
||||
)
|
||||
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() )
|
||||
{
|
||||
|
||||
}
|
||||
else if( msg.isInsert())
|
||||
{
|
||||
const auto newElems = pStruct().insertedPointIndex();
|
||||
//Vector<T> vals( newElems.size(), defaultValue_);
|
||||
return this->insertSetElement(newElems, defaultValue_);
|
||||
}
|
||||
|
||||
if(msg.isRearranged())
|
||||
{
|
||||
auto sortedIndex = pStruct().mortonSortedIndex();
|
||||
this->sortItems(sortedIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}*/
|
||||
|
||||
template <template <class, class> class VectorField, class T, class MemorySpace>
|
||||
bool pFlow::pointField<VectorField, T, MemorySpace>::readPointField(
|
||||
iIstream &is,
|
||||
const IOPattern &iop)
|
||||
{
|
||||
Field<Vector, T , vecAllocator<T>>
|
||||
fRead("file_read"+InternalFieldType::name(), InternalFieldType::fieldKey());
|
||||
|
@ -192,6 +222,28 @@ bool pFlow::pointField<VectorField, T, MemorySpace>::writePointField
|
|||
const IOPattern& iop
|
||||
)const
|
||||
{
|
||||
notImplementedFunction;
|
||||
return false;
|
||||
|
||||
hostViewType1D<T> valuesH;
|
||||
|
||||
if(this->isAllActive())
|
||||
{
|
||||
valuesH = this->fieldHost();
|
||||
}
|
||||
else
|
||||
{
|
||||
valuesH = this->activeValuesHost();
|
||||
}
|
||||
|
||||
auto data = span<T>(valuesH.data(), valuesH.size());
|
||||
|
||||
if( !writeSpan(os, data, iop) )
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"Error in writing pointStructure in stream "<<
|
||||
os.name()<<endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
|
@ -79,6 +79,17 @@ public:
|
|||
const objectFile& objf,
|
||||
pointStructure& pStruct,
|
||||
const T& defVal);
|
||||
|
||||
pointField(
|
||||
const objectFile& objf,
|
||||
pointStructure& pStruct,
|
||||
const T& defVal,
|
||||
const T& val);
|
||||
|
||||
const auto& internal()const
|
||||
{
|
||||
return static_cast<const InternalFieldType&>(*this);
|
||||
}
|
||||
|
||||
// - construct from iIOEntity, pointStructure and a value
|
||||
/*pointField( const pointStructure& pStruct, const T& val, const T& defVal, bool subscribe = true);
|
||||
|
@ -174,12 +185,12 @@ iIstream& operator >> (iIstream & is, pointField<VectorField, T, MemorySpace> &
|
|||
}
|
||||
|
||||
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) )
|
||||
if(! pF.write(os, IOPattern::AllProcessorsDifferent) )
|
||||
{
|
||||
ioErrorInFile( os.name(), os.lineNumber() )<<
|
||||
"error in writing pointField into file. \n";
|
||||
|
@ -187,7 +198,7 @@ iOstream& operator << (iOstream& os, const pointField<VectorField, T, MemorySpac
|
|||
}
|
||||
|
||||
return os;
|
||||
}*/
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -23,15 +23,24 @@ Licence:
|
|||
#include "createBoundaryFields.hpp"
|
||||
|
||||
|
||||
template class pFlow::pointField<pFlow::VectorSingle, pFlow::int8>;
|
||||
template class pFlow::pointField<pFlow::VectorSingle, pFlow::int8, pFlow::HostSpace>;
|
||||
createBaseBoundary(pFlow::VectorSingle, pFlow::int8, pFlow::HostSpace);
|
||||
createBoundary(pFlow::VectorSingle, pFlow::int8, pFlow::HostSpace, exit);
|
||||
|
||||
template class pFlow::pointField<pFlow::VectorSingle, pFlow::real>;
|
||||
template class pFlow::pointField<pFlow::VectorSingle, pFlow::int8>;
|
||||
createBaseBoundary(pFlow::VectorSingle, pFlow::int8, void);
|
||||
createBoundary(pFlow::VectorSingle, pFlow::int8, void, exit);
|
||||
|
||||
template class pFlow::pointField<pFlow::VectorSingle, pFlow::real, pFlow::HostSpace>;
|
||||
createBaseBoundary(pFlow::VectorSingle, pFlow::real, pFlow::HostSpace);
|
||||
createBoundary(pFlow::VectorSingle, pFlow::real, pFlow::HostSpace, exit);
|
||||
|
||||
|
||||
template class pFlow::pointField<pFlow::VectorSingle, pFlow::real>;
|
||||
createBaseBoundary(pFlow::VectorSingle, pFlow::real, void);
|
||||
createBoundary(pFlow::VectorSingle, pFlow::real, void, exit);
|
||||
|
||||
|
||||
/*template class pFlow::pointField<pFlow::VectorSingle, pFlow::int8, pFlow::HostSpace>;
|
||||
|
||||
template class pFlow::pointField<pFlow::VectorSingle, pFlow::int16>;
|
||||
|
|
|
@ -35,15 +35,16 @@ template<typename T>
|
|||
template<typename T>
|
||||
using pointField_D = pointField<VectorSingle, T>;
|
||||
|
||||
/*template<typename T>
|
||||
using pointField_HD = pointField<VectorDual, T>;*/
|
||||
|
||||
|
||||
using int8PointField_D = pointField<VectorSingle, int8>;
|
||||
|
||||
using int8PointField_H = pointField<VectorSingle, int8, HostSpace>;
|
||||
|
||||
using int32PointField_D = pointField<VectorSingle, int32>;
|
||||
using realPointField_D = pointField<VectorSingle, real>;
|
||||
|
||||
using realPointField_H = pointField<VectorSingle, real, HostSpace>;
|
||||
|
||||
//using int32PointField_D = pointField<VectorSingle, int32>;
|
||||
|
||||
/*using int32PointField_H = pointField<VectorSingle, int32, HostSpace>;
|
||||
|
||||
|
|
|
@ -155,51 +155,16 @@ public:
|
|||
return data_[i];
|
||||
}
|
||||
|
||||
/// Write in ASCII format, can be sued for all variable types
|
||||
INLINE_FUNCTION_H
|
||||
bool writeASCII(iOstream& os) const
|
||||
{
|
||||
os<< size()<<endl;
|
||||
os << token::BEGIN_LIST;
|
||||
if(size()>0)
|
||||
{
|
||||
for(uint32 i=0; i<size()-1; i++)
|
||||
{
|
||||
os << data_[i]<<token::NL;
|
||||
}
|
||||
os << data_[size()-1] << token::END_LIST;
|
||||
}
|
||||
else
|
||||
{
|
||||
os<< token::END_LIST;
|
||||
}
|
||||
|
||||
os.check(FUNCTION_NAME);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline
|
||||
iOstream& operator<<(iOstream& os, const span<T>& s)
|
||||
{
|
||||
|
||||
s.writeASCII(os);
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
template<typename T, template<class> class Container>
|
||||
span<T> makeSpan(Container<T>& container)
|
||||
template<typename T, typename... properties, template<class, class...> class Container>
|
||||
size_t makeSpan(Container<T, properties...>& container)
|
||||
{
|
||||
return span<T>(container.data(), container.size());
|
||||
}
|
||||
|
||||
template<typename T, template<class> class Container>
|
||||
span<T> makeSpan(const Container<T>& container)
|
||||
template<typename T, typename... properties, template<class, class...> class Container>
|
||||
size_t makeSpan(const Container<T, properties...>& container)
|
||||
{
|
||||
return span<T>(
|
||||
const_cast<T*>(container.data()),
|
||||
|
@ -227,6 +192,23 @@ span<const char> charSpan(span<const T> s)
|
|||
s.size()*el);
|
||||
}
|
||||
|
||||
template<typename T, template<class> class Container>
|
||||
span<T> makeSpan(Container<T>& container)
|
||||
{
|
||||
return span<T>(container.data(), container.size());
|
||||
}
|
||||
|
||||
template<typename T, template<class> class Container>
|
||||
span<T> makeSpan(const Container<T>& container)
|
||||
{
|
||||
return span<T>(
|
||||
const_cast<T*>(container.data()),
|
||||
container.size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // pFlow
|
||||
|
|
|
@ -20,7 +20,7 @@ pFlow::fileDictionary::fileDictionary
|
|||
)
|
||||
{
|
||||
dictionary::name_ = IOobject::path().wordPath();
|
||||
if(!IOobject::read())
|
||||
if(!IOobject::readObject())
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"Error in reading from dictionary "<< globalName()<<endl;
|
||||
|
|
|
@ -62,7 +62,7 @@ pFlow::repository* pFlow::IOobject::releaseOwner
|
|||
return old;
|
||||
}
|
||||
|
||||
bool pFlow::IOobject::read(bool rdHdr)
|
||||
bool pFlow::IOobject::readObject(bool rdHdr)
|
||||
{
|
||||
|
||||
if( implyRead() )
|
||||
|
@ -85,7 +85,7 @@ bool pFlow::IOobject::read(bool rdHdr)
|
|||
{
|
||||
if( auto ptrIS = inStream(); ptrIS )
|
||||
{
|
||||
if(!read(ptrIS(), rdHdr))return false;
|
||||
if(!readObject(ptrIS(), rdHdr))return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -101,7 +101,7 @@ bool pFlow::IOobject::read(bool rdHdr)
|
|||
}
|
||||
|
||||
|
||||
bool pFlow::IOobject::write() const
|
||||
bool pFlow::IOobject::writeObject() const
|
||||
{
|
||||
if(implyWrite())
|
||||
{
|
||||
|
@ -109,7 +109,7 @@ bool pFlow::IOobject::write() const
|
|||
{
|
||||
if(auto ptrOS = outStream(); ptrOS )
|
||||
{
|
||||
return write(ptrOS());
|
||||
return writeObject(ptrOS());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -124,7 +124,7 @@ bool pFlow::IOobject::write() const
|
|||
}
|
||||
|
||||
|
||||
bool pFlow::IOobject::read(iIstream& is, bool rdHdr)
|
||||
bool pFlow::IOobject::readObject(iIstream& is, bool rdHdr)
|
||||
{
|
||||
if(rdHdr && ioPattern().thisCallRead() )
|
||||
{
|
||||
|
@ -143,7 +143,7 @@ bool pFlow::IOobject::read(iIstream& is, bool rdHdr)
|
|||
}
|
||||
|
||||
|
||||
bool pFlow::IOobject::write(iOstream& os) const
|
||||
bool pFlow::IOobject::writeObject(iOstream& os) const
|
||||
{
|
||||
if(this->writeHeader() && ioPattern().thisProcWriteHeader())
|
||||
writeHeader(os, typeName());
|
||||
|
|
|
@ -88,16 +88,16 @@ public:
|
|||
//// - IO operations
|
||||
|
||||
// - read from file
|
||||
bool read(bool rdHdr = true);
|
||||
bool readObject(bool rdHdr = true);
|
||||
|
||||
// - write to file
|
||||
bool write() const;
|
||||
bool writeObject() const;
|
||||
|
||||
// - read from istream
|
||||
bool read(iIstream& is, bool rdHdr = true);
|
||||
bool readObject(iIstream& is, bool rdHdr = true);
|
||||
|
||||
// - write to istream
|
||||
bool write(iOstream& os) const;
|
||||
bool writeObject(iOstream& os) const;
|
||||
|
||||
virtual
|
||||
bool write(iOstream& is, const IOPattern& iop)const = 0;
|
||||
|
|
|
@ -286,7 +286,7 @@ bool pFlow::repository::write
|
|||
REPORT(1)<< "Writing to " << obj.second->path()<<END_REPORT;
|
||||
}
|
||||
|
||||
if(!obj.second->write())
|
||||
if(!obj.second->writeObject())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,23 @@
|
|||
/*------------------------------- 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 __createDataIO_hpp__
|
||||
#define __createDataIO_hpp__
|
||||
|
||||
|
|
|
@ -1,10 +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.
|
||||
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __dataIO_hpp__
|
||||
#define __dataIO_hpp__
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "types.hpp"
|
||||
#include "span.hpp"
|
||||
#include "IOPattern.hpp"
|
||||
#include "iOstream.hpp"
|
||||
|
@ -15,6 +34,35 @@
|
|||
namespace pFlow
|
||||
{
|
||||
|
||||
// - Forward
|
||||
template<typename T>
|
||||
bool writeDataAsciiBinary
|
||||
(
|
||||
iOstream& os,
|
||||
span<T> data
|
||||
);
|
||||
|
||||
template<typename T>
|
||||
bool writeDataASCII
|
||||
(
|
||||
iOstream& os,
|
||||
span<T> data
|
||||
);
|
||||
|
||||
template<typename T>
|
||||
bool readDataAscii
|
||||
(
|
||||
iIstream& is,
|
||||
std::vector<T>& vec
|
||||
);
|
||||
|
||||
template<typename T>
|
||||
bool readDataAsciiBinary
|
||||
(
|
||||
iIstream& is,
|
||||
std::vector<T>& data
|
||||
);
|
||||
|
||||
template<typename T>
|
||||
class dataIO
|
||||
{
|
||||
|
@ -58,12 +106,19 @@ public:
|
|||
iIstream& is,
|
||||
std::vector<T>& data);
|
||||
|
||||
bool readAscii(
|
||||
iIstream& is,
|
||||
std::vector<T>& vec );
|
||||
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline
|
||||
iOstream& operator<<(iOstream& os, const span<T>& s)
|
||||
{
|
||||
if(!writeDataAsciiBinary(os, s))
|
||||
{
|
||||
ioErrorInFile(os.name(), os.lineNumber());
|
||||
fatalExit;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
#ifndef __datIOMPI_hpp__
|
||||
#define __datIOMPI_hpp__
|
||||
|
||||
#include "dataIO.hpp"
|
||||
#include "pFlowProcessors.hpp"
|
||||
|
||||
#ifdef pFlow_Build_MPI
|
||||
#include "gatherMaster.hpp"
|
||||
#endif
|
||||
|
||||
namespace pFlow
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
class dataIOMPI
|
||||
:
|
||||
public dataIO<T>
|
||||
{
|
||||
protected:
|
||||
|
||||
bool gatherData(span<T> data ) override
|
||||
{
|
||||
|
||||
if(this->ioPattern_.isAllProcessorsDifferent())
|
||||
{
|
||||
this->bufferSpan_ = data;
|
||||
return true;
|
||||
}
|
||||
|
||||
if( this->ioPattern_.isMasterProcessorDistribute())
|
||||
{
|
||||
|
||||
#ifdef pFlow_Build_MPI
|
||||
|
||||
auto gatherT = pFlow::MPI::gatherMaster<T>(pFlowProcessors());
|
||||
|
||||
if(!gatherT.gatherData(data))
|
||||
{
|
||||
fatalErrorInFunction<<"Error in gathering data to master"<<endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
this->buffer_ = gatherT.moveData();
|
||||
|
||||
this->bufferSpan_ = makeSpan(this->buffer_);
|
||||
|
||||
return true;
|
||||
#else
|
||||
notImplementedFunction;
|
||||
fatalExit;
|
||||
return false;
|
||||
#endif //pFlow_Build_MPI
|
||||
|
||||
}
|
||||
|
||||
if( this->ioPattern_.isMasterProcessorOnly() || this->ioPattern_.isAllProcessorSimilar() )
|
||||
{
|
||||
if( this->ioPattern_.isMaster() )
|
||||
{
|
||||
this->bufferSpan_ = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->bufferSpan_ = span<T>(nullptr, 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
public:
|
||||
|
||||
TypeInfo("dataIO<MPI>");
|
||||
|
||||
dataIOMPI(const IOPattern& iop)
|
||||
:
|
||||
dataIO<T>(iop)
|
||||
{}
|
||||
|
||||
dataIOMPI(const dataIOMPI&) = default;
|
||||
|
||||
dataIOMPI(dataIOMPI&&) = default;
|
||||
|
||||
|
||||
dataIOMPI& operator=(const dataIOMPI&) = default;
|
||||
|
||||
dataIOMPI& operator=(dataIOMPI&&) = default;
|
||||
|
||||
~dataIOMPI() = default;
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -1,3 +1,23 @@
|
|||
/*------------------------------- 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 __datIONoMPI_hpp__
|
||||
#define __datIONoMPI_hpp__
|
||||
|
||||
|
|
|
@ -1,132 +1,127 @@
|
|||
/*------------------------------- 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>
|
||||
bool pFlow::dataIO<T>::writeData(iOstream& os, span<T> data)
|
||||
bool pFlow::writeDataAsciiBinary(iOstream& os, span<T> data)
|
||||
{
|
||||
/// first gather data from all processors (if any)
|
||||
if(!gatherData( data ) )
|
||||
|
||||
if( os.isBinary() )
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"Error in gathering data for out stream "<< os.name()<<endl;
|
||||
return false;
|
||||
}
|
||||
// first write the number of data
|
||||
uint64 numData = data.size();
|
||||
os<< numData << endl;
|
||||
|
||||
if( ioPattern_.thisProcWriteData())
|
||||
{
|
||||
if( os.isBinary() )
|
||||
// write the bindary data
|
||||
auto chBuffer = charSpan(data);
|
||||
|
||||
if(!os.write(chBuffer.data(), chBuffer.size()))
|
||||
{
|
||||
// first write the number of data
|
||||
uint64 numData = bufferSpan_.size();
|
||||
os<< numData << endl;
|
||||
|
||||
// write the bindary data
|
||||
auto chBuffer = charSpan(bufferSpan_);
|
||||
|
||||
if(!os.write(chBuffer.data(), chBuffer.size()))
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"error in writing binary data to "<<os.name()<<endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !bufferSpan_.writeASCII(os) )
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"error in writing ASCII data to "<<os.name()<<endl;
|
||||
return false;
|
||||
}
|
||||
fatalErrorInFunction<<
|
||||
"error in writing binary data to "<<os.name()<<endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return os.check(FUNCTION_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
if( !writeDataASCII(os, data) )
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"error in writing ASCII data to "<<os.name()<<endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return os.check(FUNCTION_NAME);
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
inline
|
||||
bool pFlow::dataIO<pFlow::word>::writeData(iOstream& os, span<word> data)
|
||||
template<typename T>
|
||||
bool pFlow::writeDataASCII(iOstream& os, span<T> data)
|
||||
{
|
||||
notImplementedFunction;
|
||||
fatalExit;
|
||||
/// first gather data from all processors (if any)
|
||||
if(!gatherData( data ) )
|
||||
os<< data.size()<<endl;
|
||||
os << token::BEGIN_LIST;
|
||||
if(data.size()>0)
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"Error in gathering data for out stream "<< os.name()<<endl;
|
||||
return false;
|
||||
for(uint32 i=0; i<data.size()-1; i++)
|
||||
{
|
||||
os << data[i]<<token::NL;
|
||||
}
|
||||
os << data[data.size()-1] << token::END_LIST;
|
||||
}
|
||||
|
||||
if( !bufferSpan_.writeASCII(os) )
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"error in writing ASCII data to "<<os.name()<<endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
os<< token::END_LIST;
|
||||
}
|
||||
|
||||
os.check(FUNCTION_NAME);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
bool pFlow::dataIO<T>::readData
|
||||
bool pFlow::readDataAsciiBinary
|
||||
(
|
||||
iIstream& is,
|
||||
std::vector<T>& data
|
||||
)
|
||||
{
|
||||
data.clear();
|
||||
if(ioPattern_.thisProcReadData())
|
||||
|
||||
if(is.isBinary())
|
||||
{
|
||||
if(is.isBinary())
|
||||
data.clear();
|
||||
// read length of data
|
||||
token firstToken(is);
|
||||
|
||||
size_t len = 0;
|
||||
if( firstToken.isInt64())
|
||||
{
|
||||
|
||||
// read length of data
|
||||
token firstToken(is);
|
||||
|
||||
size_t len = 0;
|
||||
if( firstToken.isInt64())
|
||||
{
|
||||
len = firstToken.int64Token();
|
||||
data.resize(len);
|
||||
}
|
||||
else
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"expected length of vector in the stream "<<is.name()<<
|
||||
"but found this "<< firstToken<<endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
is.read(reinterpret_cast<char*>(data.data()), len*sizeof(T));
|
||||
|
||||
return is.check(FUNCTION_NAME);
|
||||
len = firstToken.int64Token();
|
||||
data.resize(len);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
return readAscii(is, data);
|
||||
fatalErrorInFunction<<
|
||||
"expected length of vector in the stream "<<is.name()<<
|
||||
"but found this "<< firstToken<<endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
is.read(reinterpret_cast<char*>(data.data()), len*sizeof(T));
|
||||
|
||||
return is.check(FUNCTION_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
|
||||
return readDataAscii(is, data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool pFlow::dataIO<T>::readAscii
|
||||
bool pFlow::readDataAscii
|
||||
(
|
||||
iIstream& is,
|
||||
std::vector<T>& vec
|
||||
)
|
||||
{
|
||||
|
||||
if( !ioPattern_.thisProcReadData() ) return true;
|
||||
|
||||
is.fatalCheck(FUNCTION_NAME);
|
||||
|
||||
|
@ -187,4 +182,62 @@ bool pFlow::dataIO<T>::readAscii
|
|||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
bool pFlow::dataIO<T>::writeData(iOstream& os, span<T> data)
|
||||
{
|
||||
/// first gather data from all processors (if any)
|
||||
if(!gatherData( data ) )
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"Error in gathering data for out stream "<< os.name()<<endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( ioPattern_.thisProcWriteData())
|
||||
{
|
||||
return writeDataAsciiBinary(os, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
inline
|
||||
bool pFlow::dataIO<pFlow::word>::writeData(iOstream& os, span<word> data)
|
||||
{
|
||||
notImplementedFunction;
|
||||
fatalExit;
|
||||
/// first gather data from all processors (if any)
|
||||
if(!gatherData( data ) )
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"Error in gathering data for out stream "<< os.name()<<endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool pFlow::dataIO<T>::readData
|
||||
(
|
||||
iIstream& is,
|
||||
std::vector<T>& data
|
||||
)
|
||||
{
|
||||
data.clear();
|
||||
if(ioPattern_.thisProcReadData())
|
||||
{
|
||||
return readDataAsciiBinary(is, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,13 +71,7 @@ public:
|
|||
|
||||
TypeInfo("boundaryBase");
|
||||
|
||||
/*boundaryBase(
|
||||
const plane& bplane,
|
||||
uint32 mirrorProc,
|
||||
const word& name,
|
||||
const word& type,
|
||||
internalPoints& internal);*/
|
||||
|
||||
|
||||
boundaryBase(
|
||||
const dictionary& dict,
|
||||
const plane& bplane,
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace pFlow
|
|||
{
|
||||
|
||||
class systemControl;
|
||||
//class pFlagTypeHost;
|
||||
|
||||
|
||||
class simulationDomain
|
||||
:
|
||||
|
|
|
@ -46,8 +46,20 @@ pFlow::internalPoints::internalPoints
|
|||
)
|
||||
:
|
||||
subscriber("internalPoints"),
|
||||
pointPosition_("internalPoints", "internalPoints", posVec.capacity(), 0, RESERVE()),
|
||||
pFlagsD_(posVec.capacity(), 0, posVec.size())
|
||||
pointPosition_
|
||||
(
|
||||
"internalPoints",
|
||||
"internalPoints",
|
||||
posVec.capacity(),
|
||||
0,
|
||||
RESERVE()
|
||||
),
|
||||
pFlagsD_
|
||||
(
|
||||
static_cast<uint32>(posVec.capacity()),
|
||||
static_cast<uint32>(0),
|
||||
static_cast<uint32>(posVec.size())
|
||||
)
|
||||
{
|
||||
|
||||
pointPosition_.assign(posVec);
|
||||
|
@ -70,19 +82,34 @@ const pFlow::pFlagTypeHost&
|
|||
}
|
||||
|
||||
FUNCTION_H
|
||||
const pFlow::realx3Field_D&
|
||||
const typename pFlow::internalPoints::PointsType&
|
||||
pFlow::internalPoints::pointPosition()const
|
||||
{
|
||||
return pointPosition_;
|
||||
}
|
||||
|
||||
pFlow::hostViewType1D<pFlow::realx3>
|
||||
FUNCTION_H
|
||||
typename pFlow::internalPoints::PointsType&
|
||||
pFlow::internalPoints::pointPosition()
|
||||
{
|
||||
return pointPosition_;
|
||||
}
|
||||
|
||||
typename pFlow::internalPoints::PointsTypeHost
|
||||
pFlow::internalPoints::activePointsHost() const
|
||||
{
|
||||
auto maskH = activePointsMaskHost();
|
||||
auto pointsH = pointPositionHost();
|
||||
|
||||
hostViewType1D<realx3> aPoints("Active pointst", maskH.numActive());
|
||||
PointsTypeHost aPoints
|
||||
(
|
||||
pointPosition_.name(),
|
||||
pointPosition_.fieldKey(),
|
||||
maskH.numActive(),
|
||||
maskH.numActive(),
|
||||
RESERVE()
|
||||
);
|
||||
|
||||
auto aRange = maskH.activeRange();
|
||||
uint32 n = 0;
|
||||
for(auto i=aRange.start(); i<aRange.end(); i++)
|
||||
|
@ -97,11 +124,7 @@ pFlow::hostViewType1D<pFlow::realx3>
|
|||
return aPoints;
|
||||
}
|
||||
|
||||
FUNCTION_H
|
||||
pFlow::realx3Field_D &pFlow::internalPoints::pointPosition()
|
||||
{
|
||||
return pointPosition_;
|
||||
}
|
||||
|
||||
|
||||
FUNCTION_H
|
||||
pFlow::uint32 pFlow::internalPoints::updateFlag
|
||||
|
@ -146,6 +169,49 @@ void pFlow::internalPoints::fillNeighborsLists
|
|||
pFlagSync_ = false;
|
||||
}
|
||||
|
||||
FUNCTION_H
|
||||
bool pFlow::internalPoints::read
|
||||
(
|
||||
iIstream& is
|
||||
)
|
||||
{
|
||||
|
||||
PointsTypeHost fRead(pointPosition_.name(), pointPosition_.fieldKey());
|
||||
|
||||
if( !fRead.read(is))
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"Error in reading pointPosition from stream "<< is.name()<<endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
pointPosition_.assign(fRead);
|
||||
|
||||
pFlagsD_ = pFlagTypeDevice(pointPosition_.capacity(), 0, pointPosition_.size());
|
||||
pFlagSync_ = false;
|
||||
syncPFlag();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
FUNCTION_H
|
||||
bool pFlow::internalPoints::write
|
||||
(
|
||||
iOstream& os
|
||||
)const
|
||||
{
|
||||
if( pFlagsD_.isAllActive())
|
||||
{
|
||||
return pointPosition_.write(os);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto aPoints = this->activePointsHost();
|
||||
return aPoints.write(os);
|
||||
}
|
||||
}
|
||||
|
||||
FUNCTION_H
|
||||
bool pFlow::internalPoints::read
|
||||
(
|
||||
|
@ -154,7 +220,7 @@ bool pFlow::internalPoints::read
|
|||
)
|
||||
{
|
||||
|
||||
Field<Vector, realx3 , vecAllocator<realx3>> fRead("internalPoints", "internalPoints");
|
||||
PointsTypeHost fRead(pointPosition_.name(), pointPosition_.fieldKey());
|
||||
|
||||
if( !fRead.read(is, iop))
|
||||
{
|
||||
|
@ -163,10 +229,7 @@ bool pFlow::internalPoints::read
|
|||
return false;
|
||||
}
|
||||
|
||||
/// here there should be some mechanism for field distribution between procesors
|
||||
|
||||
|
||||
pointPosition_.assign(fRead.vectorField());
|
||||
pointPosition_.assign(fRead);
|
||||
|
||||
pFlagsD_ = pFlagTypeDevice(pointPosition_.capacity(), 0, pointPosition_.size());
|
||||
pFlagSync_ = false;
|
||||
|
@ -190,9 +253,8 @@ bool pFlow::internalPoints::write
|
|||
}
|
||||
else
|
||||
{
|
||||
auto aPoints = this->activePointsHost();
|
||||
auto spanPoints = makeSpan(aPoints); //span<realx3>(aPoints.data(), aPoints.size());
|
||||
return writeSpan(os, spanPoints, iop);
|
||||
auto aPoints = activePointsHost();
|
||||
return aPoints.write(os,iop);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ Licence:
|
|||
#include "pointFlag.hpp"
|
||||
|
||||
|
||||
//#include "indexContainer.hpp"
|
||||
|
||||
namespace pFlow
|
||||
{
|
||||
|
@ -41,20 +40,22 @@ public:
|
|||
|
||||
inline static const uint32 initialCapacity_ = 10000;
|
||||
|
||||
using pointsType = realx3Field_D;
|
||||
using PointsType = realx3Field_D;
|
||||
|
||||
using device_type = typename pointsType::device_type;
|
||||
using PointsTypeHost = typename PointsType::FieldTypeHost;
|
||||
|
||||
using memory_space = typename pointsType::memory_space;
|
||||
using device_type = typename PointsType::device_type;
|
||||
|
||||
using execution_space = typename pointsType::execution_space;
|
||||
using memory_space = typename PointsType::memory_space;
|
||||
|
||||
using execution_space = typename PointsType::execution_space;
|
||||
|
||||
protected:
|
||||
|
||||
//// - data members
|
||||
|
||||
/// Position of points on device
|
||||
realx3Field_D pointPosition_;
|
||||
PointsType pointPosition_;
|
||||
|
||||
/// flag of points on device
|
||||
mutable pFlagTypeDevice pFlagsD_;
|
||||
|
@ -112,10 +113,10 @@ public:
|
|||
|
||||
// - Const access pointPosition
|
||||
FUNCTION_H
|
||||
const realx3Field_D& pointPosition()const;
|
||||
const PointsType& pointPosition()const;
|
||||
|
||||
FUNCTION_H
|
||||
realx3Field_D& pointPosition();
|
||||
PointsType& pointPosition();
|
||||
|
||||
INLINE_FUNCTION_H
|
||||
auto pointPositionHost()const
|
||||
|
@ -129,7 +130,7 @@ public:
|
|||
return pointPosition_.deviceVector();
|
||||
}
|
||||
|
||||
hostViewType1D<realx3> activePointsHost()const;
|
||||
PointsTypeHost activePointsHost()const;
|
||||
|
||||
// - size of data structure
|
||||
INLINE_FUNCTION_H
|
||||
|
@ -185,6 +186,15 @@ public:
|
|||
|
||||
//// - IO operations
|
||||
|
||||
/// Read
|
||||
FUNCTION_H
|
||||
bool read(iIstream& is);
|
||||
|
||||
|
||||
/// Write
|
||||
FUNCTION_H
|
||||
bool write(iOstream& os)const;
|
||||
|
||||
/// Read
|
||||
FUNCTION_H
|
||||
bool read(iIstream& is, const IOPattern& iop);
|
||||
|
@ -199,7 +209,7 @@ public:
|
|||
inline
|
||||
iOstream& operator<<(iOstream& os, const internalPoints& ip)
|
||||
{
|
||||
if( !ip.write(os, IOPattern::AllProcessorsDifferent) )
|
||||
if( !ip.write(os) )
|
||||
{
|
||||
ioErrorInFile(os.name(), os.lineNumber());
|
||||
fatalExit;
|
||||
|
|
|
@ -23,8 +23,20 @@ Licence:
|
|||
#include "systemControl.hpp"
|
||||
#include "vocabs.hpp"
|
||||
|
||||
bool pFlow::pointStructure::setupPointStructure(const realx3Vector& points)
|
||||
{
|
||||
PointsTypeHost hPoints
|
||||
(
|
||||
pointPosition_.name(),
|
||||
pointPosition_.fieldKey()
|
||||
);
|
||||
|
||||
bool pFlow::pointStructure::setupPointStructure(const realx3Vector &points)
|
||||
hPoints.assign(points);
|
||||
|
||||
return setupPointStructure(hPoints);
|
||||
}
|
||||
|
||||
bool pFlow::pointStructure::setupPointStructure(const PointsTypeHost &points)
|
||||
{
|
||||
if(!simulationDomain_->initialUpdateDomains(points.getSpan()))
|
||||
{
|
||||
|
@ -35,19 +47,19 @@ bool pFlow::pointStructure::setupPointStructure(const realx3Vector &points)
|
|||
|
||||
uint32 thisN = simulationDomain_->initialNumberInThis();
|
||||
|
||||
Field<Vector, realx3 , vecAllocator<realx3>> internal
|
||||
PointsTypeHost internal
|
||||
(
|
||||
"internalPoints",
|
||||
"internalPoints",
|
||||
pointPosition_.name(),
|
||||
pointPosition_.fieldKey(),
|
||||
thisN,
|
||||
thisN,
|
||||
RESERVE()
|
||||
);
|
||||
|
||||
auto pSpan = makeSpan(points);
|
||||
auto iSpan = internal.getSpan();
|
||||
auto pSpan = points.getSpan();
|
||||
|
||||
if(!simulationDomain_->initialTransferBlockData(pSpan, iSpan))
|
||||
if(auto iSpan = internal.getSpan();
|
||||
!simulationDomain_->initialTransferBlockData(pSpan, iSpan))
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"Error in transfering the block data "<<endl;
|
||||
|
@ -66,9 +78,9 @@ bool pFlow::pointStructure::setupPointStructure(const realx3Vector &points)
|
|||
}
|
||||
|
||||
|
||||
bool pFlow::pointStructure::initializePoints(const realx3Vector &points)
|
||||
bool pFlow::pointStructure::initializePoints(const PointsTypeHost &points)
|
||||
{
|
||||
pointPosition_.assign(points.vectorField());
|
||||
pointPosition_.assign(points);
|
||||
|
||||
pFlagsD_ = pFlagTypeDevice(pointPosition_.capacity(), 0, pointPosition_.size());
|
||||
pFlagSync_ = false;
|
||||
|
@ -109,7 +121,7 @@ pFlow::pointStructure::pointStructure
|
|||
REPORT(0)<< "Reading point structure from "<<
|
||||
IOobject::path()<<END_REPORT;
|
||||
|
||||
if( !IOobject::read() )
|
||||
if( !IOobject::readObject() )
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"Error in reading from file "<<IOobject::path()<<endl;
|
||||
|
@ -173,8 +185,11 @@ bool pFlow::pointStructure::read(
|
|||
const IOPattern& iop)
|
||||
{
|
||||
|
||||
Field<Vector, realx3 , vecAllocator<realx3>>
|
||||
fRead("file_internalPoints", "internalPoints");
|
||||
PointsTypeHost fRead
|
||||
(
|
||||
this->pointPosition_.name(),
|
||||
this->pointPosition_.fieldKey()
|
||||
);
|
||||
|
||||
if( !fRead.read(is, iop))
|
||||
{
|
||||
|
@ -192,27 +207,5 @@ bool pFlow::pointStructure::write
|
|||
const IOPattern& iop
|
||||
)const
|
||||
{
|
||||
|
||||
hostViewType1D<realx3> pointsH;
|
||||
|
||||
if(isAllActive())
|
||||
{
|
||||
pointsH = pointPositionHost();
|
||||
}
|
||||
else
|
||||
{
|
||||
pointsH = activePointsHost();
|
||||
}
|
||||
|
||||
auto data = span<realx3>(pointsH.data(), pointsH.size());
|
||||
|
||||
if( !writeSpan(os, data, iop) )
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"Error in writing pointStructure in stream "<<
|
||||
os.name()<<endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return internalPoints::write(os, iop);
|
||||
}
|
||||
|
|
|
@ -39,17 +39,30 @@ class pointStructure
|
|||
public demComponent,
|
||||
public internalPoints
|
||||
{
|
||||
protected:
|
||||
public:
|
||||
|
||||
using PointsType = typename internalPoints::PointsType;
|
||||
|
||||
using PointsTypeHost = typename PointsType::FieldTypeHost;
|
||||
|
||||
using device_type = typename PointsType::device_type;
|
||||
|
||||
using memory_space = typename PointsType::memory_space;
|
||||
|
||||
using execution_space = typename PointsType::execution_space;
|
||||
|
||||
private:
|
||||
|
||||
//// - data members
|
||||
uniquePtr<simulationDomain> simulationDomain_ = nullptr;
|
||||
|
||||
boundaryList boundaries_;
|
||||
|
||||
bool setupPointStructure(const realx3Vector& points);
|
||||
|
||||
bool setupPointStructure(const realx3Vector& points);
|
||||
bool setupPointStructure(const PointsTypeHost& points);
|
||||
|
||||
bool initializePoints(const realx3Vector& points);
|
||||
bool initializePoints(const PointsTypeHost& points);
|
||||
|
||||
public:
|
||||
|
||||
|
@ -80,7 +93,7 @@ public:
|
|||
pointStructure& operator=(pointStructure&&) = delete;
|
||||
|
||||
// - destructor
|
||||
virtual ~pointStructure() = default;
|
||||
~pointStructure() override = default;
|
||||
|
||||
// - Iteration methods
|
||||
|
||||
|
@ -133,12 +146,6 @@ public:
|
|||
/// Write
|
||||
bool write(iOstream& os, const IOPattern& iop)const override;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue