mirror of
https://github.com/PhasicFlow/phasicFlow.git
synced 2025-06-22 16:28:30 +00:00
src folder
This commit is contained in:
16
src/Interaction/CMakeLists.txt
Normal file
16
src/Interaction/CMakeLists.txt
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
set(SourceFiles
|
||||
contactSearch/contactSearch/contactSearch.C
|
||||
contactSearch/ContactSearch/ContactSearchs.C
|
||||
interaction/interaction.C
|
||||
sphereInteraction/sphereInteractions.C
|
||||
)
|
||||
|
||||
set(link_libs Kokkos::kokkos phasicFlow Property Particles Geometry)
|
||||
|
||||
pFlow_add_library_install(Interaction SourceFiles link_libs)
|
||||
|
||||
#additional locations
|
||||
target_include_directories(Interaction PUBLIC "./contactSearch")
|
||||
|
||||
|
284
src/Interaction/Models/contactForce/linearCF.H
Normal file
284
src/Interaction/Models/contactForce/linearCF.H
Normal file
@ -0,0 +1,284 @@
|
||||
/*------------------------------- 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 __linearCF_H__
|
||||
#define __linearCF_H__
|
||||
|
||||
#include "types.H"
|
||||
#include "symArrays.H"
|
||||
|
||||
namespace pFlow::cfModels
|
||||
{
|
||||
|
||||
template<bool limited=true>
|
||||
class linear
|
||||
{
|
||||
public:
|
||||
|
||||
struct contactForceStorage
|
||||
{
|
||||
realx3 overlap_t_ = 0.0;
|
||||
};
|
||||
|
||||
struct linearProperties
|
||||
{
|
||||
real kn_ = 1000.0;
|
||||
real kt_ = 800.0;
|
||||
real ethan_ = 0.0;
|
||||
real ethat_ = 0.0;
|
||||
real mu_ = 0.00001;
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
linearProperties(){}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
linearProperties(real kn, real kt, real etha_n, real etha_t, real mu ):
|
||||
kn_(kn), kt_(kt), ethan_(etha_n),ethat_(etha_t), mu_(mu)
|
||||
{}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
linearProperties(const linearProperties&)=default;
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
linearProperties& operator=(const linearProperties&)=default;
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
~linearProperties() = default;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
using LinearArrayType = symArray<linearProperties>;
|
||||
|
||||
int32 numMaterial_ = 0;
|
||||
|
||||
ViewType1D<real> rho_;
|
||||
|
||||
LinearArrayType linearProperties_;
|
||||
|
||||
/**/
|
||||
|
||||
bool readLinearDictionary(const dictionary& dict)
|
||||
{
|
||||
auto kn = dict.getVal<realVector>("kn");
|
||||
auto kt = dict.getVal<realVector>("kt");
|
||||
auto en = dict.getVal<realVector>("en");
|
||||
auto et = dict.getVal<realVector>("et");
|
||||
auto mu = dict.getVal<realVector>("mu");
|
||||
|
||||
auto nElem = kn.size();
|
||||
|
||||
|
||||
if(nElem != kt.size())
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"sizes of kn("<<nElem<<") and kt("<<kt.size()<<") do not match.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(nElem != en.size())
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"sizes of kn("<<nElem<<") and en("<<en.size()<<") do not match.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(nElem != et.size())
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"sizes of kn("<<nElem<<") and et("<<et.size()<<") do not match.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(nElem != mu.size())
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"sizes of kn("<<nElem<<") and mu("<<mu.size()<<") do not match.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// check if size of vector matchs a symetric array
|
||||
uint32 nMat;
|
||||
if( !LinearArrayType::getN(nElem, nMat) )
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"sizes of properties do not match a symetric array with size ("<<
|
||||
numMaterial_<<"x"<<numMaterial_<<").\n";
|
||||
return false;
|
||||
}
|
||||
else if( numMaterial_ != nMat)
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"size mismatch for porperties. \n"<<
|
||||
"you supplied "<< numMaterial_<<" items in materials list and "<<
|
||||
nMat << " for other properties.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
realVector etha_n(nElem);
|
||||
realVector etha_t(nElem);
|
||||
forAll(i , kn)
|
||||
{
|
||||
etha_n[i] = -2.0*log(en[i])*sqrt(kn[i])/
|
||||
sqrt(pow(log(en[i]),2.0)+ pow(Pi,2.0));
|
||||
|
||||
etha_t[i] = -2.0*log( et[i]*sqrt(kt[i]) )/
|
||||
sqrt(pow(log(et[i]),2.0)+ pow(Pi,2.0));
|
||||
}
|
||||
|
||||
Vector<linearProperties> prop(nElem);
|
||||
forAll(i,kn)
|
||||
{
|
||||
prop[i] = {kn[i], kt[i], etha_n[i], etha_t[i], mu[i]};
|
||||
}
|
||||
|
||||
linearProperties_.assign(prop);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
static const char* modelName()
|
||||
{
|
||||
if constexpr (limited)
|
||||
{
|
||||
return "linearLimited";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "linearNonLimited";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
|
||||
TypeNameNV(modelName());
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
linear(){}
|
||||
|
||||
linear(int32 nMaterial, const ViewType1D<real>& rho, const dictionary& dict)
|
||||
:
|
||||
numMaterial_(nMaterial),
|
||||
rho_("rho",nMaterial),
|
||||
linearProperties_("linearProperties",nMaterial)
|
||||
{
|
||||
|
||||
Kokkos::deep_copy(rho_,rho);
|
||||
if(!readLinearDictionary(dict))
|
||||
{
|
||||
fatalExit;
|
||||
}
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
linear(const linear&) = default;
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
linear(linear&&) = default;
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
linear& operator=(const linear&) = default;
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
linear& operator=(linear&&) = default;
|
||||
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
~linear()=default;
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
int32 numMaterial()const
|
||||
{
|
||||
return numMaterial_;
|
||||
}
|
||||
|
||||
//// - Methods
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
void contactForce
|
||||
(
|
||||
const real dt,
|
||||
const int32 i,
|
||||
const int32 j,
|
||||
const int32 propId_i,
|
||||
const int32 propId_j,
|
||||
const real Ri,
|
||||
const real Rj,
|
||||
const real ovrlp_n,
|
||||
const realx3& Vr,
|
||||
const realx3& Nij,
|
||||
contactForceStorage& history,
|
||||
realx3& FCn,
|
||||
realx3& FCt
|
||||
)const
|
||||
{
|
||||
|
||||
auto prop = linearProperties_(propId_i,propId_j);
|
||||
|
||||
|
||||
real vrn = dot(Vr, Nij);
|
||||
realx3 Vt = Vr - vrn*Nij;
|
||||
|
||||
history.overlap_t_ += Vt*dt;
|
||||
|
||||
real mi = 3*Pi/4*pow(Ri,3.0)*rho_[propId_i];
|
||||
real mj = 3*Pi/4*pow(Rj,3.0)*rho_[propId_j];
|
||||
|
||||
real sqrt_meff = sqrt((mi*mj)/(mi+mj));
|
||||
|
||||
FCn = (-prop.kn_ * ovrlp_n - sqrt_meff * prop.ethan_ * vrn)*Nij;
|
||||
FCt = -prop.kt_ * history.overlap_t_ - sqrt_meff * prop.ethat_*Vt;
|
||||
|
||||
real ft = length(FCt);
|
||||
real ft_fric = prop.mu_ * length(FCn);
|
||||
|
||||
if(ft > ft_fric)
|
||||
{
|
||||
if( length(history.overlap_t_) >static_cast<real>(0.0))
|
||||
{
|
||||
if constexpr (limited)
|
||||
{
|
||||
FCt *= (ft_fric/ft);
|
||||
history.overlap_t_ = - (FCt/prop.kt_);
|
||||
}
|
||||
else
|
||||
{
|
||||
FCt = (FCt/ft)*ft_fric;
|
||||
}
|
||||
//cout<<"friction is applied here \n";
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
FCt = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} //pFlow::cfModels
|
||||
|
||||
#endif
|
300
src/Interaction/Models/contactForce/nonLinearCF.H
Normal file
300
src/Interaction/Models/contactForce/nonLinearCF.H
Normal file
@ -0,0 +1,300 @@
|
||||
/*------------------------------- 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 __nonLinearCF_H__
|
||||
#define __nonLinearCF_H__
|
||||
|
||||
#include "types.H"
|
||||
|
||||
namespace pFlow::cfModels
|
||||
{
|
||||
|
||||
template<bool limited=true>
|
||||
class nonLinear
|
||||
{
|
||||
public:
|
||||
|
||||
struct contactForceStorage
|
||||
{
|
||||
realx3 overlap_t_ = 0.0;
|
||||
};
|
||||
|
||||
struct nonLinearProperties
|
||||
{
|
||||
real Yeff_ = 1000000.0;
|
||||
real Geff_ = 8000000.0;
|
||||
real ethan_ = 0.0;
|
||||
real ethat_ = 0.0;
|
||||
real mu_ = 0.00001;
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
nonLinearProperties(){}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
nonLinearProperties(real Yeff, real Geff, real etha_n, real etha_t, real mu ):
|
||||
Yeff_(Yeff), Geff_(Geff), ethan_(etha_n),ethat_(etha_t), mu_(mu)
|
||||
{}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
nonLinearProperties(const nonLinearProperties&)=default;
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
nonLinearProperties& operator=(const nonLinearProperties&)=default;
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
~nonLinearProperties() = default;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
using NonLinearArrayType = symArray<nonLinearProperties>;
|
||||
|
||||
int32 numMaterial_ = 0;
|
||||
|
||||
ViewType1D<real> rho_;
|
||||
|
||||
NonLinearArrayType nonlinearProperties_;
|
||||
|
||||
bool readNonLinearDictionary(const dictionary& dict)
|
||||
{
|
||||
auto Yeff = dict.getVal<realVector>("Yeff");
|
||||
auto Geff = dict.getVal<realVector>("Geff");
|
||||
auto nu = dict.getVal<realVector>("nu");
|
||||
auto en = dict.getVal<realVector>("en");
|
||||
auto et = dict.getVal<realVector>("et");
|
||||
auto mu = dict.getVal<realVector>("mu");
|
||||
|
||||
auto nElem = Yeff.size();
|
||||
|
||||
if(nElem != nu.size())
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"sizes of Yeff("<<nElem<<") and nu("<<nu.size()<<") do not match.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(nElem != en.size())
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"sizes of Yeff("<<nElem<<") and en("<<en.size()<<") do not match.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(nElem != et.size())
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"sizes of Yeff("<<nElem<<") and et("<<et.size()<<") do not match.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(nElem != mu.size())
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"sizes of Yeff("<<nElem<<") and mu("<<mu.size()<<") do not match.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// check if size of vector matchs a symetric array
|
||||
uint32 nMat;
|
||||
if( !NonLinearArrayType::getN(nElem, nMat) )
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"sizes of properties do not match a symetric array with size ("<<
|
||||
numMaterial_<<"x"<<numMaterial_<<").\n";
|
||||
return false;
|
||||
}
|
||||
else if( numMaterial_ != nMat)
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"size mismatch for porperties. \n";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
realVector etha_n(nElem);
|
||||
realVector etha_t(nElem);
|
||||
forAll(i , en)
|
||||
{
|
||||
//K_hertz = 4.0/3.0*Yeff*sqrt(Reff);
|
||||
//-2.2664*log(en)*sqrt(meff*K_hertz)/sqrt( log(en)**2 + 10.1354);
|
||||
|
||||
// we take out sqrt(meff*K_hertz) here and then condier this term
|
||||
// when calculating damping part.
|
||||
etha_n[i] = -2.2664*log(en[i])/
|
||||
sqrt(pow(log(en[i]),2.0)+ pow(Pi,2.0));
|
||||
|
||||
// no damping for tangential part
|
||||
etha_t[i] = 0.0;
|
||||
|
||||
}
|
||||
|
||||
Vector<nonLinearProperties> prop(nElem);
|
||||
forAll(i,Yeff)
|
||||
{
|
||||
prop[i] = {Yeff[i], Geff[i], etha_n[i], etha_t[i], mu[i]};
|
||||
}
|
||||
|
||||
nonlinearProperties_.assign(prop);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
static const char* modelName()
|
||||
{
|
||||
if constexpr (limited)
|
||||
{
|
||||
return "nonLinearLimited";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "nonLinearNonLimited";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
TypeNameNV(modelName());
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
nonLinear(){}
|
||||
|
||||
nonLinear(
|
||||
int32 nMaterial,
|
||||
const ViewType1D<real>& rho,
|
||||
const dictionary& dict)
|
||||
:
|
||||
numMaterial_(nMaterial),
|
||||
rho_("rho",nMaterial),
|
||||
nonlinearProperties_("nonLinearProperties",nMaterial)
|
||||
{
|
||||
|
||||
Kokkos::deep_copy(rho_,rho);
|
||||
if(!readNonLinearDictionary(dict))
|
||||
{
|
||||
fatalExit;
|
||||
}
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
nonLinear(const nonLinear&) = default;
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
nonLinear(nonLinear&&) = default;
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
nonLinear& operator=(const nonLinear&) = default;
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
nonLinear& operator=(nonLinear&&) = default;
|
||||
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
~nonLinear()=default;
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
int32 numMaterial()const
|
||||
{
|
||||
return numMaterial_;
|
||||
}
|
||||
|
||||
//// - Methods
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
void contactForce
|
||||
(
|
||||
const real dt,
|
||||
const int32 i,
|
||||
const int32 j,
|
||||
const int32 propId_i,
|
||||
const int32 propId_j,
|
||||
const real Ri,
|
||||
const real Rj,
|
||||
const real ovrlp_n,
|
||||
const realx3& Vr,
|
||||
const realx3& Nij,
|
||||
contactForceStorage& history,
|
||||
realx3& FCn,
|
||||
realx3& FCt
|
||||
)const
|
||||
{
|
||||
|
||||
auto prop = nonlinearProperties_(propId_i,propId_j);
|
||||
|
||||
|
||||
real vrn = dot(Vr, Nij);
|
||||
realx3 Vt = Vr - vrn*Nij;
|
||||
|
||||
history.overlap_t_ += Vt*dt;
|
||||
|
||||
real mi = 3*Pi/4*pow(Ri,static_cast<real>(3))*rho_[propId_i];
|
||||
real mj = 3*Pi/4*pow(Rj,static_cast<real>(3))*rho_[propId_j];
|
||||
real Reff = 1.0/(1/Ri + 1/Rj);
|
||||
|
||||
real K_hertz = 4.0/3.0*prop.Yeff_*sqrt(Reff);
|
||||
real sqrt_meff_K_hertz = sqrt((mi*mj)/(mi+mj) * K_hertz);
|
||||
|
||||
|
||||
//FCn = (-prop.kn_ * ovrlp_n - sqrt_meff * prop.ethan_ * vrn)*Nij;
|
||||
//FCt = -prop.kt_ * history.overlap_t_ - sqrt_meff * prop.ethat_*Vt;
|
||||
|
||||
|
||||
|
||||
FCn = (static_cast<real>(-4.0/3.0) * prop.Yeff_ * sqrt(Reff)* pow(ovrlp_n,static_cast<real>(1.5)) -
|
||||
sqrt_meff_K_hertz*prop.ethan_*pow(ovrlp_n,static_cast<real>(0.25))*vrn)*Nij;
|
||||
|
||||
FCt = (- static_cast<real>(16.0/3.0) * prop.Geff_ * sqrt(Reff*ovrlp_n) ) * history.overlap_t_;
|
||||
|
||||
real ft = length(FCt);
|
||||
real ft_fric = prop.mu_ * length(FCn);
|
||||
|
||||
// apply friction
|
||||
if(ft > ft_fric)
|
||||
{
|
||||
if( length(history.overlap_t_) >0.0)
|
||||
{
|
||||
if constexpr (limited)
|
||||
{
|
||||
real kt = static_cast<real>(16.0/3.0) * prop.Geff_ * sqrt(Reff*ovrlp_n);
|
||||
FCt *= (ft_fric/ft);
|
||||
history.overlap_t_ = - (FCt/kt);
|
||||
}
|
||||
else
|
||||
{
|
||||
FCt = (FCt/ft)*ft_fric;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
FCt = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
} //pFlow::CFModels
|
||||
|
||||
#endif
|
44
src/Interaction/Models/contactForceModels.H
Normal file
44
src/Interaction/Models/contactForceModels.H
Normal file
@ -0,0 +1,44 @@
|
||||
/*------------------------------- 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 __contactForceModels_H__
|
||||
#define __contactForceModels_H__
|
||||
|
||||
|
||||
#include "linearCF.H"
|
||||
#include "nonLinearCF.H"
|
||||
#include "normalRolling.H"
|
||||
|
||||
|
||||
namespace pFlow::cfModels
|
||||
{
|
||||
|
||||
|
||||
using limitedLinearNormalRolling = normalRolling<linear<true>>;
|
||||
using nonLimitedLinearNormalRolling = normalRolling<linear<false>>;
|
||||
|
||||
using limitedNonLinearNormalRolling = normalRolling<nonLinear<true>>;
|
||||
using nonLimitedNonLinearNormalRolling = normalRolling<nonLinear<false>>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif //__contactForceModels_H__
|
117
src/Interaction/Models/rolling/normalRolling.H
Normal file
117
src/Interaction/Models/rolling/normalRolling.H
Normal file
@ -0,0 +1,117 @@
|
||||
/*------------------------------- 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 __normalRolling_H__
|
||||
#define __normalRolling_H__
|
||||
|
||||
|
||||
namespace pFlow::cfModels
|
||||
{
|
||||
|
||||
template<typename contactForceModel>
|
||||
class normalRolling
|
||||
:
|
||||
public contactForceModel
|
||||
{
|
||||
public:
|
||||
|
||||
using contactForceStorage =
|
||||
typename contactForceModel::contactForceStorage;
|
||||
|
||||
|
||||
realSymArray_D mur_;
|
||||
|
||||
bool readNormalDict(const dictionary& dict)
|
||||
{
|
||||
auto mur = dict.getVal<realVector>("mur");
|
||||
|
||||
uint32 nMat;
|
||||
|
||||
if(!realSymArray_D::getN(mur.size(),nMat) || nMat != this->numMaterial())
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"wrong number of values supplied in mur. \n";
|
||||
return false;
|
||||
}
|
||||
|
||||
mur_.assign(mur);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
TypeNameNV(word("normal<"+contactForceModel::TYPENAME()+">"));
|
||||
|
||||
|
||||
normalRolling(int32 nMaterial, const ViewType1D<real>& rho, const dictionary& dict)
|
||||
:
|
||||
contactForceModel(nMaterial, rho, dict),
|
||||
mur_("mur", nMaterial)
|
||||
{
|
||||
if(!readNormalDict(dict))
|
||||
{
|
||||
fatalExit;
|
||||
}
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
void rollingFriction
|
||||
(
|
||||
const real dt,
|
||||
const int32 i,
|
||||
const int32 j,
|
||||
const int32 propId_i,
|
||||
const int32 propId_j,
|
||||
const real Ri,
|
||||
const real Rj,
|
||||
const realx3& wi,
|
||||
const realx3& wj,
|
||||
const realx3& Nij,
|
||||
const realx3& FCn,
|
||||
realx3& Mri,
|
||||
realx3& Mrj
|
||||
)const
|
||||
{
|
||||
|
||||
realx3 w_hat = wi-wj;
|
||||
real w_hat_mag = length(w_hat);
|
||||
|
||||
if( !equal(w_hat_mag,0.0) )
|
||||
w_hat /= w_hat_mag;
|
||||
else
|
||||
w_hat = 0.0;
|
||||
|
||||
auto Reff = (Ri*Rj)/(Ri+Rj);
|
||||
|
||||
Mri = ( -mur_(propId_i,propId_j) *length(FCn) * Reff ) * w_hat ;
|
||||
|
||||
//removing the normal part
|
||||
// Mri = Mri - ( (Mri .dot. nij)*nij )
|
||||
|
||||
Mrj = -Mri;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
171
src/Interaction/contactLists/sortedContactList.H
Normal file
171
src/Interaction/contactLists/sortedContactList.H
Normal file
@ -0,0 +1,171 @@
|
||||
/*------------------------------- phasicFlow ---------------------------------
|
||||
O C enter of
|
||||
O O E ngineering and
|
||||
O O M ultiscale modeling of
|
||||
OOOOOOO F luid flow
|
||||
------------------------------------------------------------------------------
|
||||
Copyright (C): www.cemf.ir
|
||||
email: hamid.r.norouzi AT gmail.com
|
||||
------------------------------------------------------------------------------
|
||||
Licence:
|
||||
This file is part of phasicFlow code. It is a free software for simulating
|
||||
granular and multiphase flows. You can redistribute it and/or modify it under
|
||||
the terms of GNU General Public License v3 or any other later versions.
|
||||
|
||||
phasicFlow is distributed to help others in their research in the field of
|
||||
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __sortedContactList_H__
|
||||
#define __sortedContactList_H__
|
||||
|
||||
#include "sortedPairs.H"
|
||||
|
||||
namespace pFlow
|
||||
{
|
||||
|
||||
template<typename valueType, typename executionSpace, typename idType>
|
||||
class sortedContactList
|
||||
:
|
||||
public sortedPairs<executionSpace, idType>
|
||||
{
|
||||
public:
|
||||
|
||||
using SortedPairs = sortedPairs<executionSpace, idType>;
|
||||
|
||||
using ValueType = valueType;
|
||||
|
||||
using IdType = typename SortedPairs::IdType;
|
||||
|
||||
using ExecutionSpace = typename SortedPairs::ExecutionSpace;
|
||||
|
||||
using memory_space = typename SortedPairs::memory_space;
|
||||
|
||||
using PairType = typename SortedPairs::PairType;
|
||||
|
||||
using ContainerType = typename SortedPairs::ContainerType;
|
||||
|
||||
class TagReFillPairs{};
|
||||
|
||||
protected:
|
||||
|
||||
ViewType1D<ValueType,ExecutionSpace> values_;
|
||||
|
||||
int32 size0_ = 0;
|
||||
|
||||
ViewType1D<PairType,ExecutionSpace> sortedPairs0_;
|
||||
|
||||
ViewType1D<ValueType,ExecutionSpace> values0_;
|
||||
|
||||
|
||||
void adjustCapacity()
|
||||
{
|
||||
if(auto s = this->size(); s > values_.size())
|
||||
{
|
||||
reallocNoInit(values_, s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
using rpReFillPairs = Kokkos::RangePolicy<
|
||||
ExecutionSpace,
|
||||
Kokkos::Schedule<Kokkos::Static>,
|
||||
Kokkos::IndexType<int32>,
|
||||
TagReFillPairs>;
|
||||
|
||||
public:
|
||||
|
||||
TypeNameNV("sortedContactList");
|
||||
|
||||
|
||||
sortedContactList(int32 initialSize =1)
|
||||
:
|
||||
SortedPairs(initialSize),
|
||||
values_("values", SortedPairs::capacity()),
|
||||
sortedPairs0_("sortedPairs0", SortedPairs::capacity()),
|
||||
values0_("values0", SortedPairs::capacity())
|
||||
{}
|
||||
|
||||
bool beforeBroadSearch()
|
||||
{
|
||||
swapViews(values0_, values_);
|
||||
swapViews(sortedPairs0_, this->sortedPairs_);
|
||||
size0_ = this->size();
|
||||
return SortedPairs::beforeBroadSearch();
|
||||
}
|
||||
|
||||
bool afterBroadSearch()
|
||||
{
|
||||
SortedPairs::afterBroadSearch();
|
||||
|
||||
adjustCapacity();
|
||||
|
||||
Kokkos::parallel_for(
|
||||
"sortedContactList::reFillPairs",
|
||||
rpReFillPairs(0, this->size() ),
|
||||
*this
|
||||
);
|
||||
Kokkos::fence();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
ValueType getValue(int32 idx)const
|
||||
{
|
||||
return values_[idx];
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
void setValue(int32 idx, const ValueType& val)const
|
||||
{
|
||||
values_[idx] = val;
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
void operator()(TagReFillPairs, int32 idx)const
|
||||
{
|
||||
|
||||
auto searchLen = max(size0_/1000,10);
|
||||
auto start = max(0,idx-searchLen);
|
||||
auto end = min(size0_,idx+searchLen);
|
||||
auto newPair = this->sortedPairs_[idx];
|
||||
if( auto idx0 = binarySearch(
|
||||
sortedPairs0_,
|
||||
start,
|
||||
end,
|
||||
newPair);
|
||||
idx0>=0)
|
||||
{
|
||||
values_[idx] = values0_[idx0];
|
||||
}
|
||||
else if(auto idx0 = binarySearch(
|
||||
sortedPairs0_,
|
||||
start,
|
||||
end,
|
||||
newPair);
|
||||
idx0>=0)
|
||||
{
|
||||
values_[idx] = values0_[idx0];
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
values_[idx] = ValueType();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}; // sortedContactList
|
||||
|
||||
|
||||
|
||||
} // pFlow
|
||||
|
||||
|
||||
|
||||
#endif //__sortedContactList_H__
|
258
src/Interaction/contactLists/sortedPairs.H
Normal file
258
src/Interaction/contactLists/sortedPairs.H
Normal file
@ -0,0 +1,258 @@
|
||||
/*------------------------------- 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 __sortedPairs_H__
|
||||
#define __sortedPairs_H__
|
||||
|
||||
#include "unsortedPairs.H"
|
||||
#include "KokkosUtilities.H"
|
||||
|
||||
namespace pFlow
|
||||
{
|
||||
|
||||
|
||||
template<typename executionSpace, typename idType>
|
||||
class sortedPairs
|
||||
:
|
||||
public unsortedPairs<executionSpace, idType>
|
||||
{
|
||||
public:
|
||||
|
||||
using UnsortedPairs = unsortedPairs<executionSpace,idType>;
|
||||
|
||||
using IdType = typename UnsortedPairs::IdType;
|
||||
|
||||
using ExecutionSpace = typename UnsortedPairs::ExecutionSpace;
|
||||
|
||||
using memory_space = typename ExecutionSpace::memory_space;
|
||||
|
||||
using PairType = typename UnsortedPairs::PairType;
|
||||
|
||||
using ContainerType = typename UnsortedPairs::ContainerType;
|
||||
|
||||
struct pairAccessor
|
||||
{
|
||||
using PairType = typename sortedPairs::PairType;
|
||||
|
||||
int32 size_;
|
||||
|
||||
ViewType1D<PairType,ExecutionSpace> sortedParis_;
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
int32 size()const { return size_; }
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
int32 loopCount()const { return size_; }
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
bool isValid(int32 i)const { return i<size_; }
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
PairType getPair(int i)const { return sortedParis_[i]; }
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
bool getPair(int32 i, PairType& pair)const {
|
||||
if(i<size_) {
|
||||
pair = sortedParis_[i];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class TagFillFlag{};
|
||||
|
||||
class TagFillPairs{};
|
||||
|
||||
protected:
|
||||
|
||||
/// size of pair list
|
||||
int32 size_ = 0;
|
||||
|
||||
ViewType1D<int32,ExecutionSpace> flags_;
|
||||
|
||||
ViewType1D<PairType,ExecutionSpace> sortedPairs_;
|
||||
|
||||
using rpFillFlag = Kokkos::RangePolicy<
|
||||
ExecutionSpace,
|
||||
Kokkos::Schedule<Kokkos::Static>,
|
||||
Kokkos::IndexType<int32>,
|
||||
TagFillFlag >;
|
||||
|
||||
using rpFillPairs = Kokkos::RangePolicy<
|
||||
ExecutionSpace,
|
||||
Kokkos::Schedule<Kokkos::Static>,
|
||||
Kokkos::IndexType<int32>,
|
||||
TagFillPairs>;
|
||||
|
||||
public:
|
||||
|
||||
// - type info
|
||||
TypeNameNV("sortedPairs");
|
||||
|
||||
|
||||
// constructors
|
||||
sortedPairs(int32 initialSize =1)
|
||||
:
|
||||
UnsortedPairs(initialSize),
|
||||
flags_("flags_",UnsortedPairs::capacity()+1),
|
||||
sortedPairs_("sortedPairs_",UnsortedPairs::capacity())
|
||||
{}
|
||||
|
||||
|
||||
bool beforeBroadSearch()
|
||||
{
|
||||
this->clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool afterBroadSearch()
|
||||
{
|
||||
prepareSorted();
|
||||
return true;
|
||||
}
|
||||
|
||||
// - Device call
|
||||
// return the pair at index idx
|
||||
// perform no check for size and existance
|
||||
INLINE_FUNCTION_HD
|
||||
PairType getPair(int32 idx)const
|
||||
{
|
||||
return sortedPairs_[idx];
|
||||
}
|
||||
|
||||
// - Device/host call
|
||||
// return the pair at index idx
|
||||
INLINE_FUNCTION_HD
|
||||
bool getPair(int32 idx, PairType& p)const
|
||||
{
|
||||
if(isValid(idx))
|
||||
{
|
||||
p = getPair(idx);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
bool isValid(int32 idx)const
|
||||
{
|
||||
return idx < size_;
|
||||
}
|
||||
|
||||
|
||||
//use this when the value of size_ is updated
|
||||
INLINE_FUNCTION_H
|
||||
int32 size()const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
int32 loopCount()const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
pairAccessor getPairs()const
|
||||
{
|
||||
return {size_, sortedPairs_};
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_H
|
||||
void clear()
|
||||
{
|
||||
UnsortedPairs::clear();
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
void prepareSorted()
|
||||
{
|
||||
// first check the size of flags_
|
||||
int32 capacity = UnsortedPairs::capacity();
|
||||
|
||||
if( capacity+1 > flags_.size() )
|
||||
{
|
||||
reallocNoInit(flags_, capacity+1);
|
||||
}
|
||||
|
||||
// fill the flags
|
||||
Kokkos::parallel_for(
|
||||
"contactPairsSorted::fillFlag",
|
||||
rpFillFlag(0,capacity+1),
|
||||
*this);
|
||||
Kokkos::fence();
|
||||
|
||||
|
||||
// inclusive scan on flags_
|
||||
exclusiveScan(flags_, 0, capacity+1,flags_,0);
|
||||
|
||||
Kokkos::fence(); // Kokkos's scan is blocking I guess. So, this could be removed.
|
||||
|
||||
// get the last value of flags_ to obtain the size of sortedPairs_
|
||||
getNth(size_, flags_, capacity);
|
||||
|
||||
if(size_ == 0 )return;
|
||||
|
||||
// resize sortedPairs_ if necessary;
|
||||
if( size_>sortedPairs_.size() )
|
||||
{
|
||||
// get more space to prevent reallocations in next iterations
|
||||
int32 len = size_*1.1+1;
|
||||
reallocNoInit(sortedPairs_, len);
|
||||
}
|
||||
|
||||
Kokkos::parallel_for(
|
||||
"contactPairsSorted::fillPairs",
|
||||
rpFillPairs(0,this->capacity()),
|
||||
*this);
|
||||
Kokkos::fence();
|
||||
|
||||
// - sort paris based on the first and second
|
||||
sort(sortedPairs_, 0, size_ );
|
||||
|
||||
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
void operator()(TagFillFlag, int32 i)const
|
||||
{
|
||||
if(this->container_.valid_at(i) )
|
||||
flags_[i] = 1;
|
||||
else
|
||||
flags_[i] = 0;
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
void operator()(TagFillPairs, int32 i)const
|
||||
{
|
||||
auto fi = flags_[i];
|
||||
if(fi!=flags_[i+1])
|
||||
sortedPairs_[fi] = this->container_.key_at(i);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //__sortedPairs_H__
|
175
src/Interaction/contactLists/unsortedContactList.H
Normal file
175
src/Interaction/contactLists/unsortedContactList.H
Normal file
@ -0,0 +1,175 @@
|
||||
/*------------------------------- 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 __unsortedContactList_H__
|
||||
#define __unsortedContactList_H__
|
||||
|
||||
namespace pFlow
|
||||
{
|
||||
|
||||
|
||||
template<typename valueType, typename executionSpace, typename idType>
|
||||
class unsortedContactList
|
||||
:
|
||||
public unsortedPairs<executionSpace, idType>
|
||||
{
|
||||
public:
|
||||
|
||||
using ValueType = valueType;
|
||||
|
||||
using UnsortedPairs = unsortedPairs<executionSpace, idType>;
|
||||
|
||||
using IdType = typename UnsortedPairs::IdType;
|
||||
|
||||
using ExecutionSpace = typename UnsortedPairs::ExecutionSpace;
|
||||
|
||||
using memory_space = typename ExecutionSpace::memory_space;
|
||||
|
||||
using PairType = typename UnsortedPairs::PairType;
|
||||
|
||||
using ContainerType = typename UnsortedPairs::ContainerType;
|
||||
|
||||
class TagReFillPairs{};
|
||||
|
||||
protected:
|
||||
|
||||
/// storage for keeping the values of the current list
|
||||
ViewType1D<ValueType,ExecutionSpace> values_;
|
||||
|
||||
/// storage for keeping pairs from the previous list
|
||||
ContainerType container0_;
|
||||
|
||||
/// storage for keeping values from the previous list
|
||||
ViewType1D<ValueType,ExecutionSpace> values0_;
|
||||
|
||||
void adjustCapacity()
|
||||
{
|
||||
auto cap = this->capacity();
|
||||
if(cap > values_.size())
|
||||
{
|
||||
reallocNoInit(values_, cap);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
using rpFillPairs = Kokkos::RangePolicy<
|
||||
ExecutionSpace,
|
||||
Kokkos::Schedule<Kokkos::Static>,
|
||||
Kokkos::IndexType<int32>,
|
||||
TagReFillPairs>;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
TypeNameNV("unsortedContactList");
|
||||
|
||||
unsortedContactList(int32 capacity=1)
|
||||
:
|
||||
UnsortedPairs(capacity),
|
||||
values_("values", UnsortedPairs::capacity()),
|
||||
container0_(capacity),
|
||||
values0_("values0",container0_.capacity())
|
||||
{}
|
||||
|
||||
|
||||
bool beforeBroadSearch()
|
||||
{
|
||||
// swap conainer and values
|
||||
swapViews(values0_, values_);
|
||||
swapViews(container0_, this->container_);
|
||||
return UnsortedPairs::beforeBroadSearch();
|
||||
}
|
||||
|
||||
bool afterBroadSearch()
|
||||
{
|
||||
|
||||
UnsortedPairs::afterBroadSearch();
|
||||
|
||||
adjustCapacity();
|
||||
|
||||
Kokkos::parallel_for(
|
||||
"reFillPairs",
|
||||
rpFillPairs(0,this->capacity()),
|
||||
*this);
|
||||
Kokkos::fence();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
ValueType getValue(int32 idx)const
|
||||
{
|
||||
return values_[idx];
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
bool getValue(const PairType& p, ValueType& val)const
|
||||
{
|
||||
if(auto idx = this->find(p); idx>=0)
|
||||
{
|
||||
val = getValue(idx);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
void setValue(int32 idx, const ValueType& val)const
|
||||
{
|
||||
values_[idx] = val;
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
bool setValue(const PairType& p, const ValueType& val)const
|
||||
{
|
||||
if(auto idx = this->find(p); idx>=0)
|
||||
{
|
||||
setValue(idx, val);
|
||||
return true;;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
void operator()(TagReFillPairs, int32 idx)const
|
||||
{
|
||||
if( this->isValid(idx) )
|
||||
{
|
||||
if( int32 idx0 =
|
||||
container0_.find(this->getPair(idx));
|
||||
idx0>=0 )
|
||||
{
|
||||
values_[idx] = values0_[idx0];
|
||||
}
|
||||
else
|
||||
{
|
||||
values_[idx] = ValueType();
|
||||
}
|
||||
}
|
||||
// invalid locations should not be filled.
|
||||
}
|
||||
|
||||
}; //unsortedContactList
|
||||
|
||||
|
||||
} // pFlow
|
||||
|
||||
|
||||
#endif //__unsortedContactList_H__
|
216
src/Interaction/contactLists/unsortedPairs.H
Normal file
216
src/Interaction/contactLists/unsortedPairs.H
Normal file
@ -0,0 +1,216 @@
|
||||
/*------------------------------- 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 __unsortedPairs_H__
|
||||
#define __unsortedPairs_H__
|
||||
|
||||
#include "KokkosTypes.H"
|
||||
#include "types.H"
|
||||
|
||||
namespace pFlow
|
||||
{
|
||||
|
||||
|
||||
template<typename executionSpace, typename idType>
|
||||
class unsortedPairs
|
||||
{
|
||||
public:
|
||||
|
||||
using UnsortedPairs = unsortedPairs<executionSpace,idType>;
|
||||
|
||||
using IdType = idType;
|
||||
|
||||
using ExecutionSpace = executionSpace;
|
||||
|
||||
using memory_space = typename ExecutionSpace::memory_space;
|
||||
|
||||
using PairType = kPair<idType,idType>;
|
||||
|
||||
using ContainerType = unorderedSet<PairType, ExecutionSpace>;
|
||||
|
||||
struct pairAccessor
|
||||
{
|
||||
using PairType = typename UnsortedPairs::PairType;
|
||||
|
||||
ContainerType Container_;
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
int32 size()const { return Container_.size(); }
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
int32 loopCount()const { return Container_.capacity(); }
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
bool isValid(int32 idx)const { return Container_.valid_at(idx); }
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
PairType getPair(int idx)const { return Container_.key_at(idx); }
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
bool getPair(int32 idx, PairType& pair)const {
|
||||
if(Container_.valid_at(idx)) {
|
||||
pair = Container_.key_at(idx);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
ContainerType container_;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// - type info
|
||||
TypeNameNV("unsorderedPairs");
|
||||
|
||||
// constructor
|
||||
unsortedPairs(int32 capacity=1)
|
||||
:
|
||||
container_(capacity) // the minimum capacity would be 128
|
||||
{}
|
||||
|
||||
bool beforeBroadSearch()
|
||||
{
|
||||
container_.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool afterBroadSearch()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// - Device call
|
||||
INLINE_FUNCTION_HD
|
||||
int32 insert(idType i, idType j)const
|
||||
{
|
||||
if(auto insertResult = container_.insert(PairType(i,j)); insertResult.failed())
|
||||
return -1;
|
||||
else
|
||||
return insertResult.index();
|
||||
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
int32 insert(const PairType& p)const
|
||||
{
|
||||
if(auto insertResult = container_.insert(p); insertResult.failed())
|
||||
return -1;
|
||||
else
|
||||
return insertResult.index();
|
||||
|
||||
}
|
||||
|
||||
// - Device call
|
||||
// return the pair at index idx
|
||||
// perform no check for size and existance
|
||||
INLINE_FUNCTION_HD
|
||||
PairType getPair(int32 idx)const
|
||||
{
|
||||
return container_.key_at(idx);
|
||||
}
|
||||
|
||||
// - Device call
|
||||
// return the pair at index idx
|
||||
INLINE_FUNCTION_HD
|
||||
bool getPair(int32 idx, PairType& p)const
|
||||
{
|
||||
if(container_.valid_at(idx))
|
||||
{
|
||||
p = container_.key_at(idx);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
int32 find(const PairType & p)const
|
||||
{
|
||||
if( auto idx = container_.find(p);
|
||||
idx != Kokkos::UnorderedMapInvalidIndex )
|
||||
return idx;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
bool isValid(int32 idx)const
|
||||
{
|
||||
return container_.valid_at(idx);
|
||||
}
|
||||
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
int32 capacity() const
|
||||
{
|
||||
return container_.capacity();
|
||||
}
|
||||
|
||||
int32 loopCount()const
|
||||
{
|
||||
return container_.capacity();
|
||||
}
|
||||
|
||||
//use this when the value of size_ is updated
|
||||
INLINE_FUNCTION_H
|
||||
int32 size()const
|
||||
{
|
||||
return container_.size();
|
||||
}
|
||||
|
||||
pairAccessor getPairs()const
|
||||
{
|
||||
return {container_};
|
||||
}
|
||||
|
||||
/// increase the capacity of the container by at-least len
|
||||
/// the content will be erased.
|
||||
INLINE_FUNCTION_H
|
||||
void increaseCapacityBy(int32 len)
|
||||
{
|
||||
uint newCap = container_.capacity()+len;
|
||||
this->clear();
|
||||
container_.rehash(newCap);
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_H
|
||||
void clear()
|
||||
{
|
||||
container_.clear();
|
||||
}
|
||||
|
||||
const ContainerType& container()const
|
||||
{
|
||||
return container_;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif //__unsortedPairs_H__
|
250
src/Interaction/contactSearch/ContactSearch/ContactSearch.H
Normal file
250
src/Interaction/contactSearch/ContactSearch/ContactSearch.H
Normal file
@ -0,0 +1,250 @@
|
||||
/*------------------------------- phasicFlow ---------------------------------
|
||||
O C enter of
|
||||
O O E ngineering and
|
||||
O O M ultiscale modeling of
|
||||
OOOOOOO F luid flow
|
||||
------------------------------------------------------------------------------
|
||||
Copyright (C): www.cemf.ir
|
||||
email: hamid.r.norouzi AT gmail.com
|
||||
------------------------------------------------------------------------------
|
||||
Licence:
|
||||
This file is part of phasicFlow code. It is a free software for simulating
|
||||
granular and multiphase flows. You can redistribute it and/or modify it under
|
||||
the terms of GNU General Public License v3 or any other later versions.
|
||||
|
||||
phasicFlow is distributed to help others in their research in the field of
|
||||
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef __ContactSearch_H__
|
||||
#define __ContactSearch_H__
|
||||
|
||||
|
||||
#include "contactSearch.H"
|
||||
#include "box.H"
|
||||
|
||||
namespace pFlow
|
||||
{
|
||||
|
||||
template<
|
||||
template<class, class, class> class BaseMethod,
|
||||
template<class, class, class> class WallMapping
|
||||
>
|
||||
class ContactSearch
|
||||
:
|
||||
public contactSearch
|
||||
{
|
||||
public:
|
||||
|
||||
using IdType = typename contactSearch::IdType;
|
||||
|
||||
using IndexType = typename contactSearch::IndexType;
|
||||
|
||||
using ExecutionSpace = typename contactSearch::ExecutionSpace;
|
||||
|
||||
using PairContainerType = typename contactSearch::PairContainerType;
|
||||
|
||||
using ParticleContactSearchType =
|
||||
BaseMethod<
|
||||
ExecutionSpace,
|
||||
IdType,
|
||||
IndexType
|
||||
>;
|
||||
|
||||
using WallMappingType =
|
||||
WallMapping<
|
||||
ExecutionSpace,
|
||||
IdType,
|
||||
IndexType
|
||||
>;
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
uniquePtr<ParticleContactSearchType> particleContactSearch_ = nullptr;
|
||||
|
||||
uniquePtr<WallMappingType> wallMapping_ = nullptr;
|
||||
|
||||
public:
|
||||
|
||||
TypeNameTemplate2("ContactSearch", ParticleContactSearchType, WallMappingType);
|
||||
|
||||
ContactSearch(
|
||||
const dictionary& csDict,
|
||||
const box& domain,
|
||||
const particles& prtcl,
|
||||
const geometry& geom,
|
||||
Timers& timers)
|
||||
:
|
||||
contactSearch(csDict, domain, prtcl, geom, timers)
|
||||
|
||||
{
|
||||
|
||||
auto method = dict().getVal<word>("method");
|
||||
auto wmMethod = dict().getVal<word>("wallMapping");
|
||||
|
||||
auto nbDict = dict().subDictOrCreate(method+"Info");
|
||||
|
||||
real minD, maxD;
|
||||
this->Particles().boundingSphereMinMax(minD, maxD);
|
||||
|
||||
const auto& position = this->Particles().pointPosition().deviceVectorAll();
|
||||
const auto& diam = this->Particles().boundingSphere().deviceVectorAll();
|
||||
|
||||
particleContactSearch_ =
|
||||
makeUnique<ParticleContactSearchType>
|
||||
(
|
||||
nbDict,
|
||||
this->domain(),
|
||||
maxD,
|
||||
position,
|
||||
diam
|
||||
);
|
||||
Report(2)<<"Contact search algorithm for particle-particle is "<<
|
||||
greenText(particleContactSearch_().typeName())<<endReport;
|
||||
|
||||
|
||||
auto wmDict = dict().subDictOrCreate(wmMethod+"Info");
|
||||
|
||||
int32 wnPoints = this->Geometry().numPoints();
|
||||
int32 wnTri = this->Geometry().size();
|
||||
|
||||
const auto& wPoints = this->Geometry().points().deviceVectorAll();
|
||||
const auto& wVertices = this->Geometry().vertices().deviceVectorAll();
|
||||
|
||||
wallMapping_ =
|
||||
makeUnique<WallMappingType>(
|
||||
wmDict,
|
||||
particleContactSearch_().getCells(),
|
||||
wnPoints,
|
||||
wnTri,
|
||||
wPoints,
|
||||
wVertices
|
||||
);
|
||||
Report(2)<<"Wall mapping algorithm for particle-wall is "<<
|
||||
greenText(wallMapping_().typeName())<< endReport;
|
||||
|
||||
}
|
||||
|
||||
|
||||
add_vCtor(
|
||||
contactSearch,
|
||||
ContactSearch,
|
||||
dictionary);
|
||||
|
||||
bool broadSearch(
|
||||
PairContainerType& ppPairs,
|
||||
PairContainerType& pwPairs,
|
||||
bool force = false) override
|
||||
{
|
||||
|
||||
//output<<" ContactSearch::broadSearch::PP before.\n";
|
||||
if(particleContactSearch_)
|
||||
{
|
||||
auto activeRange = this->Particles().activeRange();
|
||||
|
||||
sphereSphereTimer_.start();
|
||||
|
||||
if(this->Particles().allActive())
|
||||
{
|
||||
particleContactSearch_().broadSearch(ppPairs, activeRange, force);
|
||||
}
|
||||
else
|
||||
{
|
||||
particleContactSearch_().broadSearch(ppPairs, activeRange, this->Particles().activePointsMaskD(), force);
|
||||
}
|
||||
|
||||
sphereSphereTimer_.end();
|
||||
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
if(wallMapping_)
|
||||
{
|
||||
sphereWallTimer_.start();
|
||||
wallMapping_().broadSearch(pwPairs, particleContactSearch_(), force);
|
||||
sphereWallTimer_.end();
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ppEnterBroadSearch()const override
|
||||
{
|
||||
if(particleContactSearch_)
|
||||
{
|
||||
return particleContactSearch_().enterBoadSearch();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool pwEnterBroadSearch()const override
|
||||
{
|
||||
if(wallMapping_)
|
||||
{
|
||||
return wallMapping_().enterBoadSearch();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool ppPerformedBroadSearch()const override
|
||||
{
|
||||
if(particleContactSearch_)
|
||||
{
|
||||
return particleContactSearch_().performedSearch();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool pwPerformedBroadSearch()const override
|
||||
{
|
||||
if(wallMapping_)
|
||||
{
|
||||
return wallMapping_().performedSearch();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*bool update(const eventMessage& msg)
|
||||
{
|
||||
if(msg.isSizeChanged() )
|
||||
{
|
||||
auto newSize = this->prtcl().size();
|
||||
if(!particleContactSearch_().objectSizeChanged(newSize))
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"erro in changing the size for particleContactSearch_ \n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(msg.isCapacityChanged() )
|
||||
{
|
||||
auto newSize = this->prtcl().capacity();
|
||||
if(!particleContactSearch_().objectSizeChanged(newSize))
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"erro in changing the capacity for particleContactSearch_ \n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}*/
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif //__ContactSearch_H__
|
26
src/Interaction/contactSearch/ContactSearch/ContactSearchs.C
Normal file
26
src/Interaction/contactSearch/ContactSearch/ContactSearchs.C
Normal file
@ -0,0 +1,26 @@
|
||||
/*------------------------------- 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 "ContactSearch.H"
|
||||
|
||||
#include "cellsSimple.H"
|
||||
#include "NBS.H"
|
||||
|
||||
template class pFlow::ContactSearch<pFlow::NBS, pFlow::cellsSimple>;
|
233
src/Interaction/contactSearch/cells.H
Normal file
233
src/Interaction/contactSearch/cells.H
Normal file
@ -0,0 +1,233 @@
|
||||
/*------------------------------- 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 __cells_H__
|
||||
#define __cells_H__
|
||||
|
||||
|
||||
#include "types.H"
|
||||
#include "box.H"
|
||||
|
||||
namespace pFlow
|
||||
{
|
||||
|
||||
template<typename indexType>
|
||||
class cells
|
||||
{
|
||||
public:
|
||||
|
||||
using CellType = triple<indexType>;
|
||||
|
||||
protected:
|
||||
|
||||
// - domain
|
||||
box domain_;
|
||||
|
||||
// - cell size
|
||||
real cellSize_;
|
||||
|
||||
CellType numCells_;
|
||||
|
||||
|
||||
// - protected methods
|
||||
INLINE_FUNCTION_H
|
||||
void calculate()
|
||||
{
|
||||
numCells_ = (domain_.maxPoint()-domain_.minPoint())/cellSize_ + realx3(1.0);
|
||||
numCells_ = max( numCells_ , CellType(static_cast<indexType>(1)) );
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
cells()
|
||||
{}
|
||||
|
||||
INLINE_FUNCTION_H
|
||||
cells(const box& domain, real cellSize)
|
||||
:
|
||||
domain_(domain),
|
||||
cellSize_(cellSize)
|
||||
{
|
||||
calculate();
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
cells(const cells&) = default;
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
cells& operator = (const cells&) = default;
|
||||
|
||||
cells getCells()const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_H
|
||||
void setCellSize(real cellSize)
|
||||
{
|
||||
cellSize_ = cellSize;
|
||||
calculate();
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
real cellSize()const
|
||||
{
|
||||
return cellSize_;
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
const CellType& numCells()const
|
||||
{
|
||||
return numCells_;
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
indexType nx()const
|
||||
{
|
||||
return numCells_.x();
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
indexType ny()const
|
||||
{
|
||||
return numCells_.y();
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
indexType nz()const
|
||||
{
|
||||
return numCells_.z();
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
int64 totalCells()const
|
||||
{
|
||||
return static_cast<int64>(numCells_.x())*
|
||||
static_cast<int64>(numCells_.y())*
|
||||
static_cast<int64>(numCells_.z());
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
CellType pointIndex(const realx3& p)const
|
||||
{
|
||||
return CellType( (p - domain_.minPoint())/cellSize_ );
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
bool pointIndexInDomain(const realx3 p, CellType& index)const
|
||||
{
|
||||
if( !domain_.isInside(p) ) return false;
|
||||
|
||||
index = this->pointIndex(p);
|
||||
return true;
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
bool inDomain(const realx3& p)const
|
||||
{
|
||||
return domain_.isInside(p);
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
bool isInRange(const CellType& cell)const
|
||||
{
|
||||
if(cell.x()<0)return false;
|
||||
if(cell.y()<0)return false;
|
||||
if(cell.z()<0)return false;
|
||||
if(cell.x()>numCells_.x()-1) return false;
|
||||
if(cell.y()>numCells_.y()-1) return false;
|
||||
if(cell.z()>numCells_.z()-1) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
bool isInRange(indexType i, indexType j, indexType k)const
|
||||
{
|
||||
if(i<0)return false;
|
||||
if(j<0)return false;
|
||||
if(k<0)return false;
|
||||
if(i>numCells_.x()-1) return false;
|
||||
if(j>numCells_.y()-1) return false;
|
||||
if(k>numCells_.z()-1) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
void extendBox(
|
||||
const CellType& p1,
|
||||
const CellType& p2,
|
||||
const CellType& p3,
|
||||
indexType extent,
|
||||
CellType& minP,
|
||||
CellType& maxP)const
|
||||
{
|
||||
minP = min( min( p1, p2), p3)-extent;
|
||||
maxP = max( max( p1, p2), p3)+extent;
|
||||
|
||||
minP = bound(minP);
|
||||
maxP = bound(maxP);
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
void extendBox(
|
||||
const realx3& p1,
|
||||
const realx3& p2,
|
||||
const realx3& p3,
|
||||
real extent,
|
||||
realx3& minP,
|
||||
realx3& maxP)const
|
||||
{
|
||||
minP = min(min(p1,p2),p3) - extent*cellSize_ ;
|
||||
maxP = max(max(p1,p2),p3) + extent*cellSize_ ;
|
||||
|
||||
minP = bound(minP);
|
||||
maxP = bound(maxP);
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
CellType bound(CellType p)const
|
||||
{
|
||||
return CellType(
|
||||
min( numCells_.x()-1, max(0,p.x())),
|
||||
min( numCells_.y()-1, max(0,p.y())),
|
||||
min( numCells_.z()-1, max(0,p.z()))
|
||||
);
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
realx3 bound(realx3 p)const
|
||||
{
|
||||
return realx3(
|
||||
min( domain_.maxPoint().x(), max(domain_.minPoint().x(),p.x())),
|
||||
min( domain_.maxPoint().y(), max(domain_.minPoint().y(),p.y())),
|
||||
min( domain_.maxPoint().z(), max(domain_.minPoint().z(),p.z()))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
78
src/Interaction/contactSearch/contactSearch/contactSearch.C
Normal file
78
src/Interaction/contactSearch/contactSearch/contactSearch.C
Normal file
@ -0,0 +1,78 @@
|
||||
/*------------------------------- 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 "contactSearch.H"
|
||||
|
||||
|
||||
|
||||
pFlow::contactSearch::contactSearch(
|
||||
const dictionary& dict,
|
||||
const box& domain,
|
||||
const particles& prtcl,
|
||||
const geometry& geom,
|
||||
Timers& timers)
|
||||
:
|
||||
interactionBase(prtcl, geom),
|
||||
domain_(domain),
|
||||
dict_(dict),
|
||||
sphereSphereTimer_("particle-particle contact search", &timers),
|
||||
sphereWallTimer_("particle-wall contact search", &timers)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
pFlow::uniquePtr<pFlow::contactSearch> pFlow::contactSearch::create(
|
||||
const dictionary& dict,
|
||||
const box& domain,
|
||||
const particles& prtcl,
|
||||
const geometry& geom,
|
||||
Timers& timers)
|
||||
{
|
||||
|
||||
word baseMethName = dict.getVal<word>("method");
|
||||
word wallMethod = dict.getVal<word>("wallMapping");
|
||||
|
||||
auto model = angleBracketsNames2("ContactSearch", baseMethName, wallMethod);
|
||||
|
||||
|
||||
Report(1)<<"Selecting contact search model . . ."<<endReport;
|
||||
|
||||
|
||||
if( dictionaryvCtorSelector_.search(model))
|
||||
{
|
||||
auto objPtr = dictionaryvCtorSelector_[model] (dict, domain, prtcl, geom, timers);
|
||||
Report(2)<<"Model "<< greenText(model)<<" is created."<<endReport;
|
||||
return objPtr;
|
||||
}
|
||||
else
|
||||
{
|
||||
printKeys
|
||||
(
|
||||
fatalError << "Ctor Selector "<< model << " dose not exist. \n"
|
||||
<<"Avaiable ones are: \n\n"
|
||||
,
|
||||
dictionaryvCtorSelector_
|
||||
);
|
||||
fatalExit;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
135
src/Interaction/contactSearch/contactSearch/contactSearch.H
Normal file
135
src/Interaction/contactSearch/contactSearch/contactSearch.H
Normal file
@ -0,0 +1,135 @@
|
||||
/*------------------------------- phasicFlow ---------------------------------
|
||||
O C enter of
|
||||
O O E ngineering and
|
||||
O O M ultiscale modeling of
|
||||
OOOOOOO F luid flow
|
||||
------------------------------------------------------------------------------
|
||||
Copyright (C): www.cemf.ir
|
||||
email: hamid.r.norouzi AT gmail.com
|
||||
------------------------------------------------------------------------------
|
||||
Licence:
|
||||
This file is part of phasicFlow code. It is a free software for simulating
|
||||
granular and multiphase flows. You can redistribute it and/or modify it under
|
||||
the terms of GNU General Public License v3 or any other later versions.
|
||||
|
||||
phasicFlow is distributed to help others in their research in the field of
|
||||
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef __contactSearch_H__
|
||||
#define __contactSearch_H__
|
||||
|
||||
|
||||
#include "interactionBase.H"
|
||||
#include "unsortedPairs.H"
|
||||
#include "box.H"
|
||||
#include "dictionary.H"
|
||||
|
||||
namespace pFlow
|
||||
{
|
||||
|
||||
|
||||
class contactSearch
|
||||
:
|
||||
public interactionBase
|
||||
{
|
||||
public:
|
||||
using IdType = typename interactionBase::IdType;
|
||||
|
||||
using IndexType = typename interactionBase::IndexType;
|
||||
|
||||
using ExecutionSpace = typename interactionBase::ExecutionSpace;
|
||||
|
||||
using PairContainerType = unsortedPairs<ExecutionSpace, IdType>;
|
||||
|
||||
protected:
|
||||
|
||||
const box& domain_;
|
||||
|
||||
dictionary dict_;
|
||||
|
||||
Timer sphereSphereTimer_;
|
||||
|
||||
Timer sphereWallTimer_;
|
||||
|
||||
auto& dict()
|
||||
{
|
||||
return dict_;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
TypeName("contactSearch");
|
||||
|
||||
contactSearch(
|
||||
const dictionary& dict,
|
||||
const box& domain,
|
||||
const particles& prtcl,
|
||||
const geometry& geom,
|
||||
Timers& timers);
|
||||
|
||||
virtual ~contactSearch()=default;
|
||||
|
||||
|
||||
create_vCtor
|
||||
(
|
||||
contactSearch,
|
||||
dictionary,
|
||||
(
|
||||
const dictionary& dict,
|
||||
const box& domain,
|
||||
const particles& prtcl,
|
||||
const geometry& geom,
|
||||
Timers& timers
|
||||
),
|
||||
(dict, domain, prtcl, geom, timers)
|
||||
);
|
||||
|
||||
const auto& domain()const
|
||||
{
|
||||
return domain_;
|
||||
}
|
||||
|
||||
const auto& dict()const
|
||||
{
|
||||
return dict_;
|
||||
}
|
||||
|
||||
|
||||
virtual
|
||||
bool broadSearch(
|
||||
PairContainerType& ppPairs,
|
||||
PairContainerType& pwPairs,
|
||||
bool force = false) = 0;
|
||||
|
||||
virtual
|
||||
bool ppEnterBroadSearch()const = 0;
|
||||
|
||||
virtual
|
||||
bool pwEnterBroadSearch()const = 0;
|
||||
|
||||
virtual
|
||||
bool ppPerformedBroadSearch()const = 0;
|
||||
|
||||
virtual
|
||||
bool pwPerformedBroadSearch()const = 0;
|
||||
|
||||
|
||||
static
|
||||
uniquePtr<contactSearch> create(
|
||||
const dictionary& dict,
|
||||
const box& domain,
|
||||
const particles& prtcl,
|
||||
const geometry& geom,
|
||||
Timers& timers);
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif //__ContactSearch_H__
|
112
src/Interaction/contactSearch/contactSearchFunctions.H
Normal file
112
src/Interaction/contactSearch/contactSearchFunctions.H
Normal file
@ -0,0 +1,112 @@
|
||||
/*------------------------------- 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 __broadSearchFunctions_H__
|
||||
#define __broadSearchFunctions_H__
|
||||
|
||||
#include "types.H"
|
||||
#include "iBox.H"
|
||||
|
||||
namespace pFlow
|
||||
{
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
uint64_t splitBy3(const uint64_t val){
|
||||
uint64_t x = val;
|
||||
x = (x | x << 32) & 0x1f00000000ffff;
|
||||
x = (x | x << 16) & 0x1f0000ff0000ff;
|
||||
x = (x | x << 8) & 0x100f00f00f00f00f;
|
||||
x = (x | x << 4) & 0x10c30c30c30c30c3;
|
||||
x = (x | x << 2) & 0x1249249249249249;
|
||||
return x;
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
uint64_t xyzToMortonCode64(uint64_t x, uint64_t y, uint64_t z)
|
||||
{
|
||||
return splitBy3(x) | (splitBy3(y) << 1) | (splitBy3(z) << 2);
|
||||
}
|
||||
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
uint64_t getThirdBits(uint64_t x)
|
||||
{
|
||||
x = x & 0x9249249249249249;
|
||||
x = (x | (x >> 2)) & 0x30c30c30c30c30c3;
|
||||
x = (x | (x >> 4)) & 0xf00f00f00f00f00f;
|
||||
x = (x | (x >> 8)) & 0x00ff0000ff0000ff;
|
||||
x = (x | (x >> 16)) & 0xffff00000000ffff;
|
||||
x = (x | (x >> 32)) & 0x00000000ffffffff;
|
||||
return x;
|
||||
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
void mortonCode64Toxyz(uint64_t morton, uint64_t& x, uint64_t& y, uint64_t& z)
|
||||
{
|
||||
x = getThirdBits(morton);
|
||||
y = getThirdBits(morton >> 1);
|
||||
z = getThirdBits(morton >> 2);
|
||||
}
|
||||
|
||||
template<typename indexType, typename cellIndexType>
|
||||
INLINE_FUNCTION_HD
|
||||
void indexToCell(const indexType idx, const triple<cellIndexType>& extent, triple<cellIndexType>& cell)
|
||||
{
|
||||
indexType nxny = extent.x()*extent.y();
|
||||
cell.z() = static_cast<cellIndexType>(idx / nxny);
|
||||
auto rem = idx % nxny;
|
||||
cell.y() = static_cast<cellIndexType>(rem / extent.x());
|
||||
cell.x() = static_cast<cellIndexType>(rem % extent.x());
|
||||
}
|
||||
|
||||
template<typename cellIndexType>
|
||||
INLINE_FUNCTION_HD
|
||||
triple<cellIndexType> boxExtent( const iBox<cellIndexType>& box)
|
||||
{
|
||||
return triple<cellIndexType>(
|
||||
box.maxPoint().x() - box.minPoint().x() + 1,
|
||||
box.maxPoint().y() - box.minPoint().y() + 1,
|
||||
box.maxPoint().z() - box.minPoint().z() + 1);
|
||||
}
|
||||
|
||||
template<typename indexType, typename cellIndexType>
|
||||
INLINE_FUNCTION_HD
|
||||
void indexToCell(const indexType idx, const iBox<cellIndexType>& box, triple<cellIndexType>& cell)
|
||||
{
|
||||
auto extent = boxExtent(box);
|
||||
indexToCell(idx, extent, cell);
|
||||
cell+= box.minPoint();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
bool sphereSphereCheck(const realx3& p1, const realx3 p2, real d1, real d2)
|
||||
{
|
||||
return length(p2-p1) < 0.5*(d2+d1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //__broadSearchFunctions_H__
|
522
src/Interaction/contactSearch/methods/NBS.H
Normal file
522
src/Interaction/contactSearch/methods/NBS.H
Normal file
@ -0,0 +1,522 @@
|
||||
/*------------------------------- 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 __NBS_H__
|
||||
#define __NBS_H__
|
||||
|
||||
#include "cells.H"
|
||||
#include "contactSearchFunctions.H"
|
||||
|
||||
namespace pFlow
|
||||
{
|
||||
|
||||
|
||||
template<
|
||||
typename executionSpace,
|
||||
typename idType,
|
||||
typename indexType=int32
|
||||
>
|
||||
class NBS
|
||||
:
|
||||
public cells<indexType>
|
||||
{
|
||||
public:
|
||||
|
||||
using IdType = idType;
|
||||
|
||||
using IndexType = indexType;
|
||||
|
||||
using Cells = cells<IndexType>;
|
||||
|
||||
using CellType = typename Cells::CellType;
|
||||
|
||||
using ExecutionSpace= executionSpace;
|
||||
|
||||
using memory_space = typename ExecutionSpace::memory_space;
|
||||
|
||||
struct TagBuild{};
|
||||
|
||||
struct TagFindPairs{};
|
||||
|
||||
protected:
|
||||
|
||||
int32 capacity_ = 1;
|
||||
|
||||
real sizeRatio_ = 1.0;
|
||||
|
||||
int32 updateFrequency_= 1;
|
||||
|
||||
int32 currentIter_ = 0;
|
||||
|
||||
bool performedSearch_ = false;
|
||||
|
||||
ViewType1D<realx3, memory_space> pointPosition_;
|
||||
|
||||
ViewType1D<real, memory_space> diameter_;
|
||||
|
||||
ViewType3D<int32, memory_space> head_;
|
||||
|
||||
ViewType1D<int32, memory_space> next_;
|
||||
|
||||
|
||||
INLINE_FUNCTION_H
|
||||
void nullify()
|
||||
{
|
||||
fill(
|
||||
head_,
|
||||
range(0,this->nx()),
|
||||
range(0,this->ny()),
|
||||
range(0,this->nz()),
|
||||
-1
|
||||
);
|
||||
|
||||
fill(
|
||||
next_,
|
||||
range(0,capacity_),
|
||||
-1
|
||||
);
|
||||
}
|
||||
|
||||
void nullify(range nextRng)
|
||||
{
|
||||
fill(
|
||||
head_,
|
||||
range(0,this->nx()),
|
||||
range(0,this->ny()),
|
||||
range(0,this->nz()),
|
||||
-1
|
||||
);
|
||||
|
||||
fill(
|
||||
next_,
|
||||
nextRng,
|
||||
-1
|
||||
);
|
||||
}
|
||||
|
||||
using mdrPolicyFindPairs =
|
||||
Kokkos::MDRangePolicy<
|
||||
Kokkos::Rank<3>,
|
||||
Kokkos::Schedule<Kokkos::Dynamic>,
|
||||
ExecutionSpace>;
|
||||
|
||||
private:
|
||||
|
||||
void checkAllocateNext(int newCap)
|
||||
{
|
||||
|
||||
if( capacity_ < newCap)
|
||||
{
|
||||
capacity_ = newCap;
|
||||
Kokkos::realloc(next_, capacity_);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void allocateHead()
|
||||
{
|
||||
Kokkos::realloc(head_, this->nx(), this->ny(), this->nz());
|
||||
}
|
||||
|
||||
bool performSearch()
|
||||
{
|
||||
if(currentIter_ % updateFrequency_ == 0)
|
||||
{
|
||||
currentIter_++;
|
||||
return true;
|
||||
|
||||
}else
|
||||
{
|
||||
currentIter_++;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE_FUNCTION_HD
|
||||
void Swap(int32& x, int32& y)
|
||||
{
|
||||
int32 tmp = x;
|
||||
x = y;
|
||||
y = tmp;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
TypeNameNV("NBS");
|
||||
|
||||
NBS(
|
||||
const box& domain,
|
||||
real cellSize,
|
||||
const ViewType1D<realx3, memory_space>& position,
|
||||
const ViewType1D<real, memory_space>& diam,
|
||||
int32 initialContainerSize = 1)
|
||||
:
|
||||
Cells(domain, cellSize),
|
||||
pointPosition_(position),
|
||||
diameter_(diam),
|
||||
head_("NBS::head_",1,1,1), //, this->nx(), this->ny(), this->nz()),
|
||||
next_("NBS::next_",1) //,position.size()),
|
||||
{
|
||||
checkAllocateNext(pointPosition_.size());
|
||||
allocateHead();
|
||||
}
|
||||
|
||||
NBS(
|
||||
dictionary dict,
|
||||
const box& domain,
|
||||
real cellSize,
|
||||
const ViewType1D<realx3, memory_space>& position,
|
||||
const ViewType1D<real, memory_space>& diam,
|
||||
int32 initialContainerSize = 1
|
||||
)
|
||||
:
|
||||
Cells(domain, cellSize),
|
||||
pointPosition_(position),
|
||||
diameter_(diam),
|
||||
head_("NBS::head_",1,1,1), //, this->nx(), this->ny(), this->nz()),
|
||||
next_("NBS::next_",1) //,position.size()),
|
||||
{
|
||||
|
||||
updateFrequency_ = max(
|
||||
dict.getVal<int32>("updateFrequency"),1 );
|
||||
|
||||
sizeRatio_ = max(dict.getVal<real>(
|
||||
"sizeRatio"),1.0);
|
||||
|
||||
this->setCellSize(cellSize*sizeRatio_);
|
||||
checkAllocateNext(pointPosition_.size());
|
||||
allocateHead();
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
NBS(const NBS&) = default;
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
NBS& operator = (const NBS&) = default;
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
~NBS()=default;
|
||||
|
||||
//// - Methods
|
||||
|
||||
bool enterBoadSearch()const
|
||||
{
|
||||
return currentIter_%updateFrequency_==0;
|
||||
}
|
||||
|
||||
bool performedSearch()const
|
||||
{
|
||||
return performedSearch_;
|
||||
}
|
||||
|
||||
// - Perform the broad search to find pairs
|
||||
// with force = true, perform broad search regardless of
|
||||
// updateFrequency_ value
|
||||
// on all the points in the range of [0,numPoints_)
|
||||
template<typename PairsContainer>
|
||||
bool broadSearch(PairsContainer& pairs, range activeRange, bool force=false)
|
||||
{
|
||||
|
||||
if(force) currentIter_ = 0;
|
||||
performedSearch_ = false;
|
||||
|
||||
if( !performSearch() ) return true;
|
||||
|
||||
build(activeRange);
|
||||
|
||||
findPairs(pairs);
|
||||
|
||||
performedSearch_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// - Perform the broad search to find pairs,
|
||||
// ignore particles with incld(i) = true,
|
||||
// with force = true, perform broad search regardless of
|
||||
// updateFrequency_ value
|
||||
template<typename PairsContainer, typename IncludeFunction>
|
||||
bool broadSearch(PairsContainer& pairs, range activeRange, IncludeFunction incld, bool force = false)
|
||||
{
|
||||
if(force) currentIter_ = 0;
|
||||
performedSearch_ = false;
|
||||
|
||||
if( !performSearch() ) return true;
|
||||
|
||||
build(activeRange, incld);
|
||||
|
||||
findPairs(pairs);
|
||||
|
||||
performedSearch_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// - build based on all points in range [0, numPoints_)
|
||||
INLINE_FUNCTION_H
|
||||
void build(range activeRange)
|
||||
{
|
||||
checkAllocateNext(activeRange.second);
|
||||
nullify(activeRange);
|
||||
|
||||
Cells cellIndex = static_cast<Cells>(*this);
|
||||
auto points = pointPosition_;
|
||||
auto next = next_;
|
||||
auto head = head_;
|
||||
|
||||
Kokkos::RangePolicy<
|
||||
Kokkos::IndexType<int32>,
|
||||
Kokkos::Schedule<Kokkos::Static>,
|
||||
ExecutionSpace> rPolicy(activeRange.first, activeRange.second);
|
||||
|
||||
Kokkos::parallel_for(
|
||||
"NBS::build",
|
||||
rPolicy,
|
||||
LAMBDA_HD(int32 i){
|
||||
|
||||
CellType ind = cellIndex.pointIndex(points[i]);
|
||||
int32 old = Kokkos::atomic_exchange(&head(ind.x(), ind.y(), ind.z()), i);
|
||||
next[i] = old;
|
||||
});
|
||||
Kokkos::fence();
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<typename IncludeFunction>
|
||||
INLINE_FUNCTION_H
|
||||
void build(range activeRange, IncludeFunction incld)
|
||||
{
|
||||
checkAllocateNext(activeRange.second);
|
||||
nullify(activeRange);
|
||||
|
||||
Cells cellIndex = static_cast<Cells>(*this);
|
||||
auto points = pointPosition_;
|
||||
auto next = next_;
|
||||
auto head = head_;
|
||||
|
||||
Kokkos::RangePolicy<
|
||||
Kokkos::IndexType<int32>,
|
||||
Kokkos::Schedule<Kokkos::Dynamic>,
|
||||
ExecutionSpace> rPolicy(activeRange.first, activeRange.second);
|
||||
|
||||
Kokkos::parallel_for(
|
||||
"NBS::build",
|
||||
rPolicy,
|
||||
LAMBDA_HD(int32 i){
|
||||
|
||||
if( incld(i) )
|
||||
{
|
||||
CellType ind = cellIndex.pointIndex(points[i]);
|
||||
auto old = Kokkos::atomic_exchange(&head(ind.x(), ind.y(), ind.z()), i);
|
||||
next[i] = old;
|
||||
}
|
||||
});
|
||||
Kokkos::fence();
|
||||
|
||||
}
|
||||
|
||||
template<typename PairsContainer>
|
||||
INLINE_FUNCTION_H
|
||||
bool findPairs(PairsContainer& pairs)
|
||||
{
|
||||
mdrPolicyFindPairs
|
||||
mdrPolicy(
|
||||
{0,0,0},
|
||||
{this->nx(),this->ny(),this->nz()} );
|
||||
|
||||
int32 getFull = 1;
|
||||
|
||||
// loop until the container size fits the numebr of contact pairs
|
||||
while (getFull > 0)
|
||||
{
|
||||
|
||||
getFull = 0;
|
||||
|
||||
Kokkos::parallel_reduce (
|
||||
"NBS::broadSearch",
|
||||
mdrPolicy,
|
||||
CLASS_LAMBDA_HD(int32 i, int32 j, int32 k, int32& getFullUpdate){
|
||||
#include "NBSLoop.H"
|
||||
}, getFull);
|
||||
|
||||
if(getFull)
|
||||
{
|
||||
// - resize the container
|
||||
// note that getFull now shows the number of failed insertions.
|
||||
uint32 len = max(getFull,50) ;
|
||||
|
||||
auto oldCap = pairs.capacity();
|
||||
|
||||
pairs.increaseCapacityBy(len);
|
||||
|
||||
Info<< "The contact pair container capacity increased from "<<
|
||||
oldCap << " to "<<pairs.capacity()<<" in NBS."<<endInfo;
|
||||
|
||||
}
|
||||
|
||||
Kokkos::fence();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool objectSizeChanged(int32 newSize)
|
||||
{
|
||||
checkAllocateNext(newSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*INLINE_FUNCTION_HD
|
||||
void operator()(
|
||||
TagFindPairs,
|
||||
int32 i,
|
||||
int32 j,
|
||||
int32 k,
|
||||
int32& getFullUpdate)const
|
||||
{
|
||||
|
||||
int32 m = head_(i,j,k);
|
||||
CellType currentCell(i,j,k);
|
||||
int32 n = -1;
|
||||
|
||||
while( m > -1 )
|
||||
{
|
||||
|
||||
auto p_m = pointPosition_[m];
|
||||
auto d_m = sizeRatio_* diameter_[m];
|
||||
|
||||
// the same cell
|
||||
n = next_(m);
|
||||
|
||||
while(n >-1)
|
||||
{
|
||||
|
||||
auto p_n = pointPosition_[n];
|
||||
auto d_n = sizeRatio_*diameter_[n];
|
||||
|
||||
if( sphereSphereCheck(p_m, p_n, d_m, d_n) )
|
||||
{
|
||||
auto ln = n;
|
||||
auto lm = m;
|
||||
if(lm>ln) Swap(lm,ln);
|
||||
if( auto res = pairs_.insert(lm,ln); res <0)
|
||||
{
|
||||
getFullUpdate++;
|
||||
}
|
||||
}
|
||||
|
||||
n = next_(n);
|
||||
}
|
||||
|
||||
// neighbor cells
|
||||
CellType neighborCell;
|
||||
for(int32 ni=0; ni<13; ni++)
|
||||
{
|
||||
if(ni==0) neighborCell = currentCell + CellType( 0, 0,-1);
|
||||
else if(ni==1) neighborCell = currentCell + CellType(-1, 0,-1);
|
||||
else if(ni==2) neighborCell = currentCell + CellType(-1, 0, 0);
|
||||
else if(ni==3) neighborCell = currentCell + CellType(-1, 0, 1);
|
||||
else if(ni==4) neighborCell = currentCell + CellType( 0,-1,-1);
|
||||
else if(ni==5) neighborCell = currentCell + CellType( 0,-1, 0);
|
||||
else if(ni==6) neighborCell = currentCell + CellType( 0,-1, 1);
|
||||
else if(ni==7) neighborCell = currentCell + CellType(-1,-1,-1);
|
||||
else if(ni==8) neighborCell = currentCell + CellType(-1,-1, 0);
|
||||
else if(ni==9) neighborCell = currentCell + CellType(-1,-1, 1);
|
||||
else if(ni==10) neighborCell = currentCell + CellType( 1,-1,-1);
|
||||
else if(ni==11) neighborCell = currentCell + CellType( 1,-1, 0);
|
||||
else if(ni==12) neighborCell = currentCell + CellType( 1,-1, 1);
|
||||
|
||||
if( this->isInRange(neighborCell) )
|
||||
{
|
||||
|
||||
n = head_(neighborCell.x(), neighborCell.y(), neighborCell.z());
|
||||
while( n>-1)
|
||||
{
|
||||
|
||||
auto p_n = pointPosition_[n];
|
||||
auto d_n = sizeRatio_*diameter_[n];
|
||||
|
||||
if(sphereSphereCheck(p_m, p_n, d_m, d_n))
|
||||
{
|
||||
auto ln = n;
|
||||
auto lm = m;
|
||||
if(lm>ln) Swap(lm,ln);
|
||||
if( auto res = pairs_.insert(lm,ln); res <0)
|
||||
{
|
||||
getFullUpdate++;
|
||||
}
|
||||
}
|
||||
n = next_[n];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
m = next_[m];
|
||||
}
|
||||
}*/
|
||||
|
||||
template <typename PairsContainer, typename teamMemberType>
|
||||
INLINE_FUNCTION_HD
|
||||
int32 addPointsInBoxToList(
|
||||
const teamMemberType& teamMember,
|
||||
IdType id,
|
||||
const iBox<IndexType>& triBox,
|
||||
const PairsContainer& pairs)const
|
||||
{
|
||||
int32 getFull = 0;
|
||||
|
||||
auto bExtent = boxExtent(triBox);
|
||||
int32 numCellBox = bExtent.x()*bExtent.y()*bExtent.z();
|
||||
|
||||
const auto head = head_;
|
||||
const auto next = next_;
|
||||
|
||||
// perform a loop over all cells in the triBox
|
||||
Kokkos::parallel_reduce(
|
||||
Kokkos::TeamThreadRange(teamMember,numCellBox),
|
||||
[=](int32 linIndex, int32& valToUpdate){
|
||||
|
||||
CellType cell;
|
||||
indexToCell(linIndex, triBox, cell);
|
||||
|
||||
int32 n = head(cell.x(),cell.y(),cell.z());
|
||||
|
||||
while( n>-1)
|
||||
{
|
||||
|
||||
// id is wall id the pair is (particle id, wall id)
|
||||
if( pairs.insert(static_cast<IdType>(n), id) < 0 )
|
||||
valToUpdate++;
|
||||
n = next(n);
|
||||
}
|
||||
|
||||
},
|
||||
getFull
|
||||
);
|
||||
|
||||
return getFull;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
100
src/Interaction/contactSearch/methods/NBSLoop.H
Normal file
100
src/Interaction/contactSearch/methods/NBSLoop.H
Normal file
@ -0,0 +1,100 @@
|
||||
/*------------------------------- 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.
|
||||
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
int32 m = head_(i,j,k);
|
||||
CellType currentCell(i,j,k);
|
||||
int32 n = -1;
|
||||
|
||||
while( m > -1 )
|
||||
{
|
||||
|
||||
auto p_m = pointPosition_[m];
|
||||
auto d_m = sizeRatio_* diameter_[m];
|
||||
|
||||
// the same cell
|
||||
n = next_(m);
|
||||
|
||||
while(n >-1)
|
||||
{
|
||||
|
||||
auto p_n = pointPosition_[n];
|
||||
auto d_n = sizeRatio_*diameter_[n];
|
||||
|
||||
if( sphereSphereCheck(p_m, p_n, d_m, d_n) )
|
||||
{
|
||||
auto ln = n;
|
||||
auto lm = m;
|
||||
if(lm>ln) Swap(lm,ln);
|
||||
if( auto res = pairs.insert(lm,ln); res <0)
|
||||
{
|
||||
getFullUpdate++;
|
||||
}
|
||||
}
|
||||
|
||||
n = next_(n);
|
||||
}
|
||||
|
||||
// neighbor cells
|
||||
CellType neighborCell;
|
||||
for(int32 ni=0; ni<13; ni++)
|
||||
{
|
||||
if(ni==0) neighborCell = currentCell + CellType( 0, 0,-1);
|
||||
else if(ni==1) neighborCell = currentCell + CellType(-1, 0,-1);
|
||||
else if(ni==2) neighborCell = currentCell + CellType(-1, 0, 0);
|
||||
else if(ni==3) neighborCell = currentCell + CellType(-1, 0, 1);
|
||||
else if(ni==4) neighborCell = currentCell + CellType( 0,-1,-1);
|
||||
else if(ni==5) neighborCell = currentCell + CellType( 0,-1, 0);
|
||||
else if(ni==6) neighborCell = currentCell + CellType( 0,-1, 1);
|
||||
else if(ni==7) neighborCell = currentCell + CellType(-1,-1,-1);
|
||||
else if(ni==8) neighborCell = currentCell + CellType(-1,-1, 0);
|
||||
else if(ni==9) neighborCell = currentCell + CellType(-1,-1, 1);
|
||||
else if(ni==10) neighborCell = currentCell + CellType( 1,-1,-1);
|
||||
else if(ni==11) neighborCell = currentCell + CellType( 1,-1, 0);
|
||||
else if(ni==12) neighborCell = currentCell + CellType( 1,-1, 1);
|
||||
|
||||
if( this->isInRange(neighborCell) )
|
||||
{
|
||||
|
||||
n = head_(neighborCell.x(), neighborCell.y(), neighborCell.z());
|
||||
while( n>-1)
|
||||
{
|
||||
|
||||
auto p_n = pointPosition_[n];
|
||||
auto d_n = sizeRatio_*diameter_[n];
|
||||
|
||||
if(sphereSphereCheck(p_m, p_n, d_m, d_n))
|
||||
{
|
||||
auto ln = n;
|
||||
auto lm = m;
|
||||
if(lm>ln) Swap(lm,ln);
|
||||
if( auto res = pairs.insert(lm,ln); res <0)
|
||||
{
|
||||
getFullUpdate++;
|
||||
}
|
||||
}
|
||||
n = next_[n];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
m = next_[m];
|
||||
}
|
||||
|
338
src/Interaction/contactSearch/wallMappings/cellsSimple.H
Normal file
338
src/Interaction/contactSearch/wallMappings/cellsSimple.H
Normal file
@ -0,0 +1,338 @@
|
||||
/*------------------------------- 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 __cellsSimple_H__
|
||||
#define __cellsSimple_H__
|
||||
|
||||
#include "types.H"
|
||||
#include "KokkosTypes.H"
|
||||
#include "cells.H"
|
||||
#include "iBox.H"
|
||||
#include "dictionary.H"
|
||||
|
||||
|
||||
namespace pFlow
|
||||
{
|
||||
|
||||
template<
|
||||
typename executionSpace,
|
||||
typename idType,
|
||||
typename indexType = int32
|
||||
>
|
||||
class cellsSimple
|
||||
:
|
||||
public cells<indexType>
|
||||
{
|
||||
public:
|
||||
|
||||
using IdType = idType;
|
||||
|
||||
using IndexType = indexType;
|
||||
|
||||
using Cells = cells<IndexType>;
|
||||
|
||||
using CellType = typename Cells::CellType;
|
||||
|
||||
using ExecutionSpace = executionSpace;
|
||||
|
||||
using memory_space = typename ExecutionSpace::memory_space;
|
||||
|
||||
using iBoxType = iBox<IndexType>;
|
||||
|
||||
bool constexpr static LOOP_ELEMENT_RANGE = true;
|
||||
|
||||
class TagFindCellRange2{};
|
||||
protected:
|
||||
|
||||
// - box extent
|
||||
real cellExtent_ = 0.6;
|
||||
|
||||
// - update frequency
|
||||
int32 updateFrequency_=1;
|
||||
|
||||
|
||||
int32 currentIter_ = 0;
|
||||
|
||||
// - number of triangle elements
|
||||
int32 numElements_ = 0;
|
||||
|
||||
// - number of points
|
||||
int32 numPoints_ = 0;
|
||||
|
||||
/// a broad search has been occured during last pass?
|
||||
bool performedSearch_ = false;
|
||||
|
||||
// - ref to vectices
|
||||
ViewType1D<int32x3, memory_space> vertices_;
|
||||
|
||||
// - ref to points in the trisurface
|
||||
ViewType1D<realx3, memory_space> points_;
|
||||
|
||||
// cell range of element/triangle bounding box
|
||||
ViewType1D<iBoxType, memory_space> elementBox_;
|
||||
|
||||
|
||||
using tpPWContactSearch = Kokkos::TeamPolicy<
|
||||
ExecutionSpace,
|
||||
Kokkos::Schedule<Kokkos::Dynamic>,
|
||||
Kokkos::IndexType<int32>
|
||||
>;
|
||||
|
||||
using rpFindCellRange2Type =
|
||||
Kokkos::RangePolicy<TagFindCellRange2, ExecutionSpace, Kokkos::IndexType<int32>>;
|
||||
|
||||
|
||||
FUNCTION_H
|
||||
void allocateArrays()
|
||||
{
|
||||
Kokkos::realloc( elementBox_, numElements_);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
bool performSearch()
|
||||
{
|
||||
if(currentIter_ % updateFrequency_ == 0)
|
||||
{
|
||||
currentIter_++;
|
||||
return true;
|
||||
|
||||
}else
|
||||
{
|
||||
currentIter_++;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
TypeNameNV("cellsSimple");
|
||||
|
||||
FUNCTION_H
|
||||
cellsSimple(
|
||||
Cells ppCells,
|
||||
real cellExtent,
|
||||
int32 numPoints,
|
||||
int32 numElements,
|
||||
const ViewType1D<realx3,memory_space>& points,
|
||||
const ViewType1D<int32x3,memory_space>& vertices
|
||||
)
|
||||
:
|
||||
Cells(ppCells),
|
||||
cellExtent_( max(cellExtent, 0.6 ) ),
|
||||
numElements_(numElements),
|
||||
numPoints_(numPoints),
|
||||
vertices_(vertices),
|
||||
points_(points)
|
||||
{
|
||||
|
||||
allocateArrays();
|
||||
}
|
||||
|
||||
cellsSimple(
|
||||
dictionary dict,
|
||||
Cells ppCells,
|
||||
int32 numPoints,
|
||||
int32 numElements,
|
||||
const ViewType1D<realx3,memory_space>& points,
|
||||
const ViewType1D<int32x3,memory_space>& vertices
|
||||
)
|
||||
:
|
||||
Cells(ppCells),
|
||||
numElements_(numElements),
|
||||
numPoints_(numPoints),
|
||||
vertices_(vertices),
|
||||
points_(points)
|
||||
{
|
||||
|
||||
updateFrequency_ = dict.getVal<int32>(
|
||||
"updateFrequency" );
|
||||
updateFrequency_ = max(updateFrequency_,1);
|
||||
|
||||
cellExtent_ = dict.getVal<real>(
|
||||
"cellExtent");
|
||||
|
||||
cellExtent_ = max(cellExtent_,0.6);
|
||||
|
||||
allocateArrays();
|
||||
|
||||
}
|
||||
|
||||
constexpr bool loopElementRange()const
|
||||
{
|
||||
return LOOP_ELEMENT_RANGE;
|
||||
}
|
||||
|
||||
// - host call
|
||||
// reset triangle elements if they have changed
|
||||
FUNCTION_H
|
||||
bool resetElements(
|
||||
int32 numElements,
|
||||
int32 numPoints,
|
||||
ViewType1D<realx3, memory_space>& points,
|
||||
ViewType1D<int32x3, memory_space>& vertices )
|
||||
{
|
||||
|
||||
numElements_ = numElements;
|
||||
numPoints_ = numPoints;
|
||||
points_ = points;
|
||||
vertices_ = vertices;
|
||||
|
||||
allocateArrays();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
iBoxType elementBox(int32 i)const
|
||||
{
|
||||
return elementBox_[i];
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
int32 numElements()const
|
||||
{
|
||||
return numElements_;
|
||||
}
|
||||
|
||||
bool enterBoadSearch()const
|
||||
{
|
||||
return currentIter_%updateFrequency_==0;
|
||||
}
|
||||
|
||||
bool performedSearch()const
|
||||
{
|
||||
return performedSearch_;
|
||||
}
|
||||
|
||||
template<typename PairsContainer, typename particleMapType>
|
||||
bool broadSearch(PairsContainer& pairs, particleMapType& particleMap, bool force=false)
|
||||
{
|
||||
if(force) currentIter_ = 0;
|
||||
performedSearch_= false;
|
||||
if(!performSearch())return true;
|
||||
|
||||
// map walls onto the cells
|
||||
this->build();
|
||||
|
||||
this->particleWallFindPairs(pairs, particleMap);
|
||||
|
||||
performedSearch_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool build()
|
||||
{
|
||||
Kokkos::parallel_for(
|
||||
"cellsSimple::findcellrange2",
|
||||
rpFindCellRange2Type(0,numElements_),
|
||||
*this);
|
||||
Kokkos::fence();
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename PairsContainer, typename particleMapType>
|
||||
bool particleWallFindPairs(PairsContainer& pairs, particleMapType& particleMap)
|
||||
{
|
||||
|
||||
int32 getFull = 1;
|
||||
|
||||
while (getFull)
|
||||
{
|
||||
|
||||
getFull = findPairsElementRange(pairs, particleMap);
|
||||
|
||||
if(getFull)
|
||||
{
|
||||
// - resize the container
|
||||
// note that getFull now shows the number of failed insertions.
|
||||
uint32 len = max(getFull, 50);
|
||||
auto oldCap = pairs.capacity();
|
||||
pairs.increaseCapacityBy(len);
|
||||
|
||||
Info<<"Contact pair container capacity increased from "<<
|
||||
oldCap << " to "
|
||||
<< pairs.capacity() <<" in cellsSimple."<<endInfo;
|
||||
|
||||
|
||||
|
||||
Kokkos::fence();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename PairsContainer, typename particleMapType>
|
||||
int32 findPairsElementRange(PairsContainer& pairs, particleMapType& particleMap)
|
||||
{
|
||||
int32 getFull =0;
|
||||
|
||||
const auto pwPairs = pairs;
|
||||
const auto elementBox = elementBox_;
|
||||
|
||||
|
||||
Kokkos::parallel_reduce(
|
||||
"cellsSimple::findPairsElementRange",
|
||||
tpPWContactSearch(numElements_, Kokkos::AUTO),
|
||||
LAMBDA_HD(
|
||||
const typename tpPWContactSearch::member_type & teamMember,
|
||||
int32& valueToUpdate){
|
||||
int32 i = teamMember.league_rank();
|
||||
IdType id = i;
|
||||
const auto triBox = elementBox[i];
|
||||
|
||||
valueToUpdate +=
|
||||
particleMap.addPointsInBoxToList(
|
||||
teamMember,
|
||||
id,
|
||||
triBox,
|
||||
pwPairs
|
||||
);
|
||||
},
|
||||
getFull
|
||||
);
|
||||
|
||||
return getFull;
|
||||
}
|
||||
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
void operator()(TagFindCellRange2, int32 i) const
|
||||
{
|
||||
auto v = vertices_[i];
|
||||
auto p1 = points_[v.x()];
|
||||
auto p2 = points_[v.y()];
|
||||
auto p3 = points_[v.z()];
|
||||
|
||||
realx3 minP, maxP;
|
||||
|
||||
this->extendBox(p1, p2, p3, cellExtent_, minP, maxP);
|
||||
//output<< minP << " maxP "<< maxP<<endl;
|
||||
elementBox_[i] = iBoxType(this->pointIndex(minP), this->pointIndex(maxP));
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
59
src/Interaction/interaction/demInteraction.H
Normal file
59
src/Interaction/interaction/demInteraction.H
Normal file
@ -0,0 +1,59 @@
|
||||
/*------------------------------- phasicFlow ---------------------------------
|
||||
O C enter of
|
||||
O O E ngineering and
|
||||
O O M ultiscale modeling of
|
||||
OOOOOOO F luid flow
|
||||
------------------------------------------------------------------------------
|
||||
Copyright (C): www.cemf.ir
|
||||
email: hamid.r.norouzi AT gmail.com
|
||||
------------------------------------------------------------------------------
|
||||
Licence:
|
||||
This file is part of phasicFlow code. It is a free software for simulating
|
||||
granular and multiphase flows. You can redistribute it and/or modify it under
|
||||
the terms of GNU General Public License v3 or any other later versions.
|
||||
|
||||
phasicFlow is distributed to help others in their research in the field of
|
||||
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __demInteraction_H__
|
||||
#define __demInteraction_H__
|
||||
|
||||
#include "property.H"
|
||||
#include "demComponent.H"
|
||||
#include "pointFields.H"
|
||||
#include "triSurfaceFields.H"
|
||||
|
||||
namespace pFlow
|
||||
{
|
||||
|
||||
class demInteraction
|
||||
:
|
||||
public property,
|
||||
public demComponent
|
||||
{
|
||||
protected:
|
||||
|
||||
public:
|
||||
demInteraction(systemControl& control)
|
||||
:
|
||||
property(),
|
||||
demComponent("interaction", control)
|
||||
{}
|
||||
|
||||
demInteraction(systemControl& control, const fileSystem& file)
|
||||
:
|
||||
property(file),
|
||||
demComponent("interaction", control)
|
||||
{}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif //__interaction_H__
|
107
src/Interaction/interaction/interaction.C
Normal file
107
src/Interaction/interaction/interaction.C
Normal file
@ -0,0 +1,107 @@
|
||||
/*------------------------------- 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 "interaction.H"
|
||||
|
||||
|
||||
pFlow::interaction::interaction
|
||||
(
|
||||
systemControl& control,
|
||||
const particles& prtcl,
|
||||
const geometry& geom
|
||||
)
|
||||
:
|
||||
demInteraction(control, control.caseSetup().path()+interactionFile__),
|
||||
interactionBase(prtcl, geom),
|
||||
fileDict_(control.caseSetup().emplaceObject<dictionary>(
|
||||
objectFile(
|
||||
interactionFile__,
|
||||
"",
|
||||
objectFile::READ_ALWAYS,
|
||||
objectFile::WRITE_NEVER),
|
||||
interactionFile__,
|
||||
true ))
|
||||
{
|
||||
this->subscribe(prtcl.pStruct());
|
||||
|
||||
contactSearch_ = contactSearch::create(
|
||||
fileDict_.subDict("contactSearch"),
|
||||
this->control().domain(),
|
||||
prtcl,
|
||||
geom,
|
||||
timers()
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
pFlow::uniquePtr<pFlow::interaction> pFlow::interaction::create
|
||||
(
|
||||
systemControl& control,
|
||||
const particles& prtcl,
|
||||
const geometry& geom
|
||||
)
|
||||
{
|
||||
word shapeTypeName = prtcl.shapeTypeName();
|
||||
word motionTypeName = geom.motionModelTypeName();
|
||||
|
||||
fileSystem file = control.caseSetup().path()+interactionFile__;
|
||||
|
||||
dictionary dict(interactionFile__, file);
|
||||
auto interactionDict= dict.subDict("model");
|
||||
|
||||
word clType = dict.getVal<word>("contactListType");
|
||||
word cfModel = interactionDict.getVal<word>("contactForceModel");
|
||||
word rfModel = interactionDict.getVal<word>("rollingFrictionModel");
|
||||
|
||||
|
||||
auto interactionModel = angleBracketsNames3(
|
||||
shapeTypeName+"Interaction",
|
||||
angleBracketsNames(rfModel,cfModel),
|
||||
motionTypeName,
|
||||
clType);
|
||||
|
||||
|
||||
Report(1)<< "Selecting interaction model..."<<endReport;
|
||||
if( systemControlvCtorSelector_.search(interactionModel) )
|
||||
{
|
||||
auto objPtr =
|
||||
systemControlvCtorSelector_[interactionModel]
|
||||
(control, prtcl, geom);
|
||||
|
||||
Report(2)<<"Model "<<greenText(interactionModel)<<" is created."<<endReport;
|
||||
return objPtr;
|
||||
}
|
||||
else
|
||||
{
|
||||
printKeys
|
||||
(
|
||||
fatalError << "Ctor Selector "<<
|
||||
interactionModel << " dose not exist. \n"
|
||||
<<"Avaiable ones are: \n\n"
|
||||
,
|
||||
systemControlvCtorSelector_
|
||||
);
|
||||
fatalExit;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
||||
}
|
109
src/Interaction/interaction/interaction.H
Normal file
109
src/Interaction/interaction/interaction.H
Normal file
@ -0,0 +1,109 @@
|
||||
/*------------------------------- 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 __interaction_H__
|
||||
#define __interaction_H__
|
||||
|
||||
#include "demInteraction.H"
|
||||
#include "eventObserver.H"
|
||||
#include "interactionBase.H"
|
||||
#include "contactSearch.H"
|
||||
|
||||
|
||||
|
||||
namespace pFlow
|
||||
{
|
||||
|
||||
class interaction
|
||||
:
|
||||
public demInteraction,
|
||||
public eventObserver,
|
||||
public interactionBase
|
||||
{
|
||||
public:
|
||||
|
||||
using IdType = typename interactionBase::IdType;
|
||||
|
||||
using IndexType = typename interactionBase::IndexType;
|
||||
|
||||
using ExecutionSpace = typename interactionBase::ExecutionSpace;
|
||||
|
||||
protected:
|
||||
|
||||
/// interaction file dictionary
|
||||
dictionary& fileDict_;
|
||||
|
||||
/// contact search object for pp and pw interactions
|
||||
uniquePtr<contactSearch> contactSearch_ = nullptr;
|
||||
|
||||
public:
|
||||
|
||||
TypeName("interaction");
|
||||
|
||||
|
||||
//// - constructors
|
||||
|
||||
interaction(
|
||||
systemControl& control,
|
||||
const particles& prtcl,
|
||||
const geometry& geom );
|
||||
|
||||
|
||||
|
||||
virtual ~interaction() = default;
|
||||
|
||||
create_vCtor(
|
||||
interaction,
|
||||
systemControl,
|
||||
(
|
||||
systemControl& control,
|
||||
const particles& prtcl,
|
||||
const geometry& geom
|
||||
),
|
||||
(control, prtcl, geom)
|
||||
);
|
||||
|
||||
auto& contactSearchPtr()
|
||||
{
|
||||
return contactSearch_;
|
||||
}
|
||||
|
||||
auto& contactSearchRef()
|
||||
{
|
||||
return contactSearch_();
|
||||
}
|
||||
|
||||
const auto& fileDict()const
|
||||
{
|
||||
return fileDict_;
|
||||
}
|
||||
|
||||
static
|
||||
uniquePtr<interaction> create(
|
||||
systemControl& control,
|
||||
const particles& prtcl,
|
||||
const geometry& geom);
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif //__interaction_H__
|
84
src/Interaction/interaction/interactionBase.H
Normal file
84
src/Interaction/interaction/interactionBase.H
Normal file
@ -0,0 +1,84 @@
|
||||
/*------------------------------- 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 __interactionBase_H__
|
||||
#define __interactionBase_H__
|
||||
|
||||
#include "interactionTypes.H"
|
||||
#include "particles.H"
|
||||
#include "geometry.H"
|
||||
|
||||
namespace pFlow
|
||||
{
|
||||
|
||||
class interactionBase
|
||||
{
|
||||
public:
|
||||
|
||||
using IndexType = CELL_INDEX_TYPE;
|
||||
|
||||
using IdType = ID_TYPE;
|
||||
|
||||
using ExecutionSpace = DefaultExecutionSpace;
|
||||
|
||||
protected:
|
||||
|
||||
const particles& particles_;
|
||||
|
||||
const geometry& geometry_;
|
||||
|
||||
public:
|
||||
|
||||
interactionBase(
|
||||
const particles& prtcl,
|
||||
const geometry& geom)
|
||||
:
|
||||
particles_(prtcl),
|
||||
geometry_(geom)
|
||||
{}
|
||||
|
||||
inline
|
||||
const auto& pStruct()const
|
||||
{
|
||||
return particles_.pStruct();
|
||||
}
|
||||
|
||||
inline
|
||||
const auto& surface()const
|
||||
{
|
||||
return geometry_.surface();
|
||||
}
|
||||
|
||||
inline
|
||||
const auto& Particles()const
|
||||
{
|
||||
return particles_;
|
||||
}
|
||||
|
||||
inline auto& Geometry()const
|
||||
{
|
||||
return geometry_;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif //__interactionBase_H__
|
45
src/Interaction/interaction/interactionTypes.H
Normal file
45
src/Interaction/interaction/interactionTypes.H
Normal file
@ -0,0 +1,45 @@
|
||||
/*------------------------------- 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 __interactionTypes_H__
|
||||
#define __interactionTypes_H__
|
||||
|
||||
|
||||
|
||||
#include "types.H"
|
||||
|
||||
|
||||
namespace pFlow
|
||||
{
|
||||
|
||||
|
||||
// always use signed types
|
||||
using CELL_INDEX_TYPE = int32;
|
||||
|
||||
using ID_TYPE = int32;
|
||||
|
||||
//constexpr int32 minCellIndex = largestNegative<CELL_INDEX_TYPE>();
|
||||
|
||||
//constexpr int32 maxCellIndex = largestPositive<CELL_INDEX_TYPE>();
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif //__interactionTypes_H__
|
107
src/Interaction/sphereInteraction/pLine.H
Normal file
107
src/Interaction/sphereInteraction/pLine.H
Normal file
@ -0,0 +1,107 @@
|
||||
/*------------------------------- 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 __pLine_H__
|
||||
#define __pLine_H__
|
||||
|
||||
#include "types.H"
|
||||
|
||||
namespace pFlow::sphTriInteraction
|
||||
{
|
||||
|
||||
struct pLine
|
||||
{
|
||||
|
||||
realx3 p1_; // point 1
|
||||
realx3 p2_; // piont 2
|
||||
realx3 v_; // direction vector
|
||||
real L_; // line lenght
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
pLine(){}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
pLine(const realx3 &p1, const realx3 &p2)
|
||||
:
|
||||
p1_(p1),
|
||||
p2_(p2),
|
||||
v_(p2-p1),
|
||||
L_(length(v_))
|
||||
{}
|
||||
|
||||
// get a point on the line based on input 0<= t <= 1
|
||||
INLINE_FUNCTION_HD
|
||||
realx3 point(real t)const {
|
||||
return v_ * t + p1_;
|
||||
}
|
||||
|
||||
// return the projected point of point p on line
|
||||
INLINE_FUNCTION_HD
|
||||
realx3 projectPoint(const realx3 &p) const
|
||||
{
|
||||
return point(projectNormLength(p));
|
||||
}
|
||||
|
||||
// calculates the normalized distance between projected p and p1
|
||||
INLINE_FUNCTION_HD
|
||||
real projectNormLength(realx3 p) const
|
||||
{
|
||||
realx3 w = p - p1_;
|
||||
return dot(w,v_) / (L_*L_);
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
bool lineSphereCheck(
|
||||
const realx3 pos,
|
||||
real Rad,
|
||||
realx3 &nv,
|
||||
realx3 &cp,
|
||||
real &ovrlp)const
|
||||
{
|
||||
|
||||
|
||||
real t = projectNormLength(pos);
|
||||
|
||||
if(t >= 0.0 && t <= 1.0) cp = point(t);
|
||||
else if(t >= (-Rad / L_) && t < 0.0) cp = point(0.0);
|
||||
else if(t>1.0 && t >= (1.0 + Rad / L_)) cp = point(1.0);
|
||||
else return false;
|
||||
|
||||
realx3 vec = pos - cp; // from cp to pos
|
||||
|
||||
real dist = length(vec);
|
||||
ovrlp = Rad - dist;
|
||||
|
||||
if (ovrlp >= 0.0)
|
||||
{
|
||||
if (dist > 0)
|
||||
nv = vec / dist;
|
||||
else
|
||||
nv = v_;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
} //pFlow::sphTriInteractio
|
||||
|
||||
#endif
|
128
src/Interaction/sphereInteraction/sphereInteraction.C
Normal file
128
src/Interaction/sphereInteraction/sphereInteraction.C
Normal file
@ -0,0 +1,128 @@
|
||||
/*------------------------------- phasicFlow ---------------------------------
|
||||
O C enter of
|
||||
O O E ngineering and
|
||||
O O M ultiscale modeling of
|
||||
OOOOOOO F luid flow
|
||||
------------------------------------------------------------------------------
|
||||
Copyright (C): www.cemf.ir
|
||||
email: hamid.r.norouzi AT gmail.com
|
||||
------------------------------------------------------------------------------
|
||||
Licence:
|
||||
This file is part of phasicFlow code. It is a free software for simulating
|
||||
granular and multiphase flows. You can redistribute it and/or modify it under
|
||||
the terms of GNU General Public License v3 or any other later versions.
|
||||
|
||||
phasicFlow is distributed to help others in their research in the field of
|
||||
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
template<
|
||||
typename contactForceModel,
|
||||
typename geometryMotionModel,
|
||||
template <class, class, class> class contactListType >
|
||||
bool pFlow::sphereInteraction<contactForceModel,geometryMotionModel, contactListType>::
|
||||
createSphereInteraction()
|
||||
{
|
||||
|
||||
realVector_D rhoD(this->densities());
|
||||
|
||||
auto modelDict = this->fileDict().subDict("model");
|
||||
|
||||
Report(1)<<"Createing contact force model . . ."<<endReport;
|
||||
forceModel_ = makeUnique<ContactForceModel>(
|
||||
this->numMaterials(),
|
||||
rhoD.deviceVector(),
|
||||
modelDict );
|
||||
|
||||
|
||||
uint32 nPrtcl = sphParticles_.size();
|
||||
|
||||
ppContactList_ = makeUnique<ContactListType>(nPrtcl+1);
|
||||
|
||||
pwContactList_ = makeUnique<ContactListType>(nPrtcl/4+1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<
|
||||
typename contactForceModel,
|
||||
typename geometryMotionModel,
|
||||
template <class, class, class> class contactListType >
|
||||
bool pFlow::sphereInteraction<contactForceModel,geometryMotionModel, contactListType>::
|
||||
sphereSphereInteraction()
|
||||
{
|
||||
|
||||
|
||||
auto lastItem = ppContactList_().loopCount();
|
||||
|
||||
// create the kernel functor
|
||||
pFlow::sphereInteractionKernels::ppInteractionFunctor
|
||||
ppInteraction(
|
||||
this->dt(),
|
||||
this->forceModel_(),
|
||||
ppContactList_(), // to be read
|
||||
sphParticles_.diameter().deviceVectorAll(),
|
||||
sphParticles_.propertyId().deviceVectorAll(),
|
||||
sphParticles_.pointPosition().deviceVectorAll(),
|
||||
sphParticles_.velocity().deviceVectorAll(),
|
||||
sphParticles_.rVelocity().deviceVectorAll(),
|
||||
sphParticles_.contactForce().deviceVectorAll(),
|
||||
sphParticles_.contactTorque().deviceVectorAll()
|
||||
);
|
||||
|
||||
Kokkos::parallel_for(
|
||||
"",
|
||||
rpPPInteraction(0,lastItem),
|
||||
ppInteraction
|
||||
);
|
||||
|
||||
Kokkos::fence();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<
|
||||
typename contactForceModel,
|
||||
typename geometryMotionModel,
|
||||
template <class, class, class> class contactListType >
|
||||
bool pFlow::sphereInteraction<contactForceModel,geometryMotionModel, contactListType>::
|
||||
sphereWallInteraction()
|
||||
{
|
||||
|
||||
int32 lastItem = pwContactList_().loopCount();
|
||||
|
||||
pFlow::sphereInteractionKernels::pwInteractionFunctor
|
||||
pwInteraction(
|
||||
this->dt(),
|
||||
this->forceModel_(),
|
||||
pwContactList_(),
|
||||
geometryMotion_.getTriangleAccessor(),
|
||||
geometryMotion_.getModel() ,
|
||||
sphParticles_.diameter().deviceVectorAll() ,
|
||||
sphParticles_.propertyId().deviceVectorAll(),
|
||||
sphParticles_.pointPosition().deviceVectorAll(),
|
||||
sphParticles_.velocity().deviceVectorAll(),
|
||||
sphParticles_.rVelocity().deviceVectorAll() ,
|
||||
sphParticles_.contactForce().deviceVectorAll(),
|
||||
sphParticles_.contactTorque().deviceVectorAll() ,
|
||||
geometryMotion_.triMotionIndex().deviceVectorAll(),
|
||||
geometryMotion_.propertyId().deviceVectorAll(),
|
||||
geometryMotion_.contactForceWall().deviceVectorAll()
|
||||
);
|
||||
|
||||
Kokkos::parallel_for(
|
||||
"",
|
||||
rpPWInteraction(0,lastItem),
|
||||
pwInteraction
|
||||
);
|
||||
|
||||
|
||||
Kokkos::fence();
|
||||
|
||||
return true;
|
||||
}
|
207
src/Interaction/sphereInteraction/sphereInteraction.H
Normal file
207
src/Interaction/sphereInteraction/sphereInteraction.H
Normal 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 __sphereInteraction_H__
|
||||
#define __sphereInteraction_H__
|
||||
|
||||
#include "interaction.H"
|
||||
#include "sphereParticles.H"
|
||||
|
||||
#include "sphereInteractionKernels.H"
|
||||
|
||||
namespace pFlow
|
||||
{
|
||||
|
||||
template<
|
||||
typename contactForceModel,
|
||||
typename geometryMotionModel,
|
||||
template <class, class, class> class contactListType>
|
||||
class sphereInteraction
|
||||
:
|
||||
public interaction
|
||||
{
|
||||
public:
|
||||
|
||||
using GeometryMotionModel = geometryMotionModel;
|
||||
|
||||
using ContactForceModel = contactForceModel;
|
||||
|
||||
using MotionModel = typename geometryMotionModel::MotionModel;
|
||||
|
||||
using ModelStorage = typename ContactForceModel::contactForceStorage;
|
||||
|
||||
using IdType = typename interaction::IdType;
|
||||
|
||||
using IndexType = typename interaction::IndexType;
|
||||
|
||||
using ExecutionSpace = typename interaction::ExecutionSpace;
|
||||
|
||||
using ContactListType =
|
||||
contactListType<ModelStorage, ExecutionSpace, IdType>;
|
||||
|
||||
using PairsContainerType= typename contactSearch::PairContainerType;
|
||||
|
||||
protected:
|
||||
|
||||
/// const reference to geometry
|
||||
const GeometryMotionModel& geometryMotion_;
|
||||
|
||||
/// const reference to particles
|
||||
const sphereParticles& sphParticles_;
|
||||
|
||||
|
||||
/// contact force model
|
||||
uniquePtr<ContactForceModel> forceModel_ = nullptr;
|
||||
|
||||
/// contact list for particle-particle interactoins (keeps the history)
|
||||
uniquePtr<ContactListType> ppContactList_ = nullptr;
|
||||
|
||||
/// contact list for particle-wall interactions (keeps the history)
|
||||
uniquePtr<ContactListType> pwContactList_ = nullptr;
|
||||
|
||||
/// timer for particle-particle interaction computations
|
||||
Timer ppInteractionTimer_;
|
||||
|
||||
/// timer for particle-wall interaction computations
|
||||
Timer pwInteractionTimer_;
|
||||
|
||||
bool createSphereInteraction();
|
||||
|
||||
bool managePPContactLists();
|
||||
|
||||
bool managePWContactLists();
|
||||
|
||||
/// range policy for p-p interaction execution
|
||||
using rpPPInteraction =
|
||||
Kokkos::RangePolicy<Kokkos::IndexType<int32>, Kokkos::Schedule<Kokkos::Dynamic>>;
|
||||
|
||||
/// range policy for p-w interaction execution
|
||||
using rpPWInteraction = rpPPInteraction;
|
||||
|
||||
public:
|
||||
|
||||
TypeNameTemplate3("sphereInteraction", ContactForceModel, MotionModel, ContactListType);
|
||||
|
||||
// constructor
|
||||
|
||||
sphereInteraction(
|
||||
systemControl& control,
|
||||
const particles& prtcl,
|
||||
const geometry& geom)
|
||||
:
|
||||
interaction(control, prtcl, geom),
|
||||
geometryMotion_(dynamic_cast<const GeometryMotionModel&>(geom)),
|
||||
sphParticles_(dynamic_cast<const sphereParticles&>(prtcl)),
|
||||
ppInteractionTimer_("sphere-sphere interaction", &this->timers()),
|
||||
pwInteractionTimer_("sphere-wall interaction", &this->timers())
|
||||
{
|
||||
if(!createSphereInteraction())
|
||||
{
|
||||
fatalExit;
|
||||
}
|
||||
}
|
||||
|
||||
add_vCtor
|
||||
(
|
||||
interaction,
|
||||
sphereInteraction,
|
||||
systemControl
|
||||
);
|
||||
|
||||
|
||||
bool beforeIteration() override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool iterate() override
|
||||
{
|
||||
|
||||
if(this->contactSearch_)
|
||||
{
|
||||
if( this->contactSearch_().ppEnterBroadSearch())
|
||||
{
|
||||
ppContactList_().beforeBroadSearch();
|
||||
}
|
||||
|
||||
if(this->contactSearch_().pwEnterBroadSearch())
|
||||
{
|
||||
pwContactList_().beforeBroadSearch();
|
||||
}
|
||||
|
||||
if( !contactSearch_().broadSearch(
|
||||
ppContactList_(),
|
||||
pwContactList_()) )
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"unable to perform broadSearch.\n";
|
||||
fatalExit;
|
||||
}
|
||||
|
||||
if(this->contactSearch_().ppPerformedBroadSearch())
|
||||
{
|
||||
ppContactList_().afterBroadSearch();
|
||||
}
|
||||
|
||||
if(this->contactSearch_().pwPerformedBroadSearch())
|
||||
{
|
||||
pwContactList_().afterBroadSearch();
|
||||
}
|
||||
}
|
||||
|
||||
if( sphParticles_.numActive()<=0)return true;
|
||||
|
||||
ppInteractionTimer_.start();
|
||||
sphereSphereInteraction();
|
||||
ppInteractionTimer_.end();
|
||||
|
||||
pwInteractionTimer_.start();
|
||||
sphereWallInteraction();
|
||||
pwInteractionTimer_.end();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool afterIteration() override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool update(const eventMessage& msg)override
|
||||
{
|
||||
// it requires not action regarding any changes in the
|
||||
// point structure
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sphereSphereInteraction();
|
||||
|
||||
bool sphereWallInteraction();
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#include "sphereInteraction.C"
|
||||
|
||||
#endif //__sphereInteraction_H__
|
325
src/Interaction/sphereInteraction/sphereInteractionKernels.H
Normal file
325
src/Interaction/sphereInteraction/sphereInteractionKernels.H
Normal file
@ -0,0 +1,325 @@
|
||||
/*------------------------------- 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 __sphereInteractionKernels_H__
|
||||
#define __sphereInteractionKernels_H__
|
||||
|
||||
|
||||
#include "sphereTriSurfaceContact.H"
|
||||
|
||||
namespace pFlow::sphereInteractionKernels
|
||||
{
|
||||
|
||||
template<
|
||||
typename ContactForceModel,
|
||||
typename ContactListType>
|
||||
struct ppInteractionFunctor
|
||||
{
|
||||
|
||||
using PairType = typename ContactListType::PairType;
|
||||
using ValueType = typename ContactListType::ValueType;
|
||||
|
||||
real dt_;
|
||||
|
||||
ContactForceModel forceModel_;
|
||||
ContactListType tobeFilled_;
|
||||
|
||||
deviceViewType1D<real> diam_;
|
||||
deviceViewType1D<int8> propId_;
|
||||
deviceViewType1D<realx3> pos_;
|
||||
deviceViewType1D<realx3> lVel_;
|
||||
deviceViewType1D<realx3> rVel_;
|
||||
deviceViewType1D<realx3> cForce_;
|
||||
deviceViewType1D<realx3> cTorque_;
|
||||
|
||||
|
||||
ppInteractionFunctor(
|
||||
real dt,
|
||||
ContactForceModel forceModel,
|
||||
ContactListType tobeFilled,
|
||||
deviceViewType1D<real> diam,
|
||||
deviceViewType1D<int8> propId,
|
||||
deviceViewType1D<realx3> pos,
|
||||
deviceViewType1D<realx3> lVel,
|
||||
deviceViewType1D<realx3> rVel,
|
||||
deviceViewType1D<realx3> cForce,
|
||||
deviceViewType1D<realx3> cTorque )
|
||||
:
|
||||
dt_(dt),
|
||||
forceModel_(forceModel),
|
||||
tobeFilled_(tobeFilled),
|
||||
diam_(diam),
|
||||
propId_(propId),
|
||||
pos_(pos),
|
||||
lVel_(lVel),
|
||||
rVel_(rVel),
|
||||
cForce_(cForce), // this is converted to an atomic vector
|
||||
cTorque_(cTorque) // this is converted to an atomic vector
|
||||
{}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
void operator()(const int32 n)const
|
||||
{
|
||||
|
||||
if(!tobeFilled_.isValid(n))return;
|
||||
|
||||
auto [i,j] = tobeFilled_.getPair(n);
|
||||
|
||||
real Ri = 0.5*diam_[i];
|
||||
real Rj = 0.5*diam_[j];
|
||||
realx3 xi = pos_[i];
|
||||
realx3 xj = pos_[j];
|
||||
real dist = length(xj-xi);
|
||||
real ovrlp = (Ri+Rj) - dist;
|
||||
|
||||
if( ovrlp >0.0 )
|
||||
{
|
||||
|
||||
auto Vi = lVel_[i];
|
||||
auto Vj = lVel_[j];
|
||||
auto wi = rVel_[i];
|
||||
auto wj = rVel_[j];
|
||||
auto Nij = (xj-xi)/dist;
|
||||
auto Vr = Vi - Vj + cross((Ri*wi+Rj*wj), Nij);
|
||||
|
||||
auto history = tobeFilled_.getValue(n);
|
||||
|
||||
int32 propId_i = propId_[i];
|
||||
int32 propId_j = propId_[j];
|
||||
|
||||
realx3 FCn, FCt, Mri, Mrj, Mij, Mji;
|
||||
|
||||
// calculates contact force
|
||||
forceModel_.contactForce(
|
||||
dt_, i, j,
|
||||
propId_i, propId_j,
|
||||
Ri, Rj,
|
||||
ovrlp,
|
||||
Vr, Nij,
|
||||
history,
|
||||
FCn, FCt
|
||||
);
|
||||
|
||||
forceModel_.rollingFriction(
|
||||
dt_, i, j,
|
||||
propId_i, propId_j,
|
||||
Ri, Rj,
|
||||
wi, wj,
|
||||
Nij,
|
||||
FCn,
|
||||
Mri, Mrj
|
||||
);
|
||||
|
||||
auto M = cross(Nij,FCt);
|
||||
Mij = Ri*M+Mri;
|
||||
Mji = Rj*M+Mrj;
|
||||
|
||||
auto FC = FCn + FCt;
|
||||
|
||||
Kokkos::atomic_add(&cForce_[i].x_,FC.x_);
|
||||
Kokkos::atomic_add(&cForce_[i].y_,FC.y_);
|
||||
Kokkos::atomic_add(&cForce_[i].z_,FC.z_);
|
||||
|
||||
Kokkos::atomic_add(&cForce_[j].x_,-FC.x_);
|
||||
Kokkos::atomic_add(&cForce_[j].y_,-FC.y_);
|
||||
Kokkos::atomic_add(&cForce_[j].z_,-FC.z_);
|
||||
|
||||
Kokkos::atomic_add(&cTorque_[i].x_, Mij.x_);
|
||||
Kokkos::atomic_add(&cTorque_[i].y_, Mij.y_);
|
||||
Kokkos::atomic_add(&cTorque_[i].z_, Mij.z_);
|
||||
|
||||
Kokkos::atomic_add(&cTorque_[j].x_, Mji.x_);
|
||||
Kokkos::atomic_add(&cTorque_[j].y_, Mji.y_);
|
||||
Kokkos::atomic_add(&cTorque_[j].z_, Mji.z_);
|
||||
|
||||
|
||||
tobeFilled_.setValue(n,history);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
tobeFilled_.setValue(n, ValueType());
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<
|
||||
typename ContactForceModel,
|
||||
typename ContactListType,
|
||||
typename TraingleAccessor,
|
||||
typename MotionModel>
|
||||
struct pwInteractionFunctor
|
||||
{
|
||||
using PairType = typename ContactListType::PairType;
|
||||
using ValueType = typename ContactListType::ValueType;
|
||||
|
||||
real dt_;
|
||||
|
||||
ContactForceModel forceModel_;
|
||||
ContactListType tobeFilled_;
|
||||
|
||||
TraingleAccessor triangles_;
|
||||
MotionModel motionModel_;
|
||||
|
||||
deviceViewType1D<real> diam_;
|
||||
deviceViewType1D<int8> propId_;
|
||||
deviceViewType1D<realx3> pos_;
|
||||
deviceViewType1D<realx3> lVel_;
|
||||
deviceViewType1D<realx3> rVel_;
|
||||
deviceViewType1D<realx3> cForce_;
|
||||
deviceViewType1D<realx3> cTorque_;
|
||||
deviceViewType1D<int8> wTriMotionIndex_;
|
||||
deviceViewType1D<int8> wPropId_;
|
||||
deviceViewType1D<realx3> wCForce_;
|
||||
|
||||
|
||||
pwInteractionFunctor(
|
||||
real dt,
|
||||
ContactForceModel forceModel,
|
||||
ContactListType tobeFilled,
|
||||
TraingleAccessor triangles,
|
||||
MotionModel motionModel ,
|
||||
deviceViewType1D<real> diam ,
|
||||
deviceViewType1D<int8> propId,
|
||||
deviceViewType1D<realx3> pos ,
|
||||
deviceViewType1D<realx3> lVel,
|
||||
deviceViewType1D<realx3> rVel,
|
||||
deviceViewType1D<realx3> cForce,
|
||||
deviceViewType1D<realx3> cTorque ,
|
||||
deviceViewType1D<int8> wTriMotionIndex,
|
||||
deviceViewType1D<int8> wPropId,
|
||||
deviceViewType1D<realx3> wCForce)
|
||||
:
|
||||
dt_(dt),
|
||||
forceModel_(forceModel),
|
||||
tobeFilled_(tobeFilled),
|
||||
triangles_(triangles) ,
|
||||
motionModel_(motionModel) ,
|
||||
diam_(diam) ,
|
||||
propId_(propId),
|
||||
pos_(pos) ,
|
||||
lVel_(lVel),
|
||||
rVel_(rVel) ,
|
||||
cForce_(cForce),
|
||||
cTorque_(cTorque) ,
|
||||
wTriMotionIndex_(wTriMotionIndex) ,
|
||||
wPropId_(wPropId),
|
||||
wCForce_(wCForce)
|
||||
{}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
void operator()(const int32 n)const
|
||||
{
|
||||
|
||||
if(!tobeFilled_.isValid(n))return;
|
||||
|
||||
auto [i,tj] = tobeFilled_.getPair(n);
|
||||
|
||||
real Ri = 0.5*diam_[i];
|
||||
real Rj = 10000.0;
|
||||
realx3 xi = pos_[i];
|
||||
|
||||
realx3x3 tri = triangles_(tj);
|
||||
real ovrlp;
|
||||
realx3 Nij, cp;
|
||||
|
||||
if( pFlow::sphTriInteraction::isSphereInContactBothSides(
|
||||
tri, xi, Ri, ovrlp, Nij, cp) )
|
||||
{
|
||||
auto Vi = lVel_[i];
|
||||
auto wi = rVel_[i];
|
||||
|
||||
int32 mInd = wTriMotionIndex_[tj];
|
||||
|
||||
auto Vw = motionModel_(mInd, cp);
|
||||
|
||||
//output<< "par-wall index "<< i<<" - "<< tj<<endl;
|
||||
|
||||
auto Vr = Vi - Vw + cross(Ri*wi, Nij);
|
||||
|
||||
auto history = tobeFilled_.getValue(n);
|
||||
|
||||
int32 propId_i = propId_[i];
|
||||
int32 wPropId_j = wPropId_[tj];
|
||||
|
||||
realx3 FCn, FCt, Mri, Mrj, Mij, Mji;
|
||||
//output<< "before "<<history.overlap_t_<<endl;
|
||||
// calculates contact force
|
||||
forceModel_.contactForce(
|
||||
dt_, i, tj,
|
||||
propId_i, wPropId_j,
|
||||
Ri, Rj,
|
||||
ovrlp,
|
||||
Vr, Nij,
|
||||
history,
|
||||
FCn, FCt
|
||||
);
|
||||
|
||||
//output<< "after "<<history.overlap_t_<<endl;
|
||||
|
||||
forceModel_.rollingFriction(
|
||||
dt_, i, tj,
|
||||
propId_i, wPropId_j,
|
||||
Ri, Rj,
|
||||
wi, 0.0,
|
||||
Nij,
|
||||
FCn,
|
||||
Mri, Mrj
|
||||
);
|
||||
|
||||
auto M = cross(Nij,FCt);
|
||||
Mij = Ri*M+Mri;
|
||||
//output<< "FCt = "<<FCt <<endl;
|
||||
//output<< "FCn = "<<FCn <<endl;
|
||||
//output<<"propId i, tj"<< propId_i << " "<<wPropId_j<<endl;
|
||||
//output<<"par i , wj"<< i<<" "<< tj<<endl;
|
||||
|
||||
auto FC = FCn + FCt;
|
||||
|
||||
Kokkos::atomic_add(&cForce_[i].x_,FC.x_);
|
||||
Kokkos::atomic_add(&cForce_[i].y_,FC.y_);
|
||||
Kokkos::atomic_add(&cForce_[i].z_,FC.z_);
|
||||
|
||||
Kokkos::atomic_add(&wCForce_[tj].x_,-FC.x_);
|
||||
Kokkos::atomic_add(&wCForce_[tj].y_,-FC.y_);
|
||||
Kokkos::atomic_add(&wCForce_[tj].z_,-FC.z_);
|
||||
|
||||
|
||||
Kokkos::atomic_add(&cTorque_[i].x_, Mij.x_);
|
||||
Kokkos::atomic_add(&cTorque_[i].y_, Mij.y_);
|
||||
Kokkos::atomic_add(&cTorque_[i].z_, Mij.z_);
|
||||
|
||||
tobeFilled_.setValue(n,history);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
tobeFilled_.setValue(n,ValueType());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //__sphereInteractionKernels_H__
|
116
src/Interaction/sphereInteraction/sphereInteractions.C
Normal file
116
src/Interaction/sphereInteraction/sphereInteractions.C
Normal file
@ -0,0 +1,116 @@
|
||||
/*------------------------------- phasicFlow ---------------------------------
|
||||
O C enter of
|
||||
O O E ngineering and
|
||||
O O M ultiscale modeling of
|
||||
OOOOOOO F luid flow
|
||||
------------------------------------------------------------------------------
|
||||
Copyright (C): www.cemf.ir
|
||||
email: hamid.r.norouzi AT gmail.com
|
||||
------------------------------------------------------------------------------
|
||||
Licence:
|
||||
This file is part of phasicFlow code. It is a free software for simulating
|
||||
granular and multiphase flows. You can redistribute it and/or modify it under
|
||||
the terms of GNU General Public License v3 or any other later versions.
|
||||
|
||||
phasicFlow is distributed to help others in their research in the field of
|
||||
granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
#include "sphereInteraction.H"
|
||||
|
||||
#include "geometryMotions.H"
|
||||
|
||||
#include "contactForceModels.H"
|
||||
#include "unsortedContactList.H"
|
||||
#include "sortedContactList.H"
|
||||
|
||||
template class pFlow::sphereInteraction<
|
||||
pFlow::cfModels::limitedLinearNormalRolling,
|
||||
pFlow::fixedGeometry,
|
||||
pFlow::unsortedContactList>;
|
||||
|
||||
template class pFlow::sphereInteraction<
|
||||
pFlow::cfModels::limitedLinearNormalRolling,
|
||||
pFlow::fixedGeometry,
|
||||
pFlow::sortedContactList>;
|
||||
|
||||
template class pFlow::sphereInteraction<
|
||||
pFlow::cfModels::nonLimitedLinearNormalRolling,
|
||||
pFlow::fixedGeometry,
|
||||
pFlow::unsortedContactList>;
|
||||
|
||||
template class pFlow::sphereInteraction<
|
||||
pFlow::cfModels::nonLimitedLinearNormalRolling,
|
||||
pFlow::fixedGeometry,
|
||||
pFlow::sortedContactList>;
|
||||
|
||||
template class pFlow::sphereInteraction<
|
||||
pFlow::cfModels::limitedLinearNormalRolling,
|
||||
pFlow::rotationAxisMotionGeometry,
|
||||
pFlow::unsortedContactList>;
|
||||
|
||||
template class pFlow::sphereInteraction<
|
||||
pFlow::cfModels::limitedLinearNormalRolling,
|
||||
pFlow::rotationAxisMotionGeometry,
|
||||
pFlow::sortedContactList>;
|
||||
|
||||
template class pFlow::sphereInteraction<
|
||||
pFlow::cfModels::nonLimitedLinearNormalRolling,
|
||||
pFlow::rotationAxisMotionGeometry,
|
||||
pFlow::unsortedContactList>;
|
||||
|
||||
template class pFlow::sphereInteraction<
|
||||
pFlow::cfModels::nonLimitedLinearNormalRolling,
|
||||
pFlow::rotationAxisMotionGeometry,
|
||||
pFlow::sortedContactList>;
|
||||
|
||||
|
||||
|
||||
/// non-linear models
|
||||
|
||||
template class pFlow::sphereInteraction<
|
||||
pFlow::cfModels::limitedNonLinearNormalRolling,
|
||||
pFlow::fixedGeometry,
|
||||
pFlow::unsortedContactList>;
|
||||
|
||||
template class pFlow::sphereInteraction<
|
||||
pFlow::cfModels::limitedNonLinearNormalRolling,
|
||||
pFlow::fixedGeometry,
|
||||
pFlow::sortedContactList>;
|
||||
|
||||
template class pFlow::sphereInteraction<
|
||||
pFlow::cfModels::nonLimitedNonLinearNormalRolling,
|
||||
pFlow::fixedGeometry,
|
||||
pFlow::unsortedContactList>;
|
||||
|
||||
template class pFlow::sphereInteraction<
|
||||
pFlow::cfModels::nonLimitedNonLinearNormalRolling,
|
||||
pFlow::fixedGeometry,
|
||||
pFlow::sortedContactList>;
|
||||
|
||||
template class pFlow::sphereInteraction<
|
||||
pFlow::cfModels::limitedNonLinearNormalRolling,
|
||||
pFlow::rotationAxisMotionGeometry,
|
||||
pFlow::unsortedContactList>;
|
||||
|
||||
template class pFlow::sphereInteraction<
|
||||
pFlow::cfModels::limitedNonLinearNormalRolling,
|
||||
pFlow::rotationAxisMotionGeometry,
|
||||
pFlow::sortedContactList>;
|
||||
|
||||
template class pFlow::sphereInteraction<
|
||||
pFlow::cfModels::nonLimitedNonLinearNormalRolling,
|
||||
pFlow::rotationAxisMotionGeometry,
|
||||
pFlow::unsortedContactList>;
|
||||
|
||||
template class pFlow::sphereInteraction<
|
||||
pFlow::cfModels::nonLimitedNonLinearNormalRolling,
|
||||
pFlow::rotationAxisMotionGeometry,
|
||||
pFlow::sortedContactList>;
|
||||
|
||||
|
||||
|
||||
|
||||
|
231
src/Interaction/sphereInteraction/sphereTriSurfaceContact.H
Normal file
231
src/Interaction/sphereInteraction/sphereTriSurfaceContact.H
Normal file
@ -0,0 +1,231 @@
|
||||
/*------------------------------- 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 __sphereTriSurfaceContact_H__
|
||||
#define __sphereTriSurfaceContact_H__
|
||||
|
||||
#include "triWall.H"
|
||||
#include "pLine.H"
|
||||
|
||||
namespace pFlow::sphTriInteraction
|
||||
{
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
bool pointInPlane(
|
||||
const realx3& p1,
|
||||
const realx3& p2,
|
||||
const realx3& p3,
|
||||
const realx3& p )
|
||||
{
|
||||
|
||||
realx3 p1p = p1 - p;
|
||||
realx3 p2p = p2 - p;
|
||||
realx3 p3p = p3 - p;
|
||||
|
||||
real p1p2 = dot(p1p, p2p);
|
||||
real p2p3 = dot(p2p, p3p);
|
||||
real p2p2 = dot(p2p, p2p);
|
||||
real p1p3 = dot(p1p, p3p);
|
||||
|
||||
// first condition u.v < 0
|
||||
// u.v = [(p1-p)x(p2-p)].[(p2-p)x(p3-p)] = (p1p.p2p)(p2p.p3p) - (p2p.p2p)(p1p.p3p)
|
||||
if (p1p2*p2p3 - p2p2*p1p3 < 0.0) return false;
|
||||
|
||||
|
||||
// second condition u.w < 0
|
||||
// u.w = [(p1-p)x(p2-p)].[(p3-p)x(p1-p)] = (p1p.p3p)(p2p.p1p) - (p2p.p3p)(p1p.p1p)
|
||||
real p1p1 = dot(p1p, p1p);
|
||||
if (p1p3*p1p2 - p2p3*p1p1 < (0.0)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
void cramerRule2(real A[2][2], real B[2], real & x1, real &x2)
|
||||
{
|
||||
real det = (A[0][0] * A[1][1] - A[1][0]*A[0][1]);
|
||||
x1 = (B[0]*A[1][1] - B[1]*A[0][1]) / det;
|
||||
x2 = (A[0][0] * B[1] - A[1][0] * B[0])/ det;
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
bool pointInPlane(
|
||||
const realx3& p1,
|
||||
const realx3& p2,
|
||||
const realx3& p3,
|
||||
const realx3 &p,
|
||||
int32 &Ln)
|
||||
{
|
||||
realx3 v0 = p2 - p1;
|
||||
realx3 v1 = p3 - p1;
|
||||
realx3 v2 = p - p1;
|
||||
|
||||
real A[2][2] = { dot(v0, v0), dot(v0, v1), dot(v1, v0), dot(v1, v1) };
|
||||
real B[2] = { dot(v0, v2), dot(v1, v2) };
|
||||
real nu, w;
|
||||
|
||||
cramerRule2(A, B, nu, w);
|
||||
real nuW = nu + w;
|
||||
|
||||
|
||||
if (nuW > 1)
|
||||
{
|
||||
Ln = 2; return true;
|
||||
}
|
||||
else if (nuW >= 0)
|
||||
{
|
||||
if (nu >= 0 && w >= 0)
|
||||
{
|
||||
Ln = 0; return true;
|
||||
}
|
||||
if (nu > 0 && w < 0)
|
||||
{
|
||||
Ln = 1; return true;
|
||||
}
|
||||
if (nu < 0 && w > 0)
|
||||
{
|
||||
Ln = 3; return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Ln = 1; return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
bool isSphereInContactActiveSide(
|
||||
const realx3& p1,
|
||||
const realx3& p2,
|
||||
const realx3& p3,
|
||||
const realx3& cntr,
|
||||
real rad,
|
||||
real& ovrlp,
|
||||
realx3& norm,
|
||||
realx3& cp)
|
||||
{
|
||||
|
||||
triWall wall(true, p1,p2,p3);
|
||||
|
||||
real dist = wall.normalDistFromWall(cntr);
|
||||
|
||||
if(dist < 0.0 )return false;
|
||||
|
||||
ovrlp = rad - dist;
|
||||
|
||||
if (ovrlp > 0)
|
||||
{
|
||||
realx3 ptOnPlane = wall.nearestPointOnWall(cntr);
|
||||
|
||||
if (pointInPlane(p1, p2, p3, ptOnPlane))
|
||||
{
|
||||
cp = ptOnPlane;
|
||||
norm = -wall.n_;
|
||||
return true;
|
||||
}
|
||||
|
||||
realx3 lnv;
|
||||
|
||||
if (pLine(p1,p2).lineSphereCheck(cntr, rad, lnv, cp, ovrlp))
|
||||
{
|
||||
norm = -lnv;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( pLine(p2,p3).lineSphereCheck(cntr, rad, lnv, cp, ovrlp))
|
||||
{
|
||||
norm = -lnv;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( pLine(p3,p1).lineSphereCheck(cntr, rad, lnv, cp, ovrlp))
|
||||
{
|
||||
norm = -lnv;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
bool isSphereInContactBothSides(
|
||||
const realx3x3& tri,
|
||||
const realx3& cntr,
|
||||
real Rad,
|
||||
real& ovrlp,
|
||||
realx3& norm,
|
||||
realx3& cp)
|
||||
{
|
||||
|
||||
triWall wall(true, tri.x_,tri.y_,tri.z_);
|
||||
|
||||
real dist = wall.normalDistFromWall(cntr);
|
||||
|
||||
|
||||
ovrlp = Rad - abs(dist);
|
||||
|
||||
if (ovrlp > 0)
|
||||
{
|
||||
realx3 ptOnPlane = wall.nearestPointOnWall(cntr);
|
||||
|
||||
if (pointInPlane(tri.x_,tri.y_,tri.z_,ptOnPlane))
|
||||
{
|
||||
cp = ptOnPlane;
|
||||
|
||||
if(dist >= 0.0)
|
||||
norm = -wall.n_;
|
||||
else
|
||||
norm = wall.n_;
|
||||
return true;
|
||||
}
|
||||
|
||||
realx3 lnv;
|
||||
|
||||
if (pLine(tri.x_, tri.y_).lineSphereCheck(cntr, Rad, lnv, cp, ovrlp))
|
||||
{
|
||||
norm = -lnv;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( pLine(tri.y_, tri.z_).lineSphereCheck(cntr, Rad, lnv, cp, ovrlp))
|
||||
{
|
||||
norm = -lnv;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( pLine(tri.z_, tri.x_).lineSphereCheck(cntr, Rad, lnv, cp, ovrlp))
|
||||
{
|
||||
norm = -lnv;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
} // pFlow::sphTriInteraction
|
||||
|
||||
|
||||
#endif //__sphereTriSurfaceContact_H__
|
108
src/Interaction/sphereInteraction/triWall.H
Normal file
108
src/Interaction/sphereInteraction/triWall.H
Normal file
@ -0,0 +1,108 @@
|
||||
/*------------------------------- 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 __triWall_H__
|
||||
#define __triWall_H__
|
||||
|
||||
#include "types.H"
|
||||
|
||||
namespace pFlow::sphTriInteraction
|
||||
{
|
||||
|
||||
struct triWall
|
||||
{
|
||||
|
||||
realx3 n_;
|
||||
real offset_;
|
||||
|
||||
INLINE_FUNCTION_H
|
||||
triWall(const realx3& p1, const realx3& p2, const realx3& p3)
|
||||
{
|
||||
if(!makeWall(p1,p2,p3, n_, offset_))
|
||||
{
|
||||
fatalErrorInFunction<<
|
||||
"bad input for the wall.\n";
|
||||
fatalExit;
|
||||
}
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
triWall(bool, const realx3& p1, const realx3& p2, const realx3& p3)
|
||||
{
|
||||
makeWall(p1,p2,p3,n_,offset_);
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
triWall(const realx3x3& tri)
|
||||
{
|
||||
makeWall(tri.x_, tri.y_, tri.z_, n_, offset_);
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
triWall(const triWall&) = default;
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
triWall& operator=(const triWall&) = default;
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
triWall(triWall&&) = default;
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
triWall& operator=(triWall&&) = default;
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
~triWall()=default;
|
||||
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
real normalDistFromWall(const realx3 &p) const
|
||||
{
|
||||
return dot(n_, p) + offset_;
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD
|
||||
realx3 nearestPointOnWall(const realx3 &p) const
|
||||
{
|
||||
real t = -(dot(n_, p) + offset_);
|
||||
return realx3(n_.x_*t + p.x_, n_.y_*t + p.y_, n_.z_*t + p.z_);
|
||||
}
|
||||
|
||||
INLINE_FUNCTION_HD static
|
||||
bool makeWall(
|
||||
const realx3& p1,
|
||||
const realx3& p2,
|
||||
const realx3& p3,
|
||||
realx3& n, real& offset)
|
||||
{
|
||||
n = cross(p2 - p1, p3 - p1);
|
||||
real len = length(n);
|
||||
|
||||
if (len < 0.00000000001) return false;
|
||||
n /= len;
|
||||
offset = -dot(n, p1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user