Skip to content

Commit 0dbc979

Browse files
brownbaerchenThomas Baumann
andauthored
More plots for the RBC paper (#594)
* Added order script * Fixes * Fixed plotting * Fixed recording * Added order plot for 3D RBC * Added spectrum plot * Refactor * Refactor --------- Co-authored-by: Thomas Baumann <[email protected]>
1 parent 1ba41c3 commit 0dbc979

File tree

7 files changed

+278
-11
lines changed

7 files changed

+278
-11
lines changed
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
import os
2+
import pickle
3+
import numpy as np
4+
from pySDC.helpers.fieldsIO import FieldsIO
5+
from pySDC.projects.GPU.configs.base_config import get_config
6+
from pySDC.implementations.problem_classes.RayleighBenard3D import RayleighBenard3D
7+
from mpi4py import MPI
8+
import matplotlib.pyplot as plt
9+
from pySDC.helpers.plot_helper import figsize_by_journal
10+
from pySDC.projects.GPU.analysis_scripts.RBC3D_plotting_utils import get_plotting_style, savefig
11+
12+
step_sizes = {
13+
'RBC3DG4R4Ra1e5': [8e-2, 4e-2, 2e-2, 1e-2, 5e-3],
14+
'RBC3DG4R4SDC23Ra1e5': [5e-3 * 2**i for i in range(8)],
15+
'RBC3DG4R4SDC34Ra1e5': [5e-3 * 2**i for i in range(8)],
16+
'RBC3DG4R4SDC44Ra1e5': [5e-3 * 2**i for i in range(8)],
17+
'RBC3DG4R4RKRa1e5': [5e-3 * 2**i for i in range(8)],
18+
'RBC3DG4R4EulerRa1e5': [5e-3 * 2**i for i in range(8)],
19+
}
20+
n_freefall_times = {}
21+
22+
23+
def no_logging_hook(*args, **kwargs):
24+
return None
25+
26+
27+
def get_path(args):
28+
config = get_config(args)
29+
fname = config.get_file_name()
30+
return f'{fname[:fname.index('dt')]}order.pickle'
31+
32+
33+
def compute_errors(args, dts, Tend):
34+
errors = {'u': [], 'v': [], 'w': [], 'T': [], 'p': [], 'dt': []}
35+
prob = RayleighBenard3D(nx=4, ny=4, nz=4, comm=MPI.COMM_SELF)
36+
37+
dts = np.sort(dts)[::-1]
38+
ref = run(args, dts[-1], Tend)
39+
for dt in dts[:-1]:
40+
u = run(args, dt, Tend)
41+
e = u - ref
42+
for comp in ['u', 'v', 'w', 'T', 'p']:
43+
i = prob.index(comp)
44+
e_comp = np.max(np.abs(e[i])) / np.max(np.abs(ref[i]))
45+
e_comp = MPI.COMM_WORLD.allreduce(e_comp, op=MPI.MAX)
46+
errors[comp].append(float(e_comp))
47+
errors['dt'].append(dt)
48+
49+
path = get_path(args)
50+
if MPI.COMM_WORLD.rank == 0:
51+
with open(path, 'wb') as file:
52+
pickle.dump(errors, file)
53+
print(f'Saved errors to {path}', flush=True)
54+
55+
56+
def plot_error_all_components(args): # pragma: no cover
57+
fig, ax = plt.subplots()
58+
with open(get_path(args), 'rb') as file:
59+
errors = pickle.load(file)
60+
61+
for comp in ['u', 'v', 'w', 'T', 'p']:
62+
e = np.array(errors[comp])
63+
dt = np.array(errors['dt'])
64+
order = np.log(e[1:] / e[:-1]) / np.log(dt[1:] / dt[:-1])
65+
ax.loglog(errors['dt'], errors[comp], label=f'{comp} order {np.mean(order):.1f}')
66+
67+
ax.loglog(errors['dt'], np.array(errors['dt']) ** 4, label='Order 4', ls='--')
68+
ax.loglog(errors['dt'], np.array(errors['dt']) ** 2, label='Order 2', ls='--')
69+
ax.legend()
70+
ax.set_xlabel(r'$\Delta t$')
71+
ax.set_ylabel(r'$e$')
72+
73+
74+
def compare_order(Ra): # pragma: no cover
75+
fig, ax = plt.subplots(figsize=figsize_by_journal('Nature_CS', 1, 0.6))
76+
if Ra == 1e5:
77+
names = ['RK', 'Euler', 'SDC23', 'SDC34', 'SDC44'][::-1]
78+
configs = [f'RBC3DG4R4{me}Ra1e5' for me in names]
79+
paths = [f'./data/RBC3DG4R4{me}Ra1e5-res-1-order.pickle' for me in names]
80+
81+
else:
82+
raise NotImplementedError
83+
84+
for path, config in zip(paths, configs, strict=True):
85+
with open(path, 'rb') as file:
86+
errors = pickle.load(file)
87+
88+
e = np.array(errors['T'])
89+
dt = np.array(errors['dt'])
90+
order = np.log(e[1:] / e[:-1]) / np.log(dt[1:] / dt[:-1])
91+
print(f'{config}: order: mean={np.mean(order):.1f} / median={np.median(order):.1f}')
92+
ax.loglog(dt, e, **get_plotting_style(config))
93+
94+
for _dt in dt:
95+
for i in [1, 3, 4]:
96+
ax.text(_dt, _dt**i, i, fontweight='bold', fontsize=14, ha='center', va='center')
97+
ax.loglog(dt, dt**i, ls=':', color='black')
98+
99+
ax.legend(frameon=False)
100+
ax.set_xlabel(r'$\Delta t$')
101+
ax.set_ylabel(r'$e$')
102+
savefig(fig, 'RBC3D_order_Ra1e5')
103+
104+
105+
def run(args, dt, Tend):
106+
from pySDC.projects.GPU.run_experiment import run_experiment
107+
from pySDC.core.errors import ConvergenceError
108+
109+
args['mode'] = 'run'
110+
args['dt'] = dt
111+
112+
config = get_config(args)
113+
config.Tend = n_freefall_times.get(type(config).__name__, 3)
114+
115+
desc = config.get_description(res=args['res'])
116+
prob = desc['problem_class'](**desc['problem_params'])
117+
118+
ic_config_name = type(config).__name__
119+
for name in ['RK', 'Euler', 'O3', 'O4', 'SDC23', 'SDC34', 'SDC44']:
120+
ic_config_name = ic_config_name.replace(name, 'SDC34')
121+
122+
ic_config = get_config({**args, 'config': ic_config_name})
123+
config.ic_config['config'] = type(ic_config)
124+
config.ic_config['res'] = ic_config.res
125+
config.ic_config['dt'] = ic_config.dt
126+
127+
config.get_LogToFile = no_logging_hook
128+
config.Tend = Tend
129+
130+
u_hat = run_experiment(args, config)
131+
u = prob.itransform(u_hat)
132+
133+
return u
134+
135+
136+
if __name__ == '__main__':
137+
from pySDC.projects.GPU.run_experiment import parse_args
138+
139+
args = parse_args()
140+
141+
if args['mode'] == 'run':
142+
config = get_config(args)
143+
dts = step_sizes[type(config).__name__]
144+
compute_errors(args, dts, max(dts))
145+
146+
if args['config'] is not None:
147+
plot_error_all_components(args)
148+
149+
compare_order(1e5)
150+
if MPI.COMM_WORLD.rank == 0:
151+
plt.show()
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from pySDC.helpers.plot_helper import figsize_by_journal, setup_mpl
2+
import warnings
3+
4+
setup_mpl()
5+
6+
7+
def get_plotting_style(config): # pragma: no cover
8+
9+
args = {'color': None, 'ls': None, 'marker': None, 'markersize': 6, 'label': None}
10+
11+
if config == 'RBC3DG4R4SDC23Ra1e5':
12+
args['color'] = 'tab:blue'
13+
args['ls'] = '-'
14+
args['marker'] = 'o'
15+
args['label'] = 'SDC23'
16+
elif config == 'RBC3DG4R4SDC34Ra1e5':
17+
args['color'] = 'tab:orange'
18+
args['ls'] = '-'
19+
args['marker'] = '<'
20+
args['label'] = 'SDC34'
21+
elif config in ['RBC3DG4R4SDC44Ra1e5', 'RBC3DG4R4Ra1e5']:
22+
args['color'] = 'tab:green'
23+
args['ls'] = '-'
24+
args['marker'] = 'x'
25+
args['label'] = 'SDC44'
26+
elif config == 'RBC3DG4R4EulerRa1e5':
27+
args['color'] = 'tab:purple'
28+
args['ls'] = '--'
29+
args['marker'] = '.'
30+
args['label'] = 'Euler'
31+
elif config == 'RBC3DG4R4RKRa1e5':
32+
args['color'] = 'tab:red'
33+
args['ls'] = '--'
34+
args['marker'] = '>'
35+
args['label'] = 'RK444'
36+
else:
37+
warnings.warn(f'No plotting style for {config=!r}')
38+
39+
return args
40+
41+
42+
def savefig(fig, name, format='pdf', base_path='./plots', **kwargs): # pragma: no cover
43+
path = f'{base_path}/{name}.{format}'
44+
fig.savefig(path, bbox_inches='tight', **kwargs)
45+
print(f'Saved figure {path!r}')
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from pySDC.projects.GPU.analysis_scripts.process_RBC3D_data import get_pySDC_data
2+
from pySDC.projects.GPU.analysis_scripts.RBC3D_plotting_utils import figsize_by_journal, get_plotting_style, savefig
3+
import matplotlib.pyplot as plt
4+
5+
6+
def plot_spectrum(res, dt, config_name, ax): # pragma: no cover
7+
data = get_pySDC_data(res=res, dt=dt, config_name=config_name)
8+
9+
spectrum = data['avg_spectrum']
10+
k = data['k']
11+
ax.loglog(k[spectrum > 1e-16], spectrum[spectrum > 1e-16], **get_plotting_style(config_name), markevery=5)
12+
ax.set_xlabel('$k$')
13+
ax.set_ylabel(r'$\|\hat{u}_x\|$')
14+
15+
16+
def plot_spectra_Ra1e5(): # pragma: no cover
17+
fig, ax = plt.subplots(figsize=figsize_by_journal('Nature_CS', 1, 0.6))
18+
19+
configs = [f'RBC3DG4R4{name}Ra1e5' for name in ['SDC34', 'SDC23', '', 'Euler', 'RK']]
20+
dts = [0.06, 0.06, 0.06, 0.02, 0.04]
21+
res = 32
22+
23+
for config, dt in zip(configs, dts, strict=True):
24+
plot_spectrum(res, dt, config, ax)
25+
26+
ax.legend(frameon=False)
27+
savefig(fig, 'RBC3D_spectrum_Ra1e5')
28+
29+
30+
if __name__ == '__main__':
31+
plot_spectra_Ra1e5()
32+
33+
plt.show()

pySDC/projects/GPU/analysis_scripts/plot_Nu.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,11 @@
33
import numpy as np
44
from scipy import integrate
55
from pySDC.helpers.plot_helper import figsize_by_journal, setup_mpl
6+
from pySDC.projects.GPU.analysis_scripts.process_RBC3D_data import get_pySDC_data
67

78
setup_mpl()
89

910

10-
def get_pySDC_data(res=-1, dt=-1, config_name='RBC3DG4', base_path='data/RBC_time_averaged'):
11-
path = f'{base_path}/{config_name}-res{res}-dt{dt:.0e}.pickle'
12-
with open(path, 'rb') as file:
13-
data = pickle.load(file)
14-
15-
return data
16-
17-
1811
def interpolate_NuV_to_reference_times(data, reference_data, order=12):
1912
from qmat.lagrange import getSparseInterpolationMatrix
2013

pySDC/projects/GPU/analysis_scripts/process_RBC3D_data.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,5 +204,13 @@ def process_RBC3D_data(base_path='./data/RBC_time_averaged', plot=True, args=Non
204204
return path
205205

206206

207+
def get_pySDC_data(res=-1, dt=-1, config_name='RBC3DG4', base_path='data/RBC_time_averaged'):
208+
path = f'{base_path}/{config_name}-res{res}-dt{dt:.0e}.pickle'
209+
with open(path, 'rb') as file:
210+
data = pickle.load(file)
211+
212+
return data
213+
214+
207215
if __name__ == '__main__':
208216
process_RBC3D_data()

pySDC/projects/GPU/configs/RBC3D_configs.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,15 @@ def get_description(self, *args, **kwargs):
221221
return desc
222222

223223

224+
class RBC3DM4K4(RBC3Dverification):
225+
226+
def get_description(self, *args, **kwargs):
227+
desc = super().get_description(*args, **kwargs)
228+
desc['level_params']['nsweeps'] = 4
229+
desc['sweeper_params']['num_nodes'] = 4
230+
return desc
231+
232+
224233
class RBC3DverificationRK(RBC3Dverification):
225234

226235
def get_description(self, *args, res=-1, dt=-1, **kwargs):
@@ -268,6 +277,13 @@ class RBC3DG4R4SDC34Ra1e5(RBC3DM3K4):
268277
converged = 50
269278

270279

280+
class RBC3DG4R4SDC44Ra1e5(RBC3DM4K4):
281+
Tend = 200
282+
dt = 6e-2
283+
res = 32
284+
converged = 50
285+
286+
271287
class RBC3DG4R4RKRa1e5(RBC3DverificationRK):
272288
Tend = 200
273289
dt = 8e-2

pySDC/projects/GPU/tests/test_RBC_3D_analysis.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ def get_config(args):
2626
return config
2727

2828

29-
def generate_simulation_file(path):
29+
def generate_simulation_file(path, args=None):
3030
from pySDC.projects.GPU.run_experiment import run_experiment
3131

32-
args = get_args(path)
32+
args = {**get_args(path), **args} if args is not None else get_args(path)
3333
config = get_config(args)
3434

3535
run_experiment(args, config)
@@ -80,7 +80,7 @@ def test_processing(tmp_processed_data):
8080

8181

8282
def test_get_pySDC_data(tmp_processed_data, tmp_path):
83-
from pySDC.projects.GPU.analysis_scripts.plot_Nu import get_pySDC_data
83+
from pySDC.projects.GPU.analysis_scripts.process_RBC3D_data import get_pySDC_data
8484

8585
args = get_args(tmp_path)
8686
data = get_pySDC_data(res=args['res'], dt=args['dt'], config_name=args['config'], base_path=tmp_path)
@@ -112,3 +112,24 @@ def _get_Nu(_t):
112112
tI, NuI = interpolate_NuV_to_reference_times(data, ref_data, order=4)
113113
assert not np.allclose(NuI, ref_data['Nu']['V'])
114114
assert np.allclose(tI, ref_data['t'])
115+
116+
117+
def test_error_computation(tmp_sim_data, tmp_path):
118+
from pySDC.projects.GPU.analysis_scripts.RBC3D_order import compute_errors, get_path
119+
from pySDC.projects.GPU.configs.RBC3D_configs import RBC3DG4R4SDC34Ra1e5
120+
import numpy as np
121+
import pickle
122+
123+
args = get_args(tmp_path)
124+
125+
generate_simulation_file(tmp_path, args={'config': args['config'].replace('SDC23', 'SDC34')})
126+
RBC3DG4R4SDC34Ra1e5.res = args['res']
127+
RBC3DG4R4SDC34Ra1e5.dt = args['dt']
128+
129+
dts = [1e-2, 5e-4]
130+
compute_errors(args, dts, np.max(dts))
131+
132+
with open(get_path(args), 'rb') as file:
133+
errors = pickle.load(file)
134+
for comp in ['T', 'p']:
135+
assert max(errors[comp]) < 1e-12

0 commit comments

Comments
 (0)