sandbox/fpicella/cylinder_between_plates/plane_couette_force_torque_free_cylinder.c

    Single cylinder between parallel plates Dvinsky Popel 1987. Identical to [cylinder_between_plates.c], but now considering a particle with imposed angular velocity.

    double RADIUS = 0.15; // cylinder radius
    double yShift = 0.0;
    double xShift = 0.0;
    double HEIGHT = 1.0+1e-8; // channel height
    
    double nu     = 1.0; // fluid viscosity;
    
    double uFlow     = 1.;
    
    double TS_Omg = 25.; // TimeStepper intensity
    double TS_Vel = 0.1;
    
    coord pTor   = {0.}; // particle torque
    coord pFor   = {0.}; // force
    coord pTorM1 = {0.}; // torque...at previous timestep (needed for Adams Bashforth timestepper)
    coord pForM1 = {0.}; // force...at previous timestep (needed for Adams Bashforth timestepper)
    coord pVel   = {0.}; // translational velocity
    coord pOmg   = {0.}; // angular velocity
    
    #include "grid/quadtree.h"
    #include "ghigo/src/myembed.h"
    #include "fpicella/src/compute_embed_color_force_torque_RBM.h"
    #include "ghigo/src/mycentered.h"
    #include "fpicella/src/periodic-shift-treatment.h"
    
    #define FLOW (2*y*uFlow)

    We also define the shape of the domain.

    //#define circle (sq ((x)) + sq ((y-yShift)) - sq (RADIUS))
    #define circle (sq (PS(x,xShift)) + sq (PS(y,yShift)) - sq (RADIUS))
    #define channel difference(-y+HEIGHT/2.,-y-HEIGHT/2.)
    #define SOLID  solid (cs, fs, intersection(channel,circle))
    #define PARTICLE solid(csParticle,fsParticle,circle)

    Setup

    We need a field for viscosity so that the embedded boundary metric can be taken into account.

    face vector muv[];

    We define the mesh adaptation parameters.

    int lmin = 4;  // Min mesh refinement level (l=6 is 2pt/d)
    int lmax = 7; // Max mesh refinement level (l=10 is 36pt/d, l=13 is 292pt/d)
    #define cmax (1.e-3) // Absolute refinement criteria for the velocity field
    
    FILE * output_file; // global file pointer
    
    int main ()
    {
    	display_control(TS_Omg,-1000,1000);
    	display_control(TS_Vel,-1000,1000);
      display_control(RADIUS,0.00,0.5);
      display_control(yShift,-0.5,+0.5);
      display_control(xShift,-5.,+5.);
      display_control(lmin,1,9);
      display_control(lmax,1,9);
    	display_control(uFlow,-10,10);

    Space and time are dimensionless. This is necessary to be able to use the ‘mu = fm’ trick.

      size (1. [0]);
    
      L0 = 4.;
    
      X0 = Y0 = -L0/2.;
    //#ifndef FLOW
    //  periodic(left);
    //#endif
    //  periodic(top);

    We turn off the advection term. The choice of the maximum timestep and of the tolerance on the Poisson and viscous solves is not trivial. This was adjusted by trial and error to minimize (possibly) splitting errors and optimize convergence speed.

      stokes = true;
      DT = 1e0;//2e-5 [0];

    We set the tolerance of the Poisson solver.

      TOLERANCE    = 1.e-6;
      TOLERANCE_MU = 1.e-6;

    We initialize the grid.

      N = 1 << (lmax);//initialize at maximum refinement, so to have _child_
    
      init_grid (N);
    
      output_file = fopen ("Free_Particle.dat", "w");
    
    	for(lmax = 8; lmax>=7; lmax -=1){
    		for(yShift = 0.0; yShift<= 0.2125; yShift += 0.0125)
    		{
    			RADIUS = 0.25;
      		run();
    		}
    
    		for(RADIUS = 0.1; RADIUS <= 0.4; RADIUS += 0.05)
    		{
    			yShift = 0.;
      		run();
    		}
    	}
    //	run();	
    
    	fclose(output_file);
    }
    
    
    event init(i=0)
    {
    #if TREE

    When using TREE, we refine the mesh around the embedded boundary.

      astats ss;
      int ic = 0;
      do {
        ic++;
    		SOLID;
        ss = adapt_wavelet ({cs}, (double[]) {1.e-30},
                            maxlevel = (lmax), minlevel = (lmin));
      } while ((ss.nf || ss.nc) && ic < 100);
    #endif // TREE

    We set the viscosity field in the event properties.

      mu = muv;

    Set boundary conditions

      u.n[left]  = dirichlet(FLOW);
      u.t[left]  = dirichlet(0.);
        p[left]  = neumann(0.);
      u.n[right] = dirichlet(FLOW);
      u.t[right] = dirichlet(0.);
        p[right] = neumann(0.);
    }
    
    
    
    event properties (i++) // refresh particle's BC on embed at each iteration...!
    {
    	u.n[embed]  = fabs(y)> 0.49 ? dirichlet(FLOW) : dirichlet(pVel.x -PS(y,yShift)*pOmg.x);
    	u.t[embed]  = fabs(y)> 0.49 ? dirichlet(0.0 ) : dirichlet(pVel.y +PS(x,xShift)*pOmg.x);
      //required to be defined ALSO on uf (see mypoisson.h line 527...)
    	uf.n[embed] = fabs(y)> 0.49 ? dirichlet(FLOW) : dirichlet(pVel.x -PS(y,yShift)*pOmg.x);
    	uf.t[embed] = fabs(y)> 0.49 ? dirichlet(0.0 ) : dirichlet(pVel.y +PS(x,xShift)*pOmg.x); // pOmg.x = pOmg.y
    
      foreach_face()
        muv.x[] = (nu)*fs.x[];
      boundary ((scalar *) {muv});
    
    }
    
    event adapt (i++) // and not classic adapt, so to keep mesh identical during subiterations...
    {
    	SOLID;
      adapt_wavelet ({cs,u}, (double[]) {1.e-2,(cmax),(cmax)},
                     maxlevel = (lmax), minlevel = (lmin));
    }
    
    //event compute_particle_forces_torques (i++)
    event advection_term (i++) // have this step just before starting with fluid computation
    {
    	// Keep forces computed from previous step (Adams Bashforth timestepper...)
    	foreach()
    		pForM1.x = pFor.x;
    	foreach()
    		pTorM1.x = pTor.x;
      //
    	scalar csParticle[];
    	face vector fsParticle[];
    	PARTICLE;
    	// allocate some auxiliary variables
    	coord Fp, Fmu;
      coord Tp, Tmu;
      coord center = {0.,yShift,0.};
      //coord Omega = {oParticle,oParticle,0.}; // for the moment, it works ONLY in 2D!
      embed_color_force_RBM  (p, u, mu, csParticle, center,pOmg, RADIUS, &Fp, &Fmu);
      embed_color_torque_RBM (p, u, mu, csParticle, center,pOmg, RADIUS, &Tp, &Tmu);
      double FORCEx = Fp.x + Fmu.x;
      double FORCEy = Fp.y + Fmu.y;
      double TORQUE = Tp.x + Tmu.x;
      //fprintf(output_file,"%+6.5e %04d %+6.5e %+6.5e %+6.5e %+6.5e %+6.5e %+6.5e %+6.5e\n",
      //              L0, lmax, RADIUS, pVel.x, pOmg.x, yShift,FORCEx,FORCEy,TORQUE);
      //fflush(output_file);
    // simple assignment, ok for a single particle	
    	pFor.x = FORCEx;
    	pFor.y = FORCEy;
    	pTor.x = TORQUE;
    	pTor.y = TORQUE;
    	event("compute_particle_velocities");
      fprintf(stderr,"TOTO %+3.2e %02d %+6.5e %+6.5e %+6.5e %+6.5e %+6.5e %+6.5e %+6.5e %+6.5e\n",
                    L0, lmax, RADIUS, yShift, pVel.x, pVel.y, pOmg.x,FORCEx,FORCEy,TORQUE);
    }
    
    event compute_particle_velocities (i=-1)
    {
    //	if(i<1){ // Explicit euler, eeded for initialization...
    		foreach_dimension(){
    			pVel.x += pFor.x*dt*TS_Vel;
    			pOmg.x += pTor.x*dt*TS_Omg;
    		}
    //	}
    //	else // 2-steps Adams Bashforth
    //	{
    //		foreach_dimension(){
    //			pOmg.x += (3./2.*pTor.x-1./2.*pTorM1.x)*dt*TS_Omg;
    //			pVel.x += (3./2.*pFor.x-1./2.*pForM1.x)*dt*TS_Vel;
    //		}
    //	}
    }

    We look 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-5){ // since I'm looking for a steady solution, this must be quite small...
                               // making the simulation quite expensive
      	fprintf(output_file,"%+3.2e %02d %+6.5e %+6.5e %+6.5e %+6.5e %+6.5e %+6.5e %+6.5e %+6.5e\n",
                    L0, lmax, RADIUS, yShift, pVel.x, pVel.y, pOmg.x,pFor.x,pFor.y,pTor.x);
      	fflush(output_file);
        return 1; /* stop */
      }
    }

    Forces on the cylinder

    set grid
    set xlabel "Radius"
    set ylabel "Omega"
    set title "Free cylinder in plane Couette, y=0"
    
    # Plot data from file, only lines with column 6 equal to 0 (i.e. yShift = 0)
    plot '../Dvinsky_Popel_1987_fig_11.dat' using ( $1):( $2) \
         with lines lw 5 lc rgb "red" title "Dvinsky Popel 1987, fig 11",\
         'Free_Particle.dat' using ( $4==0 && $2==7 ? $3 : 1/0 ):( $4==0  && $2==7 ? +$7 : 1/0 ) \
         with points pt 7 ps 2 lc rgb "blue" title "lmax 7",\
         'Free_Particle.dat' using ( $4==0 && $2==8 ? $3 : 1/0 ):( $4==0  && $2==8 ? +$7 : 1/0 ) \
         with points pt 7 ps 2 lc rgb "green" title "lmax 8"
    Free cylinder in plane Couette, y=0 (script)

    Free cylinder in plane Couette, y=0 (script)

    set grid
    set xlabel "y"
    set ylabel "U_x"
    set title "Free cylinder in plane Couette, R=0.25"
    
    # Plot data from file, only lines with column 6 equal to 0 (i.e. yShift = 0)
    plot '../Dvinsky_Popel_1987_fig_10a_R_025.dat' using ($1-0.5):( $2) \
         with lines lw 5 lc rgb "red" title "Dvinsky Popel 1987, fig 10a",\
         'Free_Particle.dat' using ( $3==0.25 && $2==7 ? $4 : 1/0 ):( $3==0.25  && $2==7 ? +$5 : 1/0 ) \
         with points pt 7 ps 2 lc rgb "blue" title "lmax 7",\
         'Free_Particle.dat' using ( $3==0.25 && $2==8 ? $4 : 1/0 ):( $3==0.25  && $2==8 ? +$5 : 1/0 ) \
         with points pt 7 ps 1 lc rgb "green" title "lmax 8"
    Free cylinder in plane Couette, R=0.25 (script)

    Free cylinder in plane Couette, R=0.25 (script)

    For the torque, it clearly is ok now, I could try to improve the computational domain - mesh refinement - domain size

    set grid
    set xlabel "y"
    set ylabel "Omega"
    set title "Free cylinder in plane Couette, R=0.25"
    
    # Plot data from file, only lines with column 6 equal to 0 (i.e. yShift = 0)
    plot '../Dvinsky_Popel_1987_fig_10b_R_025.dat' using ($1-0.5):( $2) \
         with lines lw 5 lc rgb "red" title "Dvinsky Popel 1987, fig 10b",\
         'Free_Particle.dat' using ( $3==0.25 && $2==7 ? $4 : 1/0 ):( $3==0.25  && $2==7 ? +$7 : 1/0 ) \
         with points pt 7 ps 2 lc rgb "blue" title "lmax 7",\
         'Free_Particle.dat' using ( $3==0.25 && $2==8 ? $4 : 1/0 ):( $3==0.25  && $2==8 ? +$7 : 1/0 ) \
         with points pt 7 ps 1 lc rgb "green" title "lmax 8"
    Free cylinder in plane Couette, R=0.25 (script)

    Free cylinder in plane Couette, R=0.25 (script)

    For the torque, it clearly is ok now, I could try to improve the computational domain - mesh refinement - domain size

    but honestly, it does not seem to work any better than this.