OpenLB 1.7
Loading...
Searching...
No Matches
particleDynamicsFunctions.h
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2021 Nicolas Hafen, Mathias J. Krause
4 * E-mail contact: info@openlb.net
5 * The most recent release of OpenLB can be downloaded at
6 * <http://www.openlb.net/>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22*/
23
24
25/* This file contains functions used for the calculation of particle related dynamics.
26 *
27*/
28
29#ifndef PARTICLE_DYNAMICS_FUNCTIONS_H
30#define PARTICLE_DYNAMICS_FUNCTIONS_H
31
32
35#include <cassert>
36
37namespace olb {
38
39namespace particles {
40
41template <unsigned D>
42constexpr bool isPeriodic(const Vector<bool, D>& periodic)
43{
44 bool isPeriodic = periodic[0] || periodic[1];
45 if constexpr (D == 3) {
46 isPeriodic = isPeriodic || periodic[2];
47 }
48 return isPeriodic;
49}
50
51namespace defaults{
52 template <unsigned D>
53 const auto periodicity = [](){
54 if constexpr (D==3) {
55 return Vector<bool,3>(false,false,false);
56 } else {
57 return Vector<bool,2>(false,false);
58 }
59 };
60}
61
62namespace contact {
63template <typename T, typename PARTICLECONTACTTYPE, typename WALLCONTACTTYPE>
64void communicateContacts(ContactContainer<T, PARTICLECONTACTTYPE, WALLCONTACTTYPE>& contactContainer);
65}
66
67namespace dynamics {
68
69
70
71//Calculate torque from force and lever
72template<unsigned D, typename T>
75 Vector<T,D> force, PhysR<T,D> lever )
76 {
77 if constexpr (D==2){
79 } else {
80 return crossProduct( lever, force );
81 }
82 }
83};
84
85
87
88
89//Calculate local velocity
90template <typename T, typename PARTICLETYPE>
92{
93 using namespace descriptors;
94
95 const PhysR<T,PARTICLETYPE::d> position =
96 particle.template getField<GENERAL,POSITION>();
97 const Vector<T,PARTICLETYPE::d> velocity =
98 particle.template getField<MOBILITY,VELOCITY>();
100 angVelocity(particle.template getField<MOBILITY,ANG_VELOCITY>());
101
102 return util::calculateLocalVelocity(position, velocity, angVelocity, input);
103}
104
105
107
109template<typename T, typename PARTICLETYPE>
112 T serializedFunctorForceField[], int iP )
113{
114 constexpr unsigned D = PARTICLETYPE::d;
115 constexpr unsigned Drot = utilities::dimensions::convert<D>::rotation;
116 constexpr int serialSize = D+Drot+1;
117
118 const int idxForce = iP*(serialSize);
119 const int idxTorque = idxForce+D;
120 const int idxTorqueEnd = idxTorque+Drot;
121
122 //Get force
123 //TODO: include funcionality to OLB-Vector someday to avoid std::vector cast
124 force = std::vector<T>( serializedFunctorForceField+idxForce,
125 serializedFunctorForceField+idxTorque);
126 //Get torque
127 torque = std::vector<T>( serializedFunctorForceField+idxTorque,
128 serializedFunctorForceField+idxTorqueEnd );
129}
130
131
133template<typename T, typename PARTICLETYPE>
135 T serializedFunctorForceField[], int iP )
136{
137 constexpr unsigned D = PARTICLETYPE::d;
138 constexpr int serialSize = D;
139
140 const int idxForce = iP*(serialSize);
141 const int idxForceEnd = idxForce+D;
142
143 //Get force
144 //TODO: include funcionality to OLB-Vector someday to avoid std::vector cast
145 force = std::vector<T>( serializedFunctorForceField+idxForce,
146 serializedFunctorForceField+idxForceEnd);
147}
148
150template<typename T, typename PARTICLETYPE, typename FORCEFUNCTOR>
151void applySerializableParticleForce( FORCEFUNCTOR& forceF, ParticleSystem<T,PARTICLETYPE>& particleSystem, std::size_t iP0=0 )
152{
153 constexpr unsigned D = PARTICLETYPE::d;
154 constexpr unsigned Drot = utilities::dimensions::convert<D>::rotation;
155
156 //Create serialized force field and dummy input
157 int input[1]{};
158 T serializedFunctorForceField[forceF.getTargetDim()]; //TODO: could be decreased by only considering valid_particles
159
160 //Initialize serialized force field when directly using block functors
161 // -as this is usually done inside the super functor
162 if constexpr (std::is_base_of<BlockF<T,PARTICLETYPE::d>, FORCEFUNCTOR>::value){
163 for (int iS=0; iS<forceF.getTargetDim(); ++iS) {
164 serializedFunctorForceField[iS] = 0.;
165 }
166 }
167
168 //Retrieve boundary force field
169 forceF(serializedFunctorForceField, input);
170
171 //Loop over particles and apply individual force and torque contribution
172 //TODO: for parallized particles, this represents a redundant loop over the particle system
173 for (std::size_t iP=iP0; iP<particleSystem.size(); iP++) {
174 auto particle = particleSystem.get(iP);
175
176 Vector<T,D> force;
177 std::size_t iPeval = iP-iP0; //Shift, if iP!=0
178 if constexpr ( PARTICLETYPE::template providesNested<descriptors::FORCING,descriptors::TORQUE>() ) {
179 Vector<T,Drot> torque;
180 unserializeForceTorqueVoxels<T,PARTICLETYPE>( force, torque, serializedFunctorForceField, iPeval );
181 particle.template setField<descriptors::FORCING,descriptors::TORQUE>(
183 }
184 else {
185 unserializeForce<T,PARTICLETYPE>( force, serializedFunctorForceField, iPeval );
186 }
187
188 //DEBUG OUTPUT
189// int rank = singleton::mpi().getRank();
190// std::cout << " force(pSys=" << &particleSystem << ",rank=" << rank << ")=" << force << std::endl;
191 particle.template setField<descriptors::FORCING,descriptors::FORCE>( force );
192 }
193}
194
197template<typename T, typename PARTICLETYPE, typename FORCEFUNCTOR, typename PCONDITION=conditions::valid_particles>
198void applyLocalParticleForce( FORCEFUNCTOR& forceF, ParticleSystem<T,PARTICLETYPE>& particleSystem, std::size_t iP0=0 )
199{
200 //Iterate over particles and apply functor's evaluate() directly
201 for (std::size_t iP=iP0; iP!=particleSystem.size(); iP++) {
202 auto particle = particleSystem.get(iP);
203 //Execute F when particle meets condition
204 doWhenMeetingCondition<T,PARTICLETYPE,PCONDITION>( particle,
205 [&](auto& particle){
206 //Evaluate force functor
207 T output[1]; //dummy output
208 forceF.evaluate(output, particle, iP);
209 });
210 }
211}
212
214template<typename T, typename PARTICLETYPE>
216{
217 //Define init lambda expression
218 typedef std::function<bool(const std::type_info&,int,std::string)> FunctionType;
219 FunctionType initFunction = [](const std::type_info& typeInfo, int fieldSize, std::string fieldContentStr) {
220 return true; //resetField=true
221 };
222 //Call recursive field traversal function with lambda expression
224 initFunction, dynamicFieldGroups, iP );
225}
226
227
228
230//containing those, not included in particle tasks
231
233template<typename T, typename DESCRIPTOR, typename PARTICLETYPE, typename PARTICLECONTACTTYPE, typename WALLCONTACTTYPE,
234 typename F=decltype(defaults::periodicity<DESCRIPTOR::d>)>
236 ParticleSystem<T,PARTICLETYPE>& particleSystem,
238 const SuperGeometry<T,DESCRIPTOR::d>& sGeometry,
240 UnitConverter<T,DESCRIPTOR> const& converter,
241 std::vector<SolidBoundary<T,DESCRIPTOR::d>>& solidBoundaries,
242 F getSetupPeriodicity = defaults::periodicity<DESCRIPTOR::d>)
243{
244 static_assert(DESCRIPTOR::template provides<descriptors::CONTACT_DETECTION>(),
245 "The field CONTACT_DETECTION must be provided.");
246 constexpr unsigned D = DESCRIPTOR::d;
247 using namespace descriptors;
248
249 contactContainer.cleanContacts();
250
251 const PhysR<T,D> min = communication::getCuboidMin<T,D>(sGeometry.getCuboidGeometry());
252 const PhysR<T,D> max = communication::getCuboidMax<T,D>(sGeometry.getCuboidGeometry(), min);
253
254 //Loop over particles
255 for (std::size_t iP=0; iP<particleSystem.size(); ++iP) {
256 auto particle = particleSystem.get(iP);
257 //Write particle field
258 setSuperParticleField( sGeometry, min, max, sLattice, converter,
259 particleSystem, contactContainer, iP, particle,
260 solidBoundaries, getSetupPeriodicity );
261
262 }
263
264 contact::communicateContacts<T,PARTICLECONTACTTYPE,WALLCONTACTTYPE>(contactContainer);
265}
266
268template<typename T, typename DESCRIPTOR, typename PARTICLETYPE, typename PARTICLECONTACTTYPE, typename WALLCONTACTTYPE,
269 typename F=decltype(defaults::periodicity<DESCRIPTOR::d>)>
271 ParticleSystem<T,PARTICLETYPE>& particleSystem,
273 const SuperGeometry<T,DESCRIPTOR::d>& sGeometry,
275 UnitConverter<T,DESCRIPTOR> const& converter,
276 F getSetupPeriodicity = defaults::periodicity<DESCRIPTOR::d>)
277{
278 std::vector<SolidBoundary<T,DESCRIPTOR::d>> solidBoundaries = std::vector<SolidBoundary<T,DESCRIPTOR::d>>();
279 coupleResolvedParticlesToLattice(particleSystem, contactContainer, sGeometry, sLattice, converter, solidBoundaries, getSetupPeriodicity);
280}
281
282
284template<typename T, typename DESCRIPTOR, typename PARTICLETYPE, typename PARTICLECONTACTTYPE, typename WALLCONTACTTYPE,
285 typename F=decltype(defaults::periodicity<DESCRIPTOR::d>)>
289 const SuperGeometry<T,DESCRIPTOR::d>& sGeometry,
291 UnitConverter<T,DESCRIPTOR> const& converter,
292 std::vector<SolidBoundary<T,DESCRIPTOR::d>>& solidBoundaries,
293 F getSetupPeriodicity = defaults::periodicity<DESCRIPTOR::d>)
294{
295 static_assert(DESCRIPTOR::template provides<descriptors::CONTACT_DETECTION>(),
296 "The field CONTACT_DETECTION must be provided.");
297 constexpr unsigned D = DESCRIPTOR::d;
298 using namespace descriptors;
299
300 const PhysR<T,D> min = communication::getCuboidMin<T,D>(sGeometry.getCuboidGeometry());
301 const PhysR<T,D> max = communication::getCuboidMax<T,D>(sGeometry.getCuboidGeometry(), min);
302
303 //Loop over particles
304 communication::forParticlesInSuperParticleSystem<T, PARTICLETYPE, conditions::valid_particles>(
305 sParticleSystem,
306 [&](Particle<T, PARTICLETYPE>& particle,
307 ParticleSystem<T, PARTICLETYPE>& particleSystem, int globiC) {
308 const std::size_t globalParticleID =
309 particle.template getField<PARALLELIZATION, ID>();
310 //Write particle field
311 setSuperParticleField(sGeometry, min, max, sLattice, converter,
312 particleSystem, contactContainer,
313 globalParticleID, particle, solidBoundaries,
314 getSetupPeriodicity, globiC );
315 });
316}
317
319template<typename T, typename DESCRIPTOR, typename PARTICLETYPE, typename PARTICLECONTACTTYPE, typename WALLCONTACTTYPE,
320 typename F=decltype(defaults::periodicity<DESCRIPTOR::d>)>
324 const SuperGeometry<T,DESCRIPTOR::d>& sGeometry,
326 UnitConverter<T,DESCRIPTOR> const& converter,
327 F getSetupPeriodicity = defaults::periodicity<DESCRIPTOR::d>)
328{
329 std::vector<SolidBoundary<T,DESCRIPTOR::d>> solidBoundaries = std::vector<SolidBoundary<T,DESCRIPTOR::d>>();
330 coupleResolvedParticlesToLattice(sParticleSystem, contactContainer, sGeometry, sLattice, converter, solidBoundaries, getSetupPeriodicity);
331}
332
333
334template<typename T, typename PARTICLETYPE>
336{
337 using namespace descriptors;
338 constexpr unsigned D = PARTICLETYPE::d;
339 constexpr unsigned Drot = utilities::dimensions::convert<D>::rotation;
340 static_assert(D==3, "ERROR: 2D version of calcKineticEnergy not implemented yet!");
341
342 T pMass = particle.template getField<PHYSPROPERTIES, MASS>();
343 Vector<T,D> vel(particle.template getField<MOBILITY, VELOCITY>());
344 Vector<T,Drot> pMofi(particle.template getField<PHYSPROPERTIES, MOFI>());
345 Vector<T,Drot> angVel(particle.template getField<MOBILITY, ANG_VELOCITY>());
346
347 T eTrans = T{0.5} * pMass * util::normSqr<T,D>(vel);
348 T eRot = .5*(pMofi[0]*angVel[0]*angVel[0]
349 +pMofi[1]*angVel[1]*angVel[1]
350 +pMofi[2]*angVel[2]*angVel[2]);
351 T eKin = eTrans+eRot;
352
353 return eKin;
354}
355
356
357} //namespace dynamics
358
359} //namespace particles
360
361} //namespace olb
362
363
364#endif
Storage for dynamic field groups (Prototype for ParticleSystem)
Representation of a statistic for a parallel 2D geometry.
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
auto & get()
Expose container.
constexpr std::size_t size()
Size of ParticleSystem.
void communicateContacts(ContactContainer< T, PARTICLECONTACTTYPE, WALLCONTACTTYPE > &contactContainer)
void applyLocalParticleForce(FORCEFUNCTOR &forceF, ParticleSystem< T, PARTICLETYPE > &particleSystem, std::size_t iP0=0)
Apply boundary force provided by force functor to the particle center as torque and force.
void applySerializableParticleForce(FORCEFUNCTOR &forceF, ParticleSystem< T, PARTICLETYPE > &particleSystem, std::size_t iP0=0)
Apply boundary force provided by force functor to the particle center as torque and force.
void unserializeForceTorqueVoxels(Vector< T, PARTICLETYPE::d > &force, Vector< T, utilities::dimensions::convert< PARTICLETYPE::d >::rotation > &torque, T serializedFunctorForceField[], int iP)
Unserialize force field provieded by force integration functor (e.g. momentumExchange)
constexpr Vector< T, PARTICLETYPE::d > calculateLocalVelocity(Particle< T, PARTICLETYPE > &particle, const PhysR< T, PARTICLETYPE::d > &input)
T calcKineticEnergy(Particle< T, PARTICLETYPE > &particle)
void initializeParticle(DynamicFieldGroupsD< T, typename PARTICLETYPE::fields_t > &dynamicFieldGroups, std::size_t iP)
Initialize all fields in particle (necessary for clang)
void unserializeForce(Vector< T, PARTICLETYPE::d > &force, T serializedFunctorForceField[], int iP)
Unserialize force field provieded by force integration functor (e.g. stokesDragForce)
void coupleResolvedParticlesToLattice(ParticleSystem< T, PARTICLETYPE > &particleSystem, contact::ContactContainer< T, PARTICLECONTACTTYPE, WALLCONTACTTYPE > &contactContainer, const SuperGeometry< T, DESCRIPTOR::d > &sGeometry, SuperLattice< T, DESCRIPTOR > &sLattice, UnitConverter< T, DESCRIPTOR > const &converter, std::vector< SolidBoundary< T, DESCRIPTOR::d > > &solidBoundaries, F getSetupPeriodicity=defaults::periodicity< DESCRIPTOR::d >)
Couple particle to lattice and detect contacts of resolved particles.
constexpr bool isPeriodic(const Vector< bool, D > &periodic)
void setSuperParticleField(const SuperGeometry< T, DESCRIPTOR::d > &sGeometry, SuperLattice< T, DESCRIPTOR > &sLattice, UnitConverter< T, DESCRIPTOR > const &converter, Particle< T, PARTICLETYPE > &particle, const Vector< bool, DESCRIPTOR::d > &periodicity)
Set particle field with peridic support.
constexpr Vector< T, D > calculateLocalVelocity(const Vector< T, D > &rotationCenter, const Vector< T, D > &velocity, const Vector< T, utilities::dimensions::convert< D >::rotation > &angularVelocity, const Vector< T, D > &position)
Calculate local velocity.
Top level namespace for all of OpenLB.
auto crossProduct(const ScalarVector< T, D, IMPL > &a, const ScalarVector< T, D, IMPL_ > &b)
Definition vector.h:235
Traversal of nested field contents for output and initialization.
void cleanContacts()
Clean contacts - remove "empty" contacts.
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.