sandbox/prouvost/AMR_examples/basilisk_logo/AMRlogo.c

    In this script, we present the core concept of AMR (Adaptive Mesh Refinement) through an analogy with pictures where we consider that an element of the mesh corresponds to one pixel of a picture.

    #include "utils.h"
    #include "input.h"
    #include "run.h"

    Below: for .vtk output. The .vtk files have no interest to be computed on the Basilisk website, so I commented the concerned lines. I didn’t erase them, as they can be usefull as an example for whose who want to use these output in their simulations

    /* #include "./vtknew_cell.h"  */
    
    
    int main(){
        init_grid(1<<8);
        run();
    }
    
    event tend(i=10){}

    AMR

    We import a gray-scale version of the Basilisk logo and, in each cell, we put one value corresponding to the gray value.

    event movie(i++){
          
        scalar gris[];
        FILE * fp = fopen("./logo_ascii.h","r");  // import the (modified and grayed) basilisk logo
        input_pgm(gris,fp);
        fclose(fp);
    
        foreach()
          if (y>0.82 && gris[]==0.)
            gris[]=1.;

    Once the values are stored in the mesh elements, we perform AMR (i.e. we change the element size repartition in the domain). Each new cell can be finer or coarser than the original cells, and still contains one value of gray.

        // AMR
        for (int il=0;il<=12;il++){
          int k = 100-10*i;
          double eps=0.005+(0.5-0.005)*cube(1.*k/100.);
          adapt_wavelet({gris},(double[]){eps},maxlevel=8);
        }

    Commented lines below: .vtk outputs.

        /* scalar lev[]; */
        /* foreach() */
        /* 	 lev[]=level; */
        /* boundary({lev}); */
    
        /* char fname[80]; */
        /* sprintf(fname,"fields_%i.vtk",k); */
        /* fp = fopen(fname,"w"); */
        /* output_vtk((scalar*){lev,gris},fp); */
        /* fclose(fp); */

    We output two video: one with the gray value in each element, and one with the level of the elements (level of element directly linked to element size).

        output_ppm (gris, file = "gris.mp4", box = {{0.,0.},{1.,1.}}, linear = true, spread = 2, n = 256); // it would be nicer with a gray scale and a reduced framerate
    
        scalar l[];
        foreach()
          l[] = level;
    
        output_ppm (l, file = "level.mp4", box = {{0.,0.},{1.,1.}}, linear = false, min = 3, max = 8, n = 256); // it would be nicer a reduced framerate 
    
    }

    We show the two video. We see on the starting coarse mesh (mesh containing big elements), that the corresponding picture is underresolved and fuzzy. As soon as the mesh element are refined, the the logo becomes sufficiently resolved.

    Evolution of the gray level

    Evolution of the level of refinement

    If we imagine that the logo is the solution of an EDP, we can say that the solution is not correct on the coarse mesh (the picture is underrsolved, which corresponds to a solution containing huge errors), whereas on the finer meshes, the solution seems correct (small errors). On the opposite, finer meshes implies more elements, and thus more expensive computations. In that perspective, doing AMR means searching an optimized mesh (optimized cell size repartition), which minimizes the error for a given number of element, or which minimizes the number of element for a given error tolerance.