Parallel IO before round 2

This commit is contained in:
Hamidreza Norouzi 2023-10-28 12:09:40 +03:30
parent 66fc880fcd
commit d65aa02cbb
39 changed files with 1618 additions and 516 deletions

View File

@ -4,8 +4,6 @@ types/basicTypes/bTypesFunctions.cpp
types/basicTypes/Logical.cpp
types/types.cpp
globals/error.cpp
streams/token/tokenIO.cpp
@ -35,10 +33,16 @@ dictionary/entry/dataEntry.cpp
dictionary/twoPartEntry/twoPartEntry.cpp
containers/Vector/Vectors.cpp
containers/Field/Fields.cpp
repository/IOobject/objectFile.cpp
repository/IOobject/IOfileHeader.cpp
repository/IOobject/IOobject.cpp
repository/IOobject/IOPattern.cpp
structuredData/line/line.cpp
structuredData/infinitePlane/infinitePlane.cpp
structuredData/plane/plane.cpp
)

View File

@ -18,7 +18,7 @@ Licence:
-----------------------------------------------------------------------------*/
template<template<class, class> class VectorField, class T, class PropType>
/*template<template<class, class> class VectorField, class T, class PropType>
bool pFlow::Field<VectorField, T, PropType>::readUniform
(
iIstream& is,
@ -94,10 +94,10 @@ bool pFlow::Field<VectorField, T, PropType>::readNonUniform
return true;
}
}*/
template<template<class, class> class VectorField, class T, class PropType>
/*template<template<class, class> class VectorField, class T, class PropType>
bool pFlow::Field<VectorField, T, PropType>::readField
(
iIstream& is,
@ -177,6 +177,50 @@ bool pFlow::Field<VectorField, T, PropType>::writeField(iOstream& os)const
os.endEntry();
return true;
}*/
template<template<class, class> class VectorField, class T, class PropType>
bool pFlow::Field<VectorField, T, PropType>::read
(
iIstream& is,
IOPattern::IOType iotype
)
{
bool tokenFound;
tokenFound = is.findToken(fieldKey_);
if( !tokenFound )
{
ioErrorInFile( is.name(), is.lineNumber() ) <<
" error in searching for filedkey " << fieldKey_<<endl;
return false;
}
if( !VectorType::read(is, iotype) )
{
ioErrorInFile(is.name(), is.lineNumber())<<
"error in reading field data from field "<< this->name()<<endl;
}
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,
IOPattern::IOType iotype)const
{
os.writeWordKeyword(fieldKey_)<<endl;
VectorType::write(os, iotype);
os.endEntry();
return true;
}

View File

@ -21,8 +21,13 @@ Licence:
#ifndef __Field_hpp__
#define __Field_hpp__
#include "VectorSingle.hpp"
#include "vocabs.hpp"
//#include "VectorSingle.hpp"
//#include "vocabs.hpp"
#include "types.hpp"
#include "Vector.hpp"
namespace pFlow
{
@ -62,144 +67,108 @@ protected:
const word fieldKey_ = FKey;
bool readUniform( iIstream& is, size_t len, bool readLength = true);
/*bool readUniform( iIstream& is, size_t len, bool readLength = true);
bool readNonUniform( iIstream& is, size_t len);
bool readNonUniform( iIstream& is, size_t len);*/
public:
// - type info
/// type info
TypeInfoTemplateNV2("Field", T, VectorType::memoerySpaceName());
//// - Constructors
// construct an empty Filed with default fieldKey
/// 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
/// 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
/// Construct a field with name and fieldKey and specified len
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
/// Construct a field with name, fieldKey and
/// set length to len and value 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
/// Construct a field with name, fieldKey, capacity and len
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
/// Construct a field with fieldKey and Vector vec
Field(const word& fieldKey, const Vector<T>& vec)
:
VectorType(vec),
VectorType(vec.name(), vec.vectorField()),
fieldKey_(fieldKey)
{}
// construct an empty field with name and fieldKey
/// Construct a field with name, fieldKey and Vector vec
Field(const word& name, const word& fieldKey, const Vector<T>& vec)
:
VectorType(name, vec.vectorField()),
fieldKey_(fieldKey)
{}
/// Construct a field with name and fieldKey and std::vector
Field(const word& name, const word& fieldKey, const std::vector<T>& vec)
:
VectorType(name, vec),
fieldKey_(fieldKey)
{}
// - copy construct with new name and 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
/// Default copy constructor
Field(const FieldType&) = default;
// - default copy assignment
FieldType& operator = (const FieldType&) = default;
/// Copy assignment, name and fieldKey
/// on the left hand side are preserved
FieldType& operator = (const FieldType& rhs)
{
if(&rhs == this) return *this;
VectorType::operator=(rhs);
return *this;
}
// - no move constructor
Field(FieldType&&) = delete;
/// Move constructor
Field(FieldType&&) = default;
// - no move assignment
FieldType& operator = (FieldType&&) = delete;
/// Move assignment
FieldType& operator = (FieldType&&) = default;
// - clone as a uniquePtr
/// clone as a uniquePtr
INLINE_FUNCTION_H
uniquePtr<FieldType> clone() const
{
return makeUnique<FieldType>(*this);
}
// - clone as a raw pointer
/// clone as a raw pointer
INLINE_FUNCTION_H
FieldType* clonePtr()const
{
@ -208,31 +177,27 @@ public:
//// - Methods
/// return field key
const word& fieldKey()const
{
return fieldKey_;
}
//// - IO operations
bool readField(iIstream& is, const size_t len, bool resume, bool readLength = true);
/*bool readField(iIstream& is, const size_t len, bool resume, bool readLength = true);
bool readField(iIstream& is, bool resume );
bool writeField(iOstream& os)const;
bool writeField(iOstream& os)const;*/
bool read(iIstream& is, bool resume = false)
{
return readField(is, resume);
}
bool read(iIstream& is, IOPattern::IOType iotype);
bool write(iOstream& os)const
{
return writeField(os);
}
bool write(iOstream& os, IOPattern::IOType iotype )const;
};
@ -240,7 +205,7 @@ public:
template<template<class, class> class VectorField, class T, class PropType>
inline iIstream& operator >> (iIstream & is, Field<VectorField, T, PropType> & ifld )
{
if( !ifld.readField(is, false) )
if( !ifld.read(is, IOPattern::MasterProcessor) )
{
ioErrorInFile (is.name(), is.lineNumber());
fatalExit;
@ -252,7 +217,7 @@ 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) )
if( !ofld.write(os, IOPattern::AllProcessorsDifferent) )
{
ioErrorInFile(os.name(), os.lineNumber());
fatalExit;

View File

@ -23,7 +23,7 @@ Licence:
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::int8, pFlow::HostSpace>;
template class pFlow::Field<pFlow::VectorSingle, pFlow::int16>;
@ -76,6 +76,6 @@ 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>>;
template class pFlow::Field<pFlow::Vector, pFlow::word, pFlow::vecAllocator<pFlow::word>>;*/

View File

@ -24,22 +24,17 @@ Licence:
#include "types.hpp"
#include "Field.hpp"
#include "VectorSingle.hpp"
#include "VectorDual.hpp"
//#include "VectorDual.hpp"
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_D = Field<VectorSingle, int32>;
using int32Field_H = Field<VectorSingle, int32, HostSpace>;
@ -81,16 +76,14 @@ using int64x3Field_H = Field<VectorSingle, int64x3, HostSpace>;
using realx3x3Field_D = Field<VectorSingle, realx3x3>;
using realx3x3Field_H = Field<VectorSingle, realx3x3, HostSpace>;
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 int8Field_HD = Field<VectorDual, int8>;
using int32Field_HD = Field<VectorDual, int32>;
@ -104,15 +97,13 @@ 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 realx3x3Field_HD = Field<VectorDual, realx3x3>;*/
using wordField = Field<Vector, word , vecAllocator<word>>;

View File

@ -23,111 +23,21 @@ template<typename T, typename Allocator>
bool pFlow::Vector<T, Allocator>::readVector
(
iIstream& is,
size_t len
IOPattern::IOType iotype
)
{
if(is.isBinary() && !std::is_same_v<T,word>)
{
this->resize(len);
is.read(reinterpret_cast<char*>(this->data()), this->size()*sizeof(T));
}
else
{
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;
return readStdVector(is, vectorField(), iotype);
}
template<typename T, typename Allocator>
bool pFlow::Vector<T, Allocator>::writeVector
(
iOstream& os
iOstream& os,
IOPattern::IOType iotype
) const
{
span<T> s( const_cast<T*>(this->data()), this->size());
os<<s;
// start of
/*if( os.isBinary() && !std::is_same_v<T,word>)
{
os.write(reinterpret_cast<const char*>(this->data()), this->size()*sizeof(T));
}
else
{
auto len = size();
auto stride = getVectorStride(len);
os << token::BEGIN_LIST;
size_t i = 0;
while( i<len )
{
os << this->operator[](i++);
for(size_t 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;
return writeStdVector(os, vectorField(), iotype);
}
/*template<typename T, typename Allocator>

View File

@ -33,6 +33,8 @@ Licence:
#include "iOstream.hpp"
#include "iIstream.hpp"
#include "stdVectorHelper.hpp"
#ifndef __RESERVE__
#define __RESERVE__
struct RESERVE{};
@ -40,7 +42,7 @@ Licence:
namespace pFlow
{
template<typename T, typename Allocator>
class Vector;
@ -48,18 +50,7 @@ class Vector;
#include "VectorFwd.hpp"
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
@ -351,19 +342,20 @@ public:
inline VectorType operator -()const;
bool readVector(iIstream& is, size_t len=0);
/// Read vector (assume ASCII in input)
bool readVector(iIstream& is, IOPattern::IOType iotype);
bool writeVector(iOstream& os) const;
/// write vector
bool writeVector(iOstream& os, IOPattern::IOType iotype) const;
bool read(iIstream& is)
bool read(iIstream& is, IOPattern::IOType iotype)
{
return readVector(is);
return readVector(is, iotype);
}
bool write(iOstream& os)const
bool write(iOstream& os, IOPattern::IOType iotype)const
{
return writeVector(os);
return writeVector(os, iotype);
}
};
@ -372,7 +364,7 @@ public:
template<typename T, typename Allocator>
inline iIstream& operator >> (iIstream & is, Vector<T, Allocator> & ivec )
{
if( !ivec.readVector(is) )
if( !ivec.readVector(is, IOPattern::MasterProcessor) )
{
ioErrorInFile (is.name(), is.lineNumber());
fatalExit;
@ -382,19 +374,16 @@ inline iIstream& operator >> (iIstream & is, Vector<T, Allocator> & ivec )
template<typename T, typename Allocator>
inline iOstream& operator << (iOstream& os, const Vector<T, Allocator>& ovec )
{
if( !ovec.writeVector(os) )
{
if( !ovec.writeVector(os, IOPattern::AllProcessorsDifferent) )
{
ioErrorInFile(os.name(), os.lineNumber());
fatalExit;
}
return os;
}
} // pFlow

View File

@ -22,7 +22,7 @@ Licence:
// instantiation just for numeral types
template class pFlow::Vector<pFlow::int8>;
/*template class pFlow::Vector<pFlow::int8>;
template class pFlow::Vector<pFlow::int32>;
@ -32,7 +32,7 @@ template class pFlow::Vector<pFlow::real>;
template class pFlow::Vector<pFlow::realx3>;
template class pFlow::Vector<pFlow::realx3x3>;
template class pFlow::Vector<pFlow::realx3x3>;*/

View File

@ -0,0 +1,132 @@
/*------------------------------- 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 __stdVectorHelper_hpp__
#define __stdVectorHelper_hpp__
#include <vector>
#include <algorithm>
#include "span.hpp"
#include "iOstream.hpp"
#include "iIstream.hpp"
#include "dataIO.hpp"
namespace pFlow
{
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>
inline
bool writeSpan(
iOstream& os,
const span<T>& sp,
IOPattern::IOType iotype)
{
dataIO io(iotype);
if(!io.writeData(os, sp))
{
fatalErrorInFunction;
return false;
}
return true;
}
template<typename T, typename Allocator>
bool writeStdVector
(
iOstream& os,
const std::vector<T,Allocator>& vec,
IOPattern::IOType iotype
)
{
span<T> sp( const_cast<T*>(vec.data()), vec.size());
return writeSpan(os, sp, iotype);
}
template<typename T, typename Allocator>
bool readStdVector
(
iIstream& is,
std::vector<T,Allocator>& vec,
IOPattern::IOType iotype
)
{
dataIO io(iotype);
if(!io.readData(is, vec))
{
fatalErrorInFunction;
return false;
}
return true;
}
template<typename T, typename Allocator>
iOstream& operator<<( iOstream& os, const std::vector<T,Allocator>& vec)
{
if(!writeStdVector(os, vec, IOPattern::AllProcessorsDifferent))
{
fatalErrorInFunction;
fatalExit;
}
return os;
}
/// Always assume ASCII is in the input stream
template<typename T, typename Allocator>
iIstream& operator>>(iIstream& is, std::vector<T,Allocator>& vec)
{
if( !readStdVector(is,vec, IOPattern::MasterProcessor))
{
fatalErrorInFunction;
fatalExit;
}
return is;
}
} // pFlow
#endif

View File

@ -26,7 +26,6 @@ Licence:
#include "globalSettings.hpp"
#include "typeInfo.hpp"
#include "types.hpp"
#include "error.hpp"
#include "indexContainer.hpp"
@ -35,7 +34,7 @@ Licence:
#include "span.hpp"
#include "Vector.hpp"
#include "phasicFlowKokkos.hpp"
#include "dataIO.hpp"
#ifndef __RESERVE__
@ -240,7 +239,7 @@ public:
:
VectorSingle(src.name(), src)
{
copy(deviceVector(), src.deviceVector());
//copy(deviceVector(), src.deviceVector());
}
/// Copy construct with a new name (perform deep copy)
@ -577,34 +576,27 @@ public:
//// - IO operations
/// Read vector from is stream (ASCII or Binary)
/// For binary read, len should be provided
/// Read vector from stream (ASCII)
FUNCTION_H
bool readVector(iIstream& is, size_t len=0)
bool read(iIstream& is, IOPattern::IOType iotype)
{
Vector<T> vecFromFile;
if( !vecFromFile.readVector(is,len) ) return false;
std::vector<T> vecFromFile;
if(! readStdVector(is, vecFromFile, iotype)) return false;
this->assign(vecFromFile);
return true;
}
/// Read vector from stream (ASCII)
/// Write the vector to os
FUNCTION_H
bool read(iIstream& is)
{
return readVector(is);
}
/// Write the vector to os (ASCII or Binary)
FUNCTION_H
bool write(iOstream& os)const
bool write(iOstream& os, IOPattern::IOType iotype)const
{
auto hVec = hostVector();
auto sp = span<T>( const_cast<T*>(hVec.data()), hVec.size());
os<<sp;
return true;
return writeSpan(os, sp, iotype);
}
}; // class VectorSingle
@ -612,7 +604,7 @@ public:
template<typename T, typename MemorySpace>
inline iIstream& operator >> (iIstream & is, VectorSingle<T, MemorySpace> & ivec )
{
if( !ivec.read(is) )
if( !ivec.read(is, IOPattern::MasterProcessor ) )
{
ioErrorInFile (is.name(), is.lineNumber());
fatalExit;
@ -624,7 +616,7 @@ template<typename T, typename MemorySpace>
inline iOstream& operator << (iOstream& os, const VectorSingle<T, MemorySpace>& ovec )
{
if( !ovec.write(os) )
if( !ovec.write(os, IOPattern::AllProcessorsDifferent) )
{
ioErrorInFile(os.name(), os.lineNumber());
fatalExit;
@ -634,8 +626,6 @@ inline iOstream& operator << (iOstream& os, const VectorSingle<T, MemorySpace>&
}
} // - pFlow
#include "VectorSingleAlgorithms.hpp"

View File

@ -159,6 +159,7 @@ public:
INLINE_FUNCTION_H
bool writeASCII(iOstream& os) const
{
os<< size()<<endl;
os << token::BEGIN_LIST;
if(size()>0)
{
@ -177,34 +178,22 @@ public:
return true;
}
/// Write in Binray format, can be used for numeral types (Not word or similar ones)
INLINE_FUNCTION_H
bool writeBinary(iOstream& os) const
{
os.write(reinterpret_cast<const char*>(data_), this->size()*sizeof(T));
os.check(FUNCTION_NAME);
return true;
}
};
template<typename T>
inline
iOstream& operator<<(iOstream& os, const span<T>& s)
{
if( os.isBinary() && !std::is_same_v<T,word>)
{
s.writeBinary(os);
}
else
{
s.writeASCII(os);
}
s.writeASCII(os);
return os;
}
} // pFlow
#endif //__span_hpp__

View File

@ -41,6 +41,18 @@ bool pFlow::fileSystem::checkFileName(const word& name)
}
/// From full path
pFlow::fileSystem::fileSystem(const word & wPath)
:
path_(wPath),
isDir_(std::filesystem::is_directory(path_))
{
std::cout<<"file name is " << fileName()<<std::endl;
if( !isDir_ && !checkFileName(fileName()))
{
fatalExit;
}
}
pFlow::fileSystem::fileSystem( const word& dir, const word& file)
{
@ -74,10 +86,9 @@ pFlow::fileSystem::fileSystem( const char* dir, const char* file)
pFlow::fileSystem::fileSystem( const pathType& path )
:
path_(path)
{
isDir_ = isDirectory(*this);
}
path_(path),
isDir_(std::filesystem::is_directory(path_))
{}
pFlow::fileSystem pFlow::fileSystem::dirPath() const
{
@ -175,9 +186,7 @@ bool pFlow::fileSystem::dirExist
}
bool pFlow::fileSystem::exist
(
)const
bool pFlow::fileSystem::exist()const
{
try
{
@ -321,7 +330,7 @@ pFlow::fileSystemList pFlow::subDirectories
auto dOps = std::filesystem::directory_options::skip_permission_denied;
for( auto& subPath: std::filesystem::directory_iterator(path.path(), dOps) )
{
if(isDirectory( subPath.path() ) )
if(isDirectory( fileSystem(subPath.path()) ) )
{
dirs.emplace_back(subPath.path());
}

View File

@ -71,19 +71,19 @@ public:
protected:
/// File path
std::filesystem::path path_;
pathType path_;
/// Is this a directory path?
bool isDir_;
bool isDir_;
/// Not premitted chars in file name
inline static word notPermittedCharsFile = word(" ") + word("\t\n\0;:?*/<>\"?\'");
inline static word notPermittedCharsFile = word(" ") + word("&\t\n;:?*/<>\"?\'");
/// Is name is valid for a file?
bool static validFileName(const word& name)
{
return name.find_first_of(notPermittedCharsFile);
return name.find_first_of(notPermittedCharsFile)==word::npos;
}
/// Is a valid file name?
@ -107,13 +107,18 @@ public:
isDir_(true)
{}
/// From full path
explicit
fileSystem(const word & wPath);
/// From dir and file name
fileSystem( const word& dir, const word& file = "");
fileSystem( const word& dir, const word& file);
/// From dir and file name
fileSystem( const char* dir, const char* file = "");
fileSystem( const char* dir, const char* file="");
/// Copy
explicit
fileSystem( const pathType& path );
/// Copy

View File

@ -82,14 +82,14 @@ public:
~processors();
/// Master processors number (globaly in MPI).
static
static inline
int masterNo()
{
return 0;
}
/// Is this a parallel MPI run.
static
static inline
bool isParallel()
{
return processors::globalSize()>1;
@ -104,21 +104,21 @@ public:
bool isFinalized();
/// Is this processor the master processor?
static
static inline
bool isMaster()
{
return processors::globalRank() == processors::masterNo();
}
/// Global size of processors
static
static inline
int globalSize()
{
return globalSize_;
}
/// Rank of the processor in the global MPI
static
static inline
int globalRank()
{
return globalRank_;

View File

@ -0,0 +1,31 @@
/*------------------------------- 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 "processors.hpp"
#include "IOPattern.hpp"
pFlow::IOPattern::IOPattern( IOType iotype)
:
ioType_(iotype),
globalSize_(processors::globalSize()),
globalRank_(processors::globalRank()),
isMaster_(processors::isMaster()),
isParallel_(processors::isParallel())
{}

View File

@ -0,0 +1,152 @@
/*------------------------------- 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 __IOPattern_hpp__
#define __IOPattern_hpp__
#include "processors.hpp"
namespace pFlow
{
class IOPattern
{
public:
/**
* Type of input/output
*
* MasterProcessorOnly: Read or write is done on master processor
* and the data on master processor is affected.
*
* MasterProcessorDistribute: Read is done on master processor, but
* the data should be distributed between processors based on an externally
* specified pattern. Write is done on master processors and the data is
* collected from all processors (collection is done based on the externally
* specified pattern).
*
* AllProcessorsSimilar: Read is done on all processors and processors
* read the same data. Write is done on master processor, since
* all processors have the same copy of data.
*/
enum IOType : int
{
MasterProcessorOnly = 0,
AllProcessorsSimilar = 1,
MasterProcessorDistribute = 4
};
protected:
IOType ioType_;
int globalSize_ = 1;
int globalRank_ = 0;
bool isMaster_ = true;
bool isParallel_ = false;
public:
IOPattern( IOType iotype);
IOPattern(const IOPattern&)=default;
IOPattern& operator=(const IOPattern&)=default;
~IOPattern() = default;
inline
bool isMasterProcessorOnly()const
{
return ioType_ == MasterProcessorOnly;
}
inline
bool isAllProcessorSimilar()const
{
return ioType_ == AllProcessorsSimilar;
}
inline
bool isMasterProcessorDistribute()const
{
return ioType_ == MasterProcessorDistribute;
}
inline
bool isMaster()const
{
return isMaster_;
}
inline
bool isParallel()const
{
return isParallel_;
}
inline
bool thisProcReadData()const
{
if(isMasterProcessor() && !isMaster())return false;
if(isMasterProcessorDistribute() && !isMaster()) return false;
return true;
}
inline
bool thisProcWriteData()const
{
return isMaster();
}
inline
bool thisProcReadHeader()const
{
return thisProcReadData();
}
inline
bool thisProcWriteHeader()const
{
return isMaster();
}
inline
auto globalSize()const
{
return globalSize_;
}
inline
auto globalRank()const
{
return globalRank_;
}
};
}
#endif //__IOPattern_hpp__

View File

@ -135,6 +135,7 @@ bool pFlow::IOfileHeader::readIfPresent()const
bool pFlow::IOfileHeader::writeHeader()const
{
if( !this->readWriteHeader() ) return false;
if( !processors::isMaster() ) return false;
if( !implyWrite() ) return false;
@ -150,7 +151,10 @@ bool pFlow::IOfileHeader::writeHeader
) const
{
if(!forceWrite && !writeHeader()) return true;
if(!forceWrite)
{
if(!writeHeader()) return true;
}
writeBanner(os);
@ -180,8 +184,9 @@ bool pFlow::IOfileHeader::writeHeader(iOstream& os, bool forceWrite) const
bool pFlow::IOfileHeader::readHeader()const
{
if( !this->readWriteHeader() ) return false;
return true;
if( !implyRead())return false;
if( !this->readWriteHeader() ) return false;
return ioPattern().thisProcReadHeader();
}
bool pFlow::IOfileHeader::readHeader(iIstream& is, bool silent)
@ -228,15 +233,14 @@ bool pFlow::IOfileHeader::readHeader(iIstream& is, bool silent)
bool pFlow::IOfileHeader::writeData()const
{
if( processors::isMaster() || this->differentDataOnProcessors())
return true;
else
return false;
if(!implyWrite())return false;
return ioPattern().thisProcWriteData();
}
bool pFlow::IOfileHeader::readData()const
{
return true;
if(!implyRead())return false;
return ioPattern().thisProcReadData();
}
bool pFlow::IOfileHeader::writeBanner(iOstream& os)const

View File

@ -109,7 +109,7 @@ public:
/// Check if the header should be written to file
/// True: on master + implyWrite + readWriteHeader = true
/// False: slave or NOT implyWrite
/// False: otherwise
bool writeHeader()const;
/// Write the header to the file , typeName comes from caller
@ -119,13 +119,9 @@ public:
bool writeHeader(iOstream& os, bool forceWrite = false) const;
/// Check if the data should be written to file
/// True: on master or differentDataOnProcessor is true
/// False: otherwise
bool writeData()const;
/// Check if header should be read from file
/// True: All processors, read the file header
/// False: readWriteHeader = false
bool readHeader()const;
/// Read the header in the file
@ -135,10 +131,10 @@ public:
/// Always return true
bool readData()const;
// - write the banner
/// write the banner
bool writeBanner(iOstream& os)const;
// - wirte a separator line
/// wirte a separator line
bool writeSeparator(iOstream& os)const;
};

View File

@ -30,11 +30,11 @@ pFlow::objectFile::objectFile
pFlow::objectFile::objectFile
(
const word& name,
const fileSystem& localPath,
const readFlag& rf,
const writeFlag& wf,
bool diffDataOnProcessors,
const word& name,
const fileSystem& localPath,
const readFlag& rf,
const writeFlag& wf,
IOPattern::IOType ioType,
bool rwHdr
)
:
@ -42,7 +42,7 @@ pFlow::objectFile::objectFile
rFlag_(rf),
wFlag_(wf),
localPath_(localPath),
differentDataOnProcessors_(diffDataOnProcessors),
ioPattern_(ioType),
readWriteHeader_(rwHdr)
{
}

View File

@ -23,6 +23,7 @@ Licence:
#include "types.hpp"
#include "fileSystem.hpp"
#include "IOPattern.hpp"
namespace pFlow
@ -47,6 +48,7 @@ public:
WRITE_NEVER
};
protected:
/// Name of the entity
@ -61,16 +63,10 @@ protected:
/// Local path of entity
fileSystem localPath_ = "";
/// Number of bytes used for writing/reading real variable (mostly used for binray)
/// Number of bytes used for writing/reading real variable (used for binray)
int numBytesForReal_ = numBytesForReal__;
/// All processors have the different set of data or not?
/// True: Each processor should read its own part of data from file and should write
/// its own part of data to the file.
/// Flase: All processors read the same data from file and in writing, only master data
/// write the data to the file.
bool differentDataOnProcessors_ = true;
IOPattern ioPattern_ = {IOPattern::MasterProcessor};
/// Does the objectFile write the header or not
bool readWriteHeader_ = true;
@ -89,10 +85,10 @@ public:
objectFile
(
const word& name,
const fileSystem& localPath,
const readFlag& rf = READ_NEVER,
const writeFlag& wf = WRITE_NEVER,
bool diffDataOnProcessors = true,
const fileSystem& localPath,
const readFlag& rf = READ_NEVER,
const writeFlag& wf = WRITE_NEVER,
IOPattern::IOType ioType = IOPattern::MasterProcessor,
bool rwHdr = true
);
@ -160,10 +156,9 @@ public:
return wFlag_ == WRITE_NEVER;
}
inline
bool differentDataOnProcessors()const
const IOPattern& ioPattern()const
{
return differentDataOnProcessors_;
return ioPattern_;
}
inline

View File

@ -899,6 +899,28 @@ void pFlow::Istream::rewind()
stdStream().rdbuf()->pubseekpos(0, std::ios_base::in);
}
void pFlow::Istream::seek(size_t pos)
{
stdStream().clear(); // Clear the iostate error state flags
setGood(); // Sync local copy of iostate
resetPutBack();
// pubseekpos() rather than seekg() so that it works with gzstream
stdStream().rdbuf()->pubseekpos(pos, std::ios_base::in);
}
size_t pFlow::Istream::tell()
{
auto pos = static_cast<size_t>(stdStream().tellg());
if(stdStream().fail())
{
fatalErrorInFunction<<
"Error in getting current position from stream "<<
this->name()<<endl;
fatalExit;
}
return pos;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -156,7 +156,12 @@ public:
size_t findBinaryBlockStart()override;
/// Rewind the stream so that it may be read again
virtual void rewind();
void rewind() override;
void seek(size_t pos) override;
/// Return current position indicator
size_t tell() override;
/// Set stream flags

View File

@ -258,6 +258,10 @@ pFlow::iOstream& pFlow::Ostream::writeBinaryBlockFlag()
return *this;
}
void pFlow::Ostream::seek(size_t pos)
{
os_.seekp(pos, std::ios_base::cur);
}
void pFlow::Ostream::indent()
{
@ -267,6 +271,18 @@ void pFlow::Ostream::indent()
}
}
void pFlow::Ostream::startOfBinaryStreaming()
{
this->endl();
this->flush();
}
void pFlow::Ostream::endOfBinaryStreaming()
{
os_.seekp(0, std::ios_base::end);
this->endl();
this->flush();
}
void pFlow::Ostream::flush()
{

View File

@ -132,12 +132,20 @@ public:
iOstream& writeBinaryBlockFlag() override;
void seek(size_t pos) override;
/// Add indentation characters
void indent() override;
/// Set stream flags
ios_base::fmtflags flags(const ios_base::fmtflags f) override;
/// Add a new line and flush stream
void startOfBinaryStreaming() override;
/// Reach end of file add a new line and flush stream
void endOfBinaryStreaming() override ;
/// Flush stream
void flush() override;

View File

@ -309,6 +309,10 @@ void pFlow::iTstream::rewind()
setGood();
}
void pFlow::iTstream::seek(size_t pos)
{
notImplementedFunction;
}
void pFlow::iTstream::reset()
{
@ -318,6 +322,12 @@ void pFlow::iTstream::reset()
setGood();
}
size_t pFlow::iTstream::tell()
{
notImplementedFunction;
return -1;
}
const pFlow::tokenList& pFlow::iTstream::tokens()const
{
return tokenList_;

View File

@ -130,7 +130,11 @@ public:
iIstream& read(char* buffer, std::streamsize count) override;
/// Rewind the stream so that it may be read again
virtual void rewind();
virtual void rewind()override;
void seek(size_t pos) override;
size_t tell() override;
/// reset the iTstream and make the stream empty
virtual void reset();

View File

@ -173,6 +173,10 @@ pFlow::iOstream& pFlow::oTstream::write
return *this;
}
void pFlow::oTstream::seek(size_t pos)
{
notImplementedFunction;
}
void pFlow::oTstream::append(const token& tok)
{

View File

@ -132,6 +132,8 @@ public:
/// Write double
virtual iOstream& write(const size_t val) override;
void seek(size_t pos) override;
/// Write a block of binray data
iOstream& write(
const char* binaryData,
@ -157,6 +159,14 @@ public:
virtual void indent()
{}
/// Add a new line and flush stream
virtual void startOfBinaryStreaming()
{}
/// Reach end of file add a new line and flush stream
virtual void endOfBinaryStreaming()
{}
/// Flush stream
virtual void flush()
{}

View File

@ -7,12 +7,9 @@
#include <cstdio>
#include <numeric>
#include "dataIO.hpp"
#include "fileSystem.hpp"
#include "streams.hpp"
static const size_t numcharFlag = 8;
@ -43,19 +40,18 @@ pFlow::uint64 findBindaryBlockFlagSTD(std::FILE* fh)
if( fpos = std::ftell( fh) ; fpos == -1L )
{
fatalErrorInFunction;
return -1;
return pFlow::dataIO::ErrorReturn;
}
pFlow::uint64 filePos = static_cast<pFlow::uint64>(fpos);
// start reading char by char
int c;
unsigned char ch;
int currPos = 0;
while ( std::fread(&ch, sizeof(ch), 1, fh) == 1 )
{
if(std::ferror(fh)) return -1;
if(std::feof(fh))return -1;
if(std::ferror(fh)) return pFlow::dataIO::ErrorReturn;
if(std::feof(fh))return pFlow::dataIO::ErrorReturn;
filePos++;
@ -71,22 +67,16 @@ pFlow::uint64 findBindaryBlockFlagSTD(std::FILE* fh)
}
}
return -1;
return pFlow::dataIO::ErrorReturn;
}
#ifdef pFlow_Build_MPI
pFlow::uint64 findBindaryBlockFlagMPI(MPI_File fh)
pFlow::uint64 findBindaryBlockFlagMPI(MPI_File fh, pFlow::uint64 startPosSearch)
{
// get the current postion
MPI_Offset fpos;
if( MPI_File_get_position( fh, &fpos) != MPI_SUCCESS )
{
fatalErrorInFunction;
return false;
}
pFlow::uint64 filePos = static_cast<pFlow::uint64>(fpos);
pFlow::uint64 filePos = static_cast<pFlow::uint64>(startPosSearch);
// start reading char by char
unsigned char ch;
@ -114,7 +104,7 @@ pFlow::uint64 findBindaryBlockFlagMPI(MPI_File fh)
}
}
return -1;
return pFlow::dataIO::ErrorReturn;
}
#endif
@ -122,21 +112,18 @@ pFlow::uint64 findBindaryBlockFlagMPI(MPI_File fh)
bool pFlow::dataIO::writeDataToFileEndSTD
(
const fileSystem& filePath,
const word& wordPath,
const span<unsigned char>& data
)
{
if(!processors::isMaster()) return true;
// openfile
word wFile = filePath.wordPath();
auto fh = std::fopen(wFile.c_str(), "ab");
auto fh = std::fopen(wordPath.c_str(), "ab");
if(!fh)
{
fatalErrorInFunction<<
"Error in Opening file "<< filePath <<endl;
"Error in Opening file "<< wordPath <<endl;
std::fclose(fh);
return false;
}
@ -145,15 +132,16 @@ bool pFlow::dataIO::writeDataToFileEndSTD
if(std::fseek(fh, 0 , SEEK_END)!=0)
{
fatalErrorInFunction<<
"error at reaching end of file "<<filePath<<endl;
"error at reaching end of file "<<wordPath<<endl;
std::fclose(fh);
return false;
}
if(!writeBinaryBlockFlagSTD(fh) )
{
fatalErrorInFunction<<
"Error in writing to file "<< filePath<<endl;
"Error in writing to file "<< wordPath<<endl;
std::fclose(fh);
return false;
}
@ -166,7 +154,7 @@ bool pFlow::dataIO::writeDataToFileEndSTD
if(wc < 1)
{
fatalErrorInFunction<<
"Error in writing numChunks to file "<< filePath <<endl;
"Error in writing numChunks to file "<< wordPath <<endl;
std::fclose(fh);
return false;
}
@ -179,7 +167,7 @@ bool pFlow::dataIO::writeDataToFileEndSTD
if(wc <1)
{
fatalErrorInFunction<<
"Error in writing size of data chunk to file "<< filePath <<endl;
"Error in writing size of data chunk to file "<< wordPath <<endl;
std::fclose(fh);
return false;
}
@ -191,12 +179,15 @@ bool pFlow::dataIO::writeDataToFileEndSTD
if(wc < sizeOfData )
{
fatalErrorInFunction<<
"Error in writing size of data to file "<< filePath <<endl;
"Error in writing size of data to file "<< wordPath <<endl;
std::fclose(fh);
return false;
}
}
lastPosRead_ = static_cast<uint64>(std::ftell(fh));
// close the file
std::fclose(fh);
@ -205,7 +196,7 @@ bool pFlow::dataIO::writeDataToFileEndSTD
bool pFlow::dataIO::writeDataToFileEndMPI
(
const fileSystem& filePath,
const word& wordPath,
const span<unsigned char>& data
)
{
@ -223,19 +214,18 @@ bool pFlow::dataIO::writeDataToFileEndMPI
true
);
word wFile = filePath.wordPath();
MPI_File fh;
if( MPI_File_open(
MPI_COMM_WORLD,
wFile.c_str(),
wordPath.c_str(),
MPI_MODE_WRONLY+MPI_MODE_APPEND,
MPI_INFO_NULL,
&fh) != MPI_SUCCESS)
{
fatalErrorInFunction<<
"Cannot open file "<< filePath<<endl;
"Cannot open file "<< wordPath<<endl;
return false;
}
@ -255,7 +245,7 @@ bool pFlow::dataIO::writeDataToFileEndMPI
) != MPI_SUCCESS )
{
fatalErrorInFunction<<
"Cannot write binary block flag into "<< filePath<<endl;
"Cannot write binary block flag into "<< wordPath<<endl;
return false;
}
@ -263,7 +253,7 @@ bool pFlow::dataIO::writeDataToFileEndMPI
if( MPI_File_get_position(fh, &posOfBlock) != MPI_SUCCESS )
{
fatalErrorInFunction<<
"Cannot get the end pos of file "<< filePath<<endl;
"Cannot get the end pos of file "<< wordPath<<endl;
return false;
}
@ -295,7 +285,7 @@ bool pFlow::dataIO::writeDataToFileEndMPI
MPI_STATUS_IGNORE) != MPI_SUCCESS)
{
fatalErrorInFunction<<
"Cannot write number of chunks into "<<filePath<<endl;
"Cannot write number of chunks into "<<wordPath<<endl;
return false;
}
}
@ -312,7 +302,7 @@ bool pFlow::dataIO::writeDataToFileEndMPI
MPI_STATUS_IGNORE)!= MPI_SUCCESS)
{
fatalErrorInFunction<<
"Cannot write size of chunk into "<<filePath<<endl;
"Cannot write size of chunk into "<<wordPath<<endl;
return false;
}
@ -330,30 +320,50 @@ bool pFlow::dataIO::writeDataToFileEndMPI
MPI_STATUS_IGNORE) != MPI_SUCCESS)
{
fatalErrorInFunction<<
"Cannot write data into "<<filePath<<endl;
"Cannot write data into "<<wordPath<<endl;
return false;;
}
MPI_File_close(&fh);
MPI_Barrier(MPI_COMM_WORLD);
return true;
uint64 lastPos = chunkOffset + thisSize;
return maxReduction(lastPos, lastPosWrite_);
/*if( MPI_Allreduce(
&lastPos,
&lastPosWrite_,
1,
MPI_UINT64_T,
MPI_MAX,
MPI_COMM_WORLD) != MPI_SUCCESS )
{
fatalErrorInFunction<<
"Error in max_reduction for write operation"<<endl;
return false;
}
return true;*/
#else
return writeDataToFileEndSTD(filePath, data);
// if MPI is not active, we use std routins
return writeDataToFileEndSTD(wordPath, data);
#endif
}
bool pFlow::dataIO::readDataSTD
(
const fileSystem& filePath,
const word& wordPath,
const std::vector<uint64> chunkSizes,
span<unsigned char>& data,
uint64 binaryBlockStart
)
{
// sum of all chuncks
uint64 toRecv = std::accumulate(
chunkSizes.begin(),
@ -366,27 +376,29 @@ bool pFlow::dataIO::readDataSTD
return false;
}
word wFile = filePath.wordPath();
auto fh = std::fopen(wFile.c_str(), "rb");
auto fh = std::fopen(wordPath.c_str(), "rb");
if(!fh)
{
fatalErrorInFunction<<
"Error in Opening file "<< filePath<<endl;
"Error in Opening file "<< wordPath<<endl;
return false;
}
// start of data chunks
uint64 offset = binaryBlockStart + chunkSizeOffeset(chunkSizes.size());
if(auto res = std::fseek(fh, offset, SEEK_SET); res!= 0 )
{
fatalErrorInFunction<<
"Error in file seek "<< filePath<<endl;
"Error in file seek "<< wordPath<<endl;
std::fclose(fh);
return false;
}
if(auto res = std::fread(
data.data(),
sizeof(unsigned char),
@ -395,11 +407,13 @@ bool pFlow::dataIO::readDataSTD
res!= data.size() )
{
fatalErrorInFunction<<
"Error in reading file "<< filePath<<endl;
"Error in reading file "<< wordPath<<endl;
std::fclose(fh);
return false;
}
lastPosRead_ = static_cast<uint64>(std::ftell(fh));
std::fclose(fh);
return true;
}
@ -407,7 +421,7 @@ bool pFlow::dataIO::readDataSTD
bool pFlow::dataIO::readDataMPI
(
const fileSystem& filePath,
const word& wordPath,
const std::vector<uint64> chunkSizes,
span<unsigned char>& data,
uint64 binaryBlockStart
@ -416,19 +430,12 @@ bool pFlow::dataIO::readDataMPI
#ifdef pFlow_Build_MPI
if(chunkSizes.size() != processors::globalSize() )
{
fatalErrorInFunction;
return false;
}
word wFile = filePath.wordPath();
MPI_File fh;
if( MPI_File_open(
MPI_COMM_WORLD,
wFile.c_str(),
wordPath.c_str(),
MPI_MODE_RDONLY,
MPI_INFO_NULL,
&fh))
@ -470,29 +477,47 @@ bool pFlow::dataIO::readDataMPI
fatalErrorInFunction;
return false;
}
#else
MPI_File_close(&fh);
uint64 lastPos = offset + data.size();
/*if( MPI_Allreduce(
&lastPos,
&lastPosRead_,
1,
MPI_UINT64_T,
MPI_MAX,
MPI_COMM_WORLD) != MPI_SUCCESS)
{
fatalErrorInFunction<<
"Error in max_reduction for lastPosRead_"<<endl;
return false;
}*/
return maxReduction(lastPos, lastPosRead_);
#else
return readDataSTD(wordPath, chunkSizes, data, binaryBlockStart);
#endif
return true;
}
bool pFlow::dataIO::readMetaMPI
(
const fileSystem& filePath,
const word& wordPath,
std::vector<uint64>& chunkSizes,
uint64 startPosSearch,
uint64 &startPosBinaryBlock
)
{
word wFile = filePath.wordPath();
#ifdef pFlow_Build_MPI
MPI_File fh;
if(MPI_File_open(
MPI_COMM_WORLD,
wFile.c_str(),
wordPath.c_str(),
MPI_MODE_RDONLY,
MPI_INFO_NULL,
&fh) != MPI_SUCCESS)
@ -502,8 +527,8 @@ bool pFlow::dataIO::readMetaMPI
}
uint64 startPos = findBindaryBlockFlagMPI(fh);
if( startPos == -1 )
uint64 startPos = findBindaryBlockFlagMPI(fh, startPosSearch);
if( startPos == pFlow::dataIO::ErrorReturn )
{
fatalErrorInFunction;
return false;
@ -539,36 +564,53 @@ bool pFlow::dataIO::readMetaMPI
fatalErrorInFunction;
return false;
}
MPI_File_close(&fh);
#endif
uint64 lastPos = startPos + sizeof(numProcInFile) + chunkSizes.size();
return maxReduction(lastPos, lastPosRead_);
return true;
/*if( MPI_Allreduce(
&lastPos,
&lastPosRead_,
1,
MPI_UINT64_T,
MPI_MAX,
MPI_COMM_WORLD) != MPI_SUCCESS)
{
fatalErrorInFunction<<
"Error in max_reduction for lastPosRead_"<<endl;
return false;
}*/
#else
return readMetaSTD(wordPath, chunkSizes, startPosBinaryBlock);
#endif
}
bool pFlow::dataIO::readMetaSTD
(
const fileSystem& filePath,
const word& wordPath,
std::vector<uint64>& chunkSizes,
uint64 startPosSearch,
uint64 &startPosBinaryBlock
)
{
// only on master
if( !processors::isMaster()) return true;
word wFile = filePath.wordPath();
std::FILE *fh = std::fopen(wFile.c_str(), "rb");
std::FILE *fh = std::fopen(wordPath.c_str(), "rb");
if(!fh)
{
fatalErrorInFunction<<
"Error in Opening file "<< filePath<<endl;
"Error in Opening file "<< wordPath<<endl;
return false;
}
// set the start position for search
std::fseek(fh, startPosSearch, SEEK_SET);
uint64 startPos = findBindaryBlockFlagSTD(fh);
if(startPos == -1 )
if(startPos == ErrorReturn )
{
fatalErrorInFunction;
return false;
@ -587,7 +629,7 @@ bool pFlow::dataIO::readMetaSTD
if(res != 1 )
{
fatalErrorInFunction<<
"Error in reading file "<< filePath<<endl;
"Error in reading file "<< wordPath<<endl;
std::fclose(fh);
return false;
}
@ -600,13 +642,76 @@ bool pFlow::dataIO::readMetaSTD
if(res!= numProcInFile)
{
fatalErrorInFunction<<
"Error in reading chunkSizes from file "<< filePath<<endl;
"Error in reading chunkSizes from file "<< wordPath<<endl;
std::fclose(fh);
return false;
}
lastPosRead_ = static_cast<uint64>(std::ftell(fh));
std::fclose(fh);
return true;
}
bool pFlow::dataIO::waitForAllMPI()
{
#ifdef pFlow_Build_MPI
MPI_Barrier(MPI_COMM_WORLD);
#endif
return true;
}
bool pFlow::dataIO::maxReduction( uint64& src, uint64& dst)
{
#ifdef pFlow_Build_MPI
if(processors::isParallel())
{
if(MPI_Allreduce(
&src,
&dst,
1,
MPI_UINT64_T,
MPI_MAX,
MPI_COMM_WORLD) != MPI_SUCCESS )
{
fatalErrorInFunction<<
"Error in max_reduction for write operation"<<endl;
return false;
}
return true;
}
else
{
dst = src;
return true;
}
#else
dst = src;
return true;
#endif
}
bool pFlow::dataIO::BcastPos(uint64 & pos)
{
#ifdef pFlow_Build_MPI
if(processors::isParallel())
{
if( MPI_Bcast(
& pos,
1,
MPI_UINT64_T,
processors::masterNo(),
MPI_COMM_WORLD)!=MPI_SUCCESS )
{
fatalErrorInFunction<<
"Error in Bcast position"<<endl;
return false;
}
}
#endif
return true;
}

View File

@ -6,7 +6,7 @@
#include "types.hpp"
#include "span.hpp"
#include "processors.hpp"
#include "IOPattern.hpp"
namespace pFlow
{
@ -19,80 +19,133 @@ class dataIO
public:
/**
* Type of input/output
* MasterProcessor: Read or write is done on master processor
* and the data on master processor is affected.
* AllProcessorsDifferent: Read or write is done on all processors,
* and each processor munipulates its own data.
* AllProcessorsSimilar: Read is done on all processors but the read data
* is similar on processors. Write is done on master processor, since
* all processors have the same copy of data.
*/
enum IOType : int
{
MasterProcessor,
AllProcessorsDifferent,
AllProcessorsSimilar
};
static inline const uint64 ErrorReturn = static_cast<uint64>(-1);
protected:
IOType IOType_;
IOPattern ioPattern_;
uint64 lastPosWrite_ = 0;
uint64 lastPosRead_ = 0;
bool writeDataToFileEndSTD(
const fileSystem& filePath,
const word& wordPath,
const span<unsigned char>& data);
bool writeDataToFileEndMPI(
const fileSystem& filePath,
const word& wordPath,
const span<unsigned char>& data);
bool readDataSTD(
const fileSystem& filePath,
const word& wordPath,
const std::vector<uint64> chunkSizes,
span<unsigned char>& data,
uint64 binaryBlockStart);
bool readDataMPI(
const fileSystem& filePath,
const word& wordPath,
const std::vector<uint64> chunkSizes,
span<unsigned char>& data,
uint64 binaryBlockStart);
bool readMetaMPI(
const fileSystem& filePath,
const word& wordPath,
std::vector<uint64>& chunkSizes,
uint64 startPosSearch,
uint64 &startPosBinaryBlock);
bool readMetaSTD(
const fileSystem& filePath,
const word& wordPath,
std::vector<uint64>& chunkSizes,
uint64 startPosSearch,
uint64 &startPosBinaryBlock);
bool waitForAllMPI();
bool maxReduction( uint64& src, uint64& dst);
bool BcastPos(uint64 & pos);
public:
dataIO(IOType ioT)
dataIO(IOPattern::IOType iotype)
:
IOType_(ioT)
ioPattern_(iotype)
{}
~dataIO()=default;
template<typename T>
bool writeDataEnd(
const fileSystem& filePath,
const word& wordPath,
const span<T>& data);
template<typename T>
bool writeAsciiEnd(
iOstream& os,
const span<T>& data);
template<typename T>
bool readDataBinary(
const word& wordPath,
std::vector<T>& data,
uint64 startPos = 0);
template<typename T>
bool readAscii(
iIstream& is,
std::vector<T>& vec );
template<typename T>
bool readData(
const fileSystem& filePath,
std::vector<T>& data);
iIstream& is,
std::vector<T>& vec,
bool resume = false); // resume only works for binary
// for ascii, by default it starts from the current position
template<typename T>
bool writeData(iOstream& os,
const span<T>& data);
};
template<>
inline
bool pFlow::dataIO::writeData<pFlow::word>
(
iOstream& os,
const span<word>& data
)
{
if( !writeAsciiEnd(os, data) )
{
fatalErrorInFunction;
return false;
}
return true;
}
template<>
inline
bool pFlow::dataIO::readData<pFlow::word>(
iIstream& is,
std::vector<word>& vec,
bool resume)
{
if(!readAscii(is, vec))
{
fatalErrorInFunction;
return false;
}
return true;
}
}
#include "dataIOTemplate.cpp"

View File

@ -1,112 +1,320 @@
template<typename T>
bool pFlow::dataIO::writeDataEnd(
const fileSystem& filePath,
const word& wordPath,
const span<T>& data)
{
span<unsigned char> charSpan(
if( ioPattern_.thisProcWriteData() )
{
span<unsigned char> charSpan(
reinterpret_cast<unsigned char*> (const_cast<T*>(data.data())),
data.size()*sizeof(T));
switch (IOType_)
if( ioPattern_.isParallel() )
{
return writeDataToFileEndMPI(wordPath, charSpan);
}
else
{
return writeDataToFileEndSTD(wordPath, charSpan);
}
}
else
{
case MasterProcessor:
case AllProcessorsSimilar:
{
// This means that only master processor should write
// in this case we perform write on master processor only
// this means that the data
if(processors::isMaster())
{
return writeDataToFileEndSTD(filePath, charSpan);
}
else
{
return true;
}
break;
}
case AllProcessorsDifferent:
{
// This means that all processors should write their own
// copy of data
return writeDataToFileEndMPI(filePath, charSpan);
break;
}
return true;
}
return false;
}
template<typename T>
bool pFlow::dataIO::readData
bool pFlow::dataIO::writeAsciiEnd
(
const fileSystem& filePath,
std::vector<T>& data
iOstream& os,
const span<T>& data
)
{
if(ioPattern_.thisProcWriteData())
{
return data.writeASCII(os);
}
else
return true;
}
template<typename T>
bool pFlow::dataIO::readDataBinary
(
const word& wordPath,
std::vector<T>& data,
uint64 startPos
)
{
std::vector<uint64> chunkSizes;
uint64 startPosBinaryBlock;
// read meta data
switch (IOType_)
{
case MasterProcessor:
{
if(!readMetaSTD(
filePath,
chunkSizes,
startPosBinaryBlock))
{
return false;
}
break;
}
case AllProcessorsDifferent:
case AllProcessorsSimilar:
{
if(!readMetaMPI(
filePath,
chunkSizes,
startPosBinaryBlock))
{
return false;
}
break;
}
}
data.clear();
if(IOType_ == MasterProcessor)
if( ioPattern_.thisProcReadData())
{
auto sizeOfData = std::accumulate(
// read meta
if(!readMetaSTD(
wordPath,
chunkSizes,
startPos,
startPosBinaryBlock))
{
fatalErrorInFunction;
return false;
}
if( ioPattern_.isMasterProcessor() ||
ioPattern_.isAllProcessorSimilar()
)
{
auto sizeOfData = std::accumulate(
chunkSizes.begin(),
chunkSizes.end(),
static_cast<uint64>(0));
data.resize(sizeOfData/sizeof(T));
data.resize(sizeOfData/sizeof(T));
span<unsigned char> charSpan(
reinterpret_cast<unsigned char*>(data.data()),
data.size()*sizeof(T));
span<unsigned char> charSpan(
reinterpret_cast<unsigned char*>(data.data()),
data.size()*sizeof(T));
if(!readDataSTD(wordPath, chunkSizes, charSpan, startPosBinaryBlock))
{
fatalErrorInFunction;
return false;
}
readDataSTD(filePath, chunkSizes, charSpan, startPosBinaryBlock);
return true;
}
else if( ioPattern_.isAllProcessorDifferent() )
{
if(chunkSizes.size() != ioPattern_.globalSize())
{
if( ioPattern_.isMaster())
{
auto sizeOfData = std::accumulate(
chunkSizes.begin(),
chunkSizes.end(),
static_cast<uint64>(0));
data.resize(sizeOfData/sizeof(T));
span<unsigned char> charSpan(
reinterpret_cast<unsigned char*>(data.data()),
data.size()*sizeof(T));
if(!readDataSTD(wordPath, chunkSizes, charSpan, startPosBinaryBlock))
{
fatalErrorInFunction;
return false;
}
return true;
}
else
{
return true;
}
}
else
{
auto thisProc = ioPattern_.globalRank();
data.resize(chunkSizes[thisProc]/sizeof(T));
span<unsigned char> charSpan(
reinterpret_cast<unsigned char*>(data.data()),
data.size()*sizeof(T));
if( !readDataMPI(wordPath, chunkSizes, charSpan, startPosBinaryBlock) )
{
fatalErrorInFunction;
return false;
}
return true;
}
}
else
{
fatalErrorInFunction;
return false;
}
}
if( IOType_ == AllProcessorsDifferent )
else
{
auto thisProc = processors::globalRank();
return true;
}
data.resize(chunkSizes[thisProc]/sizeof(T));
return false;
}
span<unsigned char> charSpan(
reinterpret_cast<unsigned char*>(data.data()),
data.size()*sizeof(T));
template<typename T>
bool pFlow::dataIO::readAscii
(
iIstream& is,
std::vector<T>& vec
)
{
std::cout<<"MPI part"<<std::endl;
readDataMPI(filePath, chunkSizes, charSpan, startPosBinaryBlock);
if( !ioPattern_.thisProcReadData() ) return true;
is.fatalCheck(FUNCTION_NAME);
vec.clear();
token firstToken(is);
size_t len = 0;
if( firstToken.isInt64())
{
len = firstToken.int64Token();
vec.reserve(len);
firstToken = token(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;
vec.push_back(val);
is >> lastToken;
is.fatalCheck(FUNCTION_NAME);
}
} else
{
warningInFunction
<< "expected token "<< token::BEGIN_LIST
<< " but found "<< firstToken<<endl; ;
return false;
}
if(len>0&& len != vec.size())
{
warningInFunction<<"vector lendth specified "<< len <<
" is different from number of elements "<< vec.size()<<endl;
return false;
}
return true;
}
}
template<typename T>
bool pFlow::dataIO::readData
(
iIstream& is,
std::vector<T>& vec,
bool resume
)
{
if(is.isBinary())
{
uint64 currPos = 0;
if( resume )
{
currPos = is.tell();
}
if(! BcastPos(currPos) ) return false;
if(!this->readDataBinary(is.name(), vec, currPos))
{
fatalErrorInFunction;
return false;
}
auto lastPos = lastPosRead_;
maxReduction( lastPos, lastPosRead_);
//std::cout<<"last post read "<< lastPosRead_<<std::endl;
/// set the stream indicator to the last position
is.seek(lastPosRead_);
return true;
}
else
{
if(!readAscii(is, vec))
{
fatalErrorInFunction;
return false;
}
return true;
}
}
template<typename T>
bool pFlow::dataIO::writeData
(
iOstream& os,
const span<T>& sp
)
{
if( os.isBinary() )
{
os.startOfBinaryStreaming();
if(!writeDataEnd(os.name(), sp))
{
fatalErrorInFunction;
return false;
}
os.endOfBinaryStreaming();
}
else
{
if( !writeAsciiEnd(os, sp) )
{
fatalErrorInFunction;
return false;
}
}
return true;
}

View File

@ -180,7 +180,7 @@ public:
bool isBinary()const
{
return writeFormat_ == BINARY;
}
}
/// Return true if next operation might succeed
bool good() const

View File

@ -134,6 +134,10 @@ public:
/// Rewind the stream so that it may be read again
virtual void rewind() = 0;
virtual void seek(size_t pos) = 0;
/// Return current position indicator
virtual size_t tell() = 0;
////- find and lookups

View File

@ -144,7 +144,7 @@ public:
/// Write the flag to indicate the start of a binary block
virtual iOstream& writeBinaryBlockFlag();
virtual void seek(size_t pos) = 0;
//// - Indent
/// Add indentation characters
@ -238,6 +238,12 @@ public:
////- Stream state functions
/// Add a new line and flush stream
virtual void startOfBinaryStreaming() =0;
/// Reach end of file add a new line and flush stream
virtual void endOfBinaryStreaming() = 0 ;
/// Flush stream
virtual void flush() = 0;

View File

@ -0,0 +1,64 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
#include "infinitePlane.hpp"
pFlow::infinitePlane::infinitePlane
(
const realx3& p1,
const realx3& p2,
const realx3& p3
)
{
auto ln = cross(p2-p1, p3-p1);
if( equal(ln.length(),0.0) )
{
fatalErrorInFunction<<
"invalid input to form a infinte wall "<< realx3x3(p1,p2,p3)<<endl;
fatalExit;
}
normal_ = normalize(ln);
d_ = -dot(normal_, p1);
}
bool pFlow::infinitePlane::write(iOstream& os)const
{
os.writeWordEntry("normal", normal_);
os.writeWordEntry("d", d_);
return os.check(FUNCTION_NAME);
}
bool pFlow::infinitePlane::read(iIstream & is)
{
if(!is.nextData<realx3>("normal", normal_)) return false;
if(!is.nextData<real>("d", d_)) return false;
return true;
}
bool pFlow::infinitePlane::validPlane3
(
const realx3& p1,
const realx3& p2,
const realx3& p3
)
{
return !equal(cross(p2-p1, p3-p1).length(), 0.0);
}

View File

@ -0,0 +1,165 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
#ifndef __infinitePlane_hpp__
#define __infinitePlane_hpp__
#include "types.hpp"
//#include "dictionary.hpp"
#include "iIstream.hpp"
#include "iOstream.hpp"
namespace pFlow
{
class infinitePlane
{
protected:
/// normal vector
realx3 normal_{1,0,0};
/// distance value
real d_ = 0;
public:
// - type info
TypeInfoNV("infinitePlane");
//// - Constructors
/// Default
INLINE_FUNCTION_HD
infinitePlane(){}
/// From components
INLINE_FUNCTION_HD
infinitePlane(const realx3& normal, const real& d)
:
normal_(normal),
d_(d)
{}
INLINE_FUNCTION_HD
infinitePlane(const realx3& normal, const realx3& p)
:
normal_(normal),
d_(-dot(normal,p))
{}
/// From 3 points
infinitePlane(const realx3& p1, const realx3& p2, const realx3& p3);
FUNCTION_HD
infinitePlane(const infinitePlane&) = default;
FUNCTION_HD
infinitePlane(infinitePlane&&) = default;
FUNCTION_HD
infinitePlane& operator=(const infinitePlane&) = default;
FUNCTION_HD
infinitePlane& operator=(infinitePlane&&) = default;
~infinitePlane()=default;
/*FUNCTION_H
infinitePlane(const dictionary& dict);
FUNCTION_H
infinitePlane(iIstream& is);*/
//// - Methods
INLINE_FUNCTION_HD
real pointFromPlane(const realx3& p)const
{
return dot(normal_, p) + d_;
}
INLINE_FUNCTION_HD
bool pointInPositiveSide(const realx3& p)const
{
return pointFromPlane(p)>=0;
}
INLINE_FUNCTION_HD
bool pointInNegativeSide(const realx3& p)const
{
return pointFromPlane(p)<0;
}
INLINE_FUNCTION_HD
bool pointOnPlane(const realx3& p)const
{
return equal(pointFromPlane(p),0.0);
}
INLINE_FUNCTION_HD
realx3 projectPoint(const realx3& p)const
{
real t = -(dot(normal_, p) + d_);
return t*normal_ + p;
}
//// - IO operation
FUNCTION_H
bool write(iOstream& os)const;
bool read(iIstream & is);
/*FUNCTION_H
bool read(iIstream & is);
FUNCTION_H
bool write(iOstream& os)const;
FUNCTION_H
bool read(const dictionary& dict);
FUNCTION_H
bool write(dictionary& dict)const;*/
static bool validPlane3(
const realx3& p1,
const realx3& p2,
const realx3& p3);
};
/*FUNCTION_H
iIstream& operator >>(iIstream& is, box& b);
FUNCTION_H
iOstream& operator << (iOstream& os, const box& b);
INLINE_FUNCTION_HD
box extendBox(const box& b, const realx3& dl)
{
return box(b.minPoint()-dl , b.maxPoint()+dl);
}*/
}
#endif // __infinitePlane_hpp__

View File

@ -55,19 +55,27 @@ public:
FUNCTION_HD
line(const realx3 &lp1, const realx3 &lp2);
INLINE_FUNCTION_HD
line(const realx3 &v21, const realx3 &p1, bool)
:
v21_(v21),
p1_(p1)
{}
FUNCTION_H
line(const dictionary& dict);
FUNCTION_HD
INLINE_FUNCTION_HD
line(const line& src) = default;
FUNCTION_HD
INLINE_FUNCTION_HD
line(line&& src) = default;
FUNCTION_HD
INLINE_FUNCTION_HD
line& operator = (const line&) = default;
FUNCTION_HD
INLINE_FUNCTION_HD
line& operator = (line&&) = default;

View File

@ -0,0 +1,68 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
#include "plane.hpp"
pFlow::plane::plane
(
const realx3& p1,
const realx3& p2,
const realx3& p3,
const realx3& p4
)
:
infinitePlane(p1,p2,p3),
p1_(p1),
p2_(p2),
p3_(p3),
p4_(p4)
{
if(!pointOnPlane(p4))
{
fatalErrorInFunction<<
"points "<< realx4x3(p1,p2,p3,p4)<<" do not form a planner surface"<<endl;
fatalExit;
}
}
pFlow::plane pFlow::plane::parallelPlane(real distance)const
{
auto pp1 = line(normal_, p1_, true).point(distance);
auto pp2 = line(normal_, p2_, true).point(distance);
auto pp3 = line(normal_, p3_, true).point(distance);
auto pp4 = line(normal_, p4_, true).point(distance);
return plane(pp1, pp2, pp3, pp4);
}
bool pFlow::plane::validPlane4
(
const realx3& p1,
const realx3& p2,
const realx3& p3,
const realx3& p4
)
{
if( !validPlane3(p1,p2,p3)) return false;
if( !infinitePlane(p1,p2,p3).pointOnPlane(p4)) return false;
return true;
}

View File

@ -0,0 +1,136 @@
/*------------------------------- 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 __plane_hpp__
#define __plane_hpp__
#include "infinitePlane.hpp"
#include "line.hpp"
namespace pFlow
{
class plane
:
public infinitePlane
{
protected:
/// First point
realx3 p1_;
/// Second point
realx3 p2_;
/// Third point
realx3 p3_;
/// Fourth point
realx3 p4_;
public:
INLINE_FUNCTION_HD
plane(){}
plane(
const realx3& p1,
const realx3& p2,
const realx3& p3,
const realx3& p4);
INLINE_FUNCTION_HD
plane(const plane&) = default;
INLINE_FUNCTION_HD
plane(plane&&) = default;
INLINE_FUNCTION_HD
plane& operator = (const plane&) = default;
INLINE_FUNCTION_HD
plane& operator =( plane&&)=default;
INLINE_FUNCTION_HD
~plane()=default;
INLINE_FUNCTION_HD
const realx3& p1()const
{
return p1_;
}
INLINE_FUNCTION_HD
const realx3& p2()const
{
return p2_;
}
INLINE_FUNCTION_HD
const realx3& p3()const
{
return p3_;
}
INLINE_FUNCTION_HD
const realx3& p4()const
{
return p4_;
}
INLINE_FUNCTION_HD
line line1()const
{
return line(p1_,p2_);
}
INLINE_FUNCTION_HD
line line2()const
{
return line(p2_,p3_);
}
INLINE_FUNCTION_HD
line line3()const
{
return line(p3_,p4_);
}
INLINE_FUNCTION_HD
line line4()const
{
return line(p4_,p1_);
}
// return the parallel plane to this plane
plane parallelPlane(real distance)const;
static
bool validPlane4(
const realx3& p1,
const realx3& p2,
const realx3& p3,
const realx3& p4);
};
}
#endif //__plane_hpp__