mirror of
https://github.com/PhasicFlow/phasicFlow.git
synced 2025-07-08 03:07:03 +00:00
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:
@ -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);
|
||||
}
|
@ -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__
|
@ -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
|
Reference in New Issue
Block a user