sandbox/geoffroy/dev/gen-time-inc.h

    Generic time-integration scheme

    #include "utils.h"
    
    // Required from solver
    // fields updated by time-integration
    extern scalar * evolving;
    
    ///////////////////////////////////////////////////////////////////////////
    // Butcher tables, simplified by Kopal and re-organized by Williamson
    // See "Low-storage runge-kutta schemes", williamson,1980
    // & "Fourth-order 2N-storage rk schemes", Carpenter & Kennedy, 1994, NASA
    static double ** butcherd(order){
      // butcher[0][i] = ai
      // butcher[1][i] = bi
      double ** butcher;
      butcher = malloc(2*order*sizeof(double));
      butcher[0] = malloc(order*sizeof(double));
      butcher[1] = malloc(order*sizeof(double));
    
      butcher[0][0] = 0; //a1
      if(order == 1)
        butcher[1][0] = 1;
      else if(order == 2){
    //      a[]                         b[]  
                               butcher[1][0] = 0.5;//1
      butcher[0][1] = -0.5;    butcher[1][1] = 1;//2
      }
      else if(order == 3){
    //      a[]                         b[]   
                                 butcher[1][0] = 1/3.; //1
      butcher[0][1] = -5/9.;     butcher[1][1] = 15/16.; //2
      butcher[0][2] = -153/128.; butcher[1][2] = 8/15.; //3
      }
      else if(order == 5){
        // 5 steps for the 4th-order scheme
    //      a[]                        
      butcher[0][1] = -1 ;     
      butcher[0][2] = -1/3.+pow(2,2/3.)/6. - 2*cbrt(2)/3.;     
      butcher[0][3] = -cbrt(2) - pow(2,2/3.) - 2;      
      butcher[0][4] = -1 + cbrt(2);      
    
      //   b[]
      butcher[1][0] = 2/3. + cbrt(2)/3. + pow(2,2/3.)/6.; //1
      butcher[1][1] = -pow(2,2/3.)/6. + 1/6.;    //2
      butcher[1][2] = -1/3. - 2*cbrt(2)/3. - pow(2,2/3.)/3.; //3
      butcher[1][3] = 1/3. - cbrt(2)/3. - pow(2,2/3.)/6.; //3
      butcher[1][4] = 1/3. + cbrt(2)/6. + pow(2,2/3.)/12.; //3
      }
      else assert(false);
     return butcher;
    }
    
    //////////////////////////////////////////////////////
    // User-provided functions
    // gradient
    double (* gradient)  (double, double, double) = minmod2;
    
    // how to compute updates
    double (* update) (scalar * evolving, scalar * updates, double dtmax) = NULL;
    
    double t = 0., dt = 0.;
    static void advance_generic (scalar * output, scalar * input, scalar * updates,
    			     double dt){
      trash (output);  
      foreach() {
        scalar o,i,u;
        for(o,i,u in output,input,updates)
           o[] = i[]+dt*u[];
      }
      boundary (output);
    }
    
    static void (* advance) (scalar * output, scalar * input, scalar * updates,
    			 double dt) = advance_generic;
    event defaults (i = 0)
    {
      // limiting
      for (scalar s in all)
        s.gradient = gradient;
    
      // default values
      foreach()
        for (scalar s in all)
          s[] = 0.;
      boundary (all);
    }
    
    
    //////////////////////////////////////////////////////
    // Run function
    void run()
    {
      t = 0.;
      init_grid (N);
      timer start = timer_start();
      int i = 0; long tnc = 0;
    
      // Take care of the order 4 which is in 5 steps
      int order_k = order_t < 4 ? order_t : 5;
      // williamson/carpenter tables from butcher tables
      double ** butcher = butcherd(order_k);
          
      while (events (i, t, true)) {
        
        // list of updates and intermediary fields
        scalar * updates = list_clone (evolving);
        scalar * interm =  list_clone (evolving); 
        // interm = 0
        foreach(){
          for( scalar s in interm)
    	s[] = 0;
        }
        
        dt = dtnext (t, update (evolving, updates, DT));
        for( int order_ = 0; order_ < order_k ; order_ ++ ){
          /* Nnd-order time-integration */
          foreach() {
    	for(scalar s in interm)
    	  s[] *= butcher[0][order_];
          }
          //interm = a*qj-1
          
          update(evolving,updates,dt); // update = F(Yj-1)
          advance (interm, interm, updates, dt);  // interm = qj = a*qj-1 + dt F(Yj-1) 
         
          foreach(){
    	scalar s1,s2;
    	for(s1,s2 in evolving,interm)
    	  s1[] += s2[]*butcher[1][order_];
    
          }
          // Yj = Yj-1 + bj*qj
        }
        
        delete(interm);
        free(interm);
        delete (updates);
        free (updates);
        
        long nc = 0;
        foreach (reduction(+:nc)) 
          nc++;
        tnc += nc;
        i++; t = tnext;
      }
     
      timer_print (start, i, tnc);
      free_grid();
      free(butcher);
    }