Nek5000
SEM for Incompressible NS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
findpts_local_imp.h
Go to the documentation of this file.
1 
2 #define obbox TOKEN_PASTE(obbox_ ,D)
3 #define obbox_calc TOKEN_PASTE(PREFIXED_NAME(obbox_calc_),D)
4 #define obbox_test TOKEN_PASTE(obbox_test_ ,D)
5 #define hash_data TOKEN_PASTE(findpts_local_hash_data_,D)
6 #define hash_index TOKEN_PASTE(hash_index_ ,D)
7 #define hash_setfac TOKEN_PASTE(hash_setfac_ ,D)
8 #define hash_range TOKEN_PASTE(hash_range_ ,D)
9 #define hash_count TOKEN_PASTE(hash_count_ ,D)
10 #define hash_opt_size TOKEN_PASTE(hash_opt_size_ ,D)
11 #define hash_bb TOKEN_PASTE(hash_bb_ ,D)
12 #define hash_build TOKEN_PASTE(hash_build_ ,D)
13 #define hash_free TOKEN_PASTE(hash_free_ ,D)
14 #define findpts_el_data TOKEN_PASTE(findpts_el_data_ ,D)
15 #define findpts_el_pt TOKEN_PASTE(findpts_el_pt_ ,D)
16 #define findpts_el_setup TOKEN_PASTE(PREFIXED_NAME(findpts_el_setup_),D)
17 #define findpts_el_free TOKEN_PASTE(PREFIXED_NAME(findpts_el_free_ ),D)
18 #define findpts_el TOKEN_PASTE(PREFIXED_NAME(findpts_el_ ),D)
19 #define findpts_el_eval TOKEN_PASTE(PREFIXED_NAME(findpts_el_eval_ ),D)
20 #define findpts_el_start TOKEN_PASTE(findpts_el_start_ ,D)
21 #define findpts_el_points TOKEN_PASTE(findpts_el_points_ ,D)
22 #define findpts_local_data TOKEN_PASTE(findpts_local_data_,D)
23 #define map_points_to_els TOKEN_PASTE(map_points_to_els_ ,D)
24 #define findpts_local_setup TOKEN_PASTE(PREFIXED_NAME(findpts_local_setup_),D)
25 #define findpts_local_free TOKEN_PASTE(PREFIXED_NAME(findpts_local_free_ ),D)
26 #define findpts_local TOKEN_PASTE(PREFIXED_NAME(findpts_local_ ),D)
27 #define findpts_local_eval TOKEN_PASTE(PREFIXED_NAME(findpts_local_eval_ ),D)
28 
29 /*--------------------------------------------------------------------------
30  Point to Possible Elements Hashing
31 
32  Initializing the data:
33  uint nel; // number of elements
34  uint max_size = nr*ns*nt*nel; // maximum size of hash table
35  struct obbox *obb = ...; // bounding boxes for elements
36 
37  hash_data data;
38  hash_build(&data, obb, nel, max_size);
39 
40  Using the data:
41  double x[3]; // point to find
42 
43  uint index = hash_index_3(&data, x);
44  uint i, b = data.offset[index], e = data.offset[index+1];
45 
46  // point may be in elements
47  // data.offset[b], data.offset[b+1], ... , data.offset[e-1]
48  //
49  // list has maximum size data.max (e.g., e-b <= data.max)
50 
51  for(i=b; i!=e; ++i) {
52  uint el = data.offset[i];
53  ...
54  }
55 
56  When done:
57  hash_free(&data);
58 
59  --------------------------------------------------------------------------*/
60 
61 struct hash_data {
63  struct dbl_range bnd[D];
64  double fac[D];
65  uint *offset;
67 };
68 
69 static uint hash_index(const struct hash_data *p, const double x[D])
70 {
71  const uint n = p->hash_n;
72  return ( WHEN_3D( hash_index_aux(p->bnd[2].min,p->fac[2],n,x[2]) *n )
73  +hash_index_aux(p->bnd[1].min,p->fac[1],n,x[1]) )*n
74  +hash_index_aux(p->bnd[0].min,p->fac[0],n,x[0]);
75 }
76 
77 static void hash_setfac(struct hash_data *p, const uint n)
78 {
79  unsigned d;
80  p->hash_n = n;
81  for(d=0;d<D;++d) p->fac[d] = n/(p->bnd[d].max-p->bnd[d].min);
82 }
83 
84 static struct uint_range hash_range(const struct hash_data *p, unsigned d,
85  const struct dbl_range r)
86 {
87  struct uint_range ir;
88  const sint i0 = ifloor( (r.min - p->bnd[d].min) * p->fac[d] );
89  const uint i1 = iceil ( (r.max - p->bnd[d].min) * p->fac[d] );
90  ir.min = i0<0 ? 0 : i0;
91  ir.max = i1<p->hash_n ? i1 : p->hash_n;
92  if(ir.max==ir.min) ++ir.max;
93  return ir;
94 }
95 
96 static uint hash_count(struct hash_data *p,
97  const struct obbox *const obb, const uint nel,
98  const uint n)
99 {
100  uint i,count=0;
101  hash_setfac(p,n);
102  for(i=0;i<nel;++i) {
103  struct uint_range ir; uint ci; unsigned d;
104  ir=hash_range(p,0,obb[i].x[0]); ci = ir.max-ir.min;
105  for(d=1;d<D;++d)
106  ir=hash_range(p,d,obb[i].x[d]), ci *= ir.max-ir.min;
107  count+=ci;
108  }
109  return count;
110 }
111 
112 static uint hash_opt_size(struct hash_data *p,
113  const struct obbox *const obb, const uint nel,
114  const uint max_size)
115 {
116  uint nl=1, nu=ceil(pow(max_size-nel,1.0/D));
117  uint size_low=2+nel;
118  while(nu-nl>1) {
119  uint nm = nl+(nu-nl)/2, nmd = nm*nm, size;
120  WHEN_3D(nmd *= nm);
121  size = nmd+1+hash_count(p,obb,nel,nm);
122  if(size<=max_size) nl=nm,size_low=size; else nu=nm;
123  }
124  hash_setfac(p,nl);
125  return size_low;
126 }
127 
128 static void hash_bb(struct hash_data *p,
129  const struct obbox *const obb, const uint nel)
130 {
131  uint el; unsigned d;
132  struct dbl_range bnd[D];
133  if(nel) {
134  for(d=0;d<D;++d) bnd[d]=obb[0].x[d];
135  for(el=1;el<nel;++el)
136  for(d=0;d<D;++d)
137  bnd[d]=dbl_range_merge(bnd[d],obb[el].x[d]);
138  for(d=0;d<D;++d) p->bnd[d]=bnd[d];
139  } else {
140  for(d=0;d<D;++d) p->bnd[d].max=p->bnd[d].min=0;
141  }
142 }
143 
144 static void hash_build(struct hash_data *p,
145  const struct obbox *const obb, const uint nel,
146  const uint max_size)
147 {
148  uint i,el,size,hn,hnd,sum,max, *count;
149  hash_bb(p,obb,nel);
150  size = hash_opt_size(p,obb,nel,max_size);
151  p->offset = tmalloc(uint,size);
152  hn = p->hash_n;
153  hnd = hn*hn; WHEN_3D(hnd*=hn);
154  count = tcalloc(uint,hnd);
155  for(el=0;el<nel;++el) {
156  unsigned d; struct uint_range ir[D];
157  for(d=0;d<D;++d) ir[d]=hash_range(p,d,obb[el].x[d]);
158  #define FOR_LOOP() do { uint i,j; WHEN_3D(uint k;) \
159  WHEN_3D(for(k=ir[2].min;k<ir[2].max;++k)) \
160  for(j=ir[1].min;j<ir[1].max;++j) \
161  for(i=ir[0].min;i<ir[0].max;++i) \
162  ++count[(WHEN_3D(k*hn)+j)*hn+i]; \
163  } while(0)
164  FOR_LOOP();
165  #undef FOR_LOOP
166  }
167  sum=hnd+1, max=count[0];
168  p->offset[0]=sum;
169  for(i=0;i<hnd;++i) {
170  max = count[i]>max?count[i]:max;
171  sum += count[i];
172  p->offset[i+1] = sum;
173  }
174  p->max = max;
175  for(el=0;el<nel;++el) {
176  unsigned d; struct uint_range ir[D];
177  for(d=0;d<D;++d) ir[d]=hash_range(p,d,obb[el].x[d]);
178  #define FOR_LOOP() do { uint i,j; WHEN_3D(uint k;) \
179  WHEN_3D(for(k=ir[2].min;k<ir[2].max;++k)) \
180  for(j=ir[1].min;j<ir[1].max;++j) \
181  for(i=ir[0].min;i<ir[0].max;++i) { \
182  uint index = (WHEN_3D(k*hn)+j)*hn+i; \
183  p->offset[p->offset[index+1]-count[index]]=el; \
184  --count[index]; \
185  } \
186  } while(0)
187  FOR_LOOP();
188  #undef FOR_LOOP
189  }
190  free(count);
191 }
192 
193 static void hash_free(struct hash_data *p) { free(p->offset); }
194 
195 struct findpts_local_data {
196  unsigned ntot;
197  const double *elx[D];
198  struct obbox *obb;
199  struct hash_data hd;
201  double tol;
202 };
203 
205  const double *const elx[D],
206  const unsigned n[D], const uint nel,
207  const unsigned m[D], const double bbox_tol,
208  const uint max_hash_size,
209  const unsigned npt_max, const double newt_tol)
210 {
211  unsigned d;
212  unsigned ntot=n[0]; for(d=1;d<D;++d) ntot*=n[d];
213  fd->ntot = ntot;
214  for(d=0;d<D;++d) fd->elx[d]=elx[d];
215  fd->obb=tmalloc(struct obbox,nel);
216  obbox_calc(fd->obb,elx,n,nel,m,bbox_tol);
217  hash_build(&fd->hd,fd->obb,nel,max_hash_size);
218  findpts_el_setup(&fd->fed,n,npt_max);
219  fd->tol = newt_tol;
220 }
221 
223 {
224  findpts_el_free(&fd->fed);
225  hash_free(&fd->hd);
226  free(fd->obb);
227 }
228 
229 static void map_points_to_els(
230  struct array *const map,
231  uint *const code_base , const unsigned code_stride ,
232  const double *const x_base[D], const unsigned x_stride[D],
233  const uint npt, const struct findpts_local_data *const fd,
234  buffer *buf)
235 {
236  uint index;
237  const double *xp[D]; uint *code=code_base;
238  unsigned d; for(d=0;d<D;++d) xp[d]=x_base[d];
239  array_init(struct index_el,map,npt+(npt>>2)+1);
240  for(index=0;index<npt;++index) {
241  double x[D]; for(d=0;d<D;++d) x[d]=*xp[d];
242  { const uint hi = hash_index(&fd->hd,x);
243  const uint *elp = fd->hd.offset + fd->hd.offset[hi ],
244  *const ele = fd->hd.offset + fd->hd.offset[hi+1];
245  *code = CODE_NOT_FOUND;
246  for(; elp!=ele; ++elp) {
247  const uint el = *elp;
248  if(obbox_test(&fd->obb[el],x)>=0) {
249  struct index_el *const p =
250  array_reserve(struct index_el,map,map->n+1);
251  p[map->n].index = index;
252  p[map->n].el = el;
253  ++map->n;
254  }
255  }
256  }
257  for(d=0;d<D;++d)
258  xp[d] = (const double*)((const char*)xp[d]+ x_stride[d]);
259  code = (uint*)( (char*)code +code_stride );
260  }
261  /* group by element */
262  sarray_sort(struct index_el,map->ptr,map->n, el,0, buf);
263  /* add sentinel */
264  {
265  struct index_el *const p =
266  array_reserve(struct index_el,map,map->n+1);
267  p[map->n].el = -(uint)1;
268  }
269 }
270 
271 #define AT(T,var,i) \
272  (T*)( (char*)var##_base +(i)*var##_stride )
273 #define CAT(T,var,i) \
274  (const T*)((const char*)var##_base +(i)*var##_stride )
275 #define CATD(T,var,i,d) \
276  (const T*)((const char*)var##_base[d]+(i)*var##_stride[d])
277 
279  uint *const code_base , const unsigned code_stride ,
280  uint *const el_base , const unsigned el_stride ,
281  double *const r_base , const unsigned r_stride ,
282  double *const dist2_base , const unsigned dist2_stride ,
283  const double *const x_base[D], const unsigned x_stride[D],
284  const uint npt, struct findpts_local_data *const fd,
285  buffer *buf)
286 {
287  struct findpts_el_data *const fed = &fd->fed;
288  struct findpts_el_pt *const fpt = findpts_el_points(fed);
289  struct array map; /* point -> element map */
290  map_points_to_els(&map, code_base,code_stride, x_base,x_stride, npt, fd, buf);
291  {
292  const unsigned npt_max = fd->fed.npt_max;
293  const struct index_el *p, *const pe = (struct index_el *)map.ptr+map.n;
294  for(p=map.ptr;p!=pe;) {
295  const uint el = p->el, el_off=el*fd->ntot;
296  const double *elx[D];
297  unsigned d;
298  for(d=0;d<D;++d) elx[d]=fd->elx[d]+el_off;
299  findpts_el_start(fed,elx);
300  do {
301  const struct index_el *q;
302  unsigned i;
303  for(i=0,q=p;i<npt_max && q->el==el;++q) {
304  uint *code = AT(uint,code,q->index);
305  if(*code==CODE_INTERNAL) continue;
306  for(d=0;d<D;++d) fpt[i].x[d]=*CATD(double,x,q->index,d);
307  ++i;
308  }
309  findpts_el(fed,i,fd->tol);
310  for(i=0,q=p;i<npt_max && q->el==el;++q) {
311  const uint index=q->index;
312  uint *code = AT(uint,code,index);
313  double *dist2 = AT(double,dist2,index);
314  if(*code==CODE_INTERNAL) continue;
315  if(*code==CODE_NOT_FOUND
316  || fpt[i].flags==(1u<<(2*D)) /* converged, no constraints */
317  || fpt[i].dist2<*dist2) {
318  double *r = AT(double,r,index);
319  uint *eli = AT(uint,el,index);
320  *eli = el;
321  *code = fpt[i].flags==(1u<<(2*D)) ? CODE_INTERNAL : CODE_BORDER;
322  *dist2 = fpt[i].dist2;
323  for(d=0;d<D;++d) r[d]=fpt[i].r[d];
324  }
325  ++i;
326  }
327  p=q;
328  } while(p->el==el);
329  }
330  }
331  array_free(&map);
332 }
333 
334 /* assumes points are already grouped by elements */
336  double *const out_base, const unsigned out_stride,
337  const uint *const el_base, const unsigned el_stride,
338  const double *const r_base, const unsigned r_stride,
339  const uint npt,
340  const double *const in, struct findpts_local_data *const fd)
341 {
342  struct findpts_el_data *const fed = &fd->fed;
343  const unsigned npt_max = fed->npt_max;
344  uint p;
345  for(p=0;p<npt;) {
346  const uint el = *CAT(uint,el,p);
347  const double *const in_el = in+el*fd->ntot;
348  do {
349  unsigned i; uint q;
350  for(i=0,q=p;i<npt_max && q<npt && *CAT(uint,el,q)==el;++q) ++i;
351  findpts_el_eval( AT(double,out,p),out_stride,
352  CAT(double, r,p), r_stride, i,
353  in_el,fed);
354  p=q;
355  } while(p<npt && *CAT(uint,el,p)==el);
356  }
357 }
358 
359 #undef CATD
360 #undef CAT
361 #undef AT
362 
363 #undef findpts_local_eval
364 #undef findpts_local
365 #undef findpts_local_free
366 #undef findpts_local_setup
367 #undef map_points_to_els
368 #undef findpts_local_data
369 #undef findpts_el_points
370 #undef findpts_el_start
371 #undef findpts_el_eval
372 #undef findpts_el
373 #undef findpts_el_free
374 #undef findpts_el_setup
375 #undef findpts_el_data
376 #undef hash_free
377 #undef hash_build
378 #undef hash_bb
379 #undef hash_opt_size
380 #undef hash_count
381 #undef hash_range
382 #undef hash_setfac
383 #undef hash_index
384 #undef hash_data
385 #undef obbox_test
386 #undef obbox_calc
387 #undef obbox
388 
#define uint
Definition: types.h:70
static double sum(struct xxt *data, double v, uint n, uint tag)
Definition: xxt.c:400
static struct dbl_range dbl_range_merge(struct dbl_range a, struct dbl_range b)
Definition: findpts_local.c:21
size_t n
Definition: mem.h:111
#define tmalloc(type, count)
Definition: mem.h:91
#define sint
Definition: types.h:69
#define hash_build
#define findpts_local_setup
#define array_reserve(T, a, min)
Definition: mem.h:138
#define findpts_local_free
n
Definition: xxt_test.m:73
struct hash_data hd
#define CAT(T, var, i)
double max
Definition: lob_bnd.c:21
#define findpts_el_start
#define CODE_BORDER
Definition: findpts.c:29
#define findpts_el_data
#define x
#define CATD(T, var, i, d)
#define findpts_el_pt
double fac[D]
Definition: findpts_imp.h:34
#define hash_free
#define findpts_el_setup
#define obbox_calc
#define tcalloc(type, count)
Definition: mem.h:93
#define hash_setfac
#define findpts_el
p
Definition: xxt_test2.m:1
#define WHEN_3D(a)
Definition: findpts.c:79
#define obbox_test
Definition: mem.h:111
uint index
Definition: findpts_local.c:19
ulong hash_n
Definition: findpts_imp.h:32
#define findpts_el_eval
#define array_init(T, a, max)
Definition: mem.h:136
#define hash_index
#define D
Definition: findpts.c:78
static double elx[NR *NS]
#define obbox
uint * offset
Definition: findpts_imp.h:35
#define findpts_local_eval
#define sarray_sort(T, A, n, field, is_long, buf)
Definition: sarray_sort.h:55
static ulong hash_index_aux(double low, double fac, ulong n, double x)
Definition: findpts.c:38
for i
Definition: xxt_test.m:74
static sint iceil(double x)
Definition: findpts_local.c:30
#define findpts_local
#define hash_bb
const double * elx[D]
void * ptr
Definition: mem.h:111
#define AT(T, var, i)
#define hash_range
#define CODE_NOT_FOUND
Definition: findpts.c:30
double min
Definition: lob_bnd.c:21
#define CODE_INTERNAL
Definition: findpts.c:28
#define hash_opt_size
#define array_free(a)
Definition: mem.h:135
ulong out[N]
Definition: sort_test2.c:20
#define FOR_LOOP()
#define map_points_to_els
static sint ifloor(double x)
Definition: findpts_local.c:29
#define findpts_el_free
#define hash_count
struct findpts_el_data fed
#define findpts_el_points
struct dbl_range bnd[D]
Definition: findpts_imp.h:33