sandbox/alimare/1_test_cases/simili-RP-instab.c

    Skeleton of a Rayleigh-Plateau instability

    The goal is to build the skeleton of a simili Rayleigh-Plateau instability. In particular we are interested in the ability of retaining a skeleton even though the VOF variable wants to pinch the interface.

    #include "grid/octree.h"
    #define quadratic(x,a1,a2,a3) \
      (((a1)*((x) - 1.) + (a3)*((x) + 1.))*(x)/2. - (a2)*((x) - 1.)*((x) + 1.))
    #include "utils.h"
    #include "distance.h"
    #include "fractions.h"
    #include "view.h"
    #include "../thinning.h"
    int n_part = 0;
    #include "../../Antoonvh/scatter.h"
    #define QUADRATIC 1
    #include "../alex_functions.h"
    #include "../basic_geom.h"
    
    #define Pi 3.141592653589793
    double mini_snake(double x, double y, double z, double NB_width,
      double variation){
      coord center    = {0,0,0};
    the dimensional constraints below are not compatible
      double size     = L0/48.*(1.+variation*cos(8*Pi*z));
      return clamp(-circle(x,y,center, size) , -NB_width, NB_width);
    }
    
    int main()
    {
    
      init_grid (64);
      origin(-0.5,-0.5,-0.5);

    We initialize the distance field on the coarse initial mesh and refine it adaptively until the threshold error (on distance) is reached.

      scalar dist[];
      scalar f[];
      face vector s[];
      int MAXLEVEL    = 8;
      
      for (int j = 0; j < 8; j++){
        double NB_width = 2*L0/(1 << MAXLEVEL);
        double variation = 0.2+j*0.1;
        char name[80];
        foreach()
          dist[] = mini_snake(x,y,z, NB_width, variation);
        boundary({dist});
        restriction({dist});
    
        for (int i = 0; i < 2; i++){
            /* code */
          adapt_wavelet ({dist}, (double[]){1.e-4}, MAXLEVEL, MAXLEVEL-4);
          foreach()
            dist[] = mini_snake(x,y,z, NB_width, variation);
          boundary({dist});
          restriction({dist});
          fprintf(stderr, "loop %ld\n", grid->n );
        }
        
        NB_width = 8*L0/(1 << MAXLEVEL); // for vizualisation we extend the width
        foreach()
            dist[] = mini_snake(x,y,z, NB_width, variation);
        boundary({dist});
        restriction({dist});
    
        vertex scalar distn[];
        cell2node(dist,distn);
    
    
        fractions (distn, f, s);
        
        // clear();

    We display an isosurface of the distance function coloured with the level of refinement and the surface reconstructed from volume fractions.

        double offset = 0.005;
        view (quat = {0.159, 0.838, 0.231, -0.468},
              fov = 10, 
              tx = -0.009, ty = 0.028,
              width = 600, height = 600);
        sprintf (name, "vof-%g.png", variation);
        draw_vof ("f");
        save (name);
        view(fov = 5);
        draw_vof ("f");
        cells (n = {1,0,0}, alpha = offset);
        sprintf (name, "vofzoom-%g.png", variation);
        save (name);
    
        squares ("fabs(dist[]) < 0.9*0.03125 ? dist[] : nodata", min = -0.03125, max = 0.03125, n = 
        {1,0,0}, alpha = offset);
        cells (n = {1,0,0}, alpha = offset);
        sprintf (name, "dist-%g.png", variation);
        save(name);
    
    
        scalar c[];
        foreach(){
          if(f[])c[] =1;
          else c[] = 0;
        }
        boundary({c});
        thinning3D(c);

    To output the skeleton, we will use the Lagrangian particles of Antoonvh, the remaining cells will be shown as spheres.

        Cache skeleton = {0}; 
    
        foreach(){
          if(c[]){
            cache_append (&skeleton, point, 0);
            n_part++;
          }
        }
        if(n_part == 0){
          fprintf(stderr, "pas de squelette\n");
          exit(1);
        }
        coord * loc = malloc (n_part*sizeof(coord));
        int n = 0;
        foreach_cache(skeleton) {
          coord cc = {x, y, z};
          foreach_dimension()
            loc[n].x = cc.x;
          n++;
        }
        squares ("fabs(dist[]) < 0.9*0.03125 ? dist[] : nodata", min = -0.03125, max = 0.03125, n = 
        {1,0,0}, alpha = offset);
        cells (n = {1,0,0}, alpha = offset);
        scatter(loc, s = 40);
        sprintf (name, "medial_axis-%g.png", variation);
        save(name);
    
        free (loc);
        free (skeleton.p);
      }
    }

    We correctly detect the medial axis of our simili-Rayleigh-Plateau instability even when the VOF interface

    Fullview VOF + mesh Skeleton + distance + mesh