/** @file grid.c * @brief General grid functions common for cdr and poisson grids. */ #include #include #include #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; }