sandbox/Antoonvh/diffgausspulse3.c

    Diffusion of a Gaussian Pulse Using an Adaptive Grid

    As a follow-up of this page, we study the effect of using adaptive-grid refinement on the accuracy of the solution. On the aforementioned page we found that a resolution boundary may introduce numerical errors due to the prolongation at resolution boundaries. We will see that an adaptive-grid approach is not free its own additional issues. Rather than being directly controlled by the initialized grid resolution, the accuracy of the solution is now a function of the so-called refinement criterion (\zeta). This criterion will in turn dictate the (spatiotemporal varying) grid resolution.

    #include "grid/bitree.h"
    #include "run.h"
    #include "diffusion.h"
    
    double t0=1./3.;
    double D=0.01;
    double zeta;
    const face vector DD[]= {D};
    scalar c[];
    int m;
    
    double f(double t,double to,double xi,double D,double Delta){
      return (pow((to)/(to+t),0.5)*pow(M_PI*D*(t+to),0.5)*(erf(((xi)+(Delta/2))/(2*pow(D*(t+to),0.5)))-erf(((xi)-(Delta/2))/(2*pow(D*(t+to),0.5)))))/Delta;
    }

    We run four different simulations. We always use \zeta=0.05, unless stated otherwise. Supplemented with a maximum resolution corresponding to N=128.

    1. Using a fixed grid with N=128
    2. Using the Default settings
    3. Using \zeta=0.025
    4. Using refine\_linear for prolongation
    int main(){
      L0=5;
      X0=-L0/2;
      for (m=0;m<4;m++)
        run(); 
    }
    
    event init(t=0){
      DT=1e-4;
      init_grid(1<<7);
      if (m>0)
        zeta=0.05;
      if (m==2)
        zeta=0.025;
      if (m>2)
        c.prolongation=refine_linear;
      foreach()
        c[]=f(t,t0,x,D,Delta);
      if (m>0){
        boundary({c});
        while(adapt_wavelet({c},(double[]){zeta},7,5).nc){
          foreach()
            c[]=f(t,t0,x,D,Delta);
          boundary({c});
        }
      }
    }
    
    event diffn(i++;t<=1.) {
      dt=dtnext(DT);
      diffusion(c,dt,DD); 
    }

    An adapt event is added for adaptivity purposes.

    event adapt(i++){
      if (m>0){
        adapt_wavelet({c},(double[]){zeta},7,5); 
      }
    }
    
    event end(t=1){
      char name[100];
      sprintf(name,"Gauss%d.dat",m);
      FILE * fp = fopen(name,"w");
      foreach()
        fprintf(fp,"%g\t%g\t%g\t%g\t%g\n",x,Delta,c[],f(t,t0,x,D,Delta),fabs(c[]-f(t,t0,x,D,Delta)));
      fflush(fp);
    }

    Results

    First, the grid resolution at t=t_{end} for some different runs are plotted.

    set xr [-1:1]
    set yr [0.03:0.4]
      set xlabel 'x'
      set ylabel '{/Symbol D}'
      set logscale y
      set size square
      plot 'Gauss0.dat' using 1:2 ps 3 lc rgb 'red'  title "Fixed-grid run" ,\
           'Gauss1.dat' using 1:2 ps 2 lc rgb 'blue' title  "{/Symbol z}=0.05" ,\
           'Gauss2.dat' using 1:2 ps 1 lc rgb 'green' title "{/Symbol z}=0.025" 
    (script)

    (script)

    Looks as can be expected. Lets look at the solution from the first two adaptive-grid runs.

      unset logscale y
      set xr [-1 :1]
      set yr [0 : 1.1] 
      
      set xlabel 'x'
      set ylabel 'c'
      set size square
      set samples 10001
        plot  0.5*exp(-((x)**2)/(0.04*4/3)) lw 5 lc rgb 'magenta' title "Exact solution" ,\
             'Gauss1.dat' using 1:3 with line lw 3 lc rgb 'blue' title "{/Symbol z}=0.05}" ,\
             'Gauss2.dat' using 1:3 with line lw 2 lc rgb 'green' title "{/Symbol z}=0.025}"  ,\
             exp(-((x)**2)/(0.04*1/3)) lc rgb 'black' with line title "Initialized pulse"
    (script)

    (script)

    This looks O.K.-ish. Lets study the errors for all runs in some more detail.

      set xr [-1:1]
      set yr [0:0.01]
      set xlabel 'x'
      set ylabel 'Error'
      set size square
        plot 'Gauss0.dat' using 1:5 with line lw 3 lc rgb 'red' title "Fixed-grid run" ,\
             'Gauss1.dat' using 1:5 with line lw 3 lc rgb 'blue' title "{/Symbol z}= 0.05 "  ,\
             'Gauss2.dat' using 1:5 with line lw 2 lc rgb 'green' title "{/Symbol z}= 0.025" 
    (script)

    (script)

    This plot reveals some interesting results. First, the fixed-grid run is most accurate compared to the adaptive-grid counterparts. Second, when the \zeta is set to a smaller value, the obtained error do not really appear to decrease.

    Analysis: Why does using a smaller \zeta-value not yield better results?

    From the first figure it can be seen that setting a lower refinement cirterion does lead to more refinement. We have learned from this page that higher resolution grids can be associated with a more accurate solution. However, this page presented a cautionary note on the introduction of resolution boundaries. For this case, with the chosen \zeta-values, the increased accuracy of using more cells is not setoff by the error introduced with the additional resolution boundaries. With the aim to check this, a simulation was run with using refine\_linear prolongation attribute. The results are shown below:

      set xr [-1:1]
      set yr [0:0.01]
      set xlabel 'x'
      set ylabel 'Error'
      set size square
       plot   'Gauss0.dat' using 1:5 with line lw 3 lc rgb 'red' title "Fixed-grid run" ,\
             'Gauss1.dat' using 1:5 with line lw 3 lc rgb 'blue' title "{/Symbol z}= 0.05 "  ,\
             'Gauss3.dat' using 1:5 with line lw 2 lc rgb 'orange' title "linear prolongation,{/Symbol z}= 0.05" 
    (script)

    (script)

    It seems to be doing better, but not too convincingly. Lets check the used grid for both simulations at t=t_{end}.

    set xr [-1:1]
    set yr [0.03:0.4]
      set xlabel 'x'
      set ylabel '{/Symbol D}'
      set logscale y
      set size square
      plot 'Gauss1.dat' using 1:2 ps 3 lc rgb 'blue'  title "{/Symbol z}=0.05" ,\
           'Gauss3.dat' using 1:2 ps 2 lc rgb 'orange' title  "linear prolongation,{/Symbol z}=0.05" 
    (script)

    (script)

    Obviously, the linear-prolongation run is using much fewer cells. The is the result of the fact that linear prolongation is more accurate! The corresponding wavelet estimated error will in general be smaller compared to the (default) bilinear prolongation. This in turn will lead to more coarsening and less refinement for the more accurate method. Therefore, the comparison of the errors made in this section is not really fair.

    The next step

    To circumvent this issue a work arround can be introcuded such that refine\_bilinear is used when making the wavelet-based grid assessment whilst using refine\_linear for the treatment of resolution boundaries. The corresponding setup and results can be found here. It was found that the presented results here, represent a rather special case.