|
| 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 | + |
| 10 | +step_sizes = { |
| 11 | + 'RBC3DG4R4Ra1e5': [8e-2, 4e-2, 2e-2, 1e-2, 5e-3], |
| 12 | + 'RBC3DG4R4SDC23Ra1e5': [8e-2, 4e-2, 2e-2, 1e-2, 5e-3, 2.5e-3], |
| 13 | + 'RBC3DG4R4SDC34Ra1e5': [8e-2, 4e-2, 2e-2, 1e-2, 5e-3], |
| 14 | + 'RBC3DG4R4RKRa1e5': [8e-2, 4e-2, 2e-2, 1e-2, 5e-3, 2.5e-3], |
| 15 | + # 'RBC3DG4R4EulerRa1e5': [8e-2, 4e-2, 2e-2, 1e-2, 5e-3], |
| 16 | + 'RBC3DG4R4EulerRa1e5': [1e-3 * 2**i for i in range(5)], |
| 17 | +} |
| 18 | +n_freefall_times = {} |
| 19 | + |
| 20 | + |
| 21 | +def no_logging_hook(*args, **kwargs): |
| 22 | + return None |
| 23 | + |
| 24 | + |
| 25 | +def get_path(args): |
| 26 | + config = get_config(args) |
| 27 | + fname = config.get_file_name() |
| 28 | + return f'{fname[:fname.index('dt')]}order.pickle' |
| 29 | + |
| 30 | + |
| 31 | +def compute_errors(args, dts, Tend): |
| 32 | + errors = {'u': [], 'v': [], 'w': [], 'T': [], 'p': [], 'dt': []} |
| 33 | + prob = RayleighBenard3D(nx=4, ny=4, nz=4) |
| 34 | + |
| 35 | + dts = np.sort(dts)[::-1] |
| 36 | + ref = run(args, dts[-1], Tend) |
| 37 | + for dt in dts[:-1]: |
| 38 | + u = run(args, dt, Tend) |
| 39 | + e = u - ref |
| 40 | + for comp in ['u', 'v', 'w', 'T', 'p']: |
| 41 | + i = prob.index(comp) |
| 42 | + e_comp = np.max(np.abs(e[i])) |
| 43 | + e_comp = MPI.COMM_WORLD.allreduce(e_comp, op=MPI.MAX) |
| 44 | + errors[comp].append(e_comp) |
| 45 | + errors['dt'].append(dt) |
| 46 | + |
| 47 | + path = get_path(args) |
| 48 | + if MPI.COMM_WORLD.rank == 0: |
| 49 | + with open(path, 'wb') as file: |
| 50 | + pickle.dump(errors, file) |
| 51 | + print(f'Saved errors to {path}', flush=True) |
| 52 | + |
| 53 | + |
| 54 | +def plot_error_all_components(args): |
| 55 | + fig, ax = plt.subplots() |
| 56 | + with open(get_path(args), 'rb') as file: |
| 57 | + errors = pickle.load(file) |
| 58 | + |
| 59 | + for comp in ['u', 'v', 'w', 'T', 'p']: |
| 60 | + e = np.array(errors[comp]) |
| 61 | + dt = np.array(errors['dt']) |
| 62 | + order = np.log(e[1:] / e[:-1]) / np.log(dt[1:] / dt[:-1]) |
| 63 | + ax.loglog(errors['dt'], errors[comp], label=f'{comp} order {np.mean(order):.1f}') |
| 64 | + |
| 65 | + ax.loglog(errors['dt'], np.array(errors['dt']) ** 4, label='Order 4', ls='--') |
| 66 | + ax.loglog(errors['dt'], np.array(errors['dt']) ** 2, label='Order 2', ls='--') |
| 67 | + ax.legend() |
| 68 | + ax.set_xlabel(r'$\Delta t$') |
| 69 | + ax.set_ylabel(r'$e$') |
| 70 | + |
| 71 | + |
| 72 | +def compare_order(Ra): |
| 73 | + fig, ax = plt.subplots() |
| 74 | + ls = {'SDC': '-', 'RK': '--', 'Euler': '-.'} |
| 75 | + if Ra == 1e5: |
| 76 | + paths = [f'./data/RBC3DG4R4{me}Ra1e5-res-1-order.pickle' for me in ['', 'RK', 'Euler', 'SDC23']] |
| 77 | + labels = ['SDC', 'RK', 'Euler', 'SDC'] |
| 78 | + |
| 79 | + else: |
| 80 | + raise NotImplementedError |
| 81 | + |
| 82 | + for path, label in zip(paths, labels, strict=True): |
| 83 | + with open(path, 'rb') as file: |
| 84 | + errors = pickle.load(file) |
| 85 | + |
| 86 | + e = np.array(errors['T']) |
| 87 | + dt = np.array(errors['dt']) |
| 88 | + order = np.log(e[1:] / e[:-1]) / np.log(dt[1:] / dt[:-1]) |
| 89 | + ax.loglog(dt, e, label=f'{label} order {np.mean(order):.1f}', ls=ls[label]) |
| 90 | + |
| 91 | + ax.legend(frameon=False) |
| 92 | + ax.set_xlabel(r'$\Delta t$') |
| 93 | + ax.set_ylabel(r'$e$') |
| 94 | + |
| 95 | + |
| 96 | +def run(args, dt, Tend): |
| 97 | + from pySDC.projects.GPU.run_experiment import run_experiment |
| 98 | + from pySDC.core.errors import ConvergenceError |
| 99 | + |
| 100 | + args['mode'] = 'run' |
| 101 | + args['dt'] = dt |
| 102 | + |
| 103 | + config = get_config(args) |
| 104 | + config.Tend = n_freefall_times.get(type(config).__name__, 3) |
| 105 | + |
| 106 | + ic_config_name = type(config).__name__ |
| 107 | + for name in ['RK', 'Euler', 'O3', 'O4', 'SDC23', 'SDC34']: |
| 108 | + ic_config_name = ic_config_name.replace(name, '') |
| 109 | + ic_config = get_config({**args, 'config': ic_config_name}) |
| 110 | + config.ic_config['config'] = type(ic_config) |
| 111 | + config.ic_config['res'] = ic_config.res |
| 112 | + config.ic_config['dt'] = ic_config.dt |
| 113 | + |
| 114 | + config.get_LogToFile = no_logging_hook |
| 115 | + config.Tend = Tend |
| 116 | + |
| 117 | + u = run_experiment(args, config) |
| 118 | + return u |
| 119 | + |
| 120 | + |
| 121 | +if __name__ == '__main__': |
| 122 | + from pySDC.projects.GPU.run_experiment import parse_args |
| 123 | + |
| 124 | + args = parse_args() |
| 125 | + config = get_config(args) |
| 126 | + |
| 127 | + dts = step_sizes[type(config).__name__] |
| 128 | + if args['mode'] == 'run': |
| 129 | + compute_errors(args, dts, max(dts)) |
| 130 | + |
| 131 | + plot_error_all_components(args) |
| 132 | + compare_order(1e5) |
| 133 | + if MPI.COMM_WORLD.rank == 0: |
| 134 | + plt.show() |
0 commit comments