sandbox/jieyun/src/ebit-tree.h

    /** Injection and restriction functions for markers and color vertex.
      For the variables without interdependence. 
    */
    
    static void myface_injection (Point point, vector v) {
      foreach_dimension() {
        // 0.5 for corner case where the interface passes through the cell vertex, should be test
        // fine(v.x, 0, 0) == 0. && fine(v.x, 0, 1) == 0. but with a markers at fine(v.x, 0, 1)
        // why it shows "stack smashing detected" when v.x[] = 0.5 ??? check this
        v.x[] = 0.;
        v.x[1] = 0.;
        if (fine(v.x, 0, 0) > 0.)
          v.x[] = fine(v.x, 0, 0)/2.;
    
        if (fine(v.x, 0, 1) > 0.)
          v.x[] = 0.5 + fine(v.x, 0, 1)/2.;
        
        if (fine(v.x, 2, 0) > 0.)
          v.x[1] = fine(v.x, 2, 0)/2.;
    
        if (fine(v.x, 2, 1) > 0.)
          v.x[1] = 0.5 + fine(v.x, 2, 1)/2.;
      }    
    }
    
    static inline void myrestriction_face (Point point, scalar s) {
      myface_injection (point, s.v);
    }
    
    /** Functions for the scalar used in adapt_wavelet, which make sure that the cells near the interface are refined to maximum level. */
    
    scalar mask_intf[]; // mask used for adapt_wavelet AMR
    static inline void restriction_intf (Point point, scalar s) {
      s[] = 0.;
    }
    
    static inline void prolongation_intf (Point point, scalar s) {
      foreach_child()
        s[] = 0.;
    }
    
    // we need this to set the mask_intf to the correct value 
    // at the resolution boundary between coarse and fine level leaf cells.
    static inline void restriction_conf (Point point, scalar s) {
      double conf_max = -HUGE;
      foreach_child()
        conf_max = max(conf_max, s[]);
      s[] = conf_max;
    }
    
    // Strange, I get a correct result after copying out this function from
    // multigrid-common.h
    // The function restriction_vertex is very special. The scalar bound with
    // restriction_vertex will be treated specially by "tree_boundary_level" function
    // in the tree-common.h. The behavior of automatic boundary condition is not what we want.
    static inline void my_restriction_vertex (Point point, scalar s) {
      for (int i = 0; i <= 1; i++) {
        s[i] = fine(s,2*i);
    #if dimension >= 2  
        s[i,1] = fine(s,2*i,2);
    #endif
    #if dimension >= 3
        for (int j = 0; j <= 1; j++)
          s[i,j,1] = fine(s,2*i,2*j,2);
    #endif
      }
    }
    
    /** For color vertex*/
    #if dimension <= 2
    static void refine_vertex_ebit (Point point, scalar ss) {
      fine(ss, 1, 1) = ss[];
    
      // should check the meaning of allocated_child function
      for (int i = 0; i <= 1; i++) {
        for (int j = 0; j <= 1; j++)
          if (allocated_child(2*i, 2*j))
            fine(ss,2*i,2*j) = ss[i,j];
        
          foreach_dimension()
            if (neighbor(i).neighbors) {
              fine(ss,2*i,1) = ss[i];
            }
      }
    }
    #endif
    
    static inline void my_restriction_vertex_zero (Point point, scalar s) {
      for (int i = 0; i <= 1; i++) {
        s[i] = 0.;
    #if dimension >= 2
        s[i,1] = 0.;
    #endif
    #if dimension >= 3
        for (int j = 0; j <= 1; j++)
          s[i,j,1] = 0.;
    #endif
      }
    }
    
    event defaults (i = 0) {
      set_restriction (mask_intf, restriction_intf);
      set_prolongation (mask_intf, prolongation_intf);
      mask_intf.refine = refine_injection;
    
      mask_intf.nodump = true;
    }
    
    void set_mask (scalar intf, int n_iter = 1) {
      set_restriction (intf, restriction_conf);
      boundary ({intf});
      scalar mask_tmp[];
      set_restriction (mask_intf, restriction_conf);
      foreach()
        mask_intf[] = intf[];
    
      for (int iter = 0; iter < n_iter; iter++) {
        foreach() {
          bool is_mask = false;
          foreach_neighbor(1)
            if (mask_intf[] > 0.5)
              is_mask = true;
    
          mask_tmp[] = is_mask ? 1. : 0.;
        }
    
        foreach()
          mask_intf[] = mask_tmp[];
    
        boundary ({mask_intf});
      }
      set_restriction (mask_intf, restriction_intf);
    }
    
    #if dimension == 3
    foreach_dimension()
    static void refine_face_injection_x (Point point, scalar s) {
      vector v = s.v;
      if (!is_refined(neighbor(-1)) &&
          (is_local(cell) || is_local(neighbor(-1)))) {
        for (int j = 0; j <= 1; j++)
          for (int k = 0; k <= 1; k++)
    	      fine(v.x,0,j,k) = v.x[];
      }
      if (!is_refined(neighbor(1)) && neighbor(1).neighbors &&
          (is_local(cell) || is_local(neighbor(1)))) {
        for (int j = 0; j <= 1; j++)
          for (int k = 0; k <= 1; k++)
    	      fine(v.x,2,j,k) = v.x[1];
      }
      if (is_local(cell)) {
        for (int j = 0; j <= 1; j++)
          for (int k = 0; k <= 1; k++)
    	      fine(v.x,1,j,k) = (v.x[] + v.x[1])/2.;
      }
    }
    
    /** All these are used for debugging*/
    static void my_no_restriction_r (Point point, scalar s) {
      s.stencil.bc = s_centered;
    }
    
    static void my_no_restriction_p (Point point, scalar s) {
      s.stencil.bc = s_centered;
    }
    #endif
    
    /** Warper function of adapt_wavelet. Add the criteria of the EBIT method and 
      the embedded buondary. 
      1. For the EBIT method, the cells within the 3*3 stencil 
      of the interfacial cell are refined to maximum level.
      2. For embedded boundary, the cell in the solid region is not allowed to merge
      with the mix cell.
    */
    trace
    astats adapt_wavelet_ebit (scalar * slist,       // list of scalars
    		      double * max,         // tolerance for each scalar
    		      int maxlevel,         // maximum level of refinement
    		      int minlevel = 1,     // minimum level of refinement
    		      scalar * list = all)  // list of fields to update
    {
      int ns = 0;
      scalar * ilist = list_copy(slist);
    
      for (scalar s in slist)
        ns++;
    
      ilist = list_add(ilist, mask_intf);
      #if EMBED
      double smax[ns + 2];
      smax[ns] = 0.02;
      smax[ns + 1] = 1.e-6;
      scalar mask_embed[];
      set_restriction (mask_embed, restriction_conf);
      set_prolongation (mask_embed, refine_injection);
      mask_embed.coarsen = restriction_conf;
      mask_embed.refine = refine_injection;
    
      foreach() {
        mask_embed[] = cs[] > 0. ? 1. : 0.;
      }
      boundary ({mask_embed});
      ilist = list_add(ilist, mask_embed);
      #else
      double smax[ns + 1];
      smax[ns] = 0.02;
      #endif
    
      ns = 0;
      for (scalar s in ilist) {
        smax[ns] = max[ns];
        ns++;
      }
      
      astats st = {0, 0};
      st = adapt_wavelet (ilist, smax, maxlevel, minlevel, list);
      
      return st;
    }