Commit 3b5f6763 authored by Christoph Rettinger's avatar Christoph Rettinger

Added functionality, tests and showcase for discrete particle method coupling

parent f857c933
Pipeline #6543 passed with stage
in 120 minutes and 6 seconds
waLBerla_add_executable ( NAME BidisperseFluidizedBedDPM
DEPENDS blockforest boundary core domain_decomposition field lbm pe pe_coupling postprocessing timeloop vtk )
\ No newline at end of file
add_subdirectory( BidisperseFluidizedBed )
\ No newline at end of file
......@@ -24,6 +24,7 @@
#pragma once
#include "discrete_particle_methods/all.h"
#include "mapping/all.h"
#include "geometry/all.h"
#include "partially_saturated_cells_method/all.h"
......
//======================================================================================================================
//
// This file is part of waLBerla. waLBerla is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// waLBerla is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
//
//! \file all.h
//! \ingroup pe_coupling
//! \author Christoph Rettinger <christoph.rettinger@fau.de>
//
//======================================================================================================================
#pragma once
#include "waLBerlaDefinitions.h"
#include "correlations/all.h"
#include "evaluators/all.h"
#include "gns_lbm/all.h"
#include "utility/all.h"
//======================================================================================================================
//
// This file is part of waLBerla. waLBerla is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// waLBerla is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
//
//! \file AddedMassForceCorrelations.h
//! \ingroup pe_coupling
//! \author Christoph Rettinger <christoph.rettinger@fau.de>
//
//======================================================================================================================
#pragma once
#include "core/DataTypes.h"
#include <cmath>
namespace walberla {
namespace pe_coupling {
namespace discrete_particle_methods {
/*!\brief Correlation functions for the added mass force.
*
* To be compatible with the interface of AddedMassForceEvaluator, all functions use the following signature:
* Vector3<real_t> ( const Vector3<real_t> & timeDerivativeFluidVel, const Vector3<real_t> & timeDerivativeBodyVel,
* const real_t & bodyVolume, const real_t & fluidDensity )
*/
Vector3<real_t> addedMassForceFinn( const Vector3<real_t> & timeDerivativeFluidVel, const Vector3<real_t> & timeDerivativeBodyVel,
const real_t & bodyVolume, const real_t & fluidDensity )
{
// formula from Finn et al(2016)
const real_t Coeffam = real_t(0.5);
return bodyVolume * fluidDensity * Coeffam * ( timeDerivativeFluidVel - timeDerivativeBodyVel );
}
Vector3<real_t> noAddedMassForce( const Vector3<real_t> &, const Vector3<real_t> &, const real_t &, const real_t & )
{
return Vector3<real_t>(real_t(0));
}
} // namespace discrete_particle_methods
} // namespace pe_coupling
} // namespace walberla
//======================================================================================================================
//
// This file is part of waLBerla. waLBerla is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// waLBerla is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
//
//! \file LiftForceCorrelations.h
//! \ingroup pe_coupling
//! \author Christoph Rettinger <christoph.rettinger@fau.de>
//
//======================================================================================================================
#pragma once
#include "core/DataTypes.h"
#include <cmath>
namespace walberla {
namespace pe_coupling {
namespace discrete_particle_methods {
/*!\brief Correlation functions for the lift force.
*
* To be compatible with the interface of LiftForceEvaluator, all functions use the following signature:
* Vector3<real_t> ( const Vector3<real_t> & fluidVel, const Vector3<real_t> & curlFluidVel, const Vector3<real_t> & particleVel,
* real_t diameter, real_t fluidDynamicViscosity, real_t fluidDensity )
*/
// Saffman lift force
Vector3<real_t> liftForceSaffman ( const Vector3<real_t> & fluidVel, const Vector3<real_t> & curlFluidVel, const Vector3<real_t> & particleVel,
real_t diameter, real_t fluidDynamicViscosity, real_t fluidDensity )
{
const real_t absCurlVel = curlFluidVel.length();
if( absCurlVel < real_t(1e-10) ) return Vector3<real_t>(real_t(0));
// Finn et al (2016) for spheres
const real_t Cl = real_t(1.61) * std::sqrt( ( fluidDynamicViscosity * fluidDensity) / absCurlVel );
return Cl * diameter * diameter * ( ( fluidVel - particleVel ) % curlFluidVel );
// Sun, Xiao (2016)
//const real_t Cl = real_t(1.6);
//return Cl * fluidDensity * std::sqrt( fluidDynamicViscosity / fluidDensity ) * diameter * diameter * ( ( fluidVel - particleVel ) % curlFluidVel );
}
Vector3<real_t> noLiftForce ( const Vector3<real_t> &, const Vector3<real_t> &, const Vector3<real_t> &, real_t, real_t, real_t )
{
return Vector3<real_t>(real_t(0));
}
} // namespace discrete_particle_methods
} // namespace pe_coupling
} // namespace walberla
//======================================================================================================================
//
// This file is part of waLBerla. waLBerla is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// waLBerla is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
//
//! \file all.h
//! \ingroup pe_coupling
//! \author Christoph Rettinger <christoph.rettinger@fau.de>
//
//======================================================================================================================
#pragma once
#include "waLBerlaDefinitions.h"
#include "AddedMassForceCorrelations.h"
#include "DragForceCorrelations.h"
#include "LiftForceCorrelations.h"
//======================================================================================================================
//
// This file is part of waLBerla. waLBerla is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// waLBerla is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
//
//! \file AddedMassForceEvaluator.h
//! \ingroup pe_coupling
//! \author Christoph Rettinger <christoph.rettinger@fau.de>
//
//======================================================================================================================
#pragma once
#include "core/DataTypes.h"
#include "core/debug/Debug.h"
#include "domain_decomposition/StructuredBlockStorage.h"
#include "field/interpolators/all.h"
#include "field/distributors/all.h"
#include "field/GhostLayerField.h"
#include "lbm/field/MacroscopicValueCalculation.h"
#include "lbm/field/PdfField.h"
#include "lbm/lattice_model/ForceModel.h"
#include "pe/rigidbody/BodyIterators.h"
#include "pe/rigidbody/RigidBody.h"
#include "pe/Types.h"
#include "pe/Materials.h"
#include "BodyVelocityTimeDerivativeEvaluator.h"
#include "stencil/Directions.h"
#include <boost/function.hpp>
namespace walberla {
namespace pe_coupling {
namespace discrete_particle_methods {
/*!\brief Evaluator of the added (virtual) mass force based on the given added mass correlation.
*
* The added mass force is evaluated for each body (requires interpolation of several quantities from the fluid fields)
* and then applied onto them.
* The corresponding reaction force is added to the fluid via the given distributor.
*
* Note that the fluid velocity (and its derivatives) has to be the fluid-phase velocity (and not the volume-averaged velocity).
*
* For more infos on interpolators, see field interpolators in src/field/interpolators.
* For more infos on distributors, see src/field/distributors.
*/
template< typename FlagField_T, template<typename,typename> class FieldInterpolator_T, template<typename,typename> class Distributor_T >
class AddedMassForceEvaluator
{
public:
typedef GhostLayerField< Vector3<real_t>, 1> Vec3Field_T;
typedef FieldInterpolator_T<Vec3Field_T, FlagField_T> Vec3FieldInterpolator_T;
typedef Distributor_T<Vec3Field_T, FlagField_T> ForceDistributor_T;
AddedMassForceEvaluator( const shared_ptr<StructuredBlockStorage> & blockStorage,
const BlockDataID & forceFieldID, const BlockDataID & bodyStorageID,
const BlockDataID & flagFieldID, const Set< FlagUID > & domainFlags,
const BlockDataID & velocityTimeDerivativeFieldID,
const boost::function<Vector3<real_t> ( const Vector3<real_t> &, const Vector3<real_t> &, real_t, real_t )> & addedMassForceCorrelationFunction,
const shared_ptr< BodyVelocityTimeDerivativeEvaluator > & bodyVelocityTimeDerivativeEvaluator )
: blockStorage_( blockStorage ), bodyStorageID_( bodyStorageID ),
addedMassForceCorrelationFunction_( addedMassForceCorrelationFunction ), bodyVelocityTimeDerivativeEvaluator_( bodyVelocityTimeDerivativeEvaluator )
{
velocityTimeDerivativeFieldInterpolatorID_ = field::addFieldInterpolator< Vec3FieldInterpolator_T, FlagField_T >( blockStorage, velocityTimeDerivativeFieldID, flagFieldID, domainFlags );
forceDistributorID_ = field::addDistributor< ForceDistributor_T, FlagField_T >( blockStorage, forceFieldID, flagFieldID, domainFlags );
}
void operator()();
private:
shared_ptr<StructuredBlockStorage> blockStorage_;
const BlockDataID bodyStorageID_;
boost::function<Vector3<real_t> ( const Vector3<real_t> &, const Vector3<real_t> &, real_t, real_t )> addedMassForceCorrelationFunction_;
shared_ptr< BodyVelocityTimeDerivativeEvaluator > bodyVelocityTimeDerivativeEvaluator_;
BlockDataID velocityTimeDerivativeFieldInterpolatorID_;
BlockDataID forceDistributorID_;
};
template< typename FlagField_T, template<typename,typename> class FieldInterpolator_T, template<typename,typename> class Distributor_T >
void AddedMassForceEvaluator< FlagField_T, FieldInterpolator_T, Distributor_T >
::operator()()
{
for( auto blockIt = blockStorage_->begin(); blockIt != blockStorage_->end(); ++blockIt )
{
Vec3FieldInterpolator_T * velocityTimeDerivativeInterpolator = blockIt->getData< Vec3FieldInterpolator_T >( velocityTimeDerivativeFieldInterpolatorID_ );
ForceDistributor_T * forceDistributor = blockIt->getData< ForceDistributor_T >( forceDistributorID_ );
for( auto bodyIt = pe::LocalBodyIterator::begin(*blockIt, bodyStorageID_); bodyIt != pe::LocalBodyIterator::end(); ++bodyIt )
{
//TODO check if body should be treated by DPM
Vector3<real_t> forceOnFluid( real_t(0) );
Vector3<real_t> bodyPosition = bodyIt->getPosition();
Vector3<real_t> bodyVelocity = bodyIt->getLinearVel();
real_t bodyVolume = bodyIt->getVolume();
real_t fluidDensity( real_t(1) );
// evaluate added (virtual) mass force
Vector3<real_t> timeDerivativeFluidVelocity( real_t(0) );
Vector3<real_t> timeDerivativeBodyVelocity( real_t(0) );
bodyVelocityTimeDerivativeEvaluator_->get(timeDerivativeBodyVelocity, bodyVelocity, bodyIt->getSystemID() );
velocityTimeDerivativeInterpolator->get( bodyPosition, &timeDerivativeFluidVelocity );
Vector3<real_t> addedMassForce = addedMassForceCorrelationFunction_( timeDerivativeFluidVelocity, timeDerivativeBodyVelocity, bodyVolume, fluidDensity );
WALBERLA_ASSERT( !math::isnan(addedMassForce[0]) && !math::isnan(addedMassForce[1]) && !math::isnan(addedMassForce[2]),
"NaN found in added mass force for body at position " << bodyPosition );
bodyIt->addForce( addedMassForce );
forceOnFluid += ( -addedMassForce );
// set/distribute force on fluid
forceDistributor->distribute( bodyPosition, &forceOnFluid );
}
}
}
} // namespace discrete_particle_methods
} // namespace pe_coupling
} // namespace walberla
//======================================================================================================================
//
// This file is part of waLBerla. waLBerla is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// waLBerla is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
//
//! \file BodyVelocityTimeDerivativeEvaluator.h
//! \ingroup pe_coupling
//! \author Christoph Rettinger <christoph.rettinger@fau.de>
//
//======================================================================================================================
#pragma once
#include "domain_decomposition/StructuredBlockStorage.h"
#include "pe/rigidbody/BodyIterators.h"
#include <map>
namespace walberla {
namespace pe_coupling {
namespace discrete_particle_methods {
/*!\brief Evaluates the time derivative of the body velocity
*
* Using the operator()(), an internal map is filled with pairs of the body ID and its current velocity,
* after clearing the old map.
* Calling get(..), the body's former velocity is fetched from the map and used to calculate a simple approximation of the
* body velocity time derivative (du/dt = ( u_new - u_old ) / deltaT )
*
*/
class BodyVelocityTimeDerivativeEvaluator
{
public:
BodyVelocityTimeDerivativeEvaluator( const shared_ptr<StructuredBlockStorage> & blockStorage,
const BlockDataID & bodyStorageID, const real_t & deltaT = real_t(1) )
: blockStorage_( blockStorage ), bodyStorageID_( bodyStorageID ), deltaTinv_( real_t(1) / deltaT )
{ }
void operator()()
{
// rebuild velocity map for all known bodies (process local)
bodyVelocityMap_.clear();
for( auto blockIt = blockStorage_->begin(); blockIt != blockStorage_->end(); ++blockIt )
{
for( auto bodyIt = pe::BodyIterator::begin(*blockIt, bodyStorageID_); bodyIt != pe::BodyIterator::end(); ++bodyIt )
{
bodyVelocityMap_.insert( std::pair<walberla::id_t, Vector3< real_t > >( bodyIt->getSystemID(), bodyIt->getLinearVel() ) );
}
}
}
void resetDeltaT( const real_t & deltaT )
{
deltaTinv_ = real_t(1) / deltaT;
}
void get( Vector3<real_t> & particleVelocityTimeDerivative, const Vector3<real_t> currentParticleVelocity, const walberla::id_t & bodySystemID )
{
auto it = bodyVelocityMap_.find( bodySystemID );
WALBERLA_ASSERT( it != bodyVelocityMap_.end(), "body with ID " << bodySystemID << " not found in body velocity map!" );
particleVelocityTimeDerivative = ( currentParticleVelocity - it->second ) * deltaTinv_;
}
private:
shared_ptr<StructuredBlockStorage> blockStorage_;
const BlockDataID bodyStorageID_;
std::map< walberla::id_t, Vector3< real_t > > bodyVelocityMap_;
real_t deltaTinv_;
};
} // namespace discrete_particle_methods
} // namespace pe_coupling
} // namespace walberla
//======================================================================================================================
//
// This file is part of waLBerla. waLBerla is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// waLBerla is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
//
//! \file EffectiveViscosityFieldEvaluator.h
//! \ingroup pe_coupling
//! \author Christoph Rettinger <christoph.rettinger@fau.de>
//
//======================================================================================================================
#pragma once
#include "lbm/lattice_model/CollisionModel.h"
#include "field/GhostLayerField.h"
namespace walberla {
namespace pe_coupling {
namespace discrete_particle_methods {
// correlations for the viscosity
// no change in viscosity
real_t calculateUnchangedEffectiveViscosity( real_t fluidViscosity, real_t /*porosity*/ )
{
return fluidViscosity;
}
// see: Fattahi, Waluga, Wohlmuth - "Large scale lattice Boltzmann simulation for the coupling of free and porous media flow"
real_t calculateRescaledEffectiveViscosity( real_t fluidViscosity, real_t porosity )
{
return fluidViscosity / porosity;
}
// see: J. R. Finn, M. Li, S. V. Apte - "Particle based modelling and simulation of natural sand dynamics in the wave
// bottom boundary layer", Journal of Fluid Mechanics 796 (2016) 340–385. doi:10.1017/jfm.2016.246.
real_t calculateEilersEffectiveViscosity( real_t fluidViscosity, real_t porosity )
{
const real_t closePackingFraction = real_t(0.64);
const real_t intrinsicViscosity = real_t(2.5); //for monosized spheres
const real_t temp = real_t(1) + real_t(0.5) * intrinsicViscosity * ( real_t(1) - porosity ) / ( porosity / closePackingFraction );
return fluidViscosity * temp * temp;
}
/*!\brief Evaluates the (local) effective viscosity.
*
* The effective viscosity (using the provided correlation) is evaluated for each cell and stored,
* as the respective omega value, in a field, that can be given to a suitable LBM sweep.
*
*/
class EffectiveViscosityFieldEvaluator
{
public:
typedef GhostLayerField< real_t, 1 > ScalarField_T;
EffectiveViscosityFieldEvaluator( const BlockDataID & omegaFieldID, const ConstBlockDataID & solidVolumeFractionFieldID,
const real_t & fluidViscosity,
const boost::function<real_t (real_t, real_t)> & effectiveViscosityFunc )
: omegaFieldID_( omegaFieldID ), solidVolumeFractionFieldID_( solidVolumeFractionFieldID ), fluidViscosity_( fluidViscosity ),
effectiveViscosityFunc_( effectiveViscosityFunc )
{
}
void operator()( IBlock * const block )
{
ScalarField_T* omegaField = block->getData<ScalarField_T>(omegaFieldID_);
const ScalarField_T* svfField = block->getData<ScalarField_T>(solidVolumeFractionFieldID_);
WALBERLA_FOR_ALL_CELLS_XYZ(omegaField,
const real_t porosity = real_t(1) - svfField->get(x,y,z);
WALBERLA_ASSERT_FLOAT_UNEQUAL(porosity, real_t(0));
real_t effectiveViscosity = effectiveViscosityFunc_(fluidViscosity_, porosity);
//TODO: add level dependence for omega calculation
omegaField->get(x,y,z) = lbm::collision_model::omegaFromViscosity(effectiveViscosity);
)
}
void resetFluidViscosity( real_t newFluidViscosity )
{
fluidViscosity_ = newFluidViscosity;
}
private:
const BlockDataID omegaFieldID_;
const ConstBlockDataID solidVolumeFractionFieldID_;
real_t fluidViscosity_;
boost::function<real_t (real_t, real_t)> effectiveViscosityFunc_;
};
} // namespace discrete_particle_methods
} // namespace pe_coupling
} // namespace walberla
//======================================================================================================================
//
// This file is part of waLBerla. waLBerla is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// waLBerla is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
//
//! \file InteractionForceEvaluator.h
//! \ingroup pe_coupling
//! \author Christoph Rettinger <christoph.rettinger@fau.de>
//
//======================================================================================================================
#pragma once
#include "core/DataTypes.h"
#include "core/debug/Debug.h"
#include "domain_decomposition/StructuredBlockStorage.h"
#include "field/interpolators/all.h"
#include "field/distributors/all.h"
#include "field/GhostLayerField.h"
#include "lbm/field/MacroscopicValueCalculation.h"
#include "lbm/field/PdfField.h"
#include "lbm/lattice_model/ForceModel.h"
#include "pe/rigidbody/BodyIterators.h"
#include "pe/rigidbody/RigidBody.h"
#include "pe/rigidbody/Sphere.h"
#include "pe/Types.h"
#include "pe/Materials.h"
#include "pe_coupling/geometry/SphereEquivalentDiameter.h"
#include "stencil/Directions.h"
#include <boost/function.hpp>
#include <vector>
#include <cmath>
namespace walberla {
namespace pe_coupling {
namespace discrete_particle_methods {
/*!\brief Evaluator of the two most important interaction forces: drag and pressure gradient
*
* The evaluation of the drag force is based on the given drag correlation.
* The pressure gradient force requires a valid pressure gradient field.
* These two forces are evaluated for each body (requires interpolation of several quantities from the fluid fields)
* and then applied onto them.
* However, only the drag force (with negative sign) is applied (i.e. distributed) onto the fluid since it is assumed that
* the pressure force is already implicitly included in the formulation of the equations that describe the fluid flow.
*
* Note that the fluid velocity, contained in the velocityField, has to be the fluid-phase velocity (and not the volume-averaged velocity).
*
* For more infos on interpolators, see field interpolators in src/field/interpolators.
* For more infos on distributors, see src/field/distributors.
*/
template< typename FlagField_T, template<typename,typename> class FieldInterpolator_T, template<typename,typename> class Distributor_T >
class InteractionForceEvaluator
{
public:
typedef GhostLayerField< Vector3<real_t>, 1> Vec3Field_T;
typedef GhostLayerField< real_t, 1> ScalarField_T;
typedef FieldInterpolator_T<Vec3Field_T, FlagField_T> Vec3FieldInterpolator_T;
typedef FieldInterpolator_T<ScalarField_T, FlagField_T> ScalarFieldInterpolator_T;
typedef Distributor_T<Vec3Field_T, FlagField_T> ForceDistributor_T;
InteractionForceEvaluator( const shared_ptr<StructuredBlockStorage> & blockStorage,
const BlockDataID & forceFieldID, const BlockDataID & bodyStorageID,
const BlockDataID & flagFieldID, const Set< FlagUID > & domainFlags,
const BlockDataID & velocityFieldID, const BlockDataID & solidVolumeFractionFieldID, const BlockDataID & pressureGradientFieldID,
const boost::function<Vector3<real_t> ( const Vector3<real_t> &, const Vector3<real_t> &, real_t, real_t, real_t, real_t )> & dragForceCorrelationFunction,
real_t fluidDynamicViscosity )
: blockStorage_( blockStorage ), bodyStorageID_( bodyStorageID ),
dragForceCorrelationFunction_( dragForceCorrelationFunction ), fluidDynamicViscosity_( fluidDynamicViscosity )
{
velocityFieldInterpolatorID_ = field::addFieldInterpolator< Vec3FieldInterpolator_T, FlagField_T >( blockStorage, velocityFieldID, flagFieldID, domainFlags );
solidVolumeFractionFieldInterpolatorID_ = field::addFieldInterpolator< ScalarFieldInterpolator_T, FlagField_T >( blockStorage, solidVolumeFractionFieldID, flagFieldID, domainFlags );
pressureGradientFieldInterpolatorID_ = field::addFieldInterpolator< Vec3FieldInterpolator_T, FlagField_T >( blockStorage, pressureGradientFieldID, flagFieldID, domainFlags );
forceDistributorID_ = field::addDistributor< ForceDistributor_T, FlagField_T >( blockStorage, forceFieldID, flagFieldID, domainFlags );
}
void operator()();
private:
shared_ptr<StructuredBlockStorage> blockStorage_;
const BlockDataID bodyStorageID_;
const BlockDataID pdfFieldID_;
boost::function<Vector3<real_t> ( const Vector3<real_t> &, const Vector3<real_t> &, real_t, real_t, real_t, real_t )> dragForceCorrelationFunction_;
BlockDataID velocityFieldInterpolatorID_;
BlockDataID solidVolumeFractionFieldInterpolatorID_;
BlockDataID pressureGradientFieldInterpolatorID_;
BlockDataID forceDistributorID_;
real_t fluidDynamicViscosity_;
};
template< typename FlagField_T, template<typename,typename> class FieldInterpolator_T, template<typename,typename> class Distributor_T >
void InteractionForceEvaluator< FlagField_T, FieldInterpolator_T, Distributor_T >
::operator()()
{
for( auto blockIt = blockStorage_->begin(); blockIt != blockStorage_->end(); ++blockIt )
{