src/ast/interpreter/overload.h

    # 2 "ast/interpreter/overload.h"

    Function overloading for the interpreter

    size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream){
      size_t undef; return undef;
    }
    size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream){
      size_t undef; return undef;
    }
    int fflush(FILE *stream) {
      int undef; return undef;
    }
    int fclose(FILE *stream) {
      int undef; return undef;
    }
    FILE *fopen(const char *pathname, const char *mode) {
      FILE *undef; return undef;
    }
    void qassert (const char * file, int line, const char * cond){}
    void trash (void * alist) {}
    void NOT_UNUSED(){}
    static void tracing (const char * func, const char * file, int line) {}
    static void end_tracing (const char * func, const char * file, int line) {}
    void pmuntrace (void) {}
    void mpi_init() {}
    static void trace_off() {}
    void cadna_init (int i) {}
    void cadna_end (void) {}
    
    void * pmalloc (long size)
    {
      return malloc (size);
    }
    
    void * pcalloc (long nmemb, long size)
    {
      return calloc (nmemb, size);
    }
    
    void * prealloc (void * ptr, long size)
    {
      return realloc (ptr, size);
    }
    
    void pfree (void * ptr)
    {
      free (ptr);
    }
    
    void sysfree (void * ptr)
    {
      free (ptr);
    }
    
    char * pstrdup (const char *s)
    {
      return strdup (s);
    }
    
    char * systrdup (const char *s)
    {
      return strdup (s);
    }
    
    char * getenv (const char *name)
    {
      return NULL;
    }
    
    FILE * fopen (const char * pathname, const char * mode)
    {
      return NULL;
    }
    
    timer timer_start (void)
    {
      timer t = {0};
      return t;
    }
    
    double timer_elapsed (timer t)
    {
      return 0.;
    }
    
    void timer_print (timer t, int i, size_t tnc) {}
    
    double dtnext (double dt)
    {
      tnext = dt + 1e30;
      return dt + 1e30;
    }
    
    static
    bool overload_event()
    {
      return (iter == 0);
    }

    Foreach variables

    void _Variables() {
      Point point;
      int ig, jg, kg;
    }
    
    enum {
      unset = 1 << 0
    };
    
    void unset_double (double * x)
    {
      char * flags = x;
      flags += sizeof(double) - 1;
      *flags = unset;
    }
    
    void _init_point_variables (void)
    {
      ig = jg = kg = 0;
    }

    Grid functions

    typedef struct {
      Grid g;
      char placeholder[1024];
      char * d;
    } Intergrid;
    
    void free_grid (void)
    {
      if (grid) {
        free (((Intergrid *)grid)->d);
        free (grid);
        grid = NULL;
      }
    }
    
    void reset (void * alist, double val)
    {
      Intergrid * igrid = (Intergrid *) grid;
      real * p = igrid->d;
      if (alist)
        for (scalar * s = alist; s->i >= 0; s++)
          for (int b = 0; b < _attribute[s->i].block; b++)
    	reset_field_value (p + s->i + b, _attribute[s->i].name, 0., b);
    }
    
    static const int o_stencil = -2;

    See the definition of foreach_stencil() in /src/grid/stencils.h.

    static void _stencil()
    {
      if (baseblock) for (scalar s = baseblock[0], * i = baseblock; s.i >= 0; i++, s = *i) {
        _attribute[s.i].input = _attribute[s.i].output = false;
        _attribute[s.i].width = 0;
      }
    }

    This is a simplified version of end_stencil() in /src/grid/stencils.h.

    static void _end_stencil()
    {
      scalar * listc = NULL, * dirty = NULL;
      
      if (baseblock)
        for (scalar s = baseblock[0], * i = baseblock; s.i >= 0; i++, s = *i) {
          bool write = _attribute[s.i].output, read = _attribute[s.i].input;

    If the field is read and dirty, we need to check if boundary conditions need to be applied.

          if (read && scalar_is_dirty (s) && _attribute[s.i].width > 0)
    	listc = list_append (listc, s);

    If the field is write-accessed, we add it to the ‘dirty’ list.

          if (write) {	
    	dirty = list_append (dirty, s);
    	for (scalar d = baseblock[0], * i = baseblock; d.i >= 0; i++, d = *i)
    	  if (scalar_depends_from (d, s))
    	    dirty = list_append (dirty, d);
          }
        }

    We apply “full” boundary conditions.

      if (listc) {
        for (int d = 0; d < nboundary; d++)
          foreach()
    	for (scalar s = listc[0], * i = listc; s.i >= 0; i++, s = *i)
    	  if (_attribute[s.i].boundary[d] != periodic_bc)
    	    val(s,0,0,0) == _attribute[s.i].boundary[d] (point, point, s, NULL);
        for (scalar s = listc[0], * i = listc; s.i >= 0; i++, s = *i)
          _attribute[s.i].dirty = false;
        free (listc);
      }

    We update the dirty status of fields which will be write-accessed by the foreach loop.

      if (dirty) {
        for (scalar s = dirty[0], * i = dirty; s.i >= 0; i++, s = *i)
          _attribute[s.i].dirty = true;
        free (dirty);
      }
    }
    
    void _stencil_is_face_x(){}
    void _stencil_is_face_y(){}
    void _stencil_is_face_z(){}
    
    void _stencil_val (scalar s, int i, int j, int k)
    {
      stencil_val ((Point){0}, s, i, j, k, NULL, 0, true);
    }
    
    void _stencil_val_o (scalar s, int i, int j, int k)
    {
      stencil_val ((Point){0}, s, i, j, k, NULL, 0, true);
    }
    
    void _stencil_val_a (scalar s, int i, int j, int k)
    {
      stencil_val_a ((Point){0}, s, i, j, k, false, NULL, 0);
    }
      
    void _stencil_val_r (scalar s, int i, int j, int k)
    {
      stencil_val_a ((Point){0}, s, i, j, k, true, NULL, 0);
    }
      
    int nl = 1;
    
    void init_grid (int n)
    {
      free_grid();
      grid = calloc (1, sizeof (Intergrid));
      grid->n = 1;
      Intergrid * igrid = (Intergrid *) grid;
      igrid->d = calloc (datasize, sizeof (char));
      reset (all, 0.);
      if (nl > 2)
        nl = 2;
    }
    
    static
    void interpreter_reset_scalar (scalar s)
    {
      Intergrid * p = (Intergrid *) grid;
      char * c = p->d + s.i*sizeof (real);
      memset (c, 0, sizeof (real));
      char * flags = c + sizeof(real) - 1;
      *flags = unset;
    }
    
    double z_indexing (scalar s, bool leaves)
    {
      Intergrid * p = (Intergrid *) grid;
      real * c = p->d + s.i*sizeof (real);
      *c = 0[0];
    }
    
    static void init_block_scalar (scalar sb, const char * name, const char * ext,
    			       int n, int block)
    {
      char bname[strlen(name) + strlen(ext) + 1];
      strcpy (bname, name);
      strcat (bname, ext);
      if (n == 0) {
        _attribute[sb.i].block = block;
        baseblock = list_append (baseblock, sb);
      }
      else
        _attribute[sb.i].block = - n;
      _attribute[sb.i].name = strdup(bname); all = list_append (all, sb);
    }
    
    void realloc_scalar (int size)
    {
      Intergrid * p = (Intergrid *) grid;
      p->d = realloc (p->d, (datasize + size)*sizeof (char));
      datasize += size;
    }

    We overload new_const_scalar() so that a new constant field is allocated for each call. This is necessary when the same constant field is used for values with different dimensions.

    scalar new_const_scalar (const char * name, int i, double val)
    {
      scalar s = (scalar){nconst + 65536}; // _NVARMAX = 65536 as defined in /src/common.h
      init_const_scalar (s, name, val);
      return s;
    }
    
    void is_face_x() {}
    void is_face_y() {}
    void is_face_z() {}
    
    real * val (scalar s, int i, int j, int k)
    {
      Intergrid * igrid = (Intergrid *) grid;
      return (real *)(igrid->d + s.i*sizeof(real));
    }
    
    Point locate (double xp, double yp, double zp)
    {
      Point point; // unset
      return point;
    }
    
    bool tree_is_full() {
      return false;
    }
    
    bool is_leaf() {
      bool ret; // unset
      return ret;
    }
    
    void increment_neighbors (Point p) {}
    void decrement_neighbors (Point p) {}
    
    int refine_cell (Point point, scalar * list, int flag, Cache * refined) {
      int ret; // unset
      return ret;
    }
    
    void mpi_boundary_refine  (scalar * list) {}
    void mpi_boundary_update  (scalar * list) {}
    
    typedef struct {
      int nc, nf;
    } astats;
    
    astats adapt_wavelet (scalar * slist, double * max,
    		      int maxlevel, int minlevel, scalar * list)
    {
      astats st; // unset
      if (slist && max) {
        Intergrid * igrid = (Intergrid *) grid;
        real * g = igrid->d;
        double * v = max;
        for (scalar * s = slist; s->i >= 0; s++, v++)
          *v == *(g + s->i);
      }
      return st;
    }

    These functions are too expensive to interpret.

    void output_field (scalar * list, FILE * fp, int n, bool linear,
    		   double box[2][2])
    {}
    
    void output_ppm (scalar f, FILE * fp, int n, char * file,
    		 double min, double max, double spread,
    		 double z, bool linear, double box[2][2],
    		 scalar mask, colormap map, char * opt)
    {}
    
    void coarsen_cell_recursive (Point point, scalar * list)
    {}

    Helper functions for dimensions

    void _init_dimension (int index, long dimension)
    {
      Intergrid * p = (Intergrid *) grid;
      real * d = p->d;
      memcpy ((char *)(d + index) + 8, &dimension, 8);
    }

    Emulations of macros in /src/common.h.

    bool is_constant (scalar s)
    {
      return s.i >= _NVARMAX;
    }
    
    double constant (scalar s)
    {
      return is_constant(s) ? _constant[s.i - _NVARMAX] : 1e30;
    }
    
    int depth() { int undef; return undef; }
    int pid()   { int undef; return undef; }
    int tid()   { int undef; return undef; }
    int npe()   { int undef; return undef; }
    
    void dimensional (int a) {}
    void show_dimension_internal (double a) {}

    Emulations of macros and functions in <math.h>

    const double M_PI = 3.14159265358979 [0];
    const int RAND_MAX = 1;
    
    double fmax (double a, double b) { return a > b ? a : b; }
    double fmin (double a, double b) { return a < b ? a : b; }
    int abs (int i) { return i < 0 ? - i : i; }
    int rand() { int undef; return undef; }

    Events

    The maximum number of calls to events() is set by maxevents.

    int maxevents = 1;
    
    int events (bool action)
    {
      if (!maxevents)
        return 0;
      int iundef;
      unset_double (&t);
      if (iter) {
        for (Event * ev = Events; !ev->last; ev++)
          if (ev->i == END_EVENT)
    	for (Event * e = ev; e; e = e->next) {
    	  e->t == t;
    	  //display_value (e->action);
    	  if (action)
    	    e->action (iundef, t, e);
    	}
        maxevents--;
        return 0;
      }
      dimensional (t == DT);
      for (Event * ev = Events; !ev->last; ev++) {
        init_event (ev);
        if (ev->arrayt)
          for (double * at = ev->arrayt; *at >= 0; at++)
    	*at == t;
      }
      for (Event * ev = Events; !ev->last; ev++)
        if (ev->i != END_EVENT)
          for (Event * e = ev; e; e = e->next) {
    	dimensional (e->t == t);
    	//display_value (e->action);
    	if (action)
    	  e->action (iundef, t, e);
          }
      tnext = t;
      inext = 1;
      return 1;
    }
    
    void interpreter_set_int (int * i)
    {
      char * flags = i;
      flags += sizeof(int) - 1;
      *flags = 0;
    }

    GPU-specific functions

    void gpu_init_grid (int n) { init_grid (n); }
    
    vec4 Vec4 (float r, float g, float b, float a)
    {
      return (vec4){r, g, b, a};
    }
    
    void register_fpointer (void (* ptr) (void), const char * name, const void * nonlocals) {}
    
    void reset_gpu (void * alist, double val)
    {
      reset (alist, val);
    }

    Other functions

    scalar lookup_field (const char * name)
    {
      if (name) { interpreter_verbosity (2);
        for (scalar * s = all; s && s->i >= 0; s++)
          if (!strcmp (_attribute[s->i].name, name))
    	return *s;
        // Check whether the name is of the form ".*[0-9]+"
        int size = strlen (name) - 1;
        while (size >= 0 && name[size] >= '0' && name[size] <= '9') size--;
        size++;
        if (size > 0 && size < strlen (name))
          for (scalar * s = baseblock; s && s->i >= 0; s++)
    	if (_attribute[s->i].block > 1 &&
    	    strlen(_attribute[s->i].name) == size &&
    	    !strncmp (_attribute[s->i].name, name, size))
    	  return *s;
      }
      return (scalar){-1};
    }
    
    vector lookup_vector (const char * name)
    {
      if (name) {
        char component[strlen(name) + 3];
        strcpy (component, name);
        strcat (component, ".x");
        interpreter_maximum_iterations (256);
        for (scalar * s = all; s && s->i >= 0; s++)
          if (!strcmp (_attribute[s->i].name, component)) {
    	interpreter_maximum_iterations (32);
    	return _attribute[s->i].v;
          }
        interpreter_maximum_iterations (32);
        // Check whether the name is of the form ".*[0-9]+"
        int size = strlen (name) - 1;
        while (size >= 0 && name[size] >= '0' && name[size] <= '9') size--;
        size++;
        if (size > 0 && size < strlen (name)) {
          component[size] = '\0';
          strcat (component, ".x");
          for (scalar * s = baseblock; s && s->i >= 0; s++)
    	if (_attribute[s->i].block > 1 &&
    	    strcmp (_attribute[s->i].name, component))
    	  return *s;
        }
      }
      return (vector){{-1}};
    }