Basilisk CFD
Adaptive Cartesian mesh PDE framework
Loading...
Searching...
No Matches
nh-staggered.h
Go to the documentation of this file.
1/** @file nh-staggered.h
2 */
3/**
4# The vertically-staggered non-hydrostatic solver
5
6See section 3.6.1 of [Popinet (2019)](/Bibliography#popinet2019). Note
7that this uses the vertical momentum *qz* rather than vertical
8velocity *w* and will not be compatible with [hydro.h](). */
9
10#define NH 1
11
12#include "poisson.h"
13
15
17double * alpha = NULL, * gammap = NULL;
18
19/** @brief Event: defaults (i = 0) */
20void event_defaults (void)
21{
22 non_hydro = true;
23
24 assert (qzl == NULL && phil == NULL &&
25 alpha == NULL && beta == NULL && gammap == NULL);
26 assert (nl > 0);
27 alpha = malloc (nl*sizeof(double));
28 gammap = malloc (nl*sizeof(double));
29 beta = malloc (nl*sizeof(double));
30 for (int l = 0; l < nl; l++) {
31 scalar qz = {0} /* new scalar */;
32 scalar phi = {0} /* new scalar */;
33 qzl = list_append (qzl, qz);
35 beta[l] = 1./nl;
36 }
37 reset (qzl, 0.);
38 reset (phil, 0.);
39
40 if (!tracers)
41 tracers = calloc (nl, sizeof(scalar *));
42
43 int l = 0;
44 for (int _qz = 0; _qz < 1; _qz++) /* scalar in qzl */ {
46 l++;
47 }
48
49 for (int l = 0; l < nl; l++)
50 alpha[l] = gammap[l] = 1.;
51
52#if 1
53#if 0
54 if (nl == 1) {
55 alpha[0] = 3.;
56 beta[0] = 1.;
57 }
58 else if (nl == 2) {
59 // see section \pade2 of ale2.tm
60 alpha[0] = 200./69., alpha[1] = 168070./109503.;
61 beta[0] = 20./69., beta[1] = 49./69.;
62 }
63#if 0
64 else if (nl == 3) {
65 // Padé approximant: see dispersion3.tm
66 alpha[0] = 147./50.;
67 alpha[1] = 21884919./16356250.;
68 alpha[2] = 2624395780083./1792301911300.;
69 beta[0] = 7./50.;
70 beta[1] = 19663./65425.;
71 beta[2] = 14641./26170.;
72 }
73#else
74 else if (nl == 3) {
75 // Gnuplot fit: see dispersion3.tm
76 alpha[0] = 3.483931265467430;
77 alpha[1] = 1.916127288169944;
78 alpha[2] = 1.710830494276016;
79 beta[0] = 0.0569717048168878;
80 beta[1] = 0.2367448039534642;
81 beta[2] = 0.7062834912296478;
82 }
83#endif
84 else if (nl == 4) {
85 alpha[0] = 2.962285714285714;
86 alpha[1] = 1.350414737345379;
87 alpha[2] = 1.185189693944078;
88 alpha[3] = 1.472922288188395;
89 beta[0] = 0.0822857142857143;
90 beta[1] = 0.1806217280518879;
91 beta[2] = 0.2639407055948642;
92 beta[3] = 0.4731518520675335;
93 }
94 else if (nl == 5) {
95 alpha[0] = 2.974434611602751;
96 alpha[1] = 1.364709853835999;
97 alpha[2] = 1.176733678121684;
98 alpha[3] = 1.143228438965934;
99 alpha[4] = 1.490559988000380;
100 beta[0] = 0.0540806293018682;
101 beta[1] = 0.1209195157421197;
102 beta[2] = 0.1769793771848123;
103 beta[3] = 0.2310497798249295;
104 beta[4] = 0.4169706979462702;
105 }
106 else {
107 for (int l = 0; l < nl; l++)
108 alpha[l] = 1., beta[l] = 1./nl;
109 alpha[0] = 3.;
110 }
111#else
112 if (nl == 1) {
113 beta[0] = 1.;
114 alpha[0] = 1.4;
115 }
116 else if (nl == 2) {
117 // Gnuplot fit: see dispersion4.tm
118#if 1
119 beta[0] = 0.20052;
120 alpha[0] = 1.57293;
121 alpha[1] = 2.13295;
122#else
123 beta[0] = beta[1] = 0.5;
124#if 0 // Keller matching
125 alpha[0] = 3.569011576135351, alpha[1] = 17.93213572854291;
126 gammap[0] = 1.314297124600639, gammap[1] = 8.11587147030185;
127#else
128 alpha[0] = 2.74711, alpha[1] = 12.6356;
129 gammap[0] = 1., gammap[1] = 6.49546;
130#endif
131#endif
132 }
133 else if (nl == 3) {
134#if 1
135 // Gnuplot fit: see dispersion4.tm
136 beta[0] = 0.0640959;
137 beta[1] = 0.231816;
138 alpha[0] = 1.46978;
139 alpha[1] = 2.04778;
140 alpha[2] = 1.71597;
141#else
142 beta[0] = beta[1] = beta[2] = 1./3.;
143#if 0 // Keller matching
144 alpha[0] = 618.4548736462094;
145 alpha[1] = 4.337984496124031;
146 alpha[2] = 9.782144219763449;
147 gammap[0] = 33.44576523031203;
148 gammap[1] = 4.741971207087486;
149 gammap[2] = 6.894753476611884;
150#else
151 alpha[0] = 0.222769;
152 alpha[1] = 3.27677;
153 alpha[2] = 1.;
154 gammap[0] = 0.0351922;
155 gammap[1] = 0.355296;
156 gammap[2] = 1.;
157#endif
158#endif
159 }
160 else if (nl == 4) {
161 // Gnuplot fit: see dispersion4.tm
162 beta[0] = 0.0230779;
163 beta[1] = 0.0813287;
164 beta[2] = 0.252027;
165 alpha[0] = 1.4426;
166 alpha[1] = 2.03836;
167 alpha[2] = 1.69601;
168 alpha[3] = 1.6165;
169 }
170 else if (nl == 5) {
171 // Gnuplot fit: see dispersion4.tm
172 beta[0] = 0.0170975;
173 beta[1] = 0.0468568;
174 beta[2] = 0.119315;
175 beta[3] = 0.260945;
176 alpha[0] = 1.34777;
177 alpha[1] = 1.76632;
178 alpha[2] = 1.56509;
179 alpha[3] = 1.4479;
180 alpha[4] = 1.52395;
181 }
182#endif
183 beta[nl-1] = 1.;
184 for (int l = 0; l < nl - 1; l++)
185 beta[nl-1] -= beta[l];
186#endif
187}
188
189#define PHIT 6.
190
191void correct_qz (double dt, const scalar phis)
192{
193 for (int _i = 0; _i < _N; _i++) /* foreach */ {
194 scalar phi, qz, h;
195 int l = 0;
196 for (phi,qz,h in phil,qzl,hl) {
197 double phit;
198 if (l == nl - 1) {
199 double phib, hb;
200 if (l == 0) {
201 scalar s = hl[0];
202 phib = phi[], hb = s[];
203 }
204 else {
205 scalar s = phil[l-1];
206 phib = s[];
207 s = hl[l-1];
208 hb = s[];
209 }
210#if 0
211 phit = ((2.*sq(h[])*phib - phi[]*sq(hb)
212 - 5.*h[]*phi[]*hb - 6.*sq(h[])*phi[])/
213 (sq(hb) + 3.*h[]*hb + 2.*sq(h[])));
214#else
215 phit = (8.*phis[] + phib - PHIT*phi[])/3.; // top BC (Dirichlet)
216#endif
217 }
218 else {
219 scalar s = phil[l+1];
220 phit = s[];
221 }
222 qz[] -= dt*alpha[l]*(phit - phi[]);
223 l++;
224 }
225 }
226}
227
228#if 1
229/** @brief Event: viscous_term (i++) */
231{
232 if (nu > 0.) {
233#if 0
234 correct_qz (dt);
235#endif
236 // fixme: ugly hack
237 scalar lb = lambda_b, d = dut, u = u_b;
238 lambda_b = dut = u_b = zeroc;
239 for (int _i = 0; _i < _N; _i++) /* foreach */
240 // fixme: BCs should be different from those of horizontal velocity
242 lambda_b = lb; dut = d; u_b = u;
243#if 0
244 correct_qz (- dt);
245#endif
246 }
247}
248#endif
249
250static void coeffs1 (Point point, scalar * hl,
251 double * a, double (* b)[2], double * c)
252{
253 int l = 0;
254 double zr = zb[], zl = zb[-1];
255 for (int _h = 0; _h < 1; _h++) /* scalar in hl */ {
256 b[l][0] = - (zr - zl - 2.*h[-1])/(2.*Delta);
257 b[l][1] = - (zr - zl + 2.*h[])/(2.*Delta);
258 if (l == nl - 1) {
259 a[l] = (zr + h[] - zl - h[-1])/3./(2.*Delta);
260 b[l][0] -= PHIT*a[l];
261 b[l][1] -= PHIT*a[l];
262 c[l] = 0.;
263 }
264 else {
265 a[l] = 0.;
266 c[l] = (zr + h[] - zl - h[-1])/(2.*Delta);
267 }
268 l++, zr += h[], zl += h[-1];
269 }
270}
271
272// same as coeffs1 but without the [\phi\partial_x z] term
273// (in blue in control.tm)
274static void coeffs2 (Point point, scalar * hl,
275 double * a, double (* b)[2], double * c)
276{
277 int l = 0;
278 for (int _h = 0; _h < 1; _h++) /* scalar in hl */ {
279 b[l][0] = h[-1]/Delta;
280 b[l][1] = - h[]/Delta;
281 if (l == nl - 1) {
282 a[l] = 0.;
283 b[l][0] -= PHIT*a[l];
284 b[l][1] -= PHIT*a[l];
285 c[l] = 0.;
286 }
287 else {
288 a[l] = 0.;
289 c[l] = 0.;
290 }
291 l++;
292 }
293}
294
296 double * a, double * b, double * c, double * d)
297{
298 double al[nl], bl[nl][2], cl[nl];
299 double ar[nl], br[nl][2], cr[nl];
300#if 1
301 coeffs1 (point, hl, al, bl, cl);
302 coeffs1 (neighborp(1), hl, ar, br, cr);
303#else
304 coeffs2 (point, hl, al, bl, cl);
305 coeffs2 (neighborp(1), hl, ar, br, cr);
306#endif
307
308 int l = 0;
309 scalar phi, rhs, h;
310 double zr = zb[1], zl = zb[-1];
311 for (phi,rhs,h in phil,rhsl,hl) {
312 d[l] = rhs[];
313
314 c[l] = alpha[l];
315 if (l == 0)
316 a[l] = 0.; // bottom BC (Neumann)
317 else {
318 scalar hm = hl[l-1];
319 a[l] = alpha[l-1]*h[]/hm[];
320 }
321 b[l] = - a[l] - c[l];
322 if (l == nl - 1) {
323 // top BC (Dirichlet)
324 if (l == 0)
325 b[l] -= (PHIT - 1.)*c[l]/3.;
326 else {
327 b[l] -= PHIT*c[l]/3.;
328 a[l] += c[l]/3.;
329 }
330 }
331
332#if 0 // no effect
333 d[l] +=
334 h[]*(h[-1]*phi[-1] - h[1]*phi[1])*(zr + h[1] - zl - h[-1])/(4.*sq(Delta));
335 if (l > 0) {
336 scalar hb = hl[l-1], phib = phil[l-1];
337 d[l] -= h[]*(hb[-1]*phib[-1] - hb[1]*phib[1])*(zr - zl)/(4.*sq(Delta));
338 }
339#endif
340
341
342 a[l] -= gammap[l]*h[]*(ar[l] - al[l])/Delta;
343 b[l] -= gammap[l]*h[]*(br[l][0] - bl[l][1])/Delta;
344 c[l] -= gammap[l]*h[]*(cr[l] - cl[l])/Delta;
345 scalar phib = l > 0 ? phil[l-1] : phi;
346 scalar phit = l < nl - 1 ? phil[l+1] : phi;
347 d[l] += gammap[l]*h[]*
348 ((ar[l]*phib[1] + br[l][1]*phi[1] + cr[l]*phit[1]) -
349 (al[l]*phib[-1] + bl[l][0]*phi[-1] + cl[l]*phit[-1]))/Delta;
350 l++, zr += h[1], zl += h[-1];
351 }
352}
353
355 double * a, double * b, double * c, double * d)
356{
357 int l = 0;
358 scalar phi, rhs, h;
359 double zl = zb[-1], zc = zb[], zr = zb[1];
360 for (phi,rhs,h in phil,rhsl,hl) {
361 d[l] = rhs[];
362#if 0 // h\partial_x(h\partial_x\phi), case (bbb)
363 for (int _d = 0; _d < dimension; _d++)
364 d[l] -= gammap[l]*h[]*((h[] + h[-1])*phi[-1] +
365 (h[] + h[1])*phi[1])/(2.*sq(Delta));
366#else // h\partial_x\partial_x(h\phi), case (aaa)
367 for (int _d = 0; _d < dimension; _d++)
368 d[l] -= gammap[l]*h[]*(h[-1]*phi[-1] + h[1]*phi[1])/sq(Delta);
369#endif
370
371 c[l] = alpha[l];
372 if (l == 0)
373 a[l] = 0.; // bottom BC (Neumann)
374 else
375 a[l] = alpha[l-1];
376#if 0 // \partial_x(h\partial_x\phi), case (bbb)
377 // fixme: 1D only
378 b[l] = - a[l] - c[l] - gammap[l]*h[]*(h[-1] + 2.*h[] + h[1])/(2.*sq(Delta));
379#else // h\partial_x\partial_x(h\phi), case (aaa)
380 b[l] = - a[l] - c[l] - gammap[l]*2.*dimension*sq(h[]/Delta);
381#endif
382 if (l == nl - 1) {
383 // top BC (Dirichlet)
384 if (l == 0)
385 b[l] -= (PHIT - 1.)*c[l]/3.;
386 else {
387 b[l] -= PHIT*c[l]/3.;
388 a[l] += c[l]/3.;
389 }
390 }
391#if 0
392 else {
393 /**
394 gammap[l]*h[]*(((h[] + h[1])*(phi[1] - phi[]) -
395 (h[] + h[-1])*(phi[] - phi[-1]))/(2.*sq(Delta))
396 - ((zr + h[1] - zc - h[])*(s[1] + s[]) -
397 (zr - zc)*(phi[] + phi[-1])
398 -
399 (zr + h[1] - zc - h[])*(s[1] + s[]) +
400 (zr - zc)*(phi[] + phi[-1]))/(2.*Delta));
401 */
402 b[l] += gammap[l]*h[]*(zr + h[1]/2. - 2.*(zc + h[]/2.) + zl + h[-1]/2.)/
403 Delta;
404 c[l] -= gammap[l]*h[]*(zr + h[1]/2. - 2.*(zc + h[]/2.) + zl + h[-1]/2.)/
405 Delta;
406 scalar s = phil[l+1];
407 d[l] += gammap[l]*h[]*((zr + h[1]/2. - zc - h[]/2.)*(s[1] - phi[1]) -
408 (zc + h[]/2. - zl - h[-1]/2.)*(s[-1] - phi[-1]))/
409 Delta;
410 }
411#else
412#endif
413 l++, zl += h[-1], zc += h[], zr += h[1];
414 }
415}
416
417trace
418static void relax_nh (scalar * phil, scalar * rhsl, int lev, void * data)
419{
420 for (int _i = 0; _i < lev; _i++) {
421 double a[nl], b[nl], c[nl], d[nl]; // the tridiagonal system
422 matrix (point, phil, rhsl, a, b, c, d);
423 // Thomas algorithm
424 for (int l = 1; l < nl; l++) {
425 b[l] -= a[l]*c[l-1]/b[l-1];
426 d[l] -= a[l]*d[l-1]/b[l-1];
427 }
428 scalar phi = phil[nl-1];
429 phi[] = a[nl-1] = d[nl-1]/b[nl-1];
430 for (int l = nl - 2; l >= 0; l--) {
431 phi = phil[l];
432 phi[] = a[l] = (d[l] - c[l]*a[l+1])/b[l];
433 }
434 }
435}
436
437static double residual_nh (scalar * phil, scalar * rhsl,
438 scalar * resl, void * data)
439{
440 const scalar phis = *((scalar *) data);
441 double maxres = 0.;
442 /* "naive" discretisation (only 1st order on trees) */
443 foreach (reduction(max:maxres)) {
444 double a[nl], b[nl], c[nl], d[nl]; // the tridiagonal system
445 matrix (point, phil, rhsl, a, b, c, d);
446 d[nl-1] -= 8.*alpha[nl-1]*phis[]/3.;
447 int l = 0;
448 scalar phi, res;
449 for (phi,res in phil,resl) {
450 res[] = d[l] - b[l]*phi[];
451 if (l > 0) {
452 scalar phim = phil[l-1];
453 res[] -= a[l]*phim[];
454 }
455 if (l < nl - 1) {
456 scalar phip = phil[l+1];
457 res[] -= c[l]*phip[];
458 }
459 if (fabs (res[]) > maxres)
460 maxres = fabs (res[]);
461 l++;
462 }
463 }
464 return maxres;
465}
466
467trace
468static void relax_nh1 (scalar * phil, scalar * rhsl, int lev, void * data)
469{
470 for (int _i = 0; _i < lev; _i++) {
471 double a[nl], b[nl], c[nl], d[nl]; // the tridiagonal system
472 int l = 0;
473 scalar phi, rhs, h;
474 for (phi,rhs,h in phil,rhsl,hl) {
475 d[l] = rhs[];
476 for (int _d = 0; _d < dimension; _d++)
477 d[l] -= gammap[l]*h[]*((h[] + h[-1])*phi[-1] +
478 (h[] + h[1])*phi[1])/(2.*sq(Delta));
479 c[l] = alpha[l];
480 if (l == 0)
481 a[l] = 0.; // bottom BC (Neumann)
482 else
483 a[l] = alpha[l-1];
484 // fixme: 1D only
485 b[l] = - a[l] - c[l] - gammap[l]*h[]*(h[-1] + 2.*h[] + h[1])/sq(Delta);
486 if (l == nl - 1) {
487 // top BC (Dirichlet)
488 if (l == 0)
489 b[l] -= (PHIT - 1.)*c[l]/3.;
490 else {
491 b[l] -= PHIT*c[l]/3.;
492 a[l] += c[l]/3.;
493 }
494 }
495 l++;
496 }
497 // Thomas algorithm
498 for (int l = 1; l < nl; l++) {
499 b[l] -= a[l]*c[l-1]/b[l-1];
500 d[l] -= a[l]*d[l-1]/b[l-1];
501 }
502 phi = phil[nl-1];
503 phi[] = a[nl-1] = d[nl-1]/b[nl-1];
504 for (int l = nl - 2; l >= 0; l--) {
505 phi = phil[l];
506 phi[] = a[l] = (d[l] - c[l]*a[l+1])/b[l];
507 }
508 }
509}
510
511static double residual_nh2 (scalar * phil, scalar * rhsl,
512 scalar * resl, void * data)
513{
514 double maxres = 0.;
515 foreach (reduction(max:maxres)) {
516 scalar phi, rhs, res, h;
517 int l = 0;
518 double zl = zb[-1], z = zb[], zr = zb[1];
519 for (phi,rhs,res,h in phil,rhsl,resl,hl) {
520 res[] = rhs[];
521 double phit, phib, hb, alphab;
522 if (l == 0) {
523#if 1
524 phib = phi[]; // bottom BC (Neumann)
525#else
526 phib = phi[] - h[]*(zb[1] - zb[-1])*(phi[1] - phi[-1])/sq(2.*Delta);
527#endif
528 hb = h[];
529 alphab = alpha[l];
530 }
531 else {
532 scalar phi = phil[l-1], h = hl[l-1];
533 phib = phi[];
534 hb = h[];
535 alphab = alpha[l-1];
536 }
537 if (l == nl - 1)
538#if 0
539 phit = ((2.*sq(h[])*phib - phi[]*sq(hb)
540 - 5.*h[]*phi[]*hb - 6.*sq(h[])*phi[])/
541 (sq(hb) + 3.*h[]*hb + 2.*sq(h[])));
542#else
543 phit = (phib - PHIT*phi[])/3.; // top BC (Dirichlet)
544#endif
545 else {
546 scalar s = phil[l+1];
547 phit = s[];
548#if 1 // not much effect
549 res[] += h[]*((s[1] - s[-1])*(zr + h[1] - zl - h[-1]) -
550 (phi[1] - phi[-1])*(zr - zl))/sq(2.*Delta);
551#endif
552#if 0
553 res[] += h[]*((zr + h[1]/2. - z - h[]/2.)*
554 (s[1] + s[] - phi[1] - phi[]) -
555 (z + h[]/2. - zl - h[-1]/2.)*
556 (s[] + s[-1] - phi[] - phi[-1]))/(2.*Delta);
557#endif
558 }
559 res[] -= alpha[l]*(phit - phi[]) - alphab*h[]*(phi[] - phib)/hb;
560#if 1 // almost no effect
561 for (int _d = 0; _d < dimension; _d++)
562 res[] += gammap[l]*h[]*((h[] + h[-1])*(phi[] - phi[-1]) -
563 (h[] + h[1])*(phi[1] - phi[]))/(2.*sq(Delta));
564#elif 0
565 for (int _d = 0; _d < dimension; _d++)
566 res[] += gammap[l]*sq(h[])*(face_gradient_x (phi, 0) -
568#else // almost no effect
569 for (int _d = 0; _d < dimension; _d++)
570 res[] += gammap[l]*h[]*(2.*h[]*phi[] - h[-1]*phi[-1] - h[1]*phi[1])/
571 sq(Delta);
572#endif
573 if (fabs (res[]) > maxres)
574 maxres = fabs (res[]);
575 l++, zl += h[-1], z += h[], zr += h[1];
576 }
577 }
578 return maxres;
579}
580
581static double residual_nh3 (scalar * phil, scalar * rhsl,
582 scalar * resl, void * data)
583{
584 double maxres = 0.;
585 foreach (reduction(max:maxres)) {
586 double a[nl], b[nl], c[nl], d[nl]; // the tridiagonal system
587 matrix (point, phil, rhsl, a, b, c, d);
588
589 scalar phi, rhs, res, h;
590 int l = 0;
591 for (phi,rhs,res,h in phil,rhsl,resl,hl) {
592 res[] = rhs[];
593 double phit, phib, hb, alphab;
594 if (l == 0) {
595 phib = phi[]; // bottom BC (Neumann)
596 hb = h[];
597 alphab = alpha[l];
598 }
599 else {
600 scalar phi = phil[l-1], h = hl[l-1];
601 phib = phi[];
602 hb = h[];
603 alphab = alpha[l-1];
604 }
605 if (l == nl - 1)
606 phit = (phib - PHIT*phi[])/3.; // top BC (Dirichlet)
607 else {
608 scalar s = phil[l+1];
609 phit = s[];
610 }
611 res[] -= alpha[l]*(phit - phi[]) - alphab*h[]*(phi[] - phib)/hb;
612 for (int _d = 0; _d < dimension; _d++)
613 res[] += gammap[l]*h[]*((h[] + h[-1])*(phi[] - phi[-1]) -
614 (h[] + h[1])*(phi[1] - phi[]))/(2.*sq(Delta));
615
616#if 0
617 double res2 = d[l] - b[l]*phi[];
618 if (l > 0) {
619 scalar phim = phil[l-1];
620 res2 -= a[l]*phim[];
621 }
622 if (l < nl - 1) {
623 scalar phip = phil[l+1];
624 res2 -= c[l]*phip[];
625 }
626
627 fprintf (stderr, "res: %d %g %g\n", l, res[], res2);
628#endif
629
630 if (fabs (res[]) > maxres)
631 maxres = fabs (res[]);
632 l++;
633 }
634 }
635 return maxres;
636}
637
639
640/** @brief Event: pressure (i++) */
641void event_pressure (void)
642{
644 for (int _i = 0; _i < _N; _i++) /* foreach */ {
645 scalar rhs, h, qz;
646 vector uf;
647 int l = 0;
648 double zl = zb[-1], zr = zb[1];
649 vector q;
650 for (rhs,h,qz,uf,q in rhsl,hl,qzl,ufl,ql) {
651 rhs[] = qz[] - h[]*(uf.x[] + uf.x[1])*(zr + h[1] - zl - h[-1])/(4.*Delta);
652 if (l > 0) {
653 scalar qzm = qzl[l-1], hm = hl[l-1];
654 rhs[] -= h[]*qzm[]/hm[];
655 vector ufm = ufl[l-1];
656 rhs[] += h[]*(ufm.x[] + ufm.x[1])*(zr - zl)/(4.*Delta);
657 }
658 for (int _d = 0; _d < dimension; _d++)
659 rhs[] += h[]*((h[] + h[1])*uf.x[1] - (h[] + h[-1])*uf.x[])/(2.*Delta);
660 rhs[] /= dt;
661 l++, zl += h[-1], zr += h[1];
662 }
663 }
664
665 restriction (hl);
667 nrelax = 4, res = NULL, minlevel = 1, tolerance = TOLERANCE);
668 delete (rhsl), free (rhsl);
669
670 for (int _i = 0; _i < _N; _i++) /* foreach_face */ {
671 double ac[nl], bc[nl][2], cc[nl];
672 coeffs1 (point, hl, ac, bc, cc);
673
674 scalar phi, h;
675 vector uf, a;
676 int l = 0;
677 for (phi,uf,a,h in phil,ufl,al,hl) {
678 scalar phit = l < nl - 1 ? phil[l+1] : phi;
679 scalar phib = l > 0 ? phil[l-1] : phi;
680 double ax = - fm.x[]*(ac[l]*phib[-1] + bc[l][0]*phi[-1] + cc[l]*phit[-1] +
681 ac[l]*phib[] + bc[l][1]*phi[] + cc[l]*phit[])/
682 ((h[] + h[-1])/2.);
683 uf.x[] -= dt*ax;
684 a.x[] -= ax;
685 l++;
686 }
687 }
688
689 correct_qz (dt, phit);
690}
691
692/** @brief Event: cleanup (i = end, last) */
693void event_cleanup (void) {
694 free (alpha), alpha = NULL;
695 free (gammap), gammap = NULL;
696 delete (qzl), free (qzl), qzl = NULL;
697 delete (phil), free (phil), phil = NULL;
698}
#define u
Definition advection.h:30
vector uf[]
We allocate the (face) velocity field.
Definition advection.h:29
scalar * tracers
Here we set the gradient functions for each tracer (as defined in the user-provided tracers list).
Definition hydro.h:60
vector q[]
The primitive variables are the momentum , pressure , density , (face) specific volume ,...
Definition all-mach.h:44
const vector a
Definition all-mach.h:59
scalar zb[]
Definition atmosphere.h:6
scalar h[]
Definition atmosphere.h:6
#define dimension
Definition bitree.h:3
scalar * list_clone(scalar *l)
define l
free(list1)
int x
Definition common.h:76
int z
Definition common.h:76
#define face_gradient_x(a, i)
Definition common.h:403
const scalar zeroc[]
Definition common.h:392
static number sq(number x)
Definition common.h:11
scalar * list_append(scalar *list, scalar s)
Definition common.h:188
const vector fm[]
Definition common.h:396
define sysmalloc malloc define syscalloc calloc define sysrealloc realloc define sysfree free define systrdup strdup define line calloc(n, s) @ define prealloc(p
#define assert(a)
Definition config.h:107
Point point
Definition conserving.h:86
double dt
scalar phi[]
The electric potential and the volume charge density are scalars while the permittivity and conductiv...
Definition implicit.h:34
scalar s
Definition embed-tree.h:56
double d[2]
Definition embed.h:383
scalar scalar coord coord double bc
Definition embed.h:378
define neighborp(k, l, o) neighbor(k
#define reset(...)
Definition grid.h:1388
vector beta[]
Definition hele-shaw.h:40
const vector lambda_b[]
Definition diffusion.h:136
const vector dut[]
Definition diffusion.h:136
const vector u_b[]
Definition diffusion.h:136
double nu
Definition diffusion.h:135
int nl
Definition layers.h:9
#define data(k, l)
Definition linear.h:26
size_t max
Definition mtrace.h:8
void(* restriction)(Point, scalar)
size *double * b
void vertical_viscosity(Point point, double h, vector *ul, double dt)
For stability, we discretise the viscous friction term implicitly as.
Definition multilayer.h:91
scalar * phil
void event_pressure(void)
Event: pressure (i++)
static void coeffs1(Point point, scalar *hl, double *a, double(*b)[2], double *c)
void correct_qz(double dt, const scalar phis)
static trace void relax_nh1(scalar *phil, scalar *rhsl, int lev, void *data)
static double residual_nh3(scalar *phil, scalar *rhsl, scalar *resl, void *data)
static void matrix(Point point, scalar *phil, scalar *rhsl, double *a, double *b, double *c, double *d)
static double residual_nh(scalar *phil, scalar *rhsl, scalar *resl, void *data)
void event_viscous_term(void)
Event: viscous_term (i++)
double * gammap
static void matrix1(Point point, scalar *phil, scalar *rhsl, double *a, double *b, double *c, double *d)
void event_cleanup(void)
Event: cleanup (i = end, last)
double * alpha
void event_defaults(void)
Event: defaults (i = 0)
#define PHIT
static trace void relax_nh(scalar *phil, scalar *rhsl, int lev, void *data)
scalar phit
static double residual_nh2(scalar *phil, scalar *rhsl, scalar *resl, void *data)
mgstats mgp
scalar * qzl
static void coeffs2(Point point, scalar *hl, double *a, double(*b)[2], double *c)
trace mgstats mg_solve(scalar *a, scalar *b, double(*residual)(scalar *a, scalar *b, scalar *res, void *data), void(*relax)(scalar *da, scalar *res, int depth, void *data), void *data=NULL, int nrelax=4, scalar *res=NULL, int minlevel=0, double tolerance=TOLERANCE)
The user needs to provide a function which computes the residual field (and returns its maximum) as w...
Definition poisson.h:130
double TOLERANCE
Definition poisson.h:107
def _i
Definition stencils.h:405
Definition linear.h:21
Information about the convergence of the solver is returned in a structure.
Definition poisson.h:112
scalar x
Definition common.h:47
double cr
Definition vof.h:60
double cc
Definition vof.h:60
scalar c
Definition vof.h:57
double cl
Definition vof.h:60