sandbox/qmagdelaine/phase_change/1_elementary_body/static_drop.c

    Drop evaporation

    We investigate the evaporation of a single droplet in a still and relatively dry environment.

    Evaporating droplet with the vapour concentration field

    We define the geometrical, temporal and resolution parameters:

    #define R0 1.
    #define L 10. // size of the box
    
    #define MIN_LEVEL 5
    #define LEVEL 10
    #define MAX_LEVEL 12
    #define dR_refine (2.*L0/(1 << LEVEL))
    
    #define F_ERR 1e-10
    
    #define T_END 600.
    #define DT_MAX 10.
    #define DELTA_T 10. // for measurements and videos

    We use an advection solver and the functions defined in elementary_body.h:

    #include "axi.h"
    #include "../advection_Q.h"
    #include "../elementary_body.h"
    #include "view.h"
    #define BG 0.7 // light gray for background
    #define DG 0. // dark gray

    Physical parameters

    We non-dimensionalise the problem with the initial radius of the drop R, the diffusion coefficient of liquid vapour in air D and the saturation concentration of water in air c_s (this quantity having the dimension of a density M\cdot L^{-3}).

    Thus the diffusion equation for the vapour in the non-dimensional space reads: \frac{\partial c}{\partial t} = \Delta c, appropriately completed with Dirichlet conditions at the surface of the drop and at infinity: \left\{ \begin{array}{ll} c = 1 & \text{at the drop surface,}\\ c \to c_\infty/c_s & \text{far from the drop.} \end{array} \right. As the interface recedes at a (dimensional) velocity v_\text{e} = \frac{D}{\rho}\nabla c \sim \frac{D}{\rho}\frac{c_0}{R} \equiv V, a Peclet number Pe= \frac{VR}{D} = \frac{c_s}{\rho} also enters in the problem description. Typically, for the problem of a water droplet evaporating in dry air, this Peclet number is O(10^{-5}), meaning that the problem is really dominated by diffusion. Here, we choose density ratio equal to 10^{-3}, and set the relative humidity of the surroundings to 20%.

    We need time factor to set the Dirichlet condition, its role is specified in elementary_body.h.

    #define vapor_peclet 1e-3
    #define D_V 1.
    #define vcs 1.
    #define cinf 0.2
    #define dirichlet_time_factor 10.

    We allocate several scalar fields to describe both the interface and the concentration field.

    scalar f[], vapor[];
    scalar * interfaces = {f}, * tracers = {vapor};

    Thanks to symmetry, we only solve a quarter of the domain, and requires the concentration to drop at its asymptotic value at infinity (that is, at the box boundary)

    vapor[right] = dirichlet(cinf);
    vapor[top]   = dirichlet(cinf);

    The main function of the program, where we set the domain geometry to be ten times larger than the drop:

    int main() {
      size (L);
      origin (0., 0.);
      N = 1 << LEVEL;
      init_grid (N);
      DT = DT_MAX;
      run();
    }

    The initial position of the interface is defined with this function:

    #define circle(x, y, R) (sq(R) - sq(x) - sq(y))

    Before the first step, we initialize the concentration field (after having refined the grid around the future interface): c_s in the drop and c_\infty in the vapor. \mathbf{u}_f is set to zero.

    event init (i = 0) {
      #if TREE
        refine (level < MAX_LEVEL && circle(x, y, (R0 - dR_refine)) < 0.
                && circle(x, y, (R0 + dR_refine)) > 0.);
      #endif
      fraction (f, circle(x, y, R0));
      foreach()
        vapor[] = f[]*vcs + (1. - f[])*cinf;
      foreach_face()
        uf.x[] = 0.;
      boundary({vapor, uf});
      CFL = 0.2;
    }

    Evaporation velocity

    The velocity due to evaporation is computed in the stability() event to take into account this velocity in the CFL condition.

    event stability (i++) {
      vapor.D = D_V;
      vapor.peclet = vapor_peclet;
      vapor.inverse = true;
      phase_change_velocity (f, vapor, uf);
      boundary((scalar*){uf});
    }

    After the vof() event, the evaporation velocity has to be erased.

    event tracer_advection (i++) {
      foreach_face()
        uf.x[] = 0.;
      boundary((scalar*){uf});
    }

    Diffusion with immersed dirichlet condition

    The concentration field diffuses at each timestep. We need for that the maximal level in the simulation.

    event tracer_diffusion(i++) {
    
      #if TREE
        int max_level = MAX_LEVEL;
      #else
        int max_level = LEVEL;
      #endif
      
      vapor.D = D_V;
      vapor.tr_eq = vcs;
      vapor.inverse = true;
      dirichlet_diffusion (vapor, f, max_level, dt, dirichlet_time_factor);
    }
    
    #if TREE
    event adapt (i++) {
      adapt_wavelet ({f, vapor}, (double[]){1e-3, 1e-3},
    		             minlevel = MIN_LEVEL, maxlevel = MAX_LEVEL);
    }
    #endif

    Post-processings and videos

    We now juste have to write several post-processing events to save the shape of the drop, its effective radius and the vapor concentration profile.

    event interface (t = 3.*T_END/4.) {
      static FILE * fpshape = fopen("shape", "w");
      output_facets (f, fpshape);
      fflush(fpshape);
    }
    
    event outputs (t = 0.; t += max(DELTA_T, DT); t <= T_END) { 
    
      double effective_radius;
      effective_radius = pow(3.*statsf(f).sum, 1./3.);
    
      fprintf (stderr, "%.17g %.17g\n", t, effective_radius);
      fflush(stderr);
      if (t <= T_END - 20.) {
        static FILE * fpvapor = fopen("vapor_profile", "w");
        static FILE * fpvaporresc = fopen("vapor_profile_resc", "w");
        for (double y = 0.; y <= 5.; y += 0.01)
          fprintf (fpvapor, "%g %g\n", y, interpolate (vapor, 0., y));
        for (double y = effective_radius; y <= 5.; y += 0.01)
          fprintf (fpvaporresc, "%g %g %g\n", effective_radius, y/effective_radius,
                   interpolate (vapor, 0., y));
        fprintf (fpvapor, "\n");
        fprintf (fpvaporresc, "\n");
        fflush(fpvapor);
        fflush(fpvaporresc);
      }

    We create a video with the concentration in the vapor phase.

      scalar vapor_draw[];
      foreach() {
        f[] = clamp(f[], 0., 1.);
        vapor_draw[] = - vapor[];
      }
      boundary({f, vapor_draw});
    
      view (fov = 15, width = 640, height = 640, samples = 1, relative = false,
            tx = 0., ty = 0., bg = {BG, BG, BG});
      clear();
      draw_vof("f", edges = true, lw = 1.5, lc = {DG, DG, DG}, filled = 1,
               fc = {BG, BG, BG});
      squares ("vapor_draw", min = - vcs, max = vcs, linear = false,
               map = cool_warm);
      mirror (n = {1., 0., 0.}, alpha = 0.) {
        draw_vof("f", edges = true, lw = 1.5, lc = {DG, DG, DG}, filled = 1,
                 fc = {BG, BG, BG});
        squares ("vapor_draw", min = - vcs, max = vcs, linear = false,
                 map = cool_warm);
      }
      mirror (n = {0., 1., 0.}, alpha = 0.) { // vapor
        draw_vof("f", edges = true, lw = 1.5, lc = {DG, DG, DG}, filled = 1,
                 fc = {BG, BG, BG});
        squares ("vapor_draw", min = - vcs, max = vcs, linear = false,
                 map = cool_warm);
        mirror (n = {1., 0., 0.}, alpha = 0.) {
            draw_vof("f", edges = true, lw = 1.5, lc = {DG, DG, DG}, filled = 1,
                     fc = {BG, BG, BG});
            squares ("vapor_draw", min = - vcs, max = vcs, linear = false,
                     map = cool_warm);
        }
      }
      save ("video_static_drop.mp4");
    }

    Results

    Interface shape

    We first check is the shape of drop remains spherical.

    set style line 1 pt 7 ps 0.7
    darkgray="#666666"
    blue="#5082DC"
    turquoise="#008C7D"
    orange="#FF780F"
    raspberry="#FA0F50"
    
    set size square
    set xlabel "x"
    set ylabel "y"
    set object 1 circle at 0,0 size first 0.4726 fc rgb darkgray
    plot 'shape' w l lc rgb blue t 'simulation'
    Shape of the interface (script)
    unset object 1
    set xlabel "angle"
    set ylabel "radius"
    plot 'shape' u atan(1, 2):(sqrt($1*$1 + $2*$2)) ls 1 lc rgb blue t 'local radius vs angular position'
    Local radius in function of the angular position (script)

    Radius evolution: the \text{d}^2 law

    This problem was first investigated independently by Maxwell and Langmuir. They found that quite counter-intuitively, the evaporation mass rate does not scale with the surface of the drop, but with its radius (as a consequence of evaporation being a diffusion-limited process).

    It follows that the squared-radius of the drop decreases linearly with time (so-called “\text{d}^2 law”), according to: r^2(t) = r_0^2 - 2 \frac{D(c_0-c_\infty)}{\rho}t

    Here is represented the time evolution of the effective radius of the drop, compared with the theoretical prediction:

    unset size
    set xlabel "t"
    set ylabel "R²"
    plot [0:590][0:1] 'log' u 1:($2*$2) ls 1 lc rgb blue t 'simulation', \
         1.-0.002*0.8*x lw 1.5 lc rgb orange t 'inifinite model'
    Time evolution of the squared radius r^2(t) (script)

    Concentration profiles

    Now checking the concentration profiles vs time we have

    set xlabel "r"
    set ylabel "c"
    plot 'vapor_profile' w l lc rgb blue t 'simulation'
    Raw concentration profiles vs time (script)

    The theoretical concentration profiles follow: c(r,t) = \left(\frac{R(t)}{r}\right) (c_0-c_\infty) + c_\infty This suggests to replot the concentration profiles versus the rescaled variable r/R(t):

    set xlabel "r/R"
    set ylabel "c"
    plot 'vapor_profile_resc' u 2:3 w l lc rgb blue t 'simulation', \
         0.8*(1./x) + 0.2  lw 1.5 lc rgb orange t 'infinite model'
    Tentative rescaled concentration profiles (script)

    This is not entirely satisfying.

    The reason is that our infinity is 10; confinement effects, if not dominant, are nonetheless not entirely negligible. Working out these effects, we get: c(r,t) = c_0 + \frac{c_0-c_\infty}{1-\frac{R(t)}{R_\infty}} \left(\frac{R(t)}{r} - 1\right)

    suggesting a slightly different rescaling:

    set xlabel "r/R"
    set ylabel "c_r"
    plot 'vapor_profile_resc' u 2:(($3-1.)*(1-$1/10.)+0.8) w l lc rgb blue t 'simulation', \
         0.8*(1./x) lw 1.5 lc rgb raspberry t 'confined model'
    Better rescaling for the concentration profiles, accounting for confinement effects (script)

    But wait. If taking confinement effects into account yield more neat agreement, we should modify our \text{d}^2 law accordingly? Let’s give it a try. The confined \text{d}^2 law reads: R^2(t) - \frac{2}{3R_\infty} R^3(t) = R_0^2 - \frac{2}{3R_\infty} R_0^3 - 2 \frac{D(c_0-c_\infty)}{\rho}t

    set xlabel "t"
    set ylabel "R² - 2/3 R³/L_0"
    plot [0:590][0:1] 'log' u 1:($2*$2-2./3./10.*$2*$2*$2) w p pt 7 ps 0.5 lc rgb blue t 'simulation', \
         1.-2./30.-0.002*0.8*x lw 1.5 lc rgb raspberry t 'confined model'

    A better $(script){d}

    That’s it!

    References

    [langmuir1918]

    Irving Langmuir. The evaporation of small spheres. Physical review, 12(5):368, 1918.

    [maxwell1878]

    James Clerk Maxwell. Diffusion. Encyclopedia britannica, 7:214–221, 1878.