File diff 000000000000 → d6faa5ffcedf
include/grid.h
Show inline comments
 
new file 100644
 
/** @file grid.h
 
 *  @brief Definitions for working with general grids.
 
 */
 
#ifndef _GRID_H_
 

	
 
#ifndef _TREE_H_
 
# include "tree.h"
 
#endif
 

	
 
#define RECT_COORDS  int r0, r1, z0, z1, ntheta
 
/*!< Coordinate names for the grids */
 

	
 
#define BND_AT_R        0
 
#define BND_AT_Z        2
 
#define BND_MIN         0
 
#define BND_MAX         1
 

	
 
#define BND_LEFT        (BND_AT_R | BND_MIN)
 
#define BND_RIGHT       (BND_AT_R | BND_MAX)
 
#define BND_BOTTOM      (BND_AT_Z | BND_MIN)
 
#define BND_TOP         (BND_AT_Z | BND_MAX)
 

	
 
#define BND_MASK(B_)    (1 << (B_))
 
#define BND_NONE             0
 
#define BND_MASK_LEFT        BND_MASK(BND_LEFT)
 
#define BND_MASK_RIGHT       BND_MASK(BND_RIGHT)
 
#define BND_MASK_BOTTOM      BND_MASK(BND_BOTTOM)
 
#define BND_MASK_TOP         BND_MASK(BND_TOP)
 
#define BND_MASK_ALL         (BND_MASK_LEFT | BND_MASK_RIGHT\
 
			      | BND_MASK_BOTTOM | BND_MASK_TOP)
 

	
 
#define GRID_INSIDE    (1 << (BND_TOP + 1))
 

	
 
/* Locations of the cell centers. */
 
#define r_at(r_, level_) (((double) (r_) + 0.5) * dr[level_])
 
#define z_at(z_, level_) (((double) (z_) + 0.5) * dz[level_])
 
#define theta_at(theta_) ((double) (theta_) * dtheta)
 

	
 
/* Locations of the electric field. */
 
#define er_r_at(i_, level_) ((i_ + 1) * dr[level_])
 
#define er_z_at(j_, level_) (((double) (j_) + 0.5) * dz[level_])
 
#define ez_r_at(i_, level_) (((double) (i_) + 0.5) * dr[level_])
 
#define ez_z_at(j_, level_) ((j_ + 1) * dz[level_])
 
#define etheta_theta_at(i_) (((double) (i_) + 0.5) * dtheta)
 

	
 

	
 
/** We can produce easily a true 2d code by replacing r when it appears
 
 *  due to the cylindrical coordinates by this macros.  This has a rather
 
 *  large performance penalty, so it is better to do that in compile time
 
 */
 

	
 
/* Locations of the electric field. */
 
#ifdef TRUE2D
 
# define cyl_q(X_) 1
 
# define cyl_er_r_at(i_, level_) 1
 
# define cyl_r_at(r_, level_) 1
 
#else
 
# define cyl_q(X_) (X_)
 
# define cyl_er_r_at(i_, level_) er_r_at(i_, level_) 
 
# define cyl_r_at(r_, level_) r_at(r_, level_)
 
#endif
 

	
 
/* These are shortcuts to make the iteration over grid cells easier.
 
 *  Note that it is important that the inner loop has the smallest
 
 *  stride to minimize the cache faults.
 
 */
 
#define iter_grid_z(grid_, iz_) \
 
  for(iz_ = grid_->z0; iz_ < grid_->z1; iz_++) 
 

	
 
#define iter_grid_r(grid_, ir_) \
 
  for(ir_ = grid_->r0; ir_ < grid_->r1; ir_++) 
 

	
 
#define iter_grid_theta(grid_, it_) \
 
  for(it_ = 0; it_ < grid_->ntheta; it_++) 
 

	
 
#define iter_grid(grid_, ir_, iz_) \
 
  iter_grid_z(grid_, iz_)	   \
 
       iter_grid_r(grid_, ir_)
 

	
 
#define iter_grid_3d(grid_, ir_, iz_, it_)		\
 
  iter_grid_theta(grid_, it_)				\
 
    iter_grid_z(grid_, iz_)				\
 
       iter_grid_r(grid_, ir_)
 

	
 

	
 
/* Functions to iterate over the grids _including_ 1 extra boundary */
 
#define iter_grid_z_1(grid_, iz_)			\
 
  for(iz_ = grid_->z0 - 1; iz_ < grid_->z1 + 1; iz_++) 
 

	
 
#define iter_grid_r_1(grid_, ir_) \
 
  for(ir_ = grid_->r0 - 1; ir_ < grid_->r1 + 1; ir_++) 
 

	
 
#define iter_grid_1(grid_, ir_, iz_) \
 
  iter_grid_z_1(grid_, iz_)	   \
 
       iter_grid_r(grid_, ir_)
 

	
 
#define iter_grid_3d_1(grid_, ir_, iz_, it_)		\
 
  iter_grid_theta(grid_, it_)				\
 
    iter_grid_z_1(grid_, iz_)				\
 
       iter_grid_r_1(grid_, ir_)
 

	
 

	
 
/* These include n extra cells in the boundary. We avoid that when 
 
 * ntheta == 1 because we are in the 2D case and there are no boundaries
 
 * in theta*/
 
#define iter_grid_theta_n(grid_, it_, n_)			\
 
  for(it_ = (grid_->ntheta == 1? 0: -n_); it_ < grid_->ntheta	\
 
	+ (grid_->ntheta == 1? 0: n_); it_++) 
 

	
 
#define iter_grid_z_n(grid_, iz_, n_)			\
 
  for(iz_ = grid_->z0 - n_; iz_ < grid_->z1 + n_; iz_++) 
 

	
 
#define iter_grid_r_n(grid_, ir_, n_)			\
 
  for(ir_ = grid_->r0 - n_; ir_ < grid_->r1 + n_; ir_++) 
 

	
 
#define iter_grid_n(grid_, ir_, iz_, n_)		\
 
  iter_grid_z_n(grid_, iz_, n_)				\
 
       iter_grid_r_n(grid_, ir_, n_)
 

	
 
#define iter_grid_3d_n(grid_, ir_, iz_, it_, n_)	\
 
  iter_grid_theta_n(grid_, it_, n_)			\
 
     iter_grid_z_n(grid_, iz_, n_)			\
 
       iter_grid_r_n(grid_, ir_, n_)
 

	
 

	
 
/* Iter through the parent indices that fill one grid. */
 
#define iter_grid_parent(grid_, ir_, iz_) \
 
  for(ir_ = (grid_->r0 >> 1) + (grid_->r0 % 2);				\
 
      ir_ < (grid_->r1 >> 1); ir_++)					\
 
    for(iz_ = (grid_->z0 >> 1) + (grid_->z0 % 2);			\
 
	iz_ < (grid_->z1 >> 1); iz_++)
 

	
 

	
 
/** @brief The cdr grids and poisson grids types are cdr_grid_t and
 
 *  pois_grid_t, defined in cdr.h and poisson.h.
 
 *
 
 *  This structure contains the common parts of both structures and
 
 *  thus can be used in general routines that accept any kind of grid.
 
 *  The C standard promises that we can du this.
 
 */
 
typedef struct grid_t grid_t;
 
struct grid_t {
 
  RECT_COORDS;
 
  LEAF_FIELDS(grid_t);
 
  /* ext_bound indicates which boundaries are external boundaries.
 
     e.g. ext_bound & BND_LEFT_TOP tells us whether the left-top boundary
 
     is an external one. */
 
  int ext_bound;
 
};
 

	
 
/** @brief To ease typing, you can write e.g.
 
 * printf ("Solving grid (" grid_printf_str ")\n", grid_printf_args(grid));
 
 */
 
#define grid_printf_str "{r0 = %d, z0 = %d, r1 = %d, z1 = %d, level = %d}"
 
#define grid_printf_args(G_) (G_)->r0, (G_)->z0, (G_)->r1, (G_)->z1,	\
 
    (G_)->level
 

	
 
#define _GRID_H_
 
#endif