Basilisk CFD
Adaptive Cartesian mesh PDE framework
Loading...
Searching...
No Matches
conservation.h
Go to the documentation of this file.
1/** @file conservation.h
2 */
3/**
4# Conservation of the volume of each layer
5
6This module enforces conservation of the volume of each layer using a
7spatially-constant, but varying in time, "upwelling" velocity within
8each layer which compensates any volume loss. This can be interpreted
9as a vertical volume/mass transfer between layers.
10
11This upwelling velocity is only applied when the thickness of a layer
12is larger than `hmin/10`. The value of `hmin` is typically that set in
13[entrainment.h](). */
14
15extern double * hmin;
16
17/**
18The domain considered needs to be simply-connected in order to avoid
19the transfer of mass between basins which are not connected. To
20enforce this we use the functions in [/src/tag.h](). */
21
22#include "tag.h"
23
24/**
25This stores the initial volume of each layer. */
26
27static struct {
28 double * sum;
30
31/** @brief Event: init (i = 0) */
32void event_init (void)
33{
34
35 /**
36 At initialisation we make sure that the domain is simply connected
37 by retaining only the largest "oceanic" basin. We first define an
38 indicator function which is zero on dry land and one in wet
39 areas. */
40
41 scalar d[];
42 for (int _i = 0; _i < _N; _i++) /* foreach */ {
43 double H = 0.;
45 H += h[];
46 d[] = H > dry;
47 }
48
49 /**
50 We remove cells which are only connected diagonally with their
51 neighbors. */
52
53 for (int _i = 0; _i < _N; _i++) /* foreach */
54 if ((d[] && !d[0,-1]) &&
55 ((d[-1,-1] && !d[-1]) || (d[1,-1] && !d[1])))
56 d[] = 0.;
57
58 /**
59 We only keep the largest basin. */
60
61 remove_droplets (d, -1);
62
63 /**
64 We "dry out" all the other basins. */
65
66 for (int _i = 0; _i < _N; _i++) /* foreach */
67 if (!d[]) {
69 h[] = 0.;
70 zb[] = HUGE;
71 }
72
73 /**
74 And finally we store the initial volume of each layer. */
75
76 Conservation.sum = malloc (nl*sizeof (double));
79}
80
81/**
82At each timestep... */
83
84/** @brief Event: viscous_term (i++) */
86{
88
89 /**
90 ... we compute the current volume of each layer and the area of
91 cells which are "thick enough". */
92
93 double area = 0., volume = 0.;
94 foreach (reduction(+:area) reduction(+:volume)) {
95 if (h[] > hmin[_layer]/10.)
96 area += dv();
97 volume += h[]*dv();
98 }
99
100 /**
101 The ratio of these two quantities gives the vertical displacement,
102 which is then applied in each cell which is "thick enough". */
103
104 assert (area > 0.);
105 double dh = (Conservation.sum[_layer] - volume)/area;
106 assert (dh > - hmin[_layer]/10.);
107 for (int _i = 0; _i < _N; _i++) /* foreach */
108 if (h[] > hmin[_layer]/10.)
109 h[] += dh;
110 }
111}
112
113/**
114We free memory at the end of the simulation to avoid memory leaks. */
115
116/** @brief Event: cleanup (t = end) */
117void event_cleanup (void)
118{
119 free (Conservation.sum);
120}
scalar zb[]
Definition atmosphere.h:6
scalar h[]
Definition atmosphere.h:6
free(list1)
int x
Definition common.h:76
#define HUGE
Definition common.h:6
#define dv()
Definition common.h:92
#define assert(a)
Definition config.h:107
double d[2]
Definition embed.h:383
double dry
Definition entrainment.h:30
double dh
Definition heights.h:331
static float area(const KdtRect rect)
Definition kdt.c:439
double * hmin
void event_init(void)
Event: init (i = 0)
void event_viscous_term(void)
At each timestep...
static struct @14 Conservation
The domain considered needs to be simply-connected in order to avoid the transfer of mass between bas...
void event_cleanup(void)
We free memory at the end of the simulation to avoid memory leaks.
double * sum
int nl
Definition layers.h:9
which uses a global _layer index *int _layer
Definition layers.h:15
#define foreach_layer()
def _i
Definition stencils.h:405
double sum
Definition utils.h:167
void remove_droplets(scalar f, int minsize=3, double threshold=1e-4, bool bubbles=false)
Definition tag.h:285
stats statsf(scalar f)
Definition utils.h:170