Skip to content

Commit ab16066

Browse files
Add configurations for $Ra=10^6$ to Rayleigh-Benard project (#597)
* Added Ra=1e6 configs to RBC project * Added script for Nek5000 comparison * linting
1 parent 8278871 commit ab16066

5 files changed

Lines changed: 324 additions & 29 deletions

File tree

pySDC/projects/RayleighBenard/RBC3D_configs.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ def get_initial_condition(self, P, *args, restart_idx=0, **kwargs):
101101
outfile = FieldsIO.fromFile(self.get_file_name())
102102

103103
t0, solution = outfile.readField(restart_idx)
104+
solution = solution[: P.spectral.ncomponents, ...]
104105

105106
u0 = P.u_init
106107

@@ -182,6 +183,7 @@ def get_initial_condition(self, P, *args, restart_idx=0, **kwargs):
182183
filename = ic_config.get_file_name()
183184
ic_file = FieldsIO.fromFile(filename)
184185
t0, ics = ic_file.readField(-1)
186+
ics = ics[: P.spectral.ncomponents, ...]
185187
P.logger.info(f'Loaded initial conditions from {filename!r} at t={t0}.')
186188

187189
# interpolate the initial conditions using padded transforms
@@ -265,6 +267,7 @@ def get_description(self, *args, res=-1, dt=-1, **kwargs):
265267
return desc
266268

267269

270+
# --- Ra 1e5 ---
268271
class RBC3DG4R4SDC22Ra1e5(RBC3DM2K2):
269272
Tend = 200
270273
dt = 4e-2
@@ -305,3 +308,36 @@ class RBC3DG4R4EulerRa1e5(RBC3DverificationEuler):
305308
dt = 8e-2
306309
res = 32
307310
converged = 50
311+
312+
313+
# --- Ra 1e6 ---
314+
class RBC3DG4R4SDC44Ra1e6(RBC3DM4K4):
315+
Tend = 75
316+
dt = 2e-2
317+
res = 64
318+
# converged = 22
319+
ic_config = {'config': RBC3DG4R4SDC34Ra1e5, 'res': 32, 'dt': 0.02}
320+
321+
322+
class RBC3DG4R4SDC23Ra1e6(RBC3DM2K3):
323+
Tend = 75
324+
dt = 1e-2
325+
res = 64
326+
converged = 22
327+
ic_config = {'config': RBC3DG4R4SDC34Ra1e5, 'res': 32, 'dt': 0.02}
328+
329+
330+
class RBC3DG4R4RKRa1e6(RBC3DverificationRK):
331+
Tend = 75
332+
dt = 1e-2
333+
res = 64
334+
ic_config = {'config': RBC3DG4R4SDC34Ra1e5, 'res': 32, 'dt': 0.02}
335+
# converged = 22
336+
337+
338+
class RBC3DG4R4EulerRa1e6(RBC3DverificationEuler):
339+
Tend = 75
340+
dt = 1e-2
341+
res = 64
342+
ic_config = {'config': RBC3DG4R4SDC34Ra1e5, 'res': 32, 'dt': 0.02}
343+
# converged = 22
Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,32 @@
11
from pySDC.projects.RayleighBenard.analysis_scripts.process_RBC3D_data import get_pySDC_data
22
from pySDC.projects.RayleighBenard.analysis_scripts.plotting_utils import (
3-
figsize_by_journal,
43
get_plotting_style,
54
savefig,
5+
figsize,
66
)
77
import matplotlib.pyplot as plt
88

99

10-
def plot_spectrum(res, dt, config_name, ax): # pragma: no cover
10+
def plot_spectrum(res, dt, config_name, ax, **plotting_params): # pragma: no cover
1111
data = get_pySDC_data(res=res, dt=dt, config_name=config_name)
1212

1313
spectrum = data['avg_spectrum']
1414
k = data['k']
15-
ax.loglog(k[spectrum > 1e-16], spectrum[spectrum > 1e-16], **get_plotting_style(config_name), markevery=5)
15+
ax.loglog(
16+
k[spectrum > 1e-16],
17+
spectrum[spectrum > 1e-16],
18+
**{**get_plotting_style(config_name), **plotting_params},
19+
markevery=5,
20+
)
1621
ax.set_xlabel('$k$')
1722
ax.set_ylabel(r'$\|\hat{u}_x\|$')
1823

1924

2025
def plot_spectra_Ra1e5(): # pragma: no cover
21-
fig, ax = plt.subplots(figsize=figsize_by_journal('Nature_CS', 1, 0.6))
26+
fig, ax = plt.subplots(figsize=figsize(scale=1, ratio=0.6))
2227

23-
configs = [f'RBC3DG4R4{name}Ra1e5' for name in ['SDC34', 'SDC23', '', 'Euler', 'RK']]
24-
dts = [0.06, 0.06, 0.06, 0.02, 0.04]
28+
configs = [f'RBC3DG4R4{name}Ra1e5' for name in ['SDC23', 'SDC44', 'Euler', 'RK']]
29+
dts = [0.06, 0.06, 0.02, 0.04]
2530
res = 32
2631

2732
for config, dt in zip(configs, dts, strict=True):
@@ -31,7 +36,40 @@ def plot_spectra_Ra1e5(): # pragma: no cover
3136
savefig(fig, 'RBC3D_spectrum_Ra1e5')
3237

3338

39+
def plot_spectra_Ra1e6(): # pragma: no cover
40+
fig, ax = plt.subplots(figsize=figsize(scale=1, ratio=0.6))
41+
42+
configs = [f'RBC3DG4R4{name}Ra1e6' for name in ['SDC44', 'SDC23', 'RK']]
43+
dts = [0.01, 0.01, 0.01]
44+
res = 64
45+
46+
for config, dt in zip(configs, dts, strict=True):
47+
plot_spectrum(res, dt, config, ax)
48+
49+
ax.legend(frameon=False)
50+
savefig(fig, 'RBC3D_spectrum_Ra1e6')
51+
52+
53+
def plot_all_spectra(): # pragma: no cover
54+
fig, ax = plt.subplots(figsize=figsize(scale=1, ratio=0.6))
55+
56+
Ras = ['1e5', '1e6']
57+
dts = [0.06, 0.01]
58+
res = [32, 64]
59+
colors = ['tab:blue', 'tab:orange']
60+
markers = ['x', 'o']
61+
62+
for Ra, dt, _res, color, marker in zip(Ras, dts, res, colors, markers, strict=True):
63+
config = f'RBC3DG4R4SDC44Ra{Ra}'
64+
plot_spectrum(_res, dt, config, ax, label=f'$Ra$={Ra}', color=color, marker=marker)
65+
66+
ax.legend(frameon=False)
67+
savefig(fig, 'RBC3D_all_spectra')
68+
69+
3470
if __name__ == '__main__':
35-
plot_spectra_Ra1e5()
71+
# plot_spectra_Ra1e5()
72+
# plot_spectra_Ra1e6()
73+
plot_all_spectra()
3674

3775
plt.show()
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
"""
2+
This script plots macroscopic verification of simulation data via comparison with data from https://doi.org/10.5281/zenodo.14205874
3+
In order to run this script, you need to download the dataset and copy it to `pySDC/projects/RayleighBenard/data/Nek5000`.
4+
And, you need to have generated the pySDC simulation data, of course.
5+
"""
6+
7+
import numpy as np
8+
from scipy import integrate
9+
import matplotlib.pyplot as plt
10+
11+
ints = {'1e5': 1e5, '1e6': 1e6, '1e7': 1e7}
12+
13+
14+
def get_Nek5000_Data(Ra, base_path='data/Nek5000'): # pragma: no cover
15+
assert type(Ra) == str
16+
17+
# append relative path to base path
18+
path = __file__
19+
base_path = f'{path[::-1][path[::-1].index('/'):][::-1]}../{base_path}'
20+
Pr = 0.7
21+
22+
if Ra == '1e5':
23+
dir_name = '1_1e5'
24+
start_time = 3500
25+
nelZ = 64
26+
nPoly = 5
27+
elif Ra == '1e6':
28+
dir_name = '2_1e6'
29+
start_time = 3500
30+
nelZ = 64
31+
nPoly = 7
32+
elif Ra == '1e7':
33+
dir_name = '3_1e7'
34+
start_time = 3100
35+
nelZ = 64
36+
nPoly = 9
37+
elif Ra == '1e8':
38+
dir_name = '4_1e8'
39+
start_time = 3000
40+
nelZ = 96
41+
nPoly = 7
42+
elif Ra == '1e9':
43+
dir_name = '5_1e9'
44+
start_time = 4000
45+
nelZ = 96
46+
nPoly = 9
47+
elif Ra == '1e10':
48+
dir_name = '6_1e10'
49+
start_time = 1700
50+
nelZ = 200
51+
nPoly = 7
52+
elif Ra == '1e11':
53+
dir_name = '7_1e11'
54+
start_time = 260
55+
nelZ = 256
56+
nPoly = 7
57+
else:
58+
raise
59+
60+
path = f'{base_path}/{dir_name}'
61+
data = {}
62+
63+
visc = np.sqrt(Pr / ints[Ra])
64+
65+
# get averaged data
66+
avg = np.load(f'{path}/average.npy')
67+
avg_Nu = np.mean(avg[avg[:, 0] > start_time, 3])
68+
data['Nu'] = avg_Nu
69+
data['std_Nu'] = np.std(avg[avg[:, 0] > start_time, 3])
70+
71+
Re = np.sqrt(avg[:, 1]) / visc
72+
data['Re'] = np.mean(Re[avg[:, 0] > start_time])
73+
74+
# get profile data
75+
profiles = np.load(f'{path}/profile.npy')
76+
nzPts = nelZ * nPoly + 1
77+
nSnap = int(profiles.shape[0] / nzPts)
78+
tVal = profiles[:, 0].reshape((nSnap, nzPts))[:, 0]
79+
tInterval = tVal[-1] - tVal[0]
80+
81+
data['z'] = profiles[:nzPts, 1]
82+
data['profile_T'] = profiles[:, 3].reshape((nSnap, nzPts))
83+
84+
tRMS = profiles[:, 4].reshape((nSnap, nzPts))
85+
data['rms_profile_T'] = np.sqrt(integrate.simpson(tRMS**2, tVal, axis=0) / tInterval)
86+
87+
return data
88+
89+
90+
def get_pySDC_data(Ra):
91+
from pySDC.projects.RayleighBenard.analysis_scripts.process_RBC3D_data import get_pySDC_data as _get_data
92+
93+
dts = {'1e5': 0.06, '1e6': 0.02}
94+
res = {'1e5': 32, '1e6': 64}
95+
return _get_data(config_name=f'RBC3DG4R4SDC34Ra{Ra}', dt=dts[Ra], res=res[Ra])
96+
97+
98+
def plot_Nu_scaling(ax): # pragma: no cover
99+
100+
# reference values
101+
for Ra in ['1e5', '1e6']:
102+
dat = get_Nek5000_Data(Ra)
103+
ax.errorbar(ints[Ra], dat['Nu'], yerr=dat['std_Nu'], fmt='o', color='black')
104+
105+
# pySDC values
106+
for Ra in ['1e5', '1e6']:
107+
dat = get_pySDC_data(Ra)
108+
ax.errorbar(ints[Ra], dat['avg_Nu']['V'], yerr=dat['std_Nu']['V'], fmt='.', color='tab:blue')
109+
110+
ax.errorbar(None, None, fmt='o', color='black', label='Nek5000')
111+
ax.errorbar(None, None, fmt='.', color='tab:blue', label='pySDC')
112+
ax.legend(frameon=False, loc='lower right')
113+
114+
ax.set_xscale('log')
115+
ax.set_xlabel('$Ra$')
116+
ax.set_ylabel('$Nu$')
117+
118+
119+
def plot_T_profile(ax): # pragma: no cover
120+
colors = {'1e5': 'tab:blue', '1e6': 'tab:orange'}
121+
122+
# reference values
123+
for Ra in ['1e5', '1e6']:
124+
dat = get_Nek5000_Data(Ra)
125+
ax.plot(dat['profile_T'].mean(axis=0), dat['z'], color=colors[Ra], label=f'Nek5000 Ra={Ra}')
126+
127+
# pySDC values
128+
for Ra in ['1e5', '1e6']:
129+
dat = get_pySDC_data(Ra)
130+
ax.scatter(dat['profile_T'], dat['z'], color=colors[Ra], label=f'pySDC Ra={Ra}')
131+
132+
ax.set_ylabel('$z$')
133+
ax.set_xlabel('$T$')
134+
ax.legend()
135+
136+
137+
def plot_T_rms_profile(ax): # pragma: no cover
138+
colors = {'1e5': 'tab:blue', '1e6': 'tab:orange'}
139+
140+
# reference values
141+
for Ra in ['1e5', '1e6']:
142+
dat = get_Nek5000_Data(Ra)
143+
ax.plot(dat['rms_profile_T'], dat['z'], color=colors[Ra], label=f'Nek5000 Ra={Ra}')
144+
145+
# pySDC values
146+
for Ra in ['1e5', '1e6']:
147+
dat = get_pySDC_data(Ra)
148+
ax.scatter(dat['rms_profile_T'], dat['z'], color=colors[Ra], label=f'pySDC Ra={Ra}')
149+
150+
ax.set_ylabel('$z$')
151+
ax.set_xlabel('$T$')
152+
ax.legend()
153+
154+
155+
def plot_verification(): # pragma: no cover
156+
from pySDC.projects.RayleighBenard.analysis_scripts.plotting_utils import savefig, figsize
157+
158+
fig, axs = plt.subplots(1, 2, figsize=figsize(scale=1, ratio=0.5))
159+
plot_Nu_scaling(axs[0])
160+
plot_T_profile(axs[1])
161+
fig.tight_layout()
162+
fig.savefig('plots/verification.pdf')
163+
164+
165+
if __name__ == '__main__':
166+
plot_verification()
167+
plt.show()

0 commit comments

Comments
 (0)