OpenLB 1.7
Loading...
Searching...
No Matches
latticeMomentumExchangeForce.hh
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2012 Robin Trunk, Mathias J. Kraus
4 * 2021 Nicolas Hafen
5 * E-mail contact: info@openlb.net
6 * The most recent release of OpenLB can be downloaded at
7 * <http://www.openlb.net/>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public
20 * License along with this program; if not, write to the Free
21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23*/
24
25#ifndef LATTICE_MOMENTUM_EXCHANGE_FORCE_HH
26#define LATTICE_MOMENTUM_EXCHANGE_FORCE_HH
27
30
31namespace olb {
32
33
34template <typename T, typename DESCRIPTOR, typename PARTICLETYPE, typename BLOCKFUNCTOR>
37 const SuperGeometry<T,DESCRIPTOR::d>& superGeometry,
39 const UnitConverter<T,DESCRIPTOR>& converter,
40 Vector<bool,DESCRIPTOR::d> periodic, std::size_t iP0,
41 const std::unordered_set<int>& ignoredMaterials, const F f )
42 : SuperLatticePhysF<T,DESCRIPTOR>(sLattice,converter,
43 (DESCRIPTOR::d+utilities::dimensions::convert<DESCRIPTOR::d>::rotation+1)*(particleSystem.size()-iP0))
44{
45 constexpr unsigned D = DESCRIPTOR::d;
46
47 this->getName() = "physParticleForce";
48 int maxC = this->_sLattice.getLoadBalancer().size();
49 this->_blockF.reserve(maxC);
50 const PhysR<T,D> min = particles::communication::getCuboidMin<T,D>(
51 superGeometry.getCuboidGeometry());
52 const PhysR<T,D> max = particles::communication::getCuboidMax<T,D>(
53 superGeometry.getCuboidGeometry(), min);
54
55 for (int iC = 0; iC < maxC; ++iC) {
56 this->_blockF.emplace_back( new BLOCKFUNCTOR(
57 this->_sLattice.getBlock(iC),
58 superGeometry.getBlockGeometry(iC),
59 particleSystem, converter, min, max,
60 periodic, iP0, ignoredMaterials, f));
61 }
62}
63
64template <typename T, typename DESCRIPTOR, typename PARTICLETYPE, typename BLOCKFUNCTOR>
66 const int input[])
67{
68 for (int iS=0; iS<this->getTargetDim(); ++iS) {
69 output[iS] = 0.;
70 }
71 for (int iC = 0; iC < this->_sLattice.getLoadBalancer().size(); ++iC) {
72 this->getBlockF(iC)(output, &input[1]);
73 }
74
75#ifdef PARALLEL_MODE_MPI
76 for (int iS = 0; iS < this->getTargetDim(); ++iS) {
77 singleton::mpi().reduceAndBcast(output[iS], MPI_SUM);
78 }
79#endif
80 return true;
81
82}
83
84
85template<typename T, typename DESCRIPTOR, typename PARTICLETYPE>
87 BlockLattice<T, DESCRIPTOR>& blockLattice,
88 const BlockGeometry<T,DESCRIPTOR::d>& blockGeometry,
90 const UnitConverter<T,DESCRIPTOR>& converter,
92 Vector<bool,DESCRIPTOR::d> periodic, std::size_t iP0,
93 const std::unordered_set<int>& ignoredMaterials, const F f )
94 : BlockLatticePhysF<T,DESCRIPTOR>(blockLattice, converter,
95 (DESCRIPTOR::d+utilities::dimensions::convert<DESCRIPTOR::d>::rotation+1)*(particleSystem.size()-iP0)),
96 _blockGeometry(blockGeometry), _blockLattice(blockLattice),
97 _particleSystem(particleSystem),
98 _cellMin(cellMin), _cellMax(cellMax), _periodic(periodic),
99 _iP0(iP0), _ignoredMaterials(ignoredMaterials), _f(f)
100{
101 this->getName() = "physMomentumExchangeForce";
102}
103
104template<typename T, typename DESCRIPTOR, typename PARTICLETYPE>
106{
107 constexpr unsigned D = DESCRIPTOR::d;
108 constexpr unsigned Drot = utilities::dimensions::convert<D>::rotation; //TODO: prevent rotation calculatiion, when no angle
109 constexpr int serialSize = D+Drot+1;
110
111 using namespace descriptors;
112 const PhysR<T, D> position = particles::access::getPosition(particle);
113 const T circumRadius = particles::access::getRadius(particle);
114
115 //For all cells in block particle intersection
116 int numVoxels = 0;
117 constexpr int padding = 0;
118 const std::size_t iPeval = iP - _iP0; //Shifted output index, if iP!=0
120 _blockLattice, padding, position, circumRadius,
121 [&](const LatticeR<D>& latticeRinner) {
122
123 if (_ignoredMaterials.find(_blockGeometry.getMaterial(latticeRinner)) == _ignoredMaterials.end()) {
124 Vector<T,D>tmpForce(0.);
125 PhysR<T,D> lever(0.);
126 if ( particles::resolved::momentumExchangeAtSurfaceLocation(tmpForce.data(),
127 lever, latticeRinner, this->_blockGeometry,
128 this->_blockLattice, this->_converter, particle) ){
129
130 // count cells of considered object
131 ++numVoxels;
132
133 //Shift centre of mass (for oblique rotation) if offset provided
134 if constexpr ( PARTICLETYPE::template providesNested<SURFACE,COR_OFFSET>() ){
135 lever -= Vector<T,D> ( particle.template getField<SURFACE,COR_OFFSET>() );
136 }
137
138 //Calculate torque
139 const Vector<T,Drot> torque = particles::dynamics::torque_from_force<D,T>::calculate( tmpForce, lever );
140
141 T physR[D] = {0.};
142 this->_blockGeometry.getPhysR(physR, latticeRinner);
143 _f(particle, physR, tmpForce, torque);
144
145 //Add force and torque to output
146 for (unsigned iDim=0; iDim<D; ++iDim) {
147 output[iDim+iPeval*serialSize] += tmpForce[iDim];
148 }
149 for (unsigned iRot=0; iRot<Drot; ++iRot) {
150 output[(iRot+D)+iPeval*serialSize] += torque[iRot];
151 }
152 }
153 }
154 });
155
156 output[D+Drot+iPeval*serialSize] += numVoxels;
157}
158
159template<typename T, typename DESCRIPTOR, typename PARTICLETYPE>
161{
162 constexpr unsigned D = DESCRIPTOR::d;
163
164 using namespace descriptors;
165
166 //Evaluate periodicity
167 bool anyPeriodic = false;
168 for (unsigned iDim=0; iDim<D; ++iDim) {
169 anyPeriodic = anyPeriodic || _periodic[iDim];
170 }
171
172 // iterate over all particles in _particleSystem
173 for (std::size_t iP=_iP0; iP!=_particleSystem.size(); ++iP) {
174 auto particle = _particleSystem.get(iP);
175 if (particles::access::isValid(particle)){
176 // If any direction requires periodic treatment
177 if (anyPeriodic) {
178 const T circumRadius = particles::access::getRadius(particle);
179 const PhysR<T,D> position = particles::access::getPosition(particle);
180
181 bool surfaceOutOfGeometry = false;
182 PhysR<T,D> ghostPos;
183 particles::checkSmoothIndicatorOutOfGeometry(surfaceOutOfGeometry, ghostPos,
184 _cellMin, _cellMax, position, circumRadius, _periodic);
185
186 if (!surfaceOutOfGeometry) {
187 evaluate(output, particle, iP);
188 }
189 else {
190 // Calculate force for the ghost particle
191 particle.template setField<GENERAL,POSITION>(ghostPos);
192 evaluate(output, particle, iP);
193 // Calculate force of actual particle
194 particle.template setField<GENERAL,POSITION>(position);
195 evaluate(output, particle, iP);
196 }
197 }
198 else {
199 evaluate(output, particle, iP);
200 }
201 }
202 }
203 return true;
204}
205
206
209
210
211template<typename T,typename DESCRIPTOR,typename PARTICLETYPE, bool useTorque>
214 const UnitConverter<T,DESCRIPTOR>& converter,
215 const SuperGeometry<T,DESCRIPTOR::d>& superGeometry,
217 : SuperLatticePhysF<T,DESCRIPTOR>(sLattice, converter,
218 useTorque ? utilities::dimensions::convert<DESCRIPTOR::d>::rotation : DESCRIPTOR::d)
219{
220 this->getName() = "localMomentumExchange";
221 int maxC = this->_sLattice.getLoadBalancer().size();
222 this->_blockF.reserve(maxC);
223 for (int iC = 0; iC < maxC; ++iC) {
225 this->_sLattice.getBlock(iC),
226 superGeometry.getBlockGeometry(iC),
227 particleSystem,
228 this->_converter));
229 }
230}
231
232template<typename T,typename DESCRIPTOR,typename PARTICLETYPE, bool useTorque>
235 const UnitConverter<T,DESCRIPTOR>& converter,
236 const SuperGeometry<T,DESCRIPTOR::d>& superGeometry,
238 : SuperLatticePhysF<T,DESCRIPTOR>(sLattice, converter,
239 useTorque ? utilities::dimensions::convert<DESCRIPTOR::d>::rotation : DESCRIPTOR::d)
240{
241 this->getName() = "localMomentumExchange";
242 int maxC = this->_sLattice.getLoadBalancer().size();
243 this->_blockF.reserve(maxC);
244 for (int iC = 0; iC < maxC; ++iC) {
245
246 auto bParticleSystems = sParticleSystem.getBlockParticleSystems();
247 auto& particleSystem = *bParticleSystems[iC];
248
250 this->_sLattice.getBlock(iC),
251 superGeometry.getBlockGeometry(iC),
252 particleSystem,
253 this->_converter));
254 }
255}
256
257
258template <typename T, typename DESCRIPTOR,typename PARTICLETYPE, bool useTorque>
260 BlockLattice<T,DESCRIPTOR>& blockLattice,
261 const BlockGeometry<T,DESCRIPTOR::d>& blockGeometry,
263 const UnitConverter<T,DESCRIPTOR>& converter)
264 : BlockLatticePhysF<T,DESCRIPTOR>(blockLattice,converter,
265 useTorque ? utilities::dimensions::convert<DESCRIPTOR::d>::rotation : DESCRIPTOR::d),
266 _blockLattice(blockLattice),
267 _blockGeometry(blockGeometry),
268 _particleSystem(particleSystem)
269{
270 this->getName() = "localMomentumExchange";
271}
272
273template <typename T, typename DESCRIPTOR, typename PARTICLETYPE, bool useTorque>
275{
276 using namespace descriptors;
277 const unsigned D = DESCRIPTOR::d;
279
280 for (unsigned iDim=0; iDim<D; ++iDim) {
281 output[iDim] = 0.;
282 }
283
284 // iterate over all particles in _particleSystem
285 int _iP0 = 0;
286 for (std::size_t iP=_iP0; iP!=_particleSystem.size(); ++iP) {
287 auto particle = _particleSystem.get(iP);
288 auto circumRadius = particle.template getField<SURFACE,SINDICATOR>()->getCircumRadius();
289 auto position = particle.template getField<GENERAL,POSITION>();
290
291 LatticeR<DESCRIPTOR::d> start, end;
292 if ( particles::getBlockParticleIntersection(this->_blockGeometry, T(1.)/this->_converter.getPhysDeltaX(), start, end,
293 position, circumRadius) ){
294
295 Vector<T,D>tmpForce(0.);
296 PhysR<T,D> lever(0.);
298 lever, input, this->_blockGeometry,
299 this->_blockLattice, this->_converter, particle) ){
300
301 //Shift centre of mass (for oblique rotation) if offset provided
302 if constexpr ( PARTICLETYPE::template providesNested<SURFACE,COR_OFFSET>() ){
303 lever -= Vector<T,D> ( particle.template getField<SURFACE,COR_OFFSET>() );
304 }
305
306 //Calculate torque
307 const auto torque = particles::dynamics::torque_from_force<D,T>::calculate( tmpForce, lever );
308
309 //Add force and torque to output
310 if constexpr(!useTorque){
311 for (unsigned iDim=0; iDim<D; ++iDim) {
312 output[iDim] = tmpForce[iDim];
313 }
314 } else {
315 for (unsigned iRot=0; iRot<Drot; ++iRot) {
316 output[iRot] = torque[iRot];
317 }
318 }
319 }
320 }
321 }
322 return true;
323}
324
325
326
327}
328#endif
Representation of a block geometry.
functor to get pointwise momentum exchange on local lattice (block level)
bool operator()(T output[], const int input[]) override
BlockLatticeMomentumExchangeForceLocal(BlockLattice< T, DESCRIPTOR > &blockLattice, const BlockGeometry< T, DESCRIPTOR::d > &blockGeometry, particles::ParticleSystem< T, PARTICLETYPE > &particleSystem, const UnitConverter< T, DESCRIPTOR > &converter)
Functor that returns forces acting on a particle surface, returns data in output for every particle i...
void evaluate(T output[], particles::Particle< T, PARTICLETYPE > &particle, int iP)
BlockLatticeMomentumExchangeForce(BlockLattice< T, DESCRIPTOR > &blockLattice, const BlockGeometry< T, DESCRIPTOR::d > &blockGeometry, particles::ParticleSystem< T, PARTICLETYPE > &particleSystem, const UnitConverter< T, DESCRIPTOR > &converter, PhysR< T, DESCRIPTOR::d > cellMin=PhysR< T, DESCRIPTOR::d >(0.), PhysR< T, DESCRIPTOR::d > cellMax=PhysR< T, DESCRIPTOR::d >(0.), Vector< bool, DESCRIPTOR::d > periodic=Vector< bool, DESCRIPTOR::d >(false), std::size_t iP0=0, const std::unordered_set< int > &ignoredMaterials=std::unordered_set< int >{}, const F f=[](auto &, const auto &, const auto &, const auto &){})
Platform-abstracted block lattice for external access and inter-block interaction.
Representation of a statistic for a parallel 2D geometry.
BlockGeometry< T, D > & getBlockGeometry(int locIC)
Read and write access to a single block geometry.
SuperLatticeMomentumExchangeForceLocalParallel(SuperLattice< T, DESCRIPTOR > &sLattice, const UnitConverter< T, DESCRIPTOR > &converter, const SuperGeometry< T, DESCRIPTOR::d > &superGeometry, particles::SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem)
The following are functors that work in the traditional (output[], input[]) sense,...
bool operator()(T output[], const int input[]) override
SuperLatticeParticleForce(SuperLattice< T, DESCRIPTOR > &sLattice, const SuperGeometry< T, DESCRIPTOR::d > &superGeometry, particles::ParticleSystem< T, PARTICLETYPE > &particleSystem, const UnitConverter< T, DESCRIPTOR > &converter, Vector< bool, DESCRIPTOR::d > periodic=Vector< bool, DESCRIPTOR::d >(false), std::size_t iP0=0, const std::unordered_set< int > &ignoredMaterials=std::unordered_set< int >{}, const F f=[](auto &, const auto &, const auto &, const auto &){})
Super class maintaining block lattices for a cuboid decomposition.
CuboidGeometry< T, D > & getCuboidGeometry()
Read and write access to cuboid geometry.
Conversion between physical and lattice units, as well as discretization.
Plain old scalar vector.
Definition vector.h:47
constexpr const T * data() const any_platform
Definition vector.h:161
std::vector< ParticleSystem< T, PARTICLETYPE > * > & getBlockParticleSystems()
void reduceAndBcast(T &reductVal, MPI_Op op, int root=0, MPI_Comm comm=MPI_COMM_WORLD)
Reduction operation, followed by a broadcast.
T getRadius(Particle< T, PARTICLETYPE > &particle)
Vector< T, PARTICLETYPE::d > getPosition(Particle< T, PARTICLETYPE > particle)
bool momentumExchangeAtSurfaceLocation(T momentumExchange[], PhysR< T, DESCRIPTOR::d > &lever, const LatticeR< DESCRIPTOR::d > &latticeRinner, const BlockGeometry< T, DESCRIPTOR::d > &blockGeometry, BlockLattice< T, DESCRIPTOR > &blockLattice, const UnitConverter< T, DESCRIPTOR > &converter, Particle< T, PARTICLETYPE > &particle, const int bulkMaterial=1)
bool getBlockParticleIntersection(const BlockGeometry< T, D > &blockGeometry, T invDeltaX, LatticeR< D > &start, LatticeR< D > &end, Vector< T, D > position, T circumRadius)
void forSpatialLocationsInBlockParticleIntersection(const BlockGeometry< T, DESCRIPTOR::d > &blockGeometry, BlockLattice< T, DESCRIPTOR > &blockLattice, Vector< T, DESCRIPTOR::d > position, T circumRadius, F f)
MpiManager & mpi()
Top level namespace for all of OpenLB.
std::conditional_t< DESCRIPTOR::d==2, BlockLatticePhysF2D< T, DESCRIPTOR >, BlockLatticePhysF3D< T, DESCRIPTOR > > BlockLatticePhysF
Definition aliases.h:339
std::conditional_t< DESCRIPTOR::d==2, SuperLatticePhysF2D< T, DESCRIPTOR >, SuperLatticePhysF3D< T, DESCRIPTOR > > SuperLatticePhysF
Definition aliases.h:329
static constexpr Vector< T, utilities::dimensions::convert< D >::rotation > calculate(Vector< T, D > force, PhysR< T, D > lever)
Converts dimensions by deriving from given cartesian dimension D.