phasicFlow core changes for boundary condition addition.

- Exit boundry condition, checked.
- periodic boundary condition added, checked.

to be done:
- messaging events
- reflective
- wall-particle interaction for periodic bc.
This commit is contained in:
Hamidreza Norouzi
2024-04-04 10:36:11 -07:00
parent ef0e752929
commit 65b3f5a8a0
56 changed files with 360 additions and 183 deletions

View File

@ -0,0 +1,149 @@
/*------------------------------- phasicFlow ---------------------------------
O C enter of
O O E ngineering and
O O M ultiscale modeling of
OOOOOOO F luid flow
------------------------------------------------------------------------------
Copyright (C): www.cemf.ir
email: hamid.r.norouzi AT gmail.com
------------------------------------------------------------------------------
Licence:
This file is part of phasicFlow code. It is a free software for simulating
granular and multiphase flows. You can redistribute it and/or modify it under
the terms of GNU General Public License v3 or any other later versions.
phasicFlow is distributed to help others in their research in the field of
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-----------------------------------------------------------------------------*/
template<class T, class MemorySpace>
pFlow::internalField<T, MemorySpace>::internalField
(
const word& name,
const internalPoints& internal
)
:
observer
(
&internal,
defaultMessage_
),
field_
(
name,
"ineternalField",
internal.capacity(),
internal.size(),
RESERVE()
),
internalPoints_(internal)
{}
template<class T, class MemorySpace>
pFlow::internalField<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)
{
fillInternal(val);
}
template <class T, class MemorySpace>
typename pFlow::internalField<T, MemorySpace>::FieldTypeHost
pFlow::internalField<T, MemorySpace>::activeValuesHost() const
{
auto maskH = internalPoints_.activePointsMaskHost();
auto fieldH = field_.hostView();
FieldTypeHost aField
(
field_.name(),
field_.fieldKey(),
maskH.numActive(),
maskH.numActive(),
RESERVE()
);
auto aRange = maskH.activeRange();
uint32 n = 0;
for(auto i=aRange.start(); i<aRange.end(); i++)
{
if( maskH.isActive(i) )
{
aField[n] = fieldH[i];
n++;
}
}
return aField;
}
template <class T, class MemorySpace>
bool pFlow::internalField<T, MemorySpace>:: hearChanges
(
real t,
real dt,
uint32 iter,
const message& msg,
const anyList& varList
)
{
if(msg.equivalentTo(message::CAP_CHANGED))
{
auto newCap = varList.getObject<uint32>(
message::eventName(message::CAP_CHANGED));
field_.reserve(newCap);
}
if(msg.equivalentTo(message::SIZE_CHANGED))
{
auto newSize = varList.getObject<uint32>(
message::eventName(message::SIZE_CHANGED));
field_.resize(newSize);
}
if(msg.equivalentTo(message::ITEM_DELETE))
{
// do nothing
}
if(msg.equivalentTo(message::ITEM_REARRANGE))
{
notImplementedFunction;
return false;
}
if(msg.equivalentTo(message::ITEM_INSERT))
{
notImplementedFunction;
return false;
}
return true;
}
template<class T, class MemorySpace>
bool pFlow::internalField<T, MemorySpace>::write
(
iOstream& os,
const IOPattern& iop
)const
{
auto aField = activeValuesHost();
return aField.write(os, iop);
}

View File

@ -0,0 +1,207 @@
/*------------------------------- 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 __internalField_hpp__
#define __internalField_hpp__
#include "internalPoints.hpp"
#include "Field.hpp"
#include "observer.hpp"
#include "dataIO.hpp"
#include "anyList.hpp"
namespace pFlow
{
template<class T, class MemorySpace=void>
class internalField
:
public observer
{
public:
using InternalFieldType = internalField<T, MemorySpace>;
using FieldType = Field<T, MemorySpace>;
using FieldTypeHost = Field<T, HostSpace>;
using VectorType = typename FieldType::VectorType;
using memory_space = typename FieldType::memory_space;
using execution_space = typename FieldType::execution_space;
protected:
FieldType field_;
const internalPoints& internalPoints_;
static inline
const message defaultMessage_ =
(
message::CAP_CHANGED+
message::SIZE_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);
inline
const auto& deviceViewAll()const
{
return field_.deviceViewAll();
}
inline
auto deviceView()const
{
return field_.deviceView();
}
inline
auto hostView()const
{
return field_.hostView();
}
inline
const FieldType& field()const
{
return field_;
}
inline
FieldType& field()
{
return field_;
}
const pFlagTypeDevice& activePointsMaskDevice()const
{
return internalPoints_.activePointsMaskDevice();
}
const pFlagTypeHost& activePointsMaskHost()const
{
return internalPoints_.activePointsMaskHost();
}
FieldTypeHost activeValuesHost()const;
inline
auto size()const
{
return field_.size();
}
inline
auto capacity()const
{
return field_.capacity();
}
inline
word name()const
{
return field_.name();
}
inline
word fieldKey()const
{
return field_.fieldKey();
}
inline
auto activeRange()const
{
return internalPoints_.activeRange();
}
inline
auto isAllActive()const
{
return internalPoints_.isAllActive();
}
inline
void fillInternal(const T& val)
{
field_.fillField(activeRange(), val);
}
inline
bool insertSetElement(uint32IndexContainer indices, const T& val)
{
return field_.insertSetElement(indices, val);
}
bool hearChanges
(
real t,
real dt,
uint32 iter,
const message& msg,
const anyList& varList
) override;
//// - IO
bool write(iOstream& os, const IOPattern& iop)const;
};
template<class T, class MemorySpace>
inline
iOstream& operator<<
(
iOstream& os,
const internalField<T, MemorySpace>& ifeild
)
{
if( !ifeild.write(os, IOPattern::AllProcessorsDifferent) )
{
ioErrorInFile(os.name(), os.lineNumber());
fatalExit;
}
return os;
}
} // pFlow
#include "internalField.cpp"
#include "internalFieldAlgorithms.hpp"
#endif // __internalField_hpp__

View File

@ -0,0 +1,255 @@
/*------------------------------- 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 __internalFieldAlgorithms_hpp__
#define __internalFieldAlgorithms_hpp__
namespace pFlow
{
template<class T, class MemorySpace>
inline
T min(const internalField<T,MemorySpace>& iField)
{
using exeSpace = typename internalField<T,MemorySpace>::execution_space;
using policy = Kokkos::RangePolicy<
exeSpace,
Kokkos::IndexType<uint32> >;
if constexpr(isDeviceAccessible<exeSpace>())
{
// this is a device view
auto maskD = iField.activePointsMaskDevice();
auto aRange = maskD.activeRange();
auto filed = iField.field().deviceViewAll();
T minElement;
Kokkos::parallel_reduce(
"min(internalField)",
policy(aRange.start(), aRange.end() ),
LAMBDA_HD(uint32 i, T& minUpdate)
{
if( maskD(i) )
if(filed[i] < minUpdate) minUpdate = filed[i];
},
Kokkos::Min<T>(minElement));
return minElement;
}
else
{
// this is a host view
auto maskH = iField.activePointsMaskHost();
auto aRange = maskH.activeRange();
auto filed = iField.field().deviceViewAll();
T minElement;
Kokkos::parallel_reduce(
"min(internalField)",
policy(aRange.start(), aRange.end()),
LAMBDA_HD(uint32 i, T& minUpdate)
{
if( maskH(i) )
if(filed[i] < minUpdate) minUpdate = filed[i];
},
Kokkos::Min<T>(minElement));
return minElement;
}
}
template<class T, class MemorySpace>
inline
T max(const internalField<T,MemorySpace>& iField)
{
using exeSpace = typename internalField<T,MemorySpace>::execution_space;
using policy = Kokkos::RangePolicy<
exeSpace,
Kokkos::IndexType<uint32> >;
if constexpr(isDeviceAccessible<exeSpace>())
{
// this is a device view
auto maskD = iField.activePointsMaskDevice();
auto aRange = maskD.activeRange();
auto filed = iField.field().deviceViewAll();
T maxElement;
Kokkos::parallel_reduce(
"max(internalField)",
policy(aRange.start(), aRange.end() ),
LAMBDA_HD(uint32 i, T& maxUpdate)
{
if( maskD(i) )
if( maxUpdate <filed[i]) maxUpdate = filed[i];
},
Kokkos::Max<T>(maxElement));
return maxElement;
}
else
{
// this is a host view
auto maskH = iField.activePointsMaskHost();
auto aRange = maskH.activeRange();
auto filed = iField.field().deviceViewAll();
T maxElement;
Kokkos::parallel_reduce(
"max(internalField)",
policy(aRange.start(), aRange.end() ),
LAMBDA_HD(uint32 i, T& maxUpdate)
{
if( maskH(i) )
if( maxUpdate <filed[i]) maxUpdate = filed[i];
},
Kokkos::Max<T>(maxElement));
return maxElement;
}
}
template<class T, class MemorySpace>
inline
Pair<T,T> minMax(const internalField<T,MemorySpace>& iField)
{
using exeSpace = typename internalField<T,MemorySpace>::execution_space;
using policy = Kokkos::RangePolicy<
exeSpace,
Kokkos::IndexType<uint32> >;
if constexpr(isDeviceAccessible<exeSpace>())
{
// this is a device view
auto maskD = iField.activePointsMaskDevice();
auto aRange = maskD.activeRange();
auto filed = iField.field().deviceViewAll();
T minElement;
T maxElement;
Kokkos::parallel_reduce(
"minMax(internalField)",
policy(aRange.start(), aRange.end() ),
LAMBDA_HD(uint32 i, T& minUpdate, T& maxUpdate)
{
if( maskD(i) )
{
if(maxUpdate < filed[i]) maxUpdate = filed[i];
if(filed[i] < minUpdate) minUpdate = filed[i];
}
},
Kokkos::Min<T>(minElement),
Kokkos::Max<T>(maxElement)
);
return {minElement, maxElement};
}
else
{
// this is a host view
auto maskH = iField.activePointsMaskHost();
auto aRange = maskH.activeRange();
auto filed = iField.field().deviceViewAll();
T minElement;
T maxElement;
Kokkos::parallel_reduce(
"minMax(internalField)",
policy(aRange.start(), aRange.end() ),
LAMBDA_HD(uint32 i, T& minUpdate, T& maxUpdate)
{
if( maskH(i) )
{
if(maxUpdate < filed[i]) maxUpdate = filed[i];
if(filed[i] < minUpdate) minUpdate = filed[i];
}
},
Kokkos::Min<T>(minElement),
Kokkos::Max<T>(maxElement)
);
return {minElement, maxElement};
}
}
template<class T, class MemorySpace>
inline
void fillSequence(internalField<T,MemorySpace>& iField, const T& startVal)
{
using exeSpace = typename internalField<T,MemorySpace>::execution_space;
using policy = Kokkos::RangePolicy<
exeSpace,
Kokkos::IndexType<uint32> >;
if constexpr(isDeviceAccessible<exeSpace>())
{
auto maskD = iField.activePointsMaskDevice();
auto aRange = maskD.activeRange();
auto field = iField.field().deviceViewAll();
auto aPoints = maskD.getActivePoints();
exclusiveScan(aPoints,0, aRange.end(), aPoints,0);
Kokkos::parallel_for(
"internalField::fillSequence",
policy(aRange.start(), aRange.end() ),
LAMBDA_HD(uint32 i)
{
if(maskD(i))
{
field[i] = aPoints[i]+startVal;
}
});
Kokkos::fence();
}
else
{
// this is a host view
auto maskH = iField.activePointsMaskHost();
auto aRange = maskH.activeRange();
auto field = iField.field().deviceViewAll();
auto aPoints = maskH.getActivePoints();
exclusiveScan(aPoints,0, aRange.end(), aPoints,0);
Kokkos::parallel_for(
"internalField::fillSequence",
policy(aRange.start(), aRange.end() ),
LAMBDA_HD(uint32 i)
{
if(maskH(i))
{
field[i] = aPoints[i]+startVal;
}
});
Kokkos::fence();
}
}
}
#endif