Nek5000
SEM for Incompressible NS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
lob_bnd.c
Go to the documentation of this file.
1 #include <stddef.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <math.h> /* for cos, fabs */
5 #include <float.h>
6 #include "c99.h"
7 #include "name.h"
8 #include "types.h"
9 #include "fail.h"
10 #include "mem.h"
11 #include "poly.h"
12 
13 #define lob_bnd_setup PREFIXED_NAME(lob_bnd_setup)
14 #define lob_bnd_lin_1 PREFIXED_NAME(lob_bnd_lin_1)
15 #define lob_bnd_lin_2 PREFIXED_NAME(lob_bnd_lin_2)
16 #define lob_bnd_lin_3 PREFIXED_NAME(lob_bnd_lin_3)
17 #define lob_bnd_1 PREFIXED_NAME(lob_bnd_1 )
18 #define lob_bnd_2 PREFIXED_NAME(lob_bnd_2 )
19 #define lob_bnd_3 PREFIXED_NAME(lob_bnd_3 )
20 
21 struct dbl_range { double min,max; };
22 
23 /*--------------------------------------------------------------------------
24  Bounds for Polynomials on [-1,1]^d
25  given in the Lagrangian basis on
26  Gauss-Lobatto-Legendre quadrature nodes
27 
28  The main parameters are the number of GLL nodes in each dimension
29  unsigned nr = ..., ns = ..., nt = ...;
30 
31  The number of points in the constructed piecewise (tri-,bi-)linear bounds
32  is a parameter; more points give tighter bounds, and we expect m>n.
33 
34  unsigned mr = 4*nr, ms = 4*ns, mt = 4*nt;
35 
36  The necessary setup is accomplished via:
37  double *data_r = tmalloc(double, lob_bnd_size(nr,mr));
38  double *data_s = tmalloc(double, lob_bnd_size(ns,ms));
39  double *data_t = tmalloc(double, lob_bnd_size(nt,mt));
40  lob_bnd_setup(data_r, nr,mr);
41  lob_bnd_setup(data_s, ns,ms);
42  lob_bnd_setup(data_t, nt,mt);
43 
44  Bounds may then be computed via:
45  double work1r[2*mr], work1s[2*ms];
46  double work2[2*mr*(ns+ms+1)];
47  double work3[2*mr*ms*(nt+mt+1)];
48  double ur[nr], us[ns]; // 1-d polynomials on the zr[] and zs[] nodes
49  double u2[ns][nr]; // 2-d polynomial on zr[] (x) zs[]
50  double u3[nt][ns][nr]; // 3-d polynomial on zr[] (x) zs[] (x) zt[]
51  struct dbl_range bound;
52 
53  bound = lob_bnd_1(data_r,nr,mr, ur, work1r); // compute bounds on ur
54  bound = lob_bnd_1(data_s,ns,ms, us, work1s); // compute bounds on us
55  bound = lob_bnd_2(data_r,nr,mr, data_s,ns,ms,
56  (const double*)&u2[0][0], work2); // compute bounds on u2
57  bound = lob_bnd_3(data_r,nr,mr, data_s,ns,ms, data_t,nt,mt,
58  (const double*)&u3[0][0], work3); // compute bounds on u3
59 
60  free(data_r), free(data_s), free(data_t);
61 
62  The functions lob_bnd_lin_d compute the piecewise d-linear bounds.
63  Nodes for these are Chebyshev-Lobatto:
64  h[0] = -1, h[m-1] = 1;
65  for(j=1;j<m-1;++j) h[j] = cos((m-1-j)*PI/(m-1));
66  The functions lob_bnd_d simply call these and return the min and max
67  over all nodes.
68 
69  --------------------------------------------------------------------------*/
70 
71 #define PI 3.1415926535897932384626433832795028841971693993751058209749445923
72 
73 void lob_bnd_setup(double *restrict data, unsigned n, unsigned m)
74 {{
75  unsigned nm = n*m, i,j;
76  double *restrict z=data,
77  *restrict Q=z+n, *restrict h=Q+2*n,
78  *restrict lb=h+m, *restrict lbnp=lb+2*nm;
79  double *restrict pl = tmalloc(double,5*n + gll_lag_size(n)),
80  *restrict dl = pl+n, *restrict pr=dl+n, *restrict dr=pr+n,
81  *restrict p=dr+n, *restrict gll_data=p+n;
82  lagrange_fun *lag = gll_lag_setup(gll_data,n);
83 
84  /* set z and Q to Lobatto nodes, weights */
85  lobatto_quad(z,Q,n);
86 
87  /* Q0, Q1 : linear functionals on the GLL nodal basis
88  for the zeroth and first Legendre coefficient */
89  for(i=n;i;) --i, Q[2*i]=Q[i]/2, Q[2*i+1] = 3*Q[2*i]*z[i];
90  /*for(i=0;i<n;++i) Q0[i]=Q0[i]/2, Q1[i] = 3*Q0[i]*z[i];*/
91 
92  /* h : m Chebyshev nodes */
93  h[0] = -1, h[m-1] = 1;
94  for(j=1;j<m-1;++j) h[j] = cos((m-1-j)*PI/(m-1));
95 
96  /* lv, uv : lower, upper piecewise linear bounds (nodes h) of
97  Lagrangian basis functions for Gauss-Lobatto nodes */
98  for(i=0;i<n;++i)
99  lb[(i*m+ 0)*2+1]=lb[(i*m+ 0)*2+0]=(i== 0?1:0),
100  lb[(i*m+m-1)*2+1]=lb[(i*m+m-1)*2+0]=(i==n-1?1:0);
101 
102  lag(pl,gll_data,n,1,(h[0]+h[1])/2);
103  for(j=1;j<m-1;++j) {
104  double x = h[j], xl = (x+h[j-1])/2, xr = (x+h[j+1])/2;
105  lag(pr,gll_data,n,1,xr);
106  lag(p ,gll_data,n,0,x );
107  for(i=0;i<n;++i) {
108  double lo,up, cl = pl[i] + (x-xl)*dl[i], cr = pr[i] + (x-xr)*dr[i];
109  if(cl<cr) lo=cl,up=cr; else lo=cr,up=cl;
110  if(p[i]<lo) lo=p[i]; if(up<p[i]) up=p[i];
111  lb[(i*m+j)*2+0] = lo, lb[(i*m+j)*2+1] = up;
112  }
113  memcpy(pl,pr,2*n*sizeof(double));
114  }
115 
116  /* lbnp : lb split into negative and positive parts */
117  for(i=0;i<nm;++i) {
118  double f;
119  lbnp[4*i+0]=lbnp[4*i+1]=lbnp[4*i+2]=lbnp[4*i+3]=0;
120  if((f=lb[2*i+0])<0) lbnp[4*i+0]=f; else lbnp[4*i+1]=f;
121  if((f=lb[2*i+1])<0) lbnp[4*i+2]=f; else lbnp[4*i+3]=f;
122  }
123 
124  free(pl);
125 }}
126 
127 static void lob_bnd_fst(
128  double *restrict b,
129  const double *restrict z, const double *restrict Q, const double *restrict h,
130  const double *restrict lb, unsigned n, unsigned m,
131  const double *restrict u)
132 {
133  unsigned i,j;
134  double a0=0, a1=0;
135  for(i=0;i<n;++i) a0 += Q[2*i]*u[i], a1 += Q[2*i+1]*u[i];
136  for(j=0;j<m;++j) b[2*j+1] = b[2*j+0] = a0 + a1*h[j];
137  for(i=0;i<n;++i) {
138  double w = u[i] - (a0 + a1*z[i]);
139  if(w>=0)
140  for(j=0;j<m;++j) b[2*j+0]+=w*lb[0], b[2*j+1]+=w*lb[1], lb+=2;
141  else
142  for(j=0;j<m;++j) b[2*j+0]+=w*lb[1], b[2*j+1]+=w*lb[0], lb+=2;
143  }
144 }
145 
146 static void lob_bnd_ext(
147  double *restrict b_,
148  const double *restrict z, const double *restrict Q, const double *restrict h,
149  const double *restrict lbnp, unsigned n, unsigned m,
150  const double *restrict br_, unsigned mr,
151  double *restrict a)
152 {
153  const double *restrict br = br_;
154  double *restrict b = b_;
155  unsigned i,j,k;
156  for(i=0;i<mr;++i) a[2*i+1]=a[2*i+0]=0;
157  for(j=0;j<n;++j) {
158  double t, q0 = Q[2*j], q1 = Q[2*j+1];
159  for(i=0;i<mr;++i) t=(br[0]+br[1])/2, br+=2, a[2*i]+=q0*t, a[2*i+1]+=q1*t;
160  }
161  for(i=0;i<mr;++i) {
162  double a0=a[2*i],a1=a[2*i+1];
163  for(k=0;k<m;++k) b[1]=b[0]=a0+a1*h[k], b+=2;
164  }
165  br=br_;
166  for(j=0;j<n;++j,lbnp+=4*m) {
167  double zj = z[j];
168  b = b_;
169  for(i=0;i<mr;++i) {
170  double t = a[2*i] + a[2*i+1]*zj;
171  double w0 = *br++ - t;
172  double w1 = *br++ - t;
173  if(w0>=0) /* 0 <= w0 <= w1 */
174  for(k=0;k<m;++k)
175  *b++ += w0 * lbnp[4*k+1] + w1 * lbnp[4*k+0],
176  *b++ += w1 * lbnp[4*k+3] + w0 * lbnp[4*k+2];
177  else if(w1<=0) /* w0 <= w1 <= 0 */
178  for(k=0;k<m;++k)
179  *b++ += w0 * lbnp[4*k+3] + w1 * lbnp[4*k+2],
180  *b++ += w1 * lbnp[4*k+1] + w0 * lbnp[4*k+0];
181  else /* w0 < 0 < w1 */
182  for(k=0;k<m;++k)
183  *b++ += w0 * lbnp[4*k+3] + w1 * lbnp[4*k+0],
184  *b++ += w1 * lbnp[4*k+3] + w0 * lbnp[4*k+0];
185  }
186  }
187 }
188 
189 void lob_bnd_lin_1(double *restrict b,
190  const double *restrict lob_bnd_data, unsigned n, unsigned m,
191  const double *restrict u, uint un)
192 {
193  const double *z=lob_bnd_data, *Q=z+n, *h=Q+2*n, *lb=h+m;
194  for(;un;--un, u+=n, b+=2*m) lob_bnd_fst(b, z,Q,h,lb,n,m, u);
195 }
196 
197 /* work holds 2*mr + 2*ns*mr doubles */
199  double *restrict b,
200  const double *lob_bnd_data_r, unsigned nr, unsigned mr,
201  const double *lob_bnd_data_s, unsigned ns, unsigned ms,
202  const double *restrict u, uint un, double *restrict work)
203 {
204  unsigned mrs = mr*ms;
205  const double *zr=lob_bnd_data_r,*Qr=zr+nr,*hr=Qr+2*nr,*lb_r=hr+mr;
206  const double *zs=lob_bnd_data_s,*Qs=zs+ns,*hs=Qs+2*ns,*lbnp_s=hs+ms+2*ns*ms;
207  double *a = work, *br = a+2*mr;
208  for(;un;--un, b+=2*mrs) {
209  double *br_; unsigned i;
210  for(i=0,br_=br;i<ns;++i,br_+=2*mr,u+=nr)
211  lob_bnd_fst(br_, zr,Qr,hr,lb_r,nr,mr, u);
212  lob_bnd_ext(b, zs,Qs,hs,lbnp_s,ns,ms, br,mr, a);
213  }
214 }
215 
216 /* work holds 2*mr*ms + 2*nt*ms*mr doubles */
218  double *restrict b,
219  const double *lob_bnd_data_r, unsigned nr, unsigned mr,
220  const double *lob_bnd_data_s, unsigned ns, unsigned ms,
221  const double *lob_bnd_data_t, unsigned nt, unsigned mt,
222  const double *restrict u, uint un, double *restrict work)
223 {
224  unsigned nst=ns*nt, mrst=mr*ms*mt, mrs=mr*ms, mr_ns=mr*ns;
225  const double *zr=lob_bnd_data_r,*Qr=zr+nr,*hr=Qr+2*nr,*lb_r=hr+mr;
226  const double *zs=lob_bnd_data_s,*Qs=zs+ns,*hs=Qs+2*ns,*lbnp_s=hs+ms+2*ns*ms;
227  const double *zt=lob_bnd_data_t,*Qt=zt+nt,*ht=Qt+2*nt,*lbnp_t=ht+mt+2*nt*mt;
228  double *a = work, *bs = a+2*mr*ms;
229  for(;un;--un, b+=2*mrst) {
230  double *br_, *bs_; unsigned i;
231  for(i=0,br_=b;i<nst;++i,br_+=2*mr,u+=nr)
232  lob_bnd_fst(br_, zr,Qr,hr,lb_r,nr,mr, u);
233  for(i=0,br_=b,bs_=bs;i<nt;++i,br_+=2*mr_ns,bs_+=2*mrs)
234  lob_bnd_ext(bs_, zs,Qs,hs,lbnp_s,ns,ms, br_,mr, a);
235  lob_bnd_ext(b, zt,Qt,ht,lbnp_t,nt,mt, bs,mrs, a);
236  }
237 }
238 
239 static struct dbl_range minmax(const double *restrict b, unsigned m)
240 {
241  struct dbl_range bnd;
242  bnd.min = b[0], bnd.max = b[1];
243  for(--m,b+=2;m;--m,b+=2)
244  bnd.min = b[0]<bnd.min?b[0]:bnd.min,
245  bnd.max = b[1]>bnd.max?b[1]:bnd.max;
246  return bnd;
247 }
248 
249 /* work holds 2*m doubles */
251  const double *restrict lob_bnd_data, unsigned n, unsigned m,
252  const double *restrict u, double *restrict work)
253 {
254  lob_bnd_lin_1(work, lob_bnd_data,n,m, u,1);
255  return minmax(work,m);
256 }
257 
258 /* work holds 2*mr*ms + 2*mr + 2*mr*ns
259  =2*mr*(ms+1+ns) doubles */
261  const double *lob_bnd_data_r, unsigned nr, unsigned mr,
262  const double *lob_bnd_data_s, unsigned ns, unsigned ms,
263  const double *restrict u, double *restrict work)
264 {
265  unsigned m = mr*ms;
266  lob_bnd_lin_2(work, lob_bnd_data_r,nr,mr,
267  lob_bnd_data_s,ns,ms, u,1, work+2*m);
268  return minmax(work,m);
269 }
270 
271 /* work holds 2*mr*ms*mt + 2*mr*ms + 2*nt*ms*mr
272  =2*mr*ms*(nt+mt+1) doubles */
274  const double *lob_bnd_data_r, unsigned nr, unsigned mr,
275  const double *lob_bnd_data_s, unsigned ns, unsigned ms,
276  const double *lob_bnd_data_t, unsigned nt, unsigned mt,
277  const double *restrict u, double *restrict work)
278 {
279  unsigned m = mr*ms*mt;
280  lob_bnd_lin_3(work, lob_bnd_data_r,nr,mr,
281  lob_bnd_data_s,ns,ms,
282  lob_bnd_data_t,nt,mt, u,1, work+2*m);
283  return minmax(work,m);
284 }
#define uint
Definition: types.h:70
#define tmalloc(type, count)
Definition: mem.h:91
static const unsigned mr[D]
static double zt[NT]
#define lob_bnd_3
Definition: lob_bnd.c:19
void lagrange_fun(double *restrict p, double *restrict data, unsigned n, int d, double x)
Definition: poly.c:20
#define lobatto_quad
Definition: poly.c:16
uint Q[NUM]
Definition: sort_test.c:20
n
Definition: xxt_test.m:73
double max
Definition: lob_bnd.c:21
static double zr[NR]
#define lob_bnd_lin_2
Definition: lob_bnd.c:15
#define lob_bnd_1
Definition: lob_bnd.c:17
#define x
ns
Definition: xxt_test.m:43
#define gll_lag_setup
Definition: poly.c:18
static struct crystal cr
Definition: findpts_test.c:75
static void lob_bnd_fst(double *restrict b, const double *restrict z, const double *restrict Q, const double *restrict h, const double *restrict lb, unsigned n, unsigned m, const double *restrict u)
Definition: lob_bnd.c:127
p
Definition: xxt_test2.m:1
#define gll_lag_size
Definition: poly.c:17
Qs
Definition: xxt_test.m:42
#define lob_bnd_lin_3
Definition: lob_bnd.c:16
static double zs[NS]
#define lob_bnd_2
Definition: lob_bnd.c:18
static struct dbl_range minmax(const double *restrict b, unsigned m)
Definition: lob_bnd.c:239
#define restrict
Definition: c99.h:11
for i
Definition: xxt_test.m:74
double min
Definition: lob_bnd.c:21
static const unsigned nr[3]
#define lob_bnd_setup
Definition: lob_bnd.c:13
#define lob_bnd_lin_1
Definition: lob_bnd.c:14
static double work[TNR *NS]
establishes some macros to establish naming conventions
#define PI
Definition: lob_bnd.c:71
static void lob_bnd_ext(double *restrict b_, const double *restrict z, const double *restrict Q, const double *restrict h, const double *restrict lbnp, unsigned n, unsigned m, const double *restrict br_, unsigned mr, double *restrict a)
Definition: lob_bnd.c:146
static double z[NR *NS *NT *N]
Definition: obbox_test.c:31