OpenLB 1.8.1
Loading...
Searching...
No Matches
particleMotionFunctions.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_MOTION_FUNCTIONS_H
30#define PARTICLE_MOTION_FUNCTIONS_H
31
32
33namespace olb {
34
35namespace particles {
36
37namespace dynamics {
38
40
41// Velocity verlet integration according to
42// Verlet1967 (https://doi.org/10.1103/PhysRev.159.98)
43// Swope1982 (https://doi.org/10.1063/1.442716)
44template<typename T, typename PARTICLETYPE>
45void velocityVerletTranslation( Particle<T,PARTICLETYPE>& particle, T delTime, T delTime2,
46 Vector<T,PARTICLETYPE::d> acceleration )
47{
48 using namespace descriptors;
49 constexpr unsigned D = PARTICLETYPE::d;
50 //Check field existence
51 static_assert(PARTICLETYPE::template providesNested<GENERAL,POSITION>(), "Field POSITION has to be provided");
52 static_assert(PARTICLETYPE::template providesNested<MOBILITY,VELOCITY>(), "Field VELOCITY has to be provided");
53 static_assert(PARTICLETYPE::template providesNested<MOBILITY,ACCELERATION_STRD>(), "Field ACCELERATION_STRD has to be provided");
54 //Calculate quantities
55 Vector<T,D> position( particle.template getField<GENERAL,POSITION>()
56 + particle.template getField<MOBILITY,VELOCITY>() * delTime
57 + (0.5 * particle.template getField<MOBILITY,ACCELERATION_STRD>() * delTime2) );
58 Vector<T,D> avgAcceleration( .5*(particle.template getField<MOBILITY,ACCELERATION_STRD>() + acceleration) );
59 Vector<T,D> velocity( particle.template getField<MOBILITY,VELOCITY>() + avgAcceleration * delTime );
60 //Update values
61 particle.template setField<GENERAL,POSITION>( position );
62 particle.template setField<MOBILITY,VELOCITY>( velocity );
63 particle.template setField<MOBILITY,ACCELERATION_STRD>( acceleration );
64}
65
66template<typename T, typename PARTICLETYPE>
67void velocityVerletRotation( Particle<T,PARTICLETYPE>& particle, T delTime, T delTime2,
69{
70 using namespace descriptors;
71 constexpr unsigned D = PARTICLETYPE::d;
72 constexpr unsigned Drot = utilities::dimensions::convert<D>::rotation;
73 //Check field existence
74 static_assert(PARTICLETYPE::template providesNested<SURFACE,ANGLE>(), "Field SURFACE:ANGLE has to be provided");
75 static_assert(PARTICLETYPE::template providesNested<MOBILITY,ANG_VELOCITY>(), "Field MOBILITY:ANG_VELOCITY has to be provided");
76 static_assert(PARTICLETYPE::template providesNested<MOBILITY,ANG_ACC_STRD>(), "Field MOBILITY:ANG_ACC_STRD has to be provided");
77 //Calculate quantities
78 Vector<T,Drot> angle( particle.template getField<SURFACE,ANGLE>()
79 + particle.template getField<MOBILITY,ANG_VELOCITY>() * delTime
80 + (0.5 * particle.template getField<MOBILITY,ANG_ACC_STRD>() * delTime2) );
81 Vector<T,Drot> avgAngularAcceleration( .5*(particle.template getField<MOBILITY,ANG_ACC_STRD>() + angularAcceleration) );
82 Vector<T,Drot> angularVelocity( particle.template getField<MOBILITY,ANG_VELOCITY>() + avgAngularAcceleration * delTime );
83 //Treat full rotation
84 angle = util::fmod( angle, 2.*M_PI );
85 //Update values
86 particle.template setField<SURFACE,ANGLE>(
88 particle.template setField<MOBILITY,ANG_VELOCITY>(
90 particle.template setField<MOBILITY,ANG_ACC_STRD>(
92
93}
94
95template<typename T, typename PARTICLETYPE>
97{
98 using namespace descriptors;
99 constexpr unsigned D = PARTICLETYPE::d;
100 constexpr unsigned Drot = utilities::dimensions::convert<D>::rotation;
101 //Check field existence
102 static_assert(PARTICLETYPE::template providesNested<SURFACE,ANGLE>(), "Field SURFACE:ANGLE has to be provided");
103 static_assert(PARTICLETYPE::template providesNested<MOBILITY,ANG_VELOCITY>(), "Field MOBILITY:ANG_VELOCITY has to be provided");
104 static_assert(PARTICLETYPE::template providesNested<MOBILITY,ANG_ACC_STRD>(), "Field MOBILITY:ANG_ACC_STRD has to be provided");
105 //Calculate quantities
106 Vector<T,Drot> angle( particle.template getField<SURFACE,ANGLE>() + angVel * delTime);
107 Vector<T,Drot> avgAngularAcceleration({0.});
108 Vector<T,Drot> angularVelocity( angVel );
109 //Treat full rotation
110 angle = util::fmod( angle, 2.*M_PI );
111 //Update values
112 particle.template setField<SURFACE,ANGLE>(
114 particle.template setField<MOBILITY,ANG_VELOCITY>(
116 particle.template setField<MOBILITY,ANG_ACC_STRD>(
118
119}
120
121template<typename T, typename PARTICLETYPE>
123 Vector<T,PARTICLETYPE::d> acceleration,
125{
126 //Calculate squared time step
127 T delTime2 = delTime*delTime;
128 //Calculate cartesian directions
129 velocityVerletTranslation( particle, delTime, delTime2, acceleration );
130 //Calculate rotational directions
131 if constexpr ( access::providesSurface<PARTICLETYPE>() ) {
132 velocityVerletRotation( particle, delTime, delTime2, angularAcceleration );
133 }
134}
135
136
137
138
139
141template<typename T, typename PARTICLETYPE>
143 Particle<T,PARTICLETYPE>& particle, T delTime,
144 Vector<T,PARTICLETYPE::d> acceleration )
145{
146 using namespace descriptors;
147 constexpr unsigned D = PARTICLETYPE::d;
148 //Check field existence
149 static_assert(PARTICLETYPE::template providesNested<GENERAL,POSITION>(), "Field POSITION has to be provided");
150 static_assert(PARTICLETYPE::template providesNested<MOBILITY,VELOCITY>(), "Field VELOCITY has to be provided");
151 //Calculate quantities
152 Vector<T,D> velocity( particle.template getField<MOBILITY,VELOCITY>() + acceleration * delTime );
153 Vector<T,D> position( particle.template getField<GENERAL,POSITION>() + velocity * delTime );
154 //Update values
155 particle.template setField<GENERAL,POSITION>( position );
156 particle.template setField<MOBILITY,VELOCITY>( velocity );
157}
158
159
161template<typename T, typename PARTICLETYPE>
163 Particle<T,PARTICLETYPE>& particle, T delTime,
165{
166 using namespace descriptors;
167 constexpr unsigned D = PARTICLETYPE::d;
168 //Check field existence
169 static_assert(PARTICLETYPE::template providesNested<GENERAL,POSITION>(), "Field POSITION has to be provided");
170 static_assert(PARTICLETYPE::template providesNested<MOBILITY,VELOCITY>(), "Field VELOCITY has to be provided");
171 //Calculate quantities
172 Vector<T,D> velocity( particle.template getField<MOBILITY,VELOCITY>() + acceleration * delTime );
173 Vector<T,D> position( particle.template getField<GENERAL,POSITION>() + velocity * delTime );
174 Vector<T,3> velocity_tmp ( particle.template getField<MOBILITY,VELOCITY>());
175 Vector<T,3> position_tmp (particle.template getField<GENERAL,POSITION>());
176 if(periodicity[0] == 1)
177 {
178 //velocity[0] = velocity_tmp[0];
179 position[0] = position_tmp[0];
180 /* velocity_tmp[1] = (particle.template getField<MOBILITY,VELOCITY>())[1] + acceleration[1]*delTime;
181 velocity_tmp[2] = (particle.template getField<MOBILITY,VELOCITY>())[2] + acceleration[2]*delTime;
182 position_tmp[1] = (particle.template getField<MOBILITY,POSITION>())[1] + velocity_tmp[1]*delTime;
183 position_tmp[2] = (particle.template getField<MOBILITY,POSITION>())[2] + velocity_tmp[2]*delTime;
184 velocity_tmp[0] = (particle.template getField<MOBILITY,VELOCITY>())[0];
185 position_tmp[0] = (particle.template getField<MOBILITY,POSITION>())[0];*/
186 }
187 else if (periodicity[1] == 1)
188 {
189 //velocity[1] = velocity_tmp[1];
190 position[1] = position_tmp[1];
191 /* velocity_tmp[0] = (particle.template getField<MOBILITY,VELOCITY>())[0] + acceleration[0]*delTime;
192 velocity_tmp[2] = (particle.template getField<MOBILITY,VELOCITY>())[2] + acceleration[2]*delTime;
193 position_tmp[0] = (particle.template getField<MOBILITY,POSITION>())[0] + velocity_tmp[0]*delTime;
194 position_tmp[2] = (particle.template getField<MOBILITY,POSITION>())[2] + velocity_tmp[2]*delTime;
195 velocity_tmp[1] = (particle.template getField<MOBILITY,VELOCITY>())[1];
196 position_tmp[1] = (particle.template getField<MOBILITY,POSITION>())[1];*/
197 }
198 else if (periodicity[2] == 1)
199 {
200 //velocity[2] = velocity_tmp[2];
201 position[2] = position_tmp[2];
202 /* velocity_tmp[0] = (particle.template getField<MOBILITY,VELOCITY>())[0] + acceleration[0]*delTime;
203 velocity_tmp[1] = (particle.template getField<MOBILITY,VELOCITY>())[1] + acceleration[1]*delTime;
204 position_tmp[0] = (particle.template getField<MOBILITY,POSITION>())[0] + velocity_tmp[0]*delTime;
205 position_tmp[1] = (particle.template getField<MOBILITY,POSITION>())[1] + velocity_tmp[1]*delTime;
206 velocity_tmp[2] = (particle.template getField<MOBILITY,VELOCITY>())[2];
207 position_tmp[2] = (particle.template getField<MOBILITY,POSITION>())[2];*/
208 }
209 else
210 std::cout << "No discrete normal in direction of coordinate axis" <<std::endl;
211 //Update values
212 particle.template setField<GENERAL,POSITION>( position );
213 particle.template setField<MOBILITY,VELOCITY>( velocity );
214}
215
216
217template<typename T, typename PARTICLETYPE>
219 Particle<T,PARTICLETYPE>& particle, T delTime,
221{
222 using namespace descriptors;
223 constexpr unsigned D = PARTICLETYPE::d;
225 //Check field existence
226 static_assert(PARTICLETYPE::template providesNested<SURFACE,ANGLE>(), "Field SURFACE:ANGLE has to be provided");
227 static_assert(PARTICLETYPE::template providesNested<MOBILITY,ANG_VELOCITY>(), "Field MOBILITY:ANG_VELOCITY has to be provided");
228 //Calculate quantities
229 Vector<T,Drot> angularVelocity( particle.getMobility().getAngularVelocity()
230 + angularAcceleration * delTime );
231 Vector<T,Drot> angle( particle.getSurface().getAngle() + angularVelocity * delTime );
232 //Update values
233 particle.template setField<SURFACE,ANGLE>( angle );
234 particle.template setField<MOBILITY,ANG_VELOCITY>( angularVelocity );
235}
236
237template<typename T, typename PARTICLETYPE>
239 Vector<T,PARTICLETYPE::d> acceleration,
241{
242 //Calculate cartesian directions
243 eulerIntegrationTranslation( particle, delTime, acceleration );
244 //Calculate rotational directions
245 if constexpr ( access::providesSurface<PARTICLETYPE>() ) {
246 eulerIntegrationRotation( particle, delTime, angularAcceleration );
247 }
248}
249
250//from FLUENT theory guide
251//TODO: Check and include into unit tests
252template<typename T, typename PARTICLETYPE>
254 Particle<T,PARTICLETYPE>& particle, Vector <T,PARTICLETYPE::d> acceleration, T delTime,
255 Vector <T,PARTICLETYPE::d> fluid_vel )
256{
257
258 using namespace descriptors;
259 constexpr unsigned D = PARTICLETYPE::d;
260 //Check field existence
261 static_assert(PARTICLETYPE::template providesNested<GENERAL,POSITION>(), "Field POSITION has to be provided");
262 static_assert(PARTICLETYPE::template providesNested<MOBILITY,VELOCITY>(), "Field VELOCITY has to be provided");
263 //Calculate quant accelearation[0]
264 if (acceleration[0]!=0){
265 T tau_p0 = 1./(acceleration[0])*(fluid_vel[0]-particle.template getField<MOBILITY,VELOCITY>()[0]);
266 Vector<T,D> velocity( fluid_vel+ std::exp((-delTime/tau_p0))*(particle.template getField<MOBILITY,VELOCITY>()- fluid_vel));
267 Vector<T,D> position( particle.template getField<GENERAL,POSITION>() + delTime*(fluid_vel) + tau_p0*(1- std::exp((-delTime/tau_p0)))*(particle.template getField<MOBILITY,VELOCITY>()-fluid_vel));
268 //Update values
269 particle.template setField<GENERAL,POSITION>( position );
270 particle.template setField<MOBILITY,VELOCITY>( velocity );
271 } else {
272 Vector<T,D> position( particle.template getField<GENERAL,POSITION>() + delTime*particle.template getField<MOBILITY,VELOCITY>());
273 //Update values
274 particle.template setField<GENERAL,POSITION>( position );
275 //particle.template setField<MOBILITY,VELOCITY>( velocity );
276 }
277}
278
279
280
281} //namespace dynamics
282
283} //namespace particles
284
285} //namespace olb
286
287
288#endif
#define M_PI
Plain old scalar vector.
constexpr bool providesSurface()
Provides group SURFACE.
void eulerIntegration(Particle< T, PARTICLETYPE > &particle, T delTime, Vector< T, PARTICLETYPE::d > acceleration, Vector< T, utilities::dimensions::convert< PARTICLETYPE::d >::rotation > angularAcceleration)
void velocityVerletRotor(Particle< T, PARTICLETYPE > &particle, T delTime, Vector< T, PARTICLETYPE::d > angVel)
void eulerIntegrationRotation(Particle< T, PARTICLETYPE > &particle, T delTime, Vector< T, utilities::dimensions::convert< PARTICLETYPE::d >::rotation > angularAcceleration)
void velocityVerletTranslation(Particle< T, PARTICLETYPE > &particle, T delTime, T delTime2, Vector< T, PARTICLETYPE::d > acceleration)
void analyticalTranslation(Particle< T, PARTICLETYPE > &particle, Vector< T, PARTICLETYPE::d > acceleration, T delTime, Vector< T, PARTICLETYPE::d > fluid_vel)
void velocityVerletRotation(Particle< T, PARTICLETYPE > &particle, T delTime, T delTime2, Vector< T, utilities::dimensions::convert< PARTICLETYPE::d >::rotation > angularAcceleration)
void eulerIntegrationTranslation(Particle< T, PARTICLETYPE > &particle, T delTime, Vector< T, PARTICLETYPE::d > acceleration)
Euler integration.
void velocityVerletIntegration(Particle< T, PARTICLETYPE > &particle, T delTime, Vector< T, PARTICLETYPE::d > acceleration, Vector< T, utilities::dimensions::convert< PARTICLETYPE::d >::rotation > angularAcceleration)
void eulerIntegrationTranslationPeriodic(Particle< T, PARTICLETYPE > &particle, T delTime, Vector< T, PARTICLETYPE::d > acceleration, Vector< int, PARTICLETYPE::d > periodicity)
Euler integration.
ADf< T, DIM > fmod(const ADf< T, DIM > &a, const ADf< T, DIM > &b)
Definition aDiff.h:703
Top level namespace for all of OpenLB.
Converts dimensions by deriving from given cartesian dimension D.