|
new file 100644
|
|
|
/** @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;
|
|
|
}
|