Files @ b7792cb187f7
Branch filter:

Location: MD/arcos/src/grid.c

greta
Edited file README via RhodeCode
/** @file grid.c
 *  @brief General grid functions common for cdr and poisson grids.
 */
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include "grid.h"
#include "parameters.h"
#include "proto.h"
#include "species.h"

/** @brief Gets the maximum depth of a tree (the level of its deepest node) */
int
grid_max_depth_r (grid_t *grid)
{
  int l, lc;
  grid_t *child;

  l = grid->level;
  iter_childs (grid, child) {
    lc = grid_max_depth_r (child);
    l = (l > lc)? l: lc;
  }
  return l;
}

/** @brief Gets the minimum r of a grid and all its descendants */
double
grid_rmin_r (grid_t *grid)
{
  int lev;
  double minr, cminr;
  grid_t *child;

  lev = grid->level;
  minr = r_at (grid->r0, lev);

  iter_childs (grid, child) {
    cminr = grid_rmin_r (child);
    minr = (minr > cminr)? cminr: minr;
  }
  return minr;
}

/** @brief Recursively prints one grid and all its descendants. */
void
grid_print_r (grid_t *grid, int indent)
{
  int i;
  grid_t *child;

  for (i = 0; i < indent; i++) fputs ("  ", stdout);
  printf ("grid (" grid_printf_str") {\n", grid_printf_args(grid));

  iter_childs (grid, child) {
    grid_print_r (child, indent + 1);
  }
  for (i = 0; i < indent; i++) fputs ("  ", stdout);
  fputs ("}\n", stdout);
}

/** @brief Checks whether a point is in the interior or on a given boundary
 * of a grid.
 *
 * Does the grid contain the point (i, j) (in its own coordinates)?\n
 * @a check has the following meaning:\n
 *  GRID_INSIDE : Checks if the point is in the interior of the grid\n
 *  BND_MASK_*  : Checks if it is on the given boundary (BND_MASK_ALL checks for
 *               any boundary).\n
 */
int
grid_contains (grid_t *grid, int i, int j, int check)
{
  int r0, r1, z0, z1;
  int r;

  r0 = grid->r0;
  z0 = grid->z0;
  r1 = grid->r1 - 1;
  z1 = grid->z1 - 1;

  r = FALSE;

  if (check & BND_MASK_LEFT) {
    r0 -= 1;
  }

  if (check & BND_MASK_RIGHT) {
    r1 += 1;
  }

  if (check & BND_MASK_BOTTOM) {
    z0 -= 1;
  }

  if (check & BND_MASK_TOP) {
    z1 += 1;
  }

  if (r0 < i && i < r1 && z0 < j && j < z1) 
    r = TRUE;

  if (check & GRID_INSIDE) {
    return r;
  } else {
    return (r && !grid_contains (grid, i, j, GRID_INSIDE));
  }
}

/** @brief Checks whether two grids overlap and return the rectangle that they
 * in common.
 *
 * Checks whether two grids overlap and return the rectangle that they 
 * have in common in the coordinates of the finest grid in 
 * (*left, *bottom) - (*right, *top)\n
 *
 * Note that *left, *bottom... can be modified even if the two grids do
 * not overlap.
 * @a buff1 and @a buff2 are integers that specify the numbers of cells
 * that are taken as buffer in the boundaries for @a grid1 and @a grid2.
 */
int
grid_overlap (grid_t *grid1, grid_t *grid2, int buff1, int buff2, 
	      int *left, int *bottom, int *right, int *top, int *level_diff)
{
  return grid_overlap_with_shifts (grid1, grid2, buff1, buff2, 
				  left, bottom, right, top, level_diff,
				  0, 0);
}

/** @brief Checks the overlap between two grids.
 *
 * Checks the overlap between two grids before it shifts the
 * coarser grid by (shift_r << (level_diff - 1), shift_z << (level_diff - 1)
 * (in finer grid coordinates).
 *
 *  Q: WTF! WHY!!!? \n
 *  A: We use this to implement the mapping between electric fields.  Since
 *     The electric field is evaluated not in the cell centers but in the
 *     borders, when we interpolate we have to take a shift into account.
 *     See mapper.c and mapper.h for more info.
 */
int
grid_overlap_with_shifts (grid_t *grid1, grid_t *grid2, int buff1, int buff2, 
			 int *left, int *bottom, int *right, int *top, 
			 int *level_diff, int shift_r, int shift_z)
{
  int sign;

  debug (3, "grid_overlap(" grid_printf_str", " grid_printf_str 
	 ", buff1 = %d, buff2 = %d)\n",
	 grid_printf_args(grid1), grid_printf_args(grid2),
	 buff1, buff2);

  sign = 1;

  /* If level_diff < 0, grid2 is finer */
  *level_diff = grid1->level - grid2->level;

  if (*level_diff < 0) {
    sign = -1;
    *level_diff = - *level_diff;
    XCHG (grid1, grid2);
    XCHG (buff1, buff2);
  }

  /* At this point, level_diff >= 0 and grid1 is finer 
     or equivalent to grid2 */

  *left = MAX_AT_LEVEL_WITH_SHIFT (grid1->r0 - buff1, grid2->r0 - buff2, 
				   *level_diff, shift_r);
  *right = MIN_AT_LEVEL_WITH_SHIFT (grid1->r1 + buff1, grid2->r1 + buff2, 
				    *level_diff, shift_r);

  /* Note: *right is not contained in the grid.  Hence, if *left == *right
     the two grids do not overlap.  Same for *bottom and *top, below. */
  debug (3, "*left = %d, *right = %d\n", *left, *right);
  if (*left >= *right) {
    *level_diff *= sign;
    return FALSE;
  }

  *bottom = MAX_AT_LEVEL_WITH_SHIFT (grid1->z0 - buff1, grid2->z0 - buff2, 
				     *level_diff, shift_z);
  *top = MIN_AT_LEVEL_WITH_SHIFT (grid1->z1 + buff1, grid2->z1 + buff2, 
				  *level_diff, shift_z);

  debug (3, "*bottom = %d, *top = %d\n", *bottom, *top);
  if (*bottom >= *top) {
    *level_diff *= sign;
    return FALSE;
  }
  debug (3, "pois_overlap = TRUE\n");

  *level_diff *= sign;
  return TRUE;
}

/** @brief Makes a grid inherit the ext_bound field of its parent,
 *
 * with the appropiate modifications.
 */
void
grid_inherit_ext_bound (grid_t *grid)
{
  grid_t *parent = grid->parent;

  debug (3, "grid_inherit_ext_bound (...)\n");

  grid->ext_bound = BND_NONE;

  /* If the parent does not have any external boundary, the child will also
     not have */
  if (BND_NONE == parent->ext_bound) {
    return;
  }

  if (parent->ext_bound & BND_MASK_LEFT) {
    if ((parent->r0 << 1) == grid->r0) grid->ext_bound |= BND_MASK_LEFT;
  }

  if (parent->ext_bound & BND_MASK_RIGHT) {
    if ((parent->r1 << 1) == grid->r1) grid->ext_bound |= BND_MASK_RIGHT;
  }

  if (parent->ext_bound & BND_MASK_BOTTOM) {
    if ((parent->z0 << 1) == grid->z0) grid->ext_bound |= BND_MASK_BOTTOM;
  }

  if (parent->ext_bound & BND_MASK_TOP) {
    if ((parent->z1 << 1) == grid->z1) grid->ext_bound |= BND_MASK_TOP;
  }

}


/** @brief Finds the finest descendant of grid that contains the point given by
 * the (@a r, @a z) coordinates.
 *
 * Or NULL if the point is not contained in grid.
 * We assume that only ONE sub-grid can contain a given point.
 */
grid_t *
grid_finest_containing_r (grid_t *grid, double r, double z)
{
  grid_t *leaf, *ret;
  
  if (r < er_r_at(grid->r0 - 1, grid->level) || 
      r > er_r_at(grid->r1 - 1, grid->level))
    return NULL;

  if (z < ez_z_at(grid->z0 - 1, grid->level) || 
      z > ez_z_at(grid->z1 - 1, grid->level))
    return NULL;

  iter_childs (grid, leaf) {
    ret = grid_finest_containing_r (leaf, r, z);
    if (NULL != ret)
      return ret;
  }
  return grid;
}

/** @brief How many children does one grid have? */
int
grid_howmany_children (grid_t *grid)
{
  grid_t *leaf;
  int count;

  count = 0;
  iter_childs (grid, leaf) {
    count ++;
  }
  return count;
}

/** @brief Finds child number @a n of the given grid.
 *
 * If it doesn't have enough children just returns NULL
 */
grid_t*
grid_get_child (grid_t *grid, int n)
{
  grid_t *leaf;
  int count;

  count = 0;
  iter_childs (grid, leaf) {
    if (count == n) return leaf;
    count ++;
  }
  return NULL;
}