Commit 5de4196b authored by Uwe Schulzweida's avatar Uwe Schulzweida
Browse files

gridsearch: added method GS_KDSPH.

parent 385954eb
...@@ -69,6 +69,7 @@ float distance(const float *restrict a, const float *restrict b) ...@@ -69,6 +69,7 @@ float distance(const float *restrict a, const float *restrict b)
void gridsearch_set_method(const char *methodstr) void gridsearch_set_method(const char *methodstr)
{ {
if ( strcmp(methodstr, "kdtree") == 0 ) gridsearch_method_nn = GS_KDTREE; if ( strcmp(methodstr, "kdtree") == 0 ) gridsearch_method_nn = GS_KDTREE;
else if ( strcmp(methodstr, "kdsph") == 0 ) gridsearch_method_nn = GS_KDSPH;
else if ( strcmp(methodstr, "nearpt3") == 0 ) gridsearch_method_nn = GS_NEARPT3; else if ( strcmp(methodstr, "nearpt3") == 0 ) gridsearch_method_nn = GS_NEARPT3;
else if ( strcmp(methodstr, "full") == 0 ) gridsearch_method_nn = GS_FULL; else if ( strcmp(methodstr, "full") == 0 ) gridsearch_method_nn = GS_FULL;
else else
...@@ -156,6 +157,39 @@ struct kdNode *gs_create_kdtree(size_t n, const double *restrict lons, const dou ...@@ -156,6 +157,39 @@ struct kdNode *gs_create_kdtree(size_t n, const double *restrict lons, const dou
} }
struct kdNode *gs_create_kdsph(size_t n, const double *restrict lons, const double *restrict lats)
{
struct kd_point *pointlist = (struct kd_point *) Malloc(n * sizeof(struct kd_point)); // kd_point contains 3d point
// see example_cartesian.c
if ( cdoVerbose ) printf("kdtree lib spherical init: n=%zu nthreads=%d\n", n, ompNumThreads);
kdata_t min[2], max[2];
min[0] = min[1] = 1e9;
max[0] = max[1] = -1e9;
kdata_t *restrict point;
#if defined(HAVE_OPENMP4)
#pragma omp simd
#endif
for ( size_t i = 0; i < n; i++ )
{
point = pointlist[i].point;
point[0] = lons[i];
point[1] = lats[i];
point[2] = 0; // dummy
for ( size_t j = 0; j < 2; ++j )
{
min[j] = point[j] < min[j] ? point[j] : min[j];
max[j] = point[j] > max[j] ? point[j] : max[j];
}
pointlist[i].index = i;
}
struct kdNode *kdt = kd_sph_buildTree(pointlist, n, min, max, ompNumThreads);
if ( pointlist ) Free(pointlist);
return kdt;
}
void gs_destroy_nearpt3(struct gsNear *near) void gs_destroy_nearpt3(struct gsNear *near)
{ {
if ( near ) if ( near )
...@@ -274,6 +308,7 @@ struct gridsearch *gridsearch_create_nn(size_t n, const double *restrict lons, c ...@@ -274,6 +308,7 @@ struct gridsearch *gridsearch_create_nn(size_t n, const double *restrict lons, c
if ( n == 0 ) return gs; if ( n == 0 ) return gs;
if ( gs->method_nn == GS_KDTREE ) gs->kdt = gs_create_kdtree(n, lons, lats); if ( gs->method_nn == GS_KDTREE ) gs->kdt = gs_create_kdtree(n, lons, lats);
else if ( gs->method_nn == GS_KDSPH ) gs->kdt = gs_create_kdsph(n, lons, lats);
else if ( gs->method_nn == GS_NEARPT3 ) gs->near = gs_create_nearpt3(n, lons, lats); else if ( gs->method_nn == GS_NEARPT3 ) gs->near = gs_create_nearpt3(n, lons, lats);
else if ( gs->method_nn == GS_FULL ) gs->full = gs_create_full(n, lons, lats); else if ( gs->method_nn == GS_FULL ) gs->full = gs_create_full(n, lons, lats);
...@@ -341,6 +376,27 @@ kdNode *gs_nearest_kdtree(kdNode *kdt, double lon, double lat, double *prange) ...@@ -341,6 +376,27 @@ kdNode *gs_nearest_kdtree(kdNode *kdt, double lon, double lat, double *prange)
} }
kdNode *gs_nearest_kdsph(kdNode *kdt, double lon, double lat, double *prange)
{
if ( kdt == NULL ) return NULL;
float range0 = gs_set_range(prange);
kdata_t range = KDATA_SCALE(range0);
kdata_t point[2];
point[0] = lon;
point[1] = lat;
kdNode *node = kd_nearest(kdt, point, &range, 3);
float frange = KDATA_INVSCALE(range);
if ( !(frange < range0) ) node = NULL;
if ( prange ) *prange = frange;
return node;
}
unsigned gs_nearest_nearpt3(struct gsNear *near, double lon, double lat, double *prange) unsigned gs_nearest_nearpt3(struct gsNear *near, double lon, double lat, double *prange)
{ {
size_t index = GS_NOT_FOUND; size_t index = GS_NOT_FOUND;
...@@ -429,6 +485,11 @@ size_t gridsearch_nearest(struct gridsearch *gs, double lon, double lat, double ...@@ -429,6 +485,11 @@ size_t gridsearch_nearest(struct gridsearch *gs, double lon, double lat, double
kdNode *node = gs_nearest_kdtree(gs->kdt, lon, lat, prange); kdNode *node = gs_nearest_kdtree(gs->kdt, lon, lat, prange);
if ( node ) index = (int) node->index; if ( node ) index = (int) node->index;
} }
else if ( gs->method_nn == GS_KDSPH )
{
kdNode *node = gs_nearest_kdsph(gs->kdt, lon, lat, prange);
if ( node ) index = (int) node->index;
}
else if ( gs->method_nn == GS_NEARPT3 ) else if ( gs->method_nn == GS_NEARPT3 )
{ {
index = gs_nearest_nearpt3(gs->near, lon, lat, prange); index = gs_nearest_nearpt3(gs->near, lon, lat, prange);
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#define GS_NOT_FOUND ULONG_MAX #define GS_NOT_FOUND ULONG_MAX
enum T_GRIDSEARCH_METHOD_NN {GS_FULL=1, GS_KDTREE, GS_NEARPT3}; enum T_GRIDSEARCH_METHOD_NN {GS_FULL=1, GS_KDTREE, GS_KDSPH, GS_NEARPT3};
struct gsFull { struct gsFull {
unsigned n; unsigned n;
......
...@@ -164,10 +164,8 @@ struct kd_thread_data *kd_buildArg(struct kd_point *points, ...@@ -164,10 +164,8 @@ struct kd_thread_data *kd_buildArg(struct kd_point *points,
struct kdNode *kd_buildTree(struct kd_point *points, unsigned long nPoints, struct kdNode *kd_buildTree(struct kd_point *points, unsigned long nPoints,
kdata_t *min, kdata_t *max, int dim, int max_threads); kdata_t *min, kdata_t *max, int dim, int max_threads);
void *kd_doBuildTree(void *threadarg); void *kd_doBuildTree(void *threadarg);
struct kdNode *kd_sph_buildTree(struct kd_point *points, struct kdNode *kd_sph_buildTree(struct kd_point *points, unsigned long nPoints,
unsigned long nPoints, kdata_t *min, kdata_t *max, int max_threads);
kdata_t *min, kdata_t *max,
int max_threads);
void *kd_sph_doBuildTree(void *threadarg); void *kd_sph_doBuildTree(void *threadarg);
/* Functions for range searches /* Functions for range searches
......
...@@ -24,10 +24,10 @@ kdata_t square(const kdata_t x) ...@@ -24,10 +24,10 @@ kdata_t square(const kdata_t x)
static constexpr static constexpr
kdata_t kd_dist_sq(const kdata_t *restrict a, const kdata_t *restrict b) kdata_t kd_dist_sq(const kdata_t *restrict a, const kdata_t *restrict b)
{ {
return (square((a[0]-b[0]))+square((a[1]-b[1]))+square((a[2]-b[2]))); return square((a[0]-b[0]))+square((a[1]-b[1]))+square((a[2]-b[2]));
} }
inline
kdata_t kd_min(kdata_t x, kdata_t y) kdata_t kd_min(kdata_t x, kdata_t y)
{ {
return x < y ? x : y; return x < y ? x : y;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment