Peano
Loading...
Searching...
No Matches
navier_stokes_bubbles.py
Go to the documentation of this file.
1# This file is part of the ExaHyPE2 project. For conditions of distribution and
2# use, please see the copyright notice at www.peano-framework.org
3from .scenario import Scenario
4
5import os
6import sys
7
8sys.path.insert(0, os.path.abspath("../equations"))
9from equations import NavierStokes
10
11
13 """
14 Scenarios described in doi.org/10.1007/978-3-030-43229-4_27
15
16 Simulation of cloud formations via the compressible Navier-Stokes equations.
17 See the function 'mapQuantities' below for a note on the visualisation.
18 """
19
20 _dimensions = 2
21 _offset = 0.0
22 _domain_size = 1000.0
23 _periodic_bc = False
24 _plot_dt = 50.0
25 # _end_time = 600
26 _end_time = 100
27
28 # cv = 1 / (gamma - 1) * gasConstant
29 cv = 1 / (1.4 - 1) * 287.058
30 _equation = NavierStokes(
31 dimensions=2,
32 use_advection=False,
33 use_background_state=True,
34 use_gravity=True,
35 use_viscosity=True,
36 gamma=1.4,
37 cv=cv,
38 gas_constant=287.058,
39 reference_viscosity=0.01,
40 Pr=0.71,
41 )
42
43 _reference_pressure = 100000.0
44 _background_potential_temperature = 300.0
45
46 def __init__(self):
47 return
48
50 raise NotImplementedError("perturbation should be defined in child classes")
51
53 return """
54 const auto pressure = std::pow(
55 (1 - 1 / gamma) *
56 (std::pow(std::pow(gamma, gamma / (gamma - 1)) *
57 referencePressure,
58 (gamma - 1) / gamma) /
59 (gamma - 1) -
60 gravity * std::pow(referencePressure, gasConstant / cp) * x[DIMENSIONS-1] /
61 (gasConstant * backgroundPotentialTemperature)),
62 gamma / (gamma - 1)
63 );
64"""
65
67 return (
68 """
69
70 constexpr auto gamma = 1.4;
71 constexpr auto gasConstant = 287.058;
72 constexpr auto cp = gamma / (gamma - 1) * gasConstant;
73 constexpr auto referencePressure = """
75 + """;
76 constexpr auto backgroundPotentialTemperature = """
78 + """;
79 constexpr auto gravity = 9.81;
80 constexpr auto q0 = 0.0;
81
82 """
84 + """
85
86 auto potentialT = backgroundPotentialTemperature;
87 potentialT += perturbation;
88
89 std::fill_n(Q, NumberOfUnknowns+NumberOfAuxiliaryVariables, 0.0);
90
91 // First compute overall state """
93 + """
94 const auto temperature = potentialT *
95 std::pow((pressure / referencePressure), gasConstant / cp
96 );
97
98 auto rho = pressure / (gasConstant * temperature);
99 auto height = x[DIMENSIONS-1];
100 Q[Shortcuts::rho] = rho;
101 Q[Shortcuts::height] = height;
102
103 auto j = &Q[Shortcuts::j];
104 auto Z = perturbation;
105 """
106 + self._equation_equation.evaluate_energy()
107 + """
108
109 Q[Shortcuts::E] = E;
110
111 // Then compute background state (without pot.T. perturbation)
112 const auto backgroundTemperature = backgroundPotentialTemperature *
113 std::pow((pressure / referencePressure), gasConstant / cp
114 );
115 const auto backgroundRho = pressure / (gasConstant * backgroundTemperature);
116 Q[Shortcuts::backgroundstate+0] = backgroundRho;
117 Q[Shortcuts::backgroundstate+1] = pressure;
118"""
119 )
120
122 return (
123 """
124 constexpr auto gamma = 1.4;
125 constexpr auto gasConstant = 287.058;
126 constexpr auto cp = gamma / (gamma - 1) * gasConstant;
127 constexpr auto referencePressure = """
129 + """;
130 constexpr auto backgroundPotentialTemperature = """
132 + """;
133 constexpr auto gravity = 9.81;
134 constexpr auto q0 = 0.0;
135
136 std::copy_n(Qinside, NumberOfUnknowns+NumberOfAuxiliaryVariables, Qoutside);
137
138 // Normal velocity zero after Riemann.
139 Qoutside[Shortcuts::j+normal] = -Qinside[Shortcuts::j+normal];
140
141 // First compute overall state """
143 + """
144 const auto T = backgroundPotentialTemperature *
145 std::pow((pressure / referencePressure), gasConstant / cp);
146
147 auto rho = pressure / (gasConstant * T);
148 auto height = Qoutside[Shortcuts::height];
149 auto j = &Qoutside[Shortcuts::j];
150
151 Qoutside[Shortcuts::rho] = rho;
152 Qoutside[Shortcuts::backgroundstate+0] = Qoutside[Shortcuts::rho];
153 Qoutside[Shortcuts::backgroundstate+1] = pressure;
154
155 auto Z = 0.0;
156 """
157 + self._equation_equation.evaluate_energy()
158 + """
159 Qoutside[Shortcuts::E] = E;
160"""
161 )
162
163 # Currently unused, but serves as a mapping for visualization of the output quantities.
164 # Because of the high reference pressure and background potential temperature the
165 # the variation in the conservative variables (in particular the momenta and energy) is
166 # hard to see, but it is easier to see in the primitive form (velocities, but most of all
167 # in the perturbation of the background temperature)
168 def mapQuantities(self):
169 return (
170 """
171void tests::exahype2::aderdg::ADERDGSolver::mapQuantities(
172 [[maybe_unused]] const double* const NOALIAS Q, // Q[4+3]
173 [[maybe_unused]] double* const NOALIAS outputQuantities // Q[4+3]
174){
175 constexpr auto gamma = 1.4;
176 constexpr auto gasConstant = 287.058;
177 constexpr auto cp = gamma / (gamma - 1) * gasConstant;
178 constexpr auto referencePressure = """
180 + """;
181 constexpr auto gravity = 9.81;
182 constexpr auto q0 = 0.0;
183
184 const auto j = &Q[Shortcuts::j];
185 auto E = Q[Shortcuts::E];
186 auto rho = Q[Shortcuts::rho];
187 auto height = Q[Shortcuts::height];
188
189 const auto Z = 0.0;
190 """
191 + self._equation_equation.evaluate_pressure()
192 + """
193
194 outputQuantities[Shortcuts::rho] = rho;
195 outputQuantities[Shortcuts::j+0] = Q[Shortcuts::j+0]/rho;
196 outputQuantities[Shortcuts::j+1] = Q[Shortcuts::j+1]/rho;
197#if DIMENSIONS == 3
198 outputQuantities[Shortcuts::j+2] = Q[Shortcuts::j+2]/rho;
199#endif
200 outputQuantities[Shortcuts::E] = pressure;
201
202 const auto temperature = pressure/(gasConstant * rho);
203 const auto potT = temperature / std::pow((pressure / referencePressure), (gasConstant / cp));
204
205 outputQuantities[Shortcuts::height] = potT;
206}
207"""
208 )
209
210
212 """
213 Here we simulate a homogeneous domain containing a single spherical bubble
214 of higher temperature.
215 Due to the higher temperature the bubble will rise and diffuse outward.
216
217 The bubble is best visualised in the potential temperature
218 """
219
221 return """
222 // evaluate perturbation
223 tarch::la::Vector<DIMENSIONS, double> bubbleCenter = {
224 500, 350
225#if DIMENSIONS == 3
226 ,350
227#endif
228 };
229
230 constexpr double size = 250;
231 constexpr auto tempDifference = 0.5;
232
233 const auto dist = tarch::la::norm2(x-bubbleCenter);
234 auto perturbation = dist <= size ?
235 tempDifference / 2 * (1 + std::cos((std::numbers::pi * dist) / size))
236 : 0;
237"""
238
239
241 """
242 Here we simulate a homogeneous domain containing two bubbles, one of higher
243 temperature beneath the other of colder temperature.
244 Their repsective temperatures will cause the two bubbles to move towards one
245 another and collide, causing mixing effects.
246 """
247
249 return """
250 // evaluate perturbation
251 tarch::la::Vector<DIMENSIONS, double> hotBubbleCenter = {
252 500, 300
253#if DIMENSIONS == 3
254 ,300
255#endif
256 };
257
258 tarch::la::Vector<DIMENSIONS, double> coldBubbleCenter = {
259 560, 640
260#if DIMENSIONS == 3
261 ,640
262#endif
263 };
264
265 constexpr double decay = 50.;
266 constexpr double tempDifferenceHot = 0.5;
267 constexpr double tempDifferenceCold = -0.15;
268
269 const auto d1 = tarch::la::norm2(x-hotBubbleCenter) - 150; // Hot bubble has a radius of 150
270 auto perturbation = d1 <= 0 ? tempDifferenceHot
271 : tempDifferenceHot * std::exp(-(d1 * d1) / (decay * decay));
272
273 const auto d2 = tarch::la::norm2(x-coldBubbleCenter) - 0; // Cold bubble has a radius of 0
274 perturbation += tempDifferenceCold * std::exp(-(d2 * d2) / (decay * decay));
275"""
Scenarios described in doi.org/10.1007/978-3-030-43229-4_27.
Here we simulate a homogeneous domain containing a single spherical bubble of higher temperature.
Here we simulate a homogeneous domain containing two bubbles, one of higher temperature beneath the o...