sandbox/fpicella/microswimmer_fluid_particle_dynamics/single_free_couette.c
Single cylindrical particle in a 2D couette flow, Stokes regime.
- Physical configuration Dvinsky & Popel 1987
- Numerical method: Fluid Particle method Tanaka & Araki 200
Here we determine what is the angular velocity of a force-torque free cylindrical particle in a plane couette flow.
The Fluid Particle method is implemented in basilisk here
Loosely speaking, it consist of accounting for a rigid, force-free and torque free particle, as a blob of fluid having a high viscosity.
Usually the ratio between fluid viscosity and particle viscosity is set to be the variable \eta\approx100.
In this page, we test the effectiveness of the method, as a function of spatial resolution.
REMARK
The following implementation requires the use of standard viscosity.h, hence boundaries are accounted using the mask() function (now obsolete).
This is due to the fact that using embedded boundaries, viscosity-embed.h does not account by default of variable viscosity.
#include "navier-stokes/centered.h"
#include "view.h"
I Will define here if I want a fancier/more complex way of computing angular velocity.
//#define OMEGA_EQUATION() 0.
#define OMEGA_EQUATION() interpolate_linear(locate (x, y, z),omega, x, y, z)
Uncomment if you want particles to be advected
#define Particle_Advection_ON 1
double HEIGHT = 1.0;
double STRENGTH = 100.0;
double ETA = 100.;
double RADIUS = 0.25;
#include "fpicella/src/periodic-shift-treatment.h"
#include "fpicella/src/tracer-particles-FP.h"
#include "fpicella/src/driver-FluidParticleDynamics.h"
Variable viscosity.
face vector muv[];
Variable acceleration.
Vorticity field.
scalar omega[];
Variable associated to particles that are modelling microswimmers
Particles microswimmers;
Output file, file pointer.
FILE * output_file; // global file pointer
Number of particles in simulation.
double NP = 1.;
int main()
{
(STRENGTH,-1000,1000);
display_control(ETA,-1000,1000);
display_control(RADIUS,-1000,1000); display_control
Space and time are dimensionless. This is necessary to be able to use the ‘mu = fm’ trick.
(4. [0]);
size = HUGE [0];
DT
(-L0/2., -L0/2.);
origin
periodic (right);
// periodic (top);
= true;
stokes = 1e-10;
TOLERANCE
= fopen ("Free_Particle.dat", "w");
output_file for (N = 16; N <= 128; N *= 2)
for (RADIUS = 0.15; RADIUS <= 0.4; RADIUS += 0.05)
//N=128;
run();
fclose(output_file);
}
#define WIDTH 0.5
#define EPS 1e-14
event init (t = 0) {
Initialize microswimmer particles.
= init_tp_circle(NP); microswimmers
If I've got one single particle, set it in the center of the domain.
if(NP==1)
foreach_particle(){
().x = 0.;
p().y = 0.;
p}
Initialize particle size.
foreach_particle_in(microswimmers){
().r = RADIUS;
p}
compute_SP(microswimmers);
compute_variable_viscosity();
= muv; mu
The channel geometry is defined using Constructive Solid Geometry.
mask (y > +HEIGHT/2. ? top : none);
mask (y < -HEIGHT/2. ? bottom : none);
.n[top] = dirichlet(0.);
u.t[top] = dirichlet(y);
u.n[bottom] = dirichlet(0.);
u.t[bottom] = dirichlet(y);
u.t[right] = dirichlet(0.);
u.n[right] = dirichlet(0.);
u.n[left] = dirichlet(0.);
u.t[left] = dirichlet(0.);
u}
We check for a stationary solution.
scalar un[]; // field that will contain previous solution...
event logfile (t += 0.01; i <= 1000) {
double du = change (u.y, un);
if (i > 0 && du < 1e-6){ // since I'm looking for a steady solution, this must be quite small...
foreach_particle_in(microswimmers)
fprintf(output_file,"%+3.2e %03d %+6.5e %+6.5e %+6.5e %+6.5e %+6.5e %+6.5e %+6.5e %+6.5e\n",
, N, ETA, p().r, p().x, p().y, p().theta, p().u.x, p().u.y, p().omega);
L0fflush(output_file);
return 1; /* stop */
}
}
event acceleration (i++){
// compute_microswimmer_forcing(microswimmers);
// a = av;
}
event properties (i++)
{
foreach_particle_in(microswimmers)
().r = RADIUS;
pcompute_SP(microswimmers);
compute_variable_viscosity();
= muv;
mu vorticity(u,omega);
}
Force-Torque free 2D cylinder in plane couette flow
set grid
set xlabel "Radius"
set ylabel "Omega"
set title "Free cylinder in plane Couette"
set key right left
plot \
'Free_Particle.dat' using ( $2==256 ? $4 : 1/0 ):( $2==256 ? +$10 : 1/0 ) with points pt 13 ps 2 lc rgb "#fb9f3a" title "N = 256",\
'Free_Particle.dat' using ( $2==128 ? $4 : 1/0 ):( $2==128 ? +$10 : 1/0 ) with points pt 9 ps 2 lc rgb "#b63679" title "N = 128",\
'Free_Particle.dat' using ( $2==64 ? $4 : 1/0 ):( $2==64 ? +$10 : 1/0 ) with points pt 5 ps 2 lc rgb "#3b0f70" title "N = 64",\
'Free_Particle.dat' using ( $2==32 ? $4 : 1/0 ):( $2==32 ? +$10 : 1/0 ) with points pt 7 ps 2 lc rgb "#000004" title "N = 32",\
'../../cylinder_between_plates/Dvinsky_Popel_1987_fig_11.dat' using ( $1):( $2) \
with lines lw 5 lc rgb "black" title "Dvinsky Popel 1987, fig 11"
The bigger the particle, the higher the confinement, the higher the resolution required to converge.
Still, it is quite expensive to be qualitatively acceptable.
Is there something else I should work on?
Or the approach is just not good enough for my purposes?