Nek5000
SEM for Incompressible NS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
obbox.c
Go to the documentation of this file.
1 #include <stddef.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include "c99.h"
5 #include "name.h"
6 #include "fail.h"
7 #include "types.h"
8 #include "mem.h"
9 #include "tensor.h"
10 #include "poly.h"
11 #include "lob_bnd.h"
12 
13 #define obbox_calc_2 PREFIXED_NAME(obbox_calc_2)
14 #define obbox_calc_3 PREFIXED_NAME(obbox_calc_3)
15 
16 struct obbox_2 { double c0[2], A[4];
17  struct dbl_range x[2]; };
18 
19 struct obbox_3 { double c0[3], A[9];
20  struct dbl_range x[3]; };
21 
22 
23 static void copy_strided(double *out, const double *in,
24  unsigned g, unsigned s, unsigned n)
25 {
26  if(g==1) for(;n;--n,in+=s) *out++ = *in;
27  else {
28  s *= g;
29  for(;n;--n,in+=s) memcpy(out,in,g*sizeof(double)), out+=g;
30  }
31 }
32 
33 static void mat_inv_2(double inv[4], const double A[4])
34 {
35  const double idet = 1/(A[0]*A[3]-A[1]*A[2]);
36  inv[0] = idet*A[3];
37  inv[1] = -(idet*A[1]);
38  inv[2] = -(idet*A[2]);
39  inv[3] = idet*A[0];
40 }
41 
42 static void mat_inv_3(double inv[9], const double A[9])
43 {
44  const double a = A[4]*A[8]-A[5]*A[7],
45  b = A[5]*A[6]-A[3]*A[8],
46  c = A[3]*A[7]-A[4]*A[6],
47  idet = 1/(A[0]*a+A[1]*b+A[2]*c);
48  inv[0] = idet*a;
49  inv[1] = idet*(A[2]*A[7]-A[1]*A[8]);
50  inv[2] = idet*(A[1]*A[5]-A[2]*A[4]);
51  inv[3] = idet*b;
52  inv[4] = idet*(A[0]*A[8]-A[2]*A[6]);
53  inv[5] = idet*(A[2]*A[3]-A[0]*A[5]);
54  inv[6] = idet*c;
55  inv[7] = idet*(A[1]*A[6]-A[0]*A[7]);
56  inv[8] = idet*(A[0]*A[4]-A[1]*A[3]);
57 }
58 
59 static struct dbl_range dbl_range_merge(struct dbl_range a, struct dbl_range b)
60 {
61  struct dbl_range m;
62  m.min = b.min<a.min?b.min:a.min,
63  m.max = a.max>b.max?a.max:b.max;
64  return m;
65 }
66 
67 static struct dbl_range dbl_range_expand(struct dbl_range b, double tol)
68 {
69  double a = (b.min+b.max)/2, l = (b.max-b.min)*(1+tol)/2;
70  struct dbl_range m;
71  m.min = a-l, m.max = a+l;
72  return m;
73 }
74 
75 static void bbox_2_tfm(double *out, const double x0[2], const double Ji[4],
76  const double *x, const double *y, unsigned n)
77 {
78  unsigned i;
79  for(i=0;i<n;++i) {
80  const double dx = x[i]-x0[0], dy = y[i]-x0[1];
81  out[ i] = Ji[0]*dx + Ji[1]*dy;
82  out[n+i] = Ji[2]*dx + Ji[3]*dy;
83  }
84 }
85 
86 static void bbox_3_tfm(double *out, const double x0[3], const double Ji[9],
87  const double *x, const double *y, const double *z,
88  unsigned n)
89 {
90  unsigned i;
91  for(i=0;i<n;++i) {
92  const double dx = x[i]-x0[0], dy = y[i]-x0[1], dz = z[i]-x0[2];
93  out[ i] = Ji[0]*dx + Ji[1]*dy + Ji[2]*dz;
94  out[ n+i] = Ji[3]*dx + Ji[4]*dy + Ji[5]*dz;
95  out[2*n+i] = Ji[6]*dx + Ji[7]*dy + Ji[8]*dz;
96  }
97 }
98 
99 #if 0
100 
101 /* positive when possibly inside */
102 double obbox_axis_test_2(const struct obbox_2 *const b,
103  const double x, const double y)
104 {
105  const double bx = (x-b->x[0].min)*(b->x[0].max-x);
106  return bx<0 ? bx : (y-b->x[1].min)*(b->x[1].max-y);
107 }
108 
109 /* positive when possibly inside */
110 double obbox_test_2(const struct obbox_2 *const b,
111  const double x, const double y)
112 {
113  const double bxy = obbox_axis_test_2(b,x,y);
114  if(bxy<0) return bxy; else {
115  const double dx = x-b->c0[0], dy = y-b->c0[1];
116  const double r = b->A[0]*dx + b->A[1]*dy,
117  s = b->A[2]*dx + b->A[3]*dy;
118  const double br = (r+1)*(1-r);
119  return br<0 ? br : (s+1)*(1-s);
120  }
121 }
122 
123 #endif
124 
125 #define DO_MAX(a,b) do { unsigned temp = b; if(temp>a) a=temp; } while(0)
126 
127 void obbox_calc_2(struct obbox_2 *out,
128  const double *const elx[2],
129  const unsigned n[2], uint nel,
130  const unsigned m[2], const double tol)
131 {
132  const double *x = elx[0], *y = elx[1];
133  const unsigned nr = n[0], ns = n[1];
134  const unsigned mr = m[0], ms = m[1];
135 
136  const unsigned nrs = nr*ns;
137  double *data;
138  const unsigned lbsize0 = lob_bnd_size(nr,mr),
139  lbsize1 = lob_bnd_size(ns,ms);
140  unsigned wsize = 4*ns+2*ms;
141  DO_MAX(wsize,2*nr+2*mr);
142  DO_MAX(wsize,gll_lag_size(nr));
143  DO_MAX(wsize,gll_lag_size(ns));
144  data = tmalloc(double, 2*(nr+ns)+lbsize0+lbsize1+wsize);
145 
146  {
147  double *const I0r = data, *const I0s = data+2*nr;
148  double *const lob_bnd_data_r = data+2*(nr+ns),
149  *const lob_bnd_data_s = data+2*(nr+ns)+lbsize0;
150  double *const work = data+2*(nr+ns)+lbsize0+lbsize1;
151 
152  #define SETUP_DIR(r) do { \
153  lagrange_fun *const lag = gll_lag_setup(work, n##r); \
154  lag(I0##r, work,n##r,1, 0); \
155  lob_bnd_setup(lob_bnd_data_##r, n##r,m##r); \
156  } while(0)
157 
158  SETUP_DIR(r); SETUP_DIR(s);
159 
160  #undef SETUP_DIR
161 
162  for(;nel;--nel,x+=nrs,y+=nrs,++out) {
163  double x0[2], J[4], Ji[4];
164  struct dbl_range ab[2], tb[2];
165 
166  /* double work[2*nr] */
167  x0[0] = tensor_ig2(J , I0r,nr, I0s,ns, x, work);
168  x0[1] = tensor_ig2(J+2, I0r,nr, I0s,ns, y, work);
169  mat_inv_2(Ji, J);
170 
171  /* double work[2*m##r] */
172  #define DO_BOUND(bnd,merge,r,x,work) do { \
173  struct dbl_range b = \
174  lob_bnd_1(lob_bnd_data_##r,n##r,m##r, x, work); \
175  if(merge) bnd=dbl_range_merge(bnd,b); else bnd=b; \
176  } while(0)
177 
178  /* double work[2*n##r + 2*m##r] */
179  #define DO_EDGE(merge,r,x,y,work) do { \
180  DO_BOUND(ab[0],merge,r,x,work); \
181  DO_BOUND(ab[1],merge,r,y,work); \
182  bbox_2_tfm(work, x0,Ji, x,y,n##r); \
183  DO_BOUND(tb[0],merge,r,(work) ,(work)+2*n##r); \
184  DO_BOUND(tb[1],merge,r,(work)+n##r,(work)+2*n##r); \
185  } while(0)
186 
187  DO_EDGE(0,r,x,y,work);
188  DO_EDGE(1,r,&x[nrs-nr],&y[nrs-nr],work);
189 
190  /* double work[4*ns + 2*ms] */
191  #define GET_EDGE(off) do { \
192  copy_strided(work , x+off,1,nr,ns); \
193  copy_strided(work+ns, y+off,1,nr,ns); \
194  DO_EDGE(1,s,work,work+ns,work+2*ns); \
195  } while(0)
196 
197  GET_EDGE(0);
198  GET_EDGE(nr-1);
199 
200  #undef GET_EDGE
201  #undef DO_EDGE
202  #undef DO_BOUND
203 
204  out->x[0] = dbl_range_expand(ab[0],tol),
205  out->x[1] = dbl_range_expand(ab[1],tol);
206 
207  {
208  const double av0=(tb[0].min+tb[0].max)/2, av1=(tb[1].min+tb[1].max)/2;
209  out->c0[0] = x0[0] + J[0]*av0 + J[1]*av1;
210  out->c0[1] = x0[1] + J[2]*av0 + J[3]*av1;
211  }
212  {
213  const double di0 = 2/((1+tol)*(tb[0].max-tb[0].min)),
214  di1 = 2/((1+tol)*(tb[1].max-tb[1].min));
215  out->A[0]=di0*Ji[0], out->A[1]=di0*Ji[1];
216  out->A[2]=di1*Ji[2], out->A[3]=di1*Ji[3];
217  }
218 
219  }
220  }
221 
222  free(data);
223 }
224 
225 void obbox_calc_3(struct obbox_3 *out,
226  const double *const elx[3],
227  const unsigned n[3], uint nel,
228  const unsigned m[3], const double tol)
229 {
230  const double *x = elx[0], *y = elx[1], *z = elx[2];
231  const unsigned nr = n[0], ns = n[1], nt = n[2];
232  const unsigned mr = m[0], ms = m[1], mt = m[2];
233 
234  const unsigned nrs = nr*ns, nrst = nr*ns*nt;
235  double *data;
236  const unsigned lbsize0 = lob_bnd_size(nr,mr),
237  lbsize1 = lob_bnd_size(ns,ms),
238  lbsize2 = lob_bnd_size(nt,mt);
239  unsigned wsize = 3*nr*ns+2*mr*(ns+ms+1);
240  DO_MAX(wsize,6*nr*nt+2*mr*(nt+mt+1));
241  DO_MAX(wsize,6*ns*nt+2*ms*(nt+mt+1));
242  DO_MAX(wsize,2*nr*ns+3*nr);
243  DO_MAX(wsize,gll_lag_size(nr));
244  DO_MAX(wsize,gll_lag_size(ns));
245  DO_MAX(wsize,gll_lag_size(nt));
246  data = tmalloc(double, 2*(nr+ns+nt)+lbsize0+lbsize1+lbsize2+wsize);
247 
248  {
249  double *const I0r = data, *const I0s = I0r+2*nr, *const I0t = I0s+2*ns;
250  double *const lob_bnd_data_r = data+2*(nr+ns+nt),
251  *const lob_bnd_data_s = data+2*(nr+ns+nt)+lbsize0,
252  *const lob_bnd_data_t = data+2*(nr+ns+nt)+lbsize0+lbsize1;
253  double *const work = data+2*(nr+ns+nt)+lbsize0+lbsize1+lbsize2;
254 
255  #define SETUP_DIR(r) do { \
256  lagrange_fun *const lag = gll_lag_setup(work, n##r); \
257  lag(I0##r, work,n##r,1, 0); \
258  lob_bnd_setup(lob_bnd_data_##r, n##r,m##r); \
259  } while(0)
260 
261  SETUP_DIR(r); SETUP_DIR(s); SETUP_DIR(t);
262 
263  #undef SETUP_DIR
264 
265  for(;nel;--nel,x+=nrst,y+=nrst,z+=nrst,++out) {
266  double x0[3], J[9], Ji[9];
267  struct dbl_range ab[3], tb[3];
268 
269  /* double work[2*nrs+3*nr] */
270  #define EVAL_AT_0(d,x) \
271  x0[d] = tensor_ig3(J+3*d, I0r,nr, I0s,ns, I0t,nt, x, work)
272  EVAL_AT_0(0,x); EVAL_AT_0(1,y); EVAL_AT_0(2,z);
273  mat_inv_3(Ji, J);
274  #undef EVAL_AT_0
275 
276  /* double work[2*m##r*(n##s+m##s+1)] */
277  #define DO_BOUND(bnd,merge,r,s,x,work) do { \
278  struct dbl_range b = \
279  lob_bnd_2(lob_bnd_data_##r,n##r,m##r, \
280  lob_bnd_data_##s,n##s,m##s, x, work); \
281  if(merge) bnd=dbl_range_merge(bnd,b); else bnd=b; \
282  } while(0)
283 
284  /* double work[3*n##r*n##s+2*m##r*(n##s+m##s+1)] */
285  #define DO_FACE(merge,r,s,x,y,z,work) do { \
286  DO_BOUND(ab[0],merge,r,s,x,work); \
287  DO_BOUND(ab[1],merge,r,s,y,work); \
288  DO_BOUND(ab[2],merge,r,s,z,work); \
289  bbox_3_tfm(work, x0,Ji, x,y,z,n##r*n##s); \
290  DO_BOUND(tb[0],merge,r,s,(work) ,(work)+3*n##r*n##s); \
291  DO_BOUND(tb[1],merge,r,s,(work)+ n##r*n##s,(work)+3*n##r*n##s); \
292  DO_BOUND(tb[2],merge,r,s,(work)+2*n##r*n##s,(work)+3*n##r*n##s); \
293  } while(0)
294 
295  DO_FACE(0,r,s,x,y,z,work);
296  DO_FACE(1,r,s,&x[nrst-nrs],&y[nrst-nrs],&z[nrst-nrs],work);
297 
298  /* double work[6*n##r*n##s+2*m##r*(n##s+m##s+1)] */
299  #define GET_FACE(r,s,off,n1,n2,n3) do { \
300  copy_strided(work , x+off,n1,n2,n3); \
301  copy_strided(work+ n##r*n##s, y+off,n1,n2,n3); \
302  copy_strided(work+2*n##r*n##s, z+off,n1,n2,n3); \
303  DO_FACE(1,r,s,work,work+n##r*n##s,work+2*n##r*n##s,work+3*n##r*n##s); \
304  } while(0)
305 
306  GET_FACE(r,t,0 ,nr,ns,nt);
307  GET_FACE(r,t,nrs-nr,nr,ns,nt);
308  GET_FACE(s,t,0 , 1,nr,ns*nt);
309  GET_FACE(s,t,nr-1 , 1,nr,ns*nt);
310 
311  #undef GET_FACE
312  #undef DO_FACE
313  #undef DO_BOUND
314 
315  out->x[0] = dbl_range_expand(ab[0],tol),
316  out->x[1] = dbl_range_expand(ab[1],tol);
317  out->x[2] = dbl_range_expand(ab[2],tol);
318 
319  {
320  const double av0 = (tb[0].min+tb[0].max)/2,
321  av1 = (tb[1].min+tb[1].max)/2,
322  av2 = (tb[2].min+tb[2].max)/2;
323  out->c0[0] = x0[0] + J[0]*av0 + J[1]*av1 + J[2]*av2;
324  out->c0[1] = x0[1] + J[3]*av0 + J[4]*av1 + J[5]*av2;
325  out->c0[2] = x0[2] + J[6]*av0 + J[7]*av1 + J[8]*av2;
326  }
327  {
328  const double di0 = 2/((1+tol)*(tb[0].max-tb[0].min)),
329  di1 = 2/((1+tol)*(tb[1].max-tb[1].min)),
330  di2 = 2/((1+tol)*(tb[2].max-tb[2].min));
331  out->A[0]=di0*Ji[0], out->A[1]=di0*Ji[1], out->A[2]=di0*Ji[2];
332  out->A[3]=di1*Ji[3], out->A[4]=di1*Ji[4], out->A[5]=di1*Ji[5];
333  out->A[6]=di2*Ji[6], out->A[7]=di2*Ji[7], out->A[8]=di2*Ji[8];
334  }
335 
336  }
337  }
338 
339  free(data);
340 }
341 
static double tensor_ig2(double g[2], const double *wtr, uint nr, const double *wts, uint ns, const double *u, double *work)
Definition: tensor.h:133
double A[9]
Definition: obbox.c:19
#define uint
Definition: types.h:70
#define DO_EDGE(merge, r, x, y, work)
#define tmalloc(type, count)
Definition: mem.h:91
static const unsigned mr[D]
n
Definition: xxt_test.m:73
double max
Definition: lob_bnd.c:21
static struct dbl_range dbl_range_merge(struct dbl_range a, struct dbl_range b)
Definition: obbox.c:59
#define x
Definition: obbox.c:19
ulong A[NUM][SI]
Definition: sort_test.c:17
#define DO_FACE(merge, r, s, x, y, z, work)
ns
Definition: xxt_test.m:43
#define GET_EDGE(off)
#define DO_MAX(a, b)
Definition: obbox.c:125
#define GET_FACE(r, s, off, n1, n2, n3)
#define gll_lag_size
Definition: poly.c:17
static void mat_inv_3(double inv[9], const double A[9])
Definition: obbox.c:42
struct dbl_range x[3]
Definition: obbox.c:20
static void copy_strided(double *out, const double *in, unsigned g, unsigned s, unsigned n)
Definition: obbox.c:23
struct dbl_range x[2]
Definition: obbox.c:17
#define SETUP_DIR(r)
#define obbox_calc_2
Definition: obbox.c:13
static double elx[NR *NS]
static void mat_inv_2(double inv[4], const double A[4])
Definition: obbox.c:33
double A[4]
Definition: obbox.c:16
for i
Definition: xxt_test.m:74
static double obbox_axis_test_2(const struct obbox_2 *const b, const double x[2])
Definition: obbox.h:69
static unsigned lob_bnd_size(unsigned n, unsigned m)
Definition: lob_bnd.h:64
double c0[3]
Definition: obbox.c:19
#define obbox_calc_3
Definition: obbox.c:14
static void bbox_3_tfm(double *out, const double x0[3], const double Ji[9], const double *x, const double *y, const double *z, unsigned n)
Definition: obbox.c:86
#define EVAL_AT_0(d, x)
double min
Definition: lob_bnd.c:21
Definition: obbox.c:16
static const unsigned nr[3]
ulong out[N]
Definition: sort_test2.c:20
*Als dX *Qf *Qf *dX *em X inv(chol(A)) Ai
static void bbox_2_tfm(double *out, const double x0[2], const double Ji[4], const double *x, const double *y, unsigned n)
Definition: obbox.c:75
double c0[2]
Definition: obbox.c:16
static double obbox_test_2(const struct obbox_2 *const b, const double x[2])
Definition: obbox.h:77
static double work[TNR *NS]
establishes some macros to establish naming conventions
static struct dbl_range dbl_range_expand(struct dbl_range b, double tol)
Definition: obbox.c:67
static double y[NR *NS *NT *N]
Definition: obbox_test.c:31
static double z[NR *NS *NT *N]
Definition: obbox_test.c:31