From 6cc8839c15f6d2912de1be377b0f5a3bf3fcb25a Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 15:39:23 -0400 Subject: [PATCH 01/50] Start a utils module for stuff from the output preservation test that I want to reuse in the driver. --- aronnax/utils.py | 14 ++++++++++++++ benchmarks/benchmark.py | 9 +++++---- benchmarks/profile.py | 5 +++-- test/output_preservation_test.py | 12 +----------- 4 files changed, 23 insertions(+), 17 deletions(-) create mode 100644 aronnax/utils.py diff --git a/aronnax/utils.py b/aronnax/utils.py new file mode 100644 index 00000000..ec3c78df --- /dev/null +++ b/aronnax/utils.py @@ -0,0 +1,14 @@ +from contextlib import contextmanager +import os +import subprocess as sub + +@contextmanager +def working_directory(path): + old_path = os.getcwd() + sub.check_call(["mkdir", "-p", path]) + os.chdir(path) + try: + yield + finally: + os.chdir(old_path) + diff --git a/benchmarks/benchmark.py b/benchmarks/benchmark.py index ceea7aef..5b17c3eb 100644 --- a/benchmarks/benchmark.py +++ b/benchmarks/benchmark.py @@ -13,6 +13,7 @@ import sys sys.path.append(p.join(root_path, 'test')) import output_preservation_test as opt +from aronnax.utils import working_directory n_time_steps = 502.0 scale_factor = 1000 / n_time_steps # Show times in ms @@ -21,7 +22,7 @@ def benchmark_gaussian_bump_red_grav_save(grid_points): run_time_O1 = np.zeros(len(grid_points)) run_time_Ofast = np.zeros(len(grid_points)) - with opt.working_directory(p.join(self_path, "beta_plane_bump_red_grav")): + with working_directory(p.join(self_path, "beta_plane_bump_red_grav")): aro_exec = "aronnax_test" for counter, nx in enumerate(grid_points): run_time_O1[counter] = opt.run_experiment( @@ -36,7 +37,7 @@ def benchmark_gaussian_bump_red_grav_save(grid_points): pkl.dump((grid_points, run_time_O1, run_time_Ofast), f) def benchmark_gaussian_bump_red_grav_plot(): - with opt.working_directory(p.join(self_path, "beta_plane_bump_red_grav")): + with working_directory(p.join(self_path, "beta_plane_bump_red_grav")): with open("times.pkl", "r") as f: (grid_points, run_time_O1, run_time_Ofast) = pkl.load(f) @@ -65,7 +66,7 @@ def benchmark_gaussian_bump_save(grid_points): run_time_O1 = np.zeros(len(grid_points)) run_time_Ofast = np.zeros(len(grid_points)) - with opt.working_directory(p.join(self_path, "beta_plane_bump")): + with working_directory(p.join(self_path, "beta_plane_bump")): aro_exec = "aronnax_test" for counter, nx in enumerate(grid_points): run_time_O1[counter] = opt.run_experiment( @@ -78,7 +79,7 @@ def benchmark_gaussian_bump_save(grid_points): pkl.dump((grid_points, run_time_O1, run_time_Ofast), f) def benchmark_gaussian_bump_plot(): - with opt.working_directory(p.join(self_path, "beta_plane_bump")): + with working_directory(p.join(self_path, "beta_plane_bump")): with open("times.pkl", "r") as f: (grid_points, run_time_O1, run_time_Ofast) = pkl.load(f) diff --git a/benchmarks/profile.py b/benchmarks/profile.py index f6d3808d..34d786d0 100644 --- a/benchmarks/profile.py +++ b/benchmarks/profile.py @@ -6,14 +6,15 @@ import sys sys.path.append(p.join(root_path, 'test')) import output_preservation_test as opt +from aronnax.utils import working_directory def do_red_grav(nx, aro_build, perf): - with opt.working_directory(p.join(self_path, "beta_plane_bump_red_grav")): + with working_directory(p.join(self_path, "beta_plane_bump_red_grav")): opt.run_experiment( opt.write_input_beta_plane_bump_red_grav, nx, nx, 1, aro_build, perf=perf) def do_n_layer(nx, aro_build, perf): - with opt.working_directory(p.join(self_path, "beta_plane_bump")): + with working_directory(p.join(self_path, "beta_plane_bump")): opt.run_experiment( opt.write_input_beta_plane_bump, nx, nx, 2, aro_build, perf=perf) diff --git a/test/output_preservation_test.py b/test/output_preservation_test.py index b0be41ba..841c17b6 100644 --- a/test/output_preservation_test.py +++ b/test/output_preservation_test.py @@ -1,4 +1,3 @@ -from contextlib import contextmanager import os import os.path as p import subprocess as sub @@ -9,22 +8,13 @@ import numpy as np import aronnax as aro +from aronnax.utils import working_directory self_path = p.dirname(p.abspath(__file__)) root_path = p.dirname(self_path) ### General helpers -@contextmanager -def working_directory(path): - old_path = os.getcwd() - sub.check_call(["mkdir", "-p", path]) - os.chdir(path) - try: - yield - finally: - os.chdir(old_path) - def tweak_parameters(nx, ny, layers): sub.check_call( "cat parameters.in " + From 8e9ae4d222319730b32e82ca3cce4386e4392b87 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 16:13:14 -0400 Subject: [PATCH 02/50] Draft end-to-end driver program, with enough room for flexible use and polite output. --- aronnax/driver.py | 81 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 aronnax/driver.py diff --git a/aronnax/driver.py b/aronnax/driver.py new file mode 100644 index 00000000..4fcd98ef --- /dev/null +++ b/aronnax/driver.py @@ -0,0 +1,81 @@ +import ConfigParser as par +import os.path as p +import subprocess as sub + +from aronnax.utils import working_directory + +def simulate(work_dir=".", config_path="aronnax.conf", **options): + config_file = p.join(work_dir, config_path) + config = par.RawConfigParser() + config.read(config_file) + merge_config(config, options) + with working_directory(config.get("...", "core_work_dir")): + compile_core(config) + # XXX Try to avoid overwriting the input configuration + with open('aronnax.conf', 'w') as f: + config.write(f) + sub.check_call(["rm", "-rf", "input/"]) + sub.check_call(["rm", "-rf", "output/"]) + sub.check_call(["mkdir", "-p", "output/"]) + with working_directory("input"): + generate_input_data_files(config) + generate_parameters_file(config) + run_executable(config) + sub.check_call(["rm", "-rf", "netcdf-output/"]) + sub.check_call(["mkdir", "-p", "netcdf-output/"]) + convert_output_to_netcdf(config) + +section_map = dict( + "au" : "numerics", + "ah" : "numerics", + "ar" : "numerics", + "dt" : "numerics", + "slip" : "numerics", + "nTimeSteps" : "numerics", + "dumpFreq" : "numerics", + "avFreq" : "numerics", + "hmin" : "numerics", + "maxits" : "numerics", + "eps" : "numerics", + "freesurfFac" : "numerics", + "thickness_error" : "numerics", + "hmean" : "model", + "depthFile" : "model", + "H0" : "model", + "RedGrav" : "model", + "spongeHTimeScaleFile" : "sponge", + "spongeUTimeScaleFile" : "sponge", + "spongeVTimeScaleFile" : "sponge", + "spongeHFile" : "sponge", + "spongeUFile" : "sponge", + "spongeVFile" : "sponge", + "g_vec" : "physics", + "rho0" : "physics", + "nx" : "grid", + "ny" : "grid", + "layers" : "grid", + "dx" : "grid", + "dy" : "grid", + "fUfile" : "grid", + "fVfile" : "grid", + "wetMaskFile" : "grid", + "initUfile" : "initial_conditions", + "initVfile" : "initial_conditions", + "initHfile" : "initial_conditions", + "initEtaFile" : "initial_conditions", + "zonalWindFile" : "external_forcing", + "meridionalWindFile" : "external_forcing", + "DumpWind" : "external_forcing", + "wind_mag_time_series_file" : "external_forcing", + ) + +def merge_config(config, options): + for k, v in options.iteritems(): + if k in section_map: + config.set(section_map[k], k, str(v)) + else: + raise Exception("Unrecognized option", k) + +def convert_output_to_netcdf(config): + # TODO Issue #30 + pass From 5699ef83229d3706831b3a87b1f455a53ae21b33 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 16:25:41 -0400 Subject: [PATCH 03/50] Draft schema for generation of data files. --- aronnax/driver.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/aronnax/driver.py b/aronnax/driver.py index 4fcd98ef..939277c2 100644 --- a/aronnax/driver.py +++ b/aronnax/driver.py @@ -2,6 +2,7 @@ import os.path as p import subprocess as sub +from aronnax.core import fortran_file from aronnax.utils import working_directory def simulate(work_dir=".", config_path="aronnax.conf", **options): @@ -76,6 +77,16 @@ def merge_config(config, options): else: raise Exception("Unrecognized option", k) +def generate_data_files(config): + for name, section in section_map.iteritems(): + if not name.endswith("File") and not name.endswith("file"): + continue + requested_data = config.get(section, name) + generated_data = interpret_requested_data(requested_data, config) + if generated_data is not None: + with fortran_file(name + '.bin', 'w') as f: + f.write_record(generated_data) + def convert_output_to_netcdf(config): # TODO Issue #30 pass From 42e6f690cd3f9b945f32129b46dcf7ecbca5bdfa Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 16:34:15 -0400 Subject: [PATCH 04/50] Draft dumping the parameter file. --- aronnax/driver.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/aronnax/driver.py b/aronnax/driver.py index 939277c2..885df59f 100644 --- a/aronnax/driver.py +++ b/aronnax/driver.py @@ -87,6 +87,16 @@ def generate_data_files(config): with fortran_file(name + '.bin', 'w') as f: f.write_record(generated_data) +def generate_parameters_file(config): + with open('parameters.in', 'w') as f: + for section in config.sections(): + f.write(' &') + f.write(section.toupper()) + f.write('\n') + for (name, value) in config.items(section): + f.write(' %s = %s,\n' % (name, value)) + f.write(' /\n') + def convert_output_to_netcdf(config): # TODO Issue #30 pass From cf4d9d7ffe8eb89fa9f8ffa26afe9dea7d8ed1ae Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 16:52:35 -0400 Subject: [PATCH 05/50] Interpret existing compile and run conventions in the driver framework. --- aronnax/driver.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/aronnax/driver.py b/aronnax/driver.py index 885df59f..760a1667 100644 --- a/aronnax/driver.py +++ b/aronnax/driver.py @@ -1,10 +1,14 @@ import ConfigParser as par +import os import os.path as p import subprocess as sub from aronnax.core import fortran_file from aronnax.utils import working_directory +self_path = p.dirname(p.abspath(__file__)) +root_path = p.dirname(self_path) + def simulate(work_dir=".", config_path="aronnax.conf", **options): config_file = p.join(work_dir, config_path) config = par.RawConfigParser() @@ -68,6 +72,9 @@ def simulate(work_dir=".", config_path="aronnax.conf", **options): "meridionalWindFile" : "external_forcing", "DumpWind" : "external_forcing", "wind_mag_time_series_file" : "external_forcing", + "exec" : "executable", + "valgrind" : "executable", + "perf" : "executable", ) def merge_config(config, options): @@ -77,6 +84,11 @@ def merge_config(config, options): else: raise Exception("Unrecognized option", k) +def compile_core(config): + core_name = config.get("executable", "exec") + with working_directory(root_path): + sub.check_call(["make", core_name]) + def generate_data_files(config): for name, section in section_map.iteritems(): if not name.endswith("File") and not name.endswith("file"): @@ -97,6 +109,25 @@ def generate_parameters_file(config): f.write(' %s = %s,\n' % (name, value)) f.write(' /\n') +def run_executable(config): + core_name = config.get("executable", "exec") + env = dict(os.environ, GFORTRAN_STDERR_UNIT="17") + if config.getboolean("executable", "valgrind") \ + or 'ARONNAX_TEST_VALGRIND_ALL' in os.environ: + assert not config.getboolean("executable", "perf") + sub.check_call(["valgrind", "--error-exitcode=5", p.join(root_path, aro_exec)], + env=env) + elif config.getboolean("executable", "perf"): + perf_cmds = ["perf", "stat", "-e", "r530010", # "flops", on my CPU. + "-e", "L1-dcache-loads", "-e", "L1-dcache-load-misses", + "-e", "L1-dcache-stores", "-e", "L1-dcache-store-misses", + "-e", "L1-icache-loads", "-e", "L1-icache-misses", + "-e", "L1-dcache-prefetches", + "-e", "branch-instructions", "-e", "branch-misses"] + sub.check_call(perf_cmds + [p.join(root_path, aro_exec)], env=env) + else: + sub.check_call([p.join(root_path, aro_exec)], env=env) + def convert_output_to_netcdf(config): # TODO Issue #30 pass From 8fd82889d5506bce7e56f547da2248e35ee01fac Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 17:08:46 -0400 Subject: [PATCH 06/50] Draft reading input data from raw Fortran files. --- aronnax/core.py | 27 +++++++++++++++++++++++++++ aronnax/driver.py | 1 + 2 files changed, 28 insertions(+) diff --git a/aronnax/core.py b/aronnax/core.py index 2015026f..40e20c41 100644 --- a/aronnax/core.py +++ b/aronnax/core.py @@ -152,3 +152,30 @@ def write_rectangular_pool(nx, ny): wetmask[ :, 0] = 0 wetmask[ :,-1] = 0 f.write_record(wetmask) + +def interpret_data_specifier(string): + return None + +def interpret_requested_data(requested_data, config): + """Interpret a flexible input data specification. + + The requested_data can be one of + + - TODO A string giving the path to a NetCDF file, whose content + will be interpolated to match the desired grid specification; + + - A string giving the path to a raw Fortran array file, whose + content will be used as-is; + + - TODO A numpy array in memory, whose content will be used as-is, + or TODO interpolated; or + + - A specifier for auto-generating the required data, in this format: + ::arg1,arg2,...argn + """ + candidate = interpret_data_specifier(requested_data) + if candidate is not None: + pass # TODO + # Assume Fortran file + with fortran_file(requested_data, 'r') as f: + return f.read_reals(dtype=np.float64) diff --git a/aronnax/driver.py b/aronnax/driver.py index 760a1667..26777b40 100644 --- a/aronnax/driver.py +++ b/aronnax/driver.py @@ -4,6 +4,7 @@ import subprocess as sub from aronnax.core import fortran_file +from aronnax.core import interpret_requested_data from aronnax.utils import working_directory self_path = p.dirname(p.abspath(__file__)) From 890158a9675239a0e57f1bbab29e5c92d0a782ea Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 17:23:27 -0400 Subject: [PATCH 07/50] Fiddles from trying to actually run the draft driver. --- aronnax/driver.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/aronnax/driver.py b/aronnax/driver.py index 26777b40..6d64d0da 100644 --- a/aronnax/driver.py +++ b/aronnax/driver.py @@ -15,10 +15,10 @@ def simulate(work_dir=".", config_path="aronnax.conf", **options): config = par.RawConfigParser() config.read(config_file) merge_config(config, options) - with working_directory(config.get("...", "core_work_dir")): + with working_directory(work_dir): compile_core(config) # XXX Try to avoid overwriting the input configuration - with open('aronnax.conf', 'w') as f: + with open('aronnax-merged.conf', 'w') as f: config.write(f) sub.check_call(["rm", "-rf", "input/"]) sub.check_call(["rm", "-rf", "output/"]) @@ -31,7 +31,7 @@ def simulate(work_dir=".", config_path="aronnax.conf", **options): sub.check_call(["mkdir", "-p", "netcdf-output/"]) convert_output_to_netcdf(config) -section_map = dict( +section_map = { "au" : "numerics", "ah" : "numerics", "ar" : "numerics", @@ -73,24 +73,27 @@ def simulate(work_dir=".", config_path="aronnax.conf", **options): "meridionalWindFile" : "external_forcing", "DumpWind" : "external_forcing", "wind_mag_time_series_file" : "external_forcing", - "exec" : "executable", + "exe" : "executable", "valgrind" : "executable", "perf" : "executable", - ) +} def merge_config(config, options): for k, v in options.iteritems(): if k in section_map: - config.set(section_map[k], k, str(v)) + section = section_map[k] + if not config.has_section(section): + config.add_section(section) + config.set(section, k, str(v)) else: raise Exception("Unrecognized option", k) def compile_core(config): - core_name = config.get("executable", "exec") + core_name = config.get("executable", "exe") with working_directory(root_path): sub.check_call(["make", core_name]) -def generate_data_files(config): +def generate_input_data_files(config): for name, section in section_map.iteritems(): if not name.endswith("File") and not name.endswith("file"): continue From d3b048438d188d64fbe7449e54d69f684bc7051e Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 17:42:50 -0400 Subject: [PATCH 08/50] Do what it takes to permit programmatic generation of layer height (for now) data. --- aronnax/core.py | 22 +++++++++++++++++----- aronnax/driver.py | 25 +++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/aronnax/core.py b/aronnax/core.py index 40e20c41..a270120e 100644 --- a/aronnax/core.py +++ b/aronnax/core.py @@ -94,7 +94,7 @@ def interpret_raw_file(name, nx, ny, layers): ### General input construction helpers -def write_initial_heights(grid, h_funcs): +def interpret_initial_heights(grid, h_funcs): X,Y = np.meshgrid(grid.x, grid.y) initH = np.ones((len(h_funcs), grid.ny, grid.nx)) for i, f in enumerate(h_funcs): @@ -102,6 +102,10 @@ def write_initial_heights(grid, h_funcs): initH[i,:,:] = f else: initH[i,:,:] = f(X, Y) + return initH + +def write_initial_heights(grid, h_funcs): + initH = interpret_initial_heights(grid, h_funcs) with fortran_file('initH.bin', 'w') as f: f.write_record(initH.astype(np.float64)) @@ -156,7 +160,7 @@ def write_rectangular_pool(nx, ny): def interpret_data_specifier(string): return None -def interpret_requested_data(requested_data, config): +def interpret_requested_data(requested_data, shape, config): """Interpret a flexible input data specification. The requested_data can be one of @@ -176,6 +180,14 @@ def interpret_requested_data(requested_data, config): candidate = interpret_data_specifier(requested_data) if candidate is not None: pass # TODO - # Assume Fortran file - with fortran_file(requested_data, 'r') as f: - return f.read_reals(dtype=np.float64) + if isinstance(requested_data, basestring): + # Assume Fortran file name + with fortran_file(requested_data, 'r') as f: + return f.read_reals(dtype=np.float64) + else: + grid = Grid(config.getint("grid", "nx"), config.getint("grid", "ny"), + config.getfloat("grid", "dx"), config.getfloat("grid", "dy")) + if shape == "3d": + interpret_initial_heights(grid, requested_data) + else: + raise Exception("TODO implement generation for other input shapes") diff --git a/aronnax/driver.py b/aronnax/driver.py index 6d64d0da..a67884fd 100644 --- a/aronnax/driver.py +++ b/aronnax/driver.py @@ -84,7 +84,7 @@ def merge_config(config, options): section = section_map[k] if not config.has_section(section): config.add_section(section) - config.set(section, k, str(v)) + config.set(section, k, v) else: raise Exception("Unrecognized option", k) @@ -93,12 +93,33 @@ def compile_core(config): with working_directory(root_path): sub.check_call(["make", core_name]) +data_types = { + "depthFile" : "2d", + "spongeHTimeScaleFile" : "3d", + "spongeUTimeScaleFile" : "3d", + "spongeVTimeScaleFile" : "3d", + "spongeHFile" : "3d", + "spongeUFile" : "3d", + "spongeVFile" : "3d", + "fUfile" : "2d", + "fVfile" : "2d", + "wetMaskFile" : "2d", + "initUfile" : "3d", + "initVfile" : "3d", + "initHfile" : "3d", + "initEtaFile" : "2d", + "zonalWindFile" : "2d", + "meridionalWindFile" : "2d", + "wind_mag_time_series_file" : "time", +} + def generate_input_data_files(config): for name, section in section_map.iteritems(): if not name.endswith("File") and not name.endswith("file"): continue requested_data = config.get(section, name) - generated_data = interpret_requested_data(requested_data, config) + generated_data = interpret_requested_data( + requested_data, data_types[name], config) if generated_data is not None: with fortran_file(name + '.bin', 'w') as f: f.write_record(generated_data) From 2007a934f6443da9764774b5d0787ead1cb574f9 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 17:55:41 -0400 Subject: [PATCH 09/50] Do what it takes to allow a config file to specify the wetmask as "rectangular pool". --- aronnax/core.py | 55 +++++++++++++++++++++++++++++++++-------------- aronnax/driver.py | 2 ++ 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/aronnax/core.py b/aronnax/core.py index a270120e..f27c9406 100644 --- a/aronnax/core.py +++ b/aronnax/core.py @@ -9,6 +9,7 @@ from contextlib import contextmanager import os.path as p +import re import numpy as np from scipy.io import FortranFile @@ -147,18 +148,38 @@ def write_beta_plane(grid, f0, beta): fv = f0 + Y*beta f.write_record(fv.astype(np.float64)) +def rectangular_pool(grid): + nx = grid.nx; ny = grid.ny + wetmask = np.ones((nx, ny), dtype=np.float64) + wetmask[ 0, :] = 0 + wetmask[-1, :] = 0 + wetmask[ :, 0] = 0 + wetmask[ :,-1] = 0 + return wetmask + def write_rectangular_pool(nx, ny): """Write the wet mask file for a maximal rectangular pool.""" with fortran_file('wetmask.bin', 'w') as f: - wetmask = np.ones((nx, ny), dtype=np.float64) - wetmask[ 0, :] = 0 - wetmask[-1, :] = 0 - wetmask[ :, 0] = 0 - wetmask[ :,-1] = 0 f.write_record(wetmask) +specifier_rx = re.compile(r':(.*):(.*)') + +ok_generators = { + 'rectangular_pool': rectangular_pool, +} + def interpret_data_specifier(string): - return None + m = re.match(specifier_rx, string) + if m: + name = m.group(1) + arg_str = m.group(2) + if len(arg_str) > 0: + args = [float(a) for a in arg_str.split(',')] + else: + args = [] + return (ok_generators[name], args) + else: + return None def interpret_requested_data(requested_data, shape, config): """Interpret a flexible input data specification. @@ -177,17 +198,19 @@ def interpret_requested_data(requested_data, shape, config): - A specifier for auto-generating the required data, in this format: ::arg1,arg2,...argn """ - candidate = interpret_data_specifier(requested_data) - if candidate is not None: - pass # TODO + grid = Grid(config.getint("grid", "nx"), config.getint("grid", "ny"), + config.getfloat("grid", "dx"), config.getfloat("grid", "dy")) if isinstance(requested_data, basestring): - # Assume Fortran file name - with fortran_file(requested_data, 'r') as f: - return f.read_reals(dtype=np.float64) + candidate = interpret_data_specifier(requested_data) + if candidate is not None: + (func, args) = candidate + return func(grid, *args) + else: + # Assume Fortran file name + with fortran_file(requested_data, 'r') as f: + return f.read_reals(dtype=np.float64) else: - grid = Grid(config.getint("grid", "nx"), config.getint("grid", "ny"), - config.getfloat("grid", "dx"), config.getfloat("grid", "dy")) if shape == "3d": - interpret_initial_heights(grid, requested_data) + return interpret_initial_heights(grid, requested_data) else: - raise Exception("TODO implement generation for other input shapes") + raise Exception("TODO implement custom generation for other input shapes") diff --git a/aronnax/driver.py b/aronnax/driver.py index a67884fd..dbffef2d 100644 --- a/aronnax/driver.py +++ b/aronnax/driver.py @@ -117,6 +117,8 @@ def generate_input_data_files(config): for name, section in section_map.iteritems(): if not name.endswith("File") and not name.endswith("file"): continue + if not config.has_option(section, name): + continue requested_data = config.get(section, name) generated_data = interpret_requested_data( requested_data, data_types[name], config) From a901e5bfdd1d6f6f1a5e94bf987c691d54e600f8 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 17:59:34 -0400 Subject: [PATCH 10/50] Add the u and v beta plane Coriolis components as generators. --- aronnax/core.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/aronnax/core.py b/aronnax/core.py index f27c9406..3874eafe 100644 --- a/aronnax/core.py +++ b/aronnax/core.py @@ -137,6 +137,16 @@ def write_f_plane(nx, ny, coeff): with fortran_file('fv.bin', 'w') as f: f.write_record(np.ones((nx, ny+1), dtype=np.float64) * coeff) +def beta_plane_u(grid, f0, beta): + _, Y = np.meshgrid(grid.xp1, grid.y) + fu = f0 + Y*beta + return fu + +def beta_plane_v(grid, f0, beta): + _, Y = np.meshgrid(grid.x, grid.yp1) + fv = f0 + Y*beta + return fv + def write_beta_plane(grid, f0, beta): """Write files defining a beta-plane approximation to the Coriolis force.""" with fortran_file('fu.bin', 'w') as f: @@ -165,6 +175,8 @@ def write_rectangular_pool(nx, ny): specifier_rx = re.compile(r':(.*):(.*)') ok_generators = { + 'beta_plane_u': beta_plane_u, + 'beta_plane_v': beta_plane_v, 'rectangular_pool': rectangular_pool, } From 1624067b62f4c2dbb692d8bc54622d329a4fd02f Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 18:04:43 -0400 Subject: [PATCH 11/50] More fiddles from trying to run the draft driver. --- aronnax/driver.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/aronnax/driver.py b/aronnax/driver.py index dbffef2d..b20215c1 100644 --- a/aronnax/driver.py +++ b/aronnax/driver.py @@ -12,7 +12,7 @@ def simulate(work_dir=".", config_path="aronnax.conf", **options): config_file = p.join(work_dir, config_path) - config = par.RawConfigParser() + config = default_configuration() config.read(config_file) merge_config(config, options) with working_directory(work_dir): @@ -31,6 +31,13 @@ def simulate(work_dir=".", config_path="aronnax.conf", **options): sub.check_call(["mkdir", "-p", "netcdf-output/"]) convert_output_to_netcdf(config) +def default_configuration(): + config = par.RawConfigParser() + config.add_section("executable") + config.set("executable", "valgrind", "False") + config.set("executable", "perf", "False") + return config + section_map = { "au" : "numerics", "ah" : "numerics", @@ -130,19 +137,19 @@ def generate_parameters_file(config): with open('parameters.in', 'w') as f: for section in config.sections(): f.write(' &') - f.write(section.toupper()) + f.write(section.upper()) f.write('\n') for (name, value) in config.items(section): f.write(' %s = %s,\n' % (name, value)) f.write(' /\n') def run_executable(config): - core_name = config.get("executable", "exec") + core_name = config.get("executable", "exe") env = dict(os.environ, GFORTRAN_STDERR_UNIT="17") if config.getboolean("executable", "valgrind") \ or 'ARONNAX_TEST_VALGRIND_ALL' in os.environ: assert not config.getboolean("executable", "perf") - sub.check_call(["valgrind", "--error-exitcode=5", p.join(root_path, aro_exec)], + sub.check_call(["valgrind", "--error-exitcode=5", p.join(root_path, core_name)], env=env) elif config.getboolean("executable", "perf"): perf_cmds = ["perf", "stat", "-e", "r530010", # "flops", on my CPU. @@ -151,9 +158,9 @@ def run_executable(config): "-e", "L1-icache-loads", "-e", "L1-icache-misses", "-e", "L1-dcache-prefetches", "-e", "branch-instructions", "-e", "branch-misses"] - sub.check_call(perf_cmds + [p.join(root_path, aro_exec)], env=env) + sub.check_call(perf_cmds + [p.join(root_path, core_name)], env=env) else: - sub.check_call([p.join(root_path, aro_exec)], env=env) + sub.check_call([p.join(root_path, core_name)], env=env) def convert_output_to_netcdf(config): # TODO Issue #30 From 1a2f1cfb380ca4dc7ad5def386b7685be4a07a2d Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 18:17:13 -0400 Subject: [PATCH 12/50] Format boolean values as Fortran expects, and write the names of the generated raw files, not their specs. --- aronnax/driver.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/aronnax/driver.py b/aronnax/driver.py index b20215c1..167f50b1 100644 --- a/aronnax/driver.py +++ b/aronnax/driver.py @@ -120,9 +120,12 @@ def compile_core(config): "wind_mag_time_series_file" : "time", } +def is_file_name_option(name): + return name.endswith("File") or name.endswith("file") + def generate_input_data_files(config): for name, section in section_map.iteritems(): - if not name.endswith("File") and not name.endswith("file"): + if not is_file_name_option(name): continue if not config.has_option(section, name): continue @@ -133,6 +136,17 @@ def generate_input_data_files(config): with fortran_file(name + '.bin', 'w') as f: f.write_record(generated_data) +def fortran_option_string(section, name, value, config): + if is_file_name_option(name): + return "'%s'" % (p.join("input", name + '.bin'),) + if name in ["RedGrav", "DumpWind"]: + if config.getboolean(section, name): + return ".TRUE." + else: + return ".FALSE." + else: + return value + def generate_parameters_file(config): with open('parameters.in', 'w') as f: for section in config.sections(): @@ -140,7 +154,8 @@ def generate_parameters_file(config): f.write(section.upper()) f.write('\n') for (name, value) in config.items(section): - f.write(' %s = %s,\n' % (name, value)) + val = fortran_option_string(section, name, value, config) + f.write(' %s = %s,\n' % (name, val)) f.write(' /\n') def run_executable(config): From c1de42aeb7d70457a05754dd78f39c30c8b09466 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 18:24:26 -0400 Subject: [PATCH 13/50] Force all the sections to be present, since Fortran looks for them. Also suppress ConfigParser's default behavior of case-normalizing the options. --- aronnax/driver.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/aronnax/driver.py b/aronnax/driver.py index 167f50b1..e5f288f1 100644 --- a/aronnax/driver.py +++ b/aronnax/driver.py @@ -33,11 +33,16 @@ def simulate(work_dir=".", config_path="aronnax.conf", **options): def default_configuration(): config = par.RawConfigParser() - config.add_section("executable") + for section in sections: + config.add_section(section) config.set("executable", "valgrind", "False") config.set("executable", "perf", "False") + config.optionxform = str return config +sections = ["executable", "numerics", "model", "sponge", + "physics", "grid", "initial_conditions", "external_forcing"] + section_map = { "au" : "numerics", "ah" : "numerics", From de76fa295e5be5a360067b38a66d59ce2737b272 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 18:25:53 -0400 Subject: [PATCH 14/50] It's spelled CONDITIONS, with two letters 'I'. --- aronnax.f90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aronnax.f90 b/aronnax.f90 index ff3cdcc9..13521870 100644 --- a/aronnax.f90 +++ b/aronnax.f90 @@ -116,7 +116,7 @@ program aronnax namelist /GRID/ nx, ny, layers, dx, dy, fUfile, fVfile, wetMaskFile - namelist /INITIAL_CONDITONS/ initUfile, initVfile, initHfile, initEtaFile + namelist /INITIAL_CONDITIONS/ initUfile, initVfile, initHfile, initEtaFile namelist /EXTERNAL_FORCING/ zonalWindFile, meridionalWindFile, & DumpWind, wind_mag_time_series_file @@ -127,7 +127,7 @@ program aronnax read(unit=8, nml=SPONGE) read(unit=8, nml=PHYSICS) read(unit=8, nml=GRID) - read(unit=8, nml=INITIAL_CONDITONS) + read(unit=8, nml=INITIAL_CONDITIONS) read(unit=8, nml=EXTERNAL_FORCING) close(unit=8) From eb6cb69d6018f5f12559bc783a77940eb575d0dd Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 18:37:01 -0400 Subject: [PATCH 15/50] Oops, accidentally broke write_rectangular_pool. --- aronnax/core.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/aronnax/core.py b/aronnax/core.py index 3874eafe..069a2178 100644 --- a/aronnax/core.py +++ b/aronnax/core.py @@ -170,6 +170,11 @@ def rectangular_pool(grid): def write_rectangular_pool(nx, ny): """Write the wet mask file for a maximal rectangular pool.""" with fortran_file('wetmask.bin', 'w') as f: + wetmask = np.ones((nx, ny), dtype=np.float64) + wetmask[ 0, :] = 0 + wetmask[-1, :] = 0 + wetmask[ :, 0] = 0 + wetmask[ :,-1] = 0 f.write_record(wetmask) specifier_rx = re.compile(r':(.*):(.*)') From 13b979ae9c64df6287b8be32da88ae9532ee96d8 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 18:37:29 -0400 Subject: [PATCH 16/50] Force blank file names to be written for the core's benefit even when no input data was specified. --- aronnax/driver.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/aronnax/driver.py b/aronnax/driver.py index e5f288f1..9356dab4 100644 --- a/aronnax/driver.py +++ b/aronnax/driver.py @@ -141,16 +141,23 @@ def generate_input_data_files(config): with fortran_file(name + '.bin', 'w') as f: f.write_record(generated_data) -def fortran_option_string(section, name, value, config): +def fortran_option_string(section, name, config): if is_file_name_option(name): - return "'%s'" % (p.join("input", name + '.bin'),) + if config.has_option(section, name): + # A file was generated + return "'%s'" % (p.join("input", name + '.bin'),) + else: + return "''" if name in ["RedGrav", "DumpWind"]: if config.getboolean(section, name): return ".TRUE." else: return ".FALSE." else: - return value + if config.has_option(section, name): + return config.get(section, name) + else: + return None def generate_parameters_file(config): with open('parameters.in', 'w') as f: @@ -158,9 +165,11 @@ def generate_parameters_file(config): f.write(' &') f.write(section.upper()) f.write('\n') - for (name, value) in config.items(section): - val = fortran_option_string(section, name, value, config) - f.write(' %s = %s,\n' % (name, val)) + for (name, section1) in section_map.iteritems(): + if section1 != section: continue + val = fortran_option_string(section, name, config) + if val is not None: + f.write(' %s = %s,\n' % (name, val)) f.write(' /\n') def run_executable(config): From d54a54e2c0797ce678a4eb8ab43a84e5e80e6e80 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 18:47:37 -0400 Subject: [PATCH 17/50] Rewrite the reduced gravity benchmark to use the new driver instead of output_preservation_test.run_experiment. --- aronnax/driver.py | 4 + benchmarks/.gitignore | 2 + benchmarks/benchmark.py | 11 ++- .../beta_plane_bump_red_grav/aronnax.conf | 56 +++++++++++++ .../beta_plane_bump_red_grav/parameters.in | 79 ------------------- 5 files changed, 69 insertions(+), 83 deletions(-) create mode 100644 benchmarks/beta_plane_bump_red_grav/aronnax.conf delete mode 100644 benchmarks/beta_plane_bump_red_grav/parameters.in diff --git a/aronnax/driver.py b/aronnax/driver.py index 9356dab4..3497fe5e 100644 --- a/aronnax/driver.py +++ b/aronnax/driver.py @@ -2,6 +2,7 @@ import os import os.path as p import subprocess as sub +import time from aronnax.core import fortran_file from aronnax.core import interpret_requested_data @@ -26,10 +27,13 @@ def simulate(work_dir=".", config_path="aronnax.conf", **options): with working_directory("input"): generate_input_data_files(config) generate_parameters_file(config) + then = time.time() run_executable(config) + core_run_time = time.time() - then sub.check_call(["rm", "-rf", "netcdf-output/"]) sub.check_call(["mkdir", "-p", "netcdf-output/"]) convert_output_to_netcdf(config) + return core_run_time def default_configuration(): config = par.RawConfigParser() diff --git a/benchmarks/.gitignore b/benchmarks/.gitignore index 7dce5900..9b68e0e0 100644 --- a/benchmarks/.gitignore +++ b/benchmarks/.gitignore @@ -4,3 +4,5 @@ run_finished.txt layer thickness dropped below hmin.txt *scaling.png **/times.pkl +parameters.in +aronnax-merged.conf diff --git a/benchmarks/benchmark.py b/benchmarks/benchmark.py index 5b17c3eb..9beb830e 100644 --- a/benchmarks/benchmark.py +++ b/benchmarks/benchmark.py @@ -14,6 +14,7 @@ sys.path.append(p.join(root_path, 'test')) import output_preservation_test as opt from aronnax.utils import working_directory +import aronnax.driver as aro n_time_steps = 502.0 scale_factor = 1000 / n_time_steps # Show times in ms @@ -21,17 +22,19 @@ def benchmark_gaussian_bump_red_grav_save(grid_points): run_time_O1 = np.zeros(len(grid_points)) run_time_Ofast = np.zeros(len(grid_points)) + def bump(X, Y): + return 500. + 20*np.exp(-((6e5-X)**2 + (5e5-Y)**2)/(2*1e5**2)) with working_directory(p.join(self_path, "beta_plane_bump_red_grav")): aro_exec = "aronnax_test" for counter, nx in enumerate(grid_points): - run_time_O1[counter] = opt.run_experiment( - opt.write_input_beta_plane_bump_red_grav, nx, nx, 1, aro_exec) + run_time_O1[counter] = aro.simulate( + exe=aro_exec, initHfile=[bump], nx=nx, ny=nx) aro_exec = "aronnax_core" for counter, nx in enumerate(grid_points): - run_time_Ofast[counter] = opt.run_experiment( - opt.write_input_beta_plane_bump_red_grav, nx, nx, 1, aro_exec) + run_time_Ofast[counter] = aro.simulate( + exe=aro_exec, initHfile=[bump], nx=nx, ny=nx) with open("times.pkl", "w") as f: pkl.dump((grid_points, run_time_O1, run_time_Ofast), f) diff --git a/benchmarks/beta_plane_bump_red_grav/aronnax.conf b/benchmarks/beta_plane_bump_red_grav/aronnax.conf new file mode 100644 index 00000000..30392be8 --- /dev/null +++ b/benchmarks/beta_plane_bump_red_grav/aronnax.conf @@ -0,0 +1,56 @@ +# Aronnax configuration file. Change the values, but not the names. +# +# Each namelist ends with a / +# This is important and should not be deleted. +# +# au is viscosity +# ah is thickness diffusivity +# ar is linear drag between layers +# dt is time step +# slip is free-slip (=0), no-slip (=1), or partial slip (something in between) +# nTimeSteps: number of timesteps before stopping +# dumpFreq: frequency of snapshot output +# avFreq: frequency of averaged output +# hmin: minimum layer thickness allowed by model (for stability) +# maxits: maximum iterations for the successive over relaxation algorithm. Should be at least max(nx,ny), and probably nx*ny +# eps: convergence tolerance for SOR solver +# freesurfFac: 1. = linear implicit free surface, 0. = rigid lid. So far all tests using freesurfFac = 1. have failed +# g is the gravity at interfaces (including surface). must have as many entries as there are layers +# input files are where to look for the various inputs + +[numerics] +au = 500. +ah = 0.0 +ar = 1e-8 +dt = 600. +slip = 0.0 +nTimeSteps = 502 +dumpFreq = 6e4 +avFreq = 3e5 +hmin = 100 +maxits = 1000 +eps = 1e-2 +freesurfFac = 0. +thickness_error = 1e-2 + +[model] +hmean = 400. +H0 = 2000. +RedGrav = yes + +[physics] +g_vec = 0.01 +rho0 = 1035. + +[grid] +nx = 500 +ny = 500 +layers = 1 +dx = 2e4 +dy = 2e4 +fUfile = :beta_plane_u:1e-5,2e-11 +fVfile = :beta_plane_v:1e-5,2e-11 +wetMaskFile = :rectangular_pool: + +[external_forcing] +DumpWind = no diff --git a/benchmarks/beta_plane_bump_red_grav/parameters.in b/benchmarks/beta_plane_bump_red_grav/parameters.in deleted file mode 100644 index 6791797f..00000000 --- a/benchmarks/beta_plane_bump_red_grav/parameters.in +++ /dev/null @@ -1,79 +0,0 @@ -! Parameter file. Change the values, but not the names. -! -! Each namelist ends with a / -! This is important and should not be deleted. -! -! au is viscosity -! ah is thickness diffusivity -! ar is linear drag between layers -! dt is time step -! slip is free-slip (=0), no-slip (=1), or partial slip (something in between) -! nTimeSteps: number of timesteps before stopping -! dumpFreq: frequency of snapshot output -! avFreq: frequency of averaged output -! hmin: minimum layer thickness allowed by model (for stability) -! maxits: maximum iterations for the successive over relaxation algorithm. Should be at least max(nx,ny), and probably nx*ny -! eps: convergence tolerance for SOR solver -! freesurfFac: 1. = linear implicit free surface, 0. = rigid lid. So far all tests using freesurfFac = 1. have failed -! g is the gravity at interfaces (including surface). must have as many entries as there are layers -! input files are where to look for the various inputs -! - &NUMERICS - au = 500., - ah = 0.0, - ar = 1e-8, - dt = 600., - slip = 0.0, - nTimeSteps = 502, - dumpFreq = 6e4, - avFreq = 3e5, - hmin = 100, - maxits = 1000, - eps = 1e-2, - freesurfFac = 0., - thickness_error = 1e-2, - / - &MODEL - hmean = 400., - depthFile = '', - H0 = 2000., - RedGrav = .TRUE., - / - &SPONGE - spongeHTimeScaleFile = '', - spongeUTimeScaleFile = '', - spongeVTimeScaleFile = '', - spongeHFile = '', - spongeUfile = '', - spongeVfile = '', - / - &PHYSICS - g_vec = 0.01, - rho0 = 1035., - / - &GRID - nx = 500, - ny = 500, - layers = 1, - dx = 2e4, - dy = 2e4, - fUfile = 'input/fu.bin', - fVfile = 'input/fv.bin', - wetMaskFile = 'input/wetmask.bin', - / -! Inital conditions for u, v, and h - &INITIAL_CONDITONS - initUfile = '', - initVfile = '', - initHfile = 'input/initH.bin', - initEtaFile = '', - / - &EXTERNAL_FORCING - zonalWindFile = '', - meridionalWindFile = '', - DumpWind = .FALSE., - wind_mag_time_series_file = '', - / -! input/initH.bin -! - & From 7a1f14c7047d5946b2e8929582c66e0f5120fb47 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 19:25:30 -0400 Subject: [PATCH 18/50] Rewrite the 2-layer benchmark to use the new driver as well. --- benchmarks/benchmark.py | 10 +-- benchmarks/beta_plane_bump/aronnax.conf | 57 +++++++++++++++++ benchmarks/beta_plane_bump/parameters.in | 80 ------------------------ 3 files changed, 63 insertions(+), 84 deletions(-) create mode 100644 benchmarks/beta_plane_bump/aronnax.conf delete mode 100644 benchmarks/beta_plane_bump/parameters.in diff --git a/benchmarks/benchmark.py b/benchmarks/benchmark.py index 9beb830e..e2a723b7 100644 --- a/benchmarks/benchmark.py +++ b/benchmarks/benchmark.py @@ -68,16 +68,18 @@ def benchmark_gaussian_bump_red_grav(grid_points): def benchmark_gaussian_bump_save(grid_points): run_time_O1 = np.zeros(len(grid_points)) run_time_Ofast = np.zeros(len(grid_points)) + def bump(X, Y): + return 500. + 20*np.exp(-((6e5-X)**2 + (5e5-Y)**2)/(2*1e5**2)) with working_directory(p.join(self_path, "beta_plane_bump")): aro_exec = "aronnax_test" for counter, nx in enumerate(grid_points): - run_time_O1[counter] = opt.run_experiment( - opt.write_input_beta_plane_bump, nx, nx, 2, aro_exec) + run_time_O1[counter] = aro.simulate( + exe=aro_exec, initHfile=[bump, lambda X, Y: 2000. - bump(X, Y)], nx=nx, ny=nx) aro_exec = "aronnax_core" for counter, nx in enumerate(grid_points): - run_time_Ofast[counter] = opt.run_experiment( - opt.write_input_beta_plane_bump, nx, nx, 2, aro_exec) + run_time_Ofast[counter] = aro.simulate( + exe=aro_exec, initHfile=[bump, lambda X, Y: 2000. - bump(X, Y)], nx=nx, ny=nx) with open("times.pkl", "w") as f: pkl.dump((grid_points, run_time_O1, run_time_Ofast), f) diff --git a/benchmarks/beta_plane_bump/aronnax.conf b/benchmarks/beta_plane_bump/aronnax.conf new file mode 100644 index 00000000..ce5c1a6d --- /dev/null +++ b/benchmarks/beta_plane_bump/aronnax.conf @@ -0,0 +1,57 @@ +# Aronnax configuration file. Change the values, but not the names. +# +# Each namelist ends with a / +# This is important and should not be deleted. +# +# au is viscosity +# ah is thickness diffusivity +# ar is linear drag between layers +# dt is time step +# slip is free-slip (=0), no-slip (=1), or partial slip (something in between) +# nTimeSteps: number of timesteps before stopping +# dumpFreq: frequency of snapshot output +# avFreq: frequency of averaged output +# hmin: minimum layer thickness allowed by model (for stability) +# maxits: maximum iterations for the successive over relaxation algorithm. Should be at least max(nx,ny), and probably nx*ny +# eps: convergence tolerance for SOR solver +# freesurfFac: 1. = linear implicit free surface, 0. = rigid lid. So far all tests using freesurfFac = 1. have failed +# g is the gravity at interfaces (including surface). must have as many entries as there are layers +# input files are where to look for the various inputs + +[numerics] +au = 500. +ah = 0.0 +ar = 0.0 +botDrag = 1e-6 +dt = 600. +slip = 0.0 +nTimeSteps = 502 +dumpFreq = 1.2e5 +avFreq = 1.2e5 +hmin = 100 +maxits = 1000 +eps = 1e-2 +freesurfFac = 0. +thickness_error = 1e-2 + +[model] +hmean = 400.,1600. +H0 = 2000. +RedGrav = no + +[physics] +g_vec = 9.8, 0.01 +rho0 = 1035. + +[grid] +nx = 10 +ny = 10 +layers = 2 +dx = 2e4 +dy = 2e4 +fUfile = :beta_plane_u:1e-5,2e-11 +fVfile = :beta_plane_v:1e-5,2e-11 +wetMaskFile = :rectangular_pool: + +[external_forcing] +DumpWind = no diff --git a/benchmarks/beta_plane_bump/parameters.in b/benchmarks/beta_plane_bump/parameters.in deleted file mode 100644 index 45b75577..00000000 --- a/benchmarks/beta_plane_bump/parameters.in +++ /dev/null @@ -1,80 +0,0 @@ -! Parameter file. Change the values, but not the names. -! -! Each namelist ends with a / -! This is important and should not be deleted. -! -! au is viscosity -! ah is thickness diffusivity -! ar is linear drag between layers -! dt is time step -! slip is free-slip (=0), no-slip (=1), or partial slip (something in between) -! nTimeSteps: number of timesteps before stopping -! dumpFreq: frequency of snapshot output -! avFreq: frequency of averaged output -! hmin: minimum layer thickness allowed by model (for stability) -! maxits: maximum iterations for the successive over relaxation algorithm. Should be at least max(nx,ny), and probably nx*ny -! eps: convergence tolerance for SOR solver -! freesurfFac: 1. = linear implicit free surface, 0. = rigid lid. So far all tests using freesurfFac = 1. have failed -! g is the gravity at interfaces (including surface). must have as many entries as there are layers -! input files are where to look for the various inputs -! - &NUMERICS - au = 500., - ah = 0.0, - ar = 0.0, - botDrag = 1e-6, - dt = 600., - slip = 0.0, - nTimeSteps = 502, - dumpFreq = 1.2e5, - avFreq = 1.2e5, - hmin = 100, - maxits = 1000, - eps = 1e-2, - freesurfFac = 0., - thickness_error = 1e-2, - / - &MODEL - hmean = 400.,1600., - depthFile = '', - H0 = 2000., - RedGrav = .FALSE., - / - &SPONGE - spongeHTimeScaleFile = '', - spongeUTimeScaleFile = '', - spongeVTimeScaleFile = '', - spongeHFile = '', - spongeUfile = '', - spongeVfile = '', - / - &PHYSICS - g_vec = 9.8, 0.01, - rho0 = 1035., - / - &GRID - nx = 100, - ny = 100, - layers = 2, - dx = 2e4, - dy = 2e4, - fUfile = 'input/fu.bin', - fVfile = 'input/fv.bin', - wetMaskFile = 'input/wetmask.bin', - / -! Inital conditions for u, v, and h - &INITIAL_CONDITONS - initUfile = '', - initVfile = '', - initHfile = 'input/initH.bin', - initEtaFile = '', - / - &EXTERNAL_FORCING - zonalWindFile = '', - meridionalWindFile = '', - DumpWind = .FALSE., - wind_mag_time_series_file = '', - / -! input/initH.bin -! - & From 04162797330c175d1454cf5d997d30d73e78d426 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 19:26:50 -0400 Subject: [PATCH 19/50] The benchmark script no longer depends on the test suite. --- benchmarks/benchmark.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/benchmarks/benchmark.py b/benchmarks/benchmark.py index e2a723b7..1aadb6e1 100644 --- a/benchmarks/benchmark.py +++ b/benchmarks/benchmark.py @@ -7,15 +7,12 @@ matplotlib.use("Agg") import matplotlib.pyplot as plt -self_path = p.dirname(p.abspath(__file__)) -root_path = p.dirname(self_path) - -import sys -sys.path.append(p.join(root_path, 'test')) -import output_preservation_test as opt from aronnax.utils import working_directory import aronnax.driver as aro +self_path = p.dirname(p.abspath(__file__)) +root_path = p.dirname(self_path) + n_time_steps = 502.0 scale_factor = 1000 / n_time_steps # Show times in ms From fc011efca367f5d65c300fc0769e68f61a6b478a Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 21:11:47 -0400 Subject: [PATCH 20/50] Apparently ConfigParser.getboolean doesn't understand Python booleans :( --- aronnax/driver.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aronnax/driver.py b/aronnax/driver.py index 3497fe5e..517a5030 100644 --- a/aronnax/driver.py +++ b/aronnax/driver.py @@ -100,6 +100,8 @@ def merge_config(config, options): section = section_map[k] if not config.has_section(section): config.add_section(section) + if v == True: v = "yes" + if v == False: v = "no" config.set(section, k, v) else: raise Exception("Unrecognized option", k) From 64400b12e54e6a769183b7221edfe9e60d74c40b Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 21:12:13 -0400 Subject: [PATCH 21/50] Rewrite the profiling script in terms of the new driver instead of output_preservation_test.run_experiment. --- benchmarks/profile.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/benchmarks/profile.py b/benchmarks/profile.py index 34d786d0..f3872d01 100644 --- a/benchmarks/profile.py +++ b/benchmarks/profile.py @@ -1,22 +1,24 @@ import os.path as p +import sys -self_path = p.dirname(p.abspath(__file__)) -root_path = p.dirname(self_path) +import numpy as np -import sys -sys.path.append(p.join(root_path, 'test')) -import output_preservation_test as opt from aronnax.utils import working_directory +import aronnax.driver as aro + +self_path = p.dirname(p.abspath(__file__)) + +def bump(X, Y): + return 500. + 20*np.exp(-((6e5-X)**2 + (5e5-Y)**2)/(2*1e5**2)) def do_red_grav(nx, aro_build, perf): with working_directory(p.join(self_path, "beta_plane_bump_red_grav")): - opt.run_experiment( - opt.write_input_beta_plane_bump_red_grav, nx, nx, 1, aro_build, perf=perf) + aro.simulate(exe=aro_build, initHfile=[bump], nx=nx, ny=nx, perf=perf) def do_n_layer(nx, aro_build, perf): with working_directory(p.join(self_path, "beta_plane_bump")): - opt.run_experiment( - opt.write_input_beta_plane_bump, nx, nx, 2, aro_build, perf=perf) + aro.simulate(exe=aro_build, nx=nx, ny=nx, perf=perf, + initHfile=[bump, lambda X, Y: 2000. - bump(X, Y)]) def main(): aro_build = "aronnax_prof" From a20f46ecf854057fcd2fdc7dfbf4be9c2824d6c3 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 22:29:36 -0400 Subject: [PATCH 22/50] Flush broken comment. --- benchmarks/beta_plane_bump_red_grav/aronnax.conf | 3 --- 1 file changed, 3 deletions(-) diff --git a/benchmarks/beta_plane_bump_red_grav/aronnax.conf b/benchmarks/beta_plane_bump_red_grav/aronnax.conf index 30392be8..774f600d 100644 --- a/benchmarks/beta_plane_bump_red_grav/aronnax.conf +++ b/benchmarks/beta_plane_bump_red_grav/aronnax.conf @@ -1,8 +1,5 @@ # Aronnax configuration file. Change the values, but not the names. # -# Each namelist ends with a / -# This is important and should not be deleted. -# # au is viscosity # ah is thickness diffusivity # ar is linear drag between layers From 1dfe4ea4dd5bd1554a6b7812090775a32c519d82 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 22:36:47 -0400 Subject: [PATCH 23/50] Rewrite test_gaussian_bump_red_grav to use the new driver. It passes, up to #96. --- aronnax/driver.py | 2 + test/beta_plane_bump_red_grav/aronnax.conf | 53 ++++++++++++++ test/beta_plane_bump_red_grav/parameters.in | 79 --------------------- test/output_preservation_test.py | 9 ++- 4 files changed, 63 insertions(+), 80 deletions(-) create mode 100644 test/beta_plane_bump_red_grav/aronnax.conf delete mode 100644 test/beta_plane_bump_red_grav/parameters.in diff --git a/aronnax/driver.py b/aronnax/driver.py index 517a5030..e3793f87 100644 --- a/aronnax/driver.py +++ b/aronnax/driver.py @@ -159,6 +159,8 @@ def fortran_option_string(section, name, config): return ".TRUE." else: return ".FALSE." + elif name in ["dx", "dy"]: # Horrible hack around Issue #96, to validate the rest of this refactoring. + return "2e4" else: if config.has_option(section, name): return config.get(section, name) diff --git a/test/beta_plane_bump_red_grav/aronnax.conf b/test/beta_plane_bump_red_grav/aronnax.conf new file mode 100644 index 00000000..bff350a2 --- /dev/null +++ b/test/beta_plane_bump_red_grav/aronnax.conf @@ -0,0 +1,53 @@ +# Aronnax configuration file. Change the values, but not the names. +# +# au is viscosity +# ah is thickness diffusivity +# ar is linear drag between layers +# dt is time step +# slip is free-slip (=0), no-slip (=1), or partial slip (something in between) +# nTimeSteps: number of timesteps before stopping +# dumpFreq: frequency of snapshot output +# avFreq: frequency of averaged output +# hmin: minimum layer thickness allowed by model (for stability) +# maxits: maximum iterations for the successive over relaxation algorithm. Should be at least max(nx,ny), and probably nx*ny +# eps: convergence tolerance for SOR solver +# freesurfFac: 1. = linear implicit free surface, 0. = rigid lid. So far all tests using freesurfFac = 1. have failed +# g is the gravity at interfaces (including surface). must have as many entries as there are layers +# input files are where to look for the various inputs + +[numerics] +au = 500. +ah = 0.0 +ar = 1e-8 +dt = 600. +slip = 0.0 +nTimeSteps = 502 +dumpFreq = 6e4 +avFreq = 3e5 +hmin = 100 +maxits = 1000 +eps = 1e-2 +freesurfFac = 0. +thickness_error = 1e-2 + +[model] +hmean = 400. +H0 = 2000. +RedGrav = yes + +[physics] +g_vec = 0.01 +rho0 = 1035. + +[grid] +nx = 10 +ny = 10 +layers = 1 +dx = 2e4 +dy = 2e4 +fUfile = :beta_plane_u:1e-5,2e-11 +fVfile = :beta_plane_v:1e-5,2e-11 +wetMaskFile = :rectangular_pool: + +[external_forcing] +DumpWind = no diff --git a/test/beta_plane_bump_red_grav/parameters.in b/test/beta_plane_bump_red_grav/parameters.in deleted file mode 100644 index b452b7ec..00000000 --- a/test/beta_plane_bump_red_grav/parameters.in +++ /dev/null @@ -1,79 +0,0 @@ -! Parameter file. Change the values, but not the names. -! -! Each namelist ends with a / -! This is important and should not be deleted. -! -! au is viscosity -! ah is thickness diffusivity -! ar is linear drag between layers -! dt is time step -! slip is free-slip (=0), no-slip (=1), or partial slip (something in between) -! nTimeSteps: number of timesteps before stopping -! dumpFreq: frequency of snapshot output -! avFreq: frequency of averaged output -! hmin: minimum layer thickness allowed by model (for stability) -! maxits: maximum iterations for the successive over relaxation algorithm. Should be at least max(nx,ny), and probably nx*ny -! eps: convergence tolerance for SOR solver -! freesurfFac: 1. = linear implicit free surface, 0. = rigid lid. So far all tests using freesurfFac = 1. have failed -! g is the gravity at interfaces (including surface). must have as many entries as there are layers -! input files are where to look for the various inputs -! - &NUMERICS - au = 500., - ah = 0.0, - ar = 1e-8, - dt = 600., - slip = 0.0, - nTimeSteps = 502, - dumpFreq = 6e4, - avFreq = 3e5, - hmin = 100, - maxits = 1000, - eps = 1e-2, - freesurfFac = 0., - thickness_error = 1e-2, - / - &MODEL - hmean = 400., - depthFile = '', - H0 = 2000., - RedGrav = .TRUE., - / - &SPONGE - spongeHTimeScaleFile = '', - spongeUTimeScaleFile = '', - spongeVTimeScaleFile = '', - spongeHFile = '', - spongeUfile = '', - spongeVfile = '', - / - &PHYSICS - g_vec = 0.01, - rho0 = 1035., - / - &GRID - nx = 10, - ny = 10, - layers = 1, - dx = 2e4, - dy = 2e4, - fUfile = 'input/fu.bin', - fVfile = 'input/fv.bin', - wetMaskFile = 'input/wetmask.bin', - / -! Inital conditions for u, v, and h - &INITIAL_CONDITONS - initUfile = '', - initVfile = '', - initHfile = 'input/initH.bin', - initEtaFile = '', - / - &EXTERNAL_FORCING - zonalWindFile = '', - meridionalWindFile = '', - DumpWind = .FALSE., - wind_mag_time_series_file = '', - / -! input/initH.bin -! - & diff --git a/test/output_preservation_test.py b/test/output_preservation_test.py index 841c17b6..ede907d8 100644 --- a/test/output_preservation_test.py +++ b/test/output_preservation_test.py @@ -8,6 +8,7 @@ import numpy as np import aronnax as aro +import aronnax.driver as drv from aronnax.utils import working_directory self_path = p.dirname(p.abspath(__file__)) @@ -132,9 +133,15 @@ def bump(X, Y): return 500. + 20*np.exp(-((6e5-X)**2 + (5e5-Y)**2)/(2*1e5**2)) aro.write_initial_heights(grid, [bump]) +def bump(X, Y): + return 500. + 20*np.exp(-((6e5-X)**2 + (5e5-Y)**2)/(2*1e5**2)) + def test_gaussian_bump_red_grav(): + xlen = 1e6 + ylen = 1e6 with working_directory(p.join(self_path, "beta_plane_bump_red_grav")): - run_experiment(write_input_beta_plane_bump_red_grav, 10, 10, 1) + drv.simulate(initHfile=[bump], exe="aronnax_test", + nx=10, ny=10, dx=xlen/10, dy=ylen/10) assert_outputs_close(10, 10, 1, 1.5e-13) assert_volume_conservation(10, 10, 1, 1e-5) From 2895d1185a5acd15fdfcbf51f00d1a87c1cf2ca1 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 22:43:28 -0400 Subject: [PATCH 24/50] Explicit variable name makes it a bit easier to add debug prints. --- test/output_preservation_test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/output_preservation_test.py b/test/output_preservation_test.py index ede907d8..1e24dadc 100644 --- a/test/output_preservation_test.py +++ b/test/output_preservation_test.py @@ -71,7 +71,8 @@ def assert_outputs_close(nx, ny, layers, rtol): for outfile in outfiles: ans = aro.interpret_raw_file(p.join("output/", outfile), nx, ny, layers) good_ans = aro.interpret_raw_file(p.join("good-output/", outfile), nx, ny, layers) - assert np.amax(array_relative_error(ans, good_ans)) < rtol + relerr = np.amax(array_relative_error(ans, good_ans)) + assert relerr < rtol def assert_volume_conservation(nx,ny,layers,rtol): hfiles = sorted(glob.glob("output/snap.h.*")) From b892b9702d8b2722d3c1a9e01dbe180f8ce3834a Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 22:48:54 -0400 Subject: [PATCH 25/50] Port the beta plane bump test to the new driver. Turns out the driver was ignoring the botDrag parameter. --- aronnax/driver.py | 1 + test/beta_plane_bump/aronnax.conf | 54 ++++++++++++++++++++ test/beta_plane_bump/parameters.in | 80 ------------------------------ test/output_preservation_test.py | 5 +- 4 files changed, 59 insertions(+), 81 deletions(-) create mode 100644 test/beta_plane_bump/aronnax.conf delete mode 100644 test/beta_plane_bump/parameters.in diff --git a/aronnax/driver.py b/aronnax/driver.py index e3793f87..3a851f23 100644 --- a/aronnax/driver.py +++ b/aronnax/driver.py @@ -51,6 +51,7 @@ def default_configuration(): "au" : "numerics", "ah" : "numerics", "ar" : "numerics", + "botDrag" : "numerics", "dt" : "numerics", "slip" : "numerics", "nTimeSteps" : "numerics", diff --git a/test/beta_plane_bump/aronnax.conf b/test/beta_plane_bump/aronnax.conf new file mode 100644 index 00000000..647bdb9a --- /dev/null +++ b/test/beta_plane_bump/aronnax.conf @@ -0,0 +1,54 @@ +# Aronnax configuration file. Change the values, but not the names. +# +# au is viscosity +# ah is thickness diffusivity +# ar is linear drag between layers +# dt is time step +# slip is free-slip (=0), no-slip (=1), or partial slip (something in between) +# nTimeSteps: number of timesteps before stopping +# dumpFreq: frequency of snapshot output +# avFreq: frequency of averaged output +# hmin: minimum layer thickness allowed by model (for stability) +# maxits: maximum iterations for the successive over relaxation algorithm. Should be at least max(nx,ny), and probably nx*ny +# eps: convergence tolerance for SOR solver +# freesurfFac: 1. = linear implicit free surface, 0. = rigid lid. So far all tests using freesurfFac = 1. have failed +# g is the gravity at interfaces (including surface). must have as many entries as there are layers +# input files are where to look for the various inputs + +[numerics] +au = 500. +ah = 0.0 +ar = 0.0 +botDrag = 1e-6 +dt = 600. +slip = 0.0 +nTimeSteps = 502 +dumpFreq = 1.2e5 +avFreq = 1.2e5 +hmin = 100 +maxits = 1000 +eps = 1e-2 +freesurfFac = 0. +thickness_error = 1e-2 + +[model] +hmean = 400.,1600. +H0 = 2000. +RedGrav = no + +[physics] +g_vec = 9.8, 0.01 +rho0 = 1035. + +[grid] +nx = 10 +ny = 10 +layers = 2 +dx = 2e4 +dy = 2e4 +fUfile = :beta_plane_u:1e-5,2e-11 +fVfile = :beta_plane_v:1e-5,2e-11 +wetMaskFile = :rectangular_pool: + +[external_forcing] +DumpWind = no diff --git a/test/beta_plane_bump/parameters.in b/test/beta_plane_bump/parameters.in deleted file mode 100644 index 7cfb9e8d..00000000 --- a/test/beta_plane_bump/parameters.in +++ /dev/null @@ -1,80 +0,0 @@ -! Parameter file. Change the values, but not the names. -! -! Each namelist ends with a / -! This is important and should not be deleted. -! -! au is viscosity -! ah is thickness diffusivity -! ar is linear drag between layers -! dt is time step -! slip is free-slip (=0), no-slip (=1), or partial slip (something in between) -! nTimeSteps: number of timesteps before stopping -! dumpFreq: frequency of snapshot output -! avFreq: frequency of averaged output -! hmin: minimum layer thickness allowed by model (for stability) -! maxits: maximum iterations for the successive over relaxation algorithm. Should be at least max(nx,ny), and probably nx*ny -! eps: convergence tolerance for SOR solver -! freesurfFac: 1. = linear implicit free surface, 0. = rigid lid. So far all tests using freesurfFac = 1. have failed -! g is the gravity at interfaces (including surface). must have as many entries as there are layers -! input files are where to look for the various inputs -! - &NUMERICS - au = 500., - ah = 0.0, - ar = 0.0, - botDrag = 1e-6, - dt = 600., - slip = 0.0, - nTimeSteps = 502, - dumpFreq = 1.2e5, - avFreq = 1.2e5, - hmin = 100, - maxits = 1000, - eps = 1e-2, - freesurfFac = 0., - thickness_error = 1e-2, - / - &MODEL - hmean = 400.,1600., - depthFile = '', - H0 = 2000., - RedGrav = .FALSE., - / - &SPONGE - spongeHTimeScaleFile = '', - spongeUTimeScaleFile = '', - spongeVTimeScaleFile = '', - spongeHFile = '', - spongeUfile = '', - spongeVfile = '', - / - &PHYSICS - g_vec = 9.8, 0.01, - rho0 = 1035., - / - &GRID - nx = 10, - ny = 10, - layers = 2, - dx = 2e4, - dy = 2e4, - fUfile = 'input/fu.bin', - fVfile = 'input/fv.bin', - wetMaskFile = 'input/wetmask.bin', - / -! Inital conditions for u, v, and h - &INITIAL_CONDITONS - initUfile = '', - initVfile = '', - initHfile = 'input/initH.bin', - initEtaFile = '', - / - &EXTERNAL_FORCING - zonalWindFile = '', - meridionalWindFile = '', - DumpWind = .FALSE., - wind_mag_time_series_file = '', - / -! input/initH.bin -! - & diff --git a/test/output_preservation_test.py b/test/output_preservation_test.py index 1e24dadc..1eca938b 100644 --- a/test/output_preservation_test.py +++ b/test/output_preservation_test.py @@ -159,8 +159,11 @@ def bump(X, Y): aro.write_initial_heights(grid, [bump, lambda X, Y: 2000. - bump(X, Y)]) def test_gaussian_bump(): + xlen = 1e6 + ylen = 1e6 with working_directory(p.join(self_path, "beta_plane_bump")): - run_experiment(write_input_beta_plane_bump, 10, 10, 2) + drv.simulate(initHfile=[bump, lambda X, Y: 2000. - bump(X, Y)], + nx=10, ny=10, exe="aronnax_test", dx=xlen/10, dy=ylen/10) assert_outputs_close(10, 10, 2, 2e-13) assert_volume_conservation(10, 10, 2, 1e-5) From cca22fc4f6e667234783236ca9488c2ab1419835 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 22:49:34 -0400 Subject: [PATCH 26/50] Flush another mis-copied comment. --- benchmarks/beta_plane_bump/aronnax.conf | 3 --- 1 file changed, 3 deletions(-) diff --git a/benchmarks/beta_plane_bump/aronnax.conf b/benchmarks/beta_plane_bump/aronnax.conf index ce5c1a6d..647bdb9a 100644 --- a/benchmarks/beta_plane_bump/aronnax.conf +++ b/benchmarks/beta_plane_bump/aronnax.conf @@ -1,8 +1,5 @@ # Aronnax configuration file. Change the values, but not the names. # -# Each namelist ends with a / -# This is important and should not be deleted. -# # au is viscosity # ah is thickness diffusivity # ar is linear drag between layers From 5ffc2294e68740afd56c458897a79240614609eb Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 22:50:00 -0400 Subject: [PATCH 27/50] More useful debugging output for the agreement tests. --- test/output_preservation_test.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/output_preservation_test.py b/test/output_preservation_test.py index 1eca938b..3fd716ac 100644 --- a/test/output_preservation_test.py +++ b/test/output_preservation_test.py @@ -72,6 +72,10 @@ def assert_outputs_close(nx, ny, layers, rtol): ans = aro.interpret_raw_file(p.join("output/", outfile), nx, ny, layers) good_ans = aro.interpret_raw_file(p.join("good-output/", outfile), nx, ny, layers) relerr = np.amax(array_relative_error(ans, good_ans)) + if relerr >= rtol: + print outfile + print ans + print good_ans assert relerr < rtol def assert_volume_conservation(nx,ny,layers,rtol): From 54efda70ebe1d937b81ba2a1b7f0fd835493b94a Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 22:52:26 -0400 Subject: [PATCH 28/50] Don't need these test input generation helpers anymore. --- test/output_preservation_test.py | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/test/output_preservation_test.py b/test/output_preservation_test.py index 3fd716ac..a4121113 100644 --- a/test/output_preservation_test.py +++ b/test/output_preservation_test.py @@ -126,18 +126,6 @@ def test_f_plane(): assert_outputs_close(10, 10, 2, 1e-15) assert_volume_conservation(10, 10, 2, 1e-5) -def write_input_beta_plane_bump_red_grav(nx, ny, layers): - assert layers == 1 - xlen = 1e6 - ylen = 1e6 - grid = aro.Grid(nx, ny, xlen / nx, ylen / ny) - - aro.write_beta_plane(grid, 1e-5, 2e-11) - aro.write_rectangular_pool(nx, ny) - def bump(X, Y): - return 500. + 20*np.exp(-((6e5-X)**2 + (5e5-Y)**2)/(2*1e5**2)) - aro.write_initial_heights(grid, [bump]) - def bump(X, Y): return 500. + 20*np.exp(-((6e5-X)**2 + (5e5-Y)**2)/(2*1e5**2)) @@ -150,18 +138,6 @@ def test_gaussian_bump_red_grav(): assert_outputs_close(10, 10, 1, 1.5e-13) assert_volume_conservation(10, 10, 1, 1e-5) -def write_input_beta_plane_bump(nx, ny, layers): - assert layers == 2 - xlen = 1e6 - ylen = 1e6 - grid = aro.Grid(nx, ny, xlen / nx, ylen / ny) - - aro.write_beta_plane(grid, 1e-5, 2e-11) - aro.write_rectangular_pool(nx, ny) - def bump(X, Y): - return 500. + 20*np.exp(-((6e5-X)**2 + (5e5-Y)**2)/(2*1e5**2)) - aro.write_initial_heights(grid, [bump, lambda X, Y: 2000. - bump(X, Y)]) - def test_gaussian_bump(): xlen = 1e6 ylen = 1e6 From e22d51171d089c57c81dec68e2d999e190a38265 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Mon, 17 Apr 2017 22:52:57 -0400 Subject: [PATCH 29/50] Ignore generated configuration files. --- test/.gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/.gitignore b/test/.gitignore index a8617d13..abd91f7e 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -2,3 +2,5 @@ input/ output/ run_finished.txt layer thickness dropped below hmin.txt +parameters.in +aronnax-merged.conf From ac3c5b58dffa15cc8e67369ae9d69ed74323d9c0 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Tue, 18 Apr 2017 06:48:12 -0400 Subject: [PATCH 30/50] Rewrite test_f_plane_red_grav in terms of the new driver. --- aronnax/core.py | 15 ++++-- test/f_plane_red_grav/aronnax.conf | 58 +++++++++++++++++++++ test/f_plane_red_grav/parameters.in | 79 ----------------------------- test/output_preservation_test.py | 12 ++--- 4 files changed, 73 insertions(+), 91 deletions(-) create mode 100644 test/f_plane_red_grav/aronnax.conf delete mode 100644 test/f_plane_red_grav/parameters.in diff --git a/aronnax/core.py b/aronnax/core.py index 069a2178..e3f99788 100644 --- a/aronnax/core.py +++ b/aronnax/core.py @@ -95,7 +95,7 @@ def interpret_raw_file(name, nx, ny, layers): ### General input construction helpers -def interpret_initial_heights(grid, h_funcs): +def interpret_initial_heights(grid, *h_funcs): X,Y = np.meshgrid(grid.x, grid.y) initH = np.ones((len(h_funcs), grid.ny, grid.nx)) for i, f in enumerate(h_funcs): @@ -106,7 +106,7 @@ def interpret_initial_heights(grid, h_funcs): return initH def write_initial_heights(grid, h_funcs): - initH = interpret_initial_heights(grid, h_funcs) + initH = interpret_initial_heights(grid, *h_funcs) with fortran_file('initH.bin', 'w') as f: f.write_record(initH.astype(np.float64)) @@ -130,6 +130,12 @@ def write_wind_y(grid, func): ### Specific construction helpers +def f_plane_u(grid, coeff): + return np.ones((grid.nx+1, grid.ny), dtype=np.float64) * coeff + +def f_plane_v(grid, coeff): + return np.ones((grid.nx, grid.ny+1), dtype=np.float64) * coeff + def write_f_plane(nx, ny, coeff): """Write files defining an f-plane approximation to the Coriolis force.""" with fortran_file('fu.bin', 'w') as f: @@ -180,8 +186,11 @@ def write_rectangular_pool(nx, ny): specifier_rx = re.compile(r':(.*):(.*)') ok_generators = { + 'flat': interpret_initial_heights, 'beta_plane_u': beta_plane_u, 'beta_plane_v': beta_plane_v, + 'f_plane_u': f_plane_u, + 'f_plane_v': f_plane_v, 'rectangular_pool': rectangular_pool, } @@ -228,6 +237,6 @@ def interpret_requested_data(requested_data, shape, config): return f.read_reals(dtype=np.float64) else: if shape == "3d": - return interpret_initial_heights(grid, requested_data) + return interpret_initial_heights(grid, *requested_data) else: raise Exception("TODO implement custom generation for other input shapes") diff --git a/test/f_plane_red_grav/aronnax.conf b/test/f_plane_red_grav/aronnax.conf new file mode 100644 index 00000000..f5da7127 --- /dev/null +++ b/test/f_plane_red_grav/aronnax.conf @@ -0,0 +1,58 @@ +# Parameter file. Change the values, but not the names. +# +# au is viscosity +# ah is thickness diffusivity +# ar is linear drag between layers +# dt is time step +# slip is free-slip (=0), no-slip (=1), or partial slip (something in between) +# nTimeSteps: number of timesteps before stopping +# dumpFreq: frequency of snapshot output +# avFreq: frequency of averaged output +# hmin: minimum layer thickness allowed by model (for stability) +# maxits: maximum iterations for the successive over relaxation algorithm. Should be at least max(nx,ny), and probably nx*ny +# eps: convergence tolerance for SOR solver +# freesurfFac: 1. = linear implicit free surface, 0. = rigid lid. So far all tests using freesurfFac = 1. have failed +# g is the gravity at interfaces (including surface). must have as many entries as there are layers +# input files are where to look for the various inputs + +[numerics] +au = 500. +ah = 0.0 +ar = 1e-8 +dt = 600. +slip = 0.0 +nTimeSteps = 10001 +dumpFreq = 3e6 +avFreq = 3e6 +hmin = 100 +maxits = 1000 +eps = 1e-2 +freesurfFac = 0. +thickness_error = 1e-2 + +[model] +hmean = 400. +H0 = 2000. +RedGrav = yes + +[physics] +g_vec = 0.01 +rho0 = 1035. + +[grid] +nx = 10 +ny = 10 +layers = 1 +dx = 2e4 +dy = 2e4 +fUfile = :f_plane_u:10e-4 +fVfile = :f_plane_v:10e-4 +wetMaskFile = :rectangular_pool: + +# Inital conditions for h +[initial_conditons] +initHfile = :flat:400.0 + +[external_forcing] +DumpWind = no + diff --git a/test/f_plane_red_grav/parameters.in b/test/f_plane_red_grav/parameters.in deleted file mode 100644 index 8663c323..00000000 --- a/test/f_plane_red_grav/parameters.in +++ /dev/null @@ -1,79 +0,0 @@ -! Parameter file. Change the values, but not the names. -! -! Each namelist ends with a / -! This is important and should not be deleted. -! -! au is viscosity -! ah is thickness diffusivity -! ar is linear drag between layers -! dt is time step -! slip is free-slip (=0), no-slip (=1), or partial slip (something in between) -! nTimeSteps: number of timesteps before stopping -! dumpFreq: frequency of snapshot output -! avFreq: frequency of averaged output -! hmin: minimum layer thickness allowed by model (for stability) -! maxits: maximum iterations for the successive over relaxation algorithm. Should be at least max(nx,ny), and probably nx*ny -! eps: convergence tolerance for SOR solver -! freesurfFac: 1. = linear implicit free surface, 0. = rigid lid. So far all tests using freesurfFac = 1. have failed -! g is the gravity at interfaces (including surface). must have as many entries as there are layers -! input files are where to look for the various inputs -! - &NUMERICS - au = 500., - ah = 0.0, - ar = 1e-8, - dt = 600., - slip = 0.0, - nTimeSteps = 10001, - dumpFreq = 3e6, - avFreq = 3e6, - hmin = 100, - maxits = 1000, - eps = 1e-2, - freesurfFac = 0., - thickness_error = 1e-2, - / - &MODEL - hmean = 400., - depthFile = '', - H0 = 2000., - RedGrav = .TRUE., - / - &SPONGE - spongeHTimeScaleFile = '', - spongeUTimeScaleFile = '', - spongeVTimeScaleFile = '', - spongeHFile = '', - spongeUfile = '', - spongeVfile = '', - / - &PHYSICS - g_vec = 0.01, - rho0 = 1035., - / - &GRID - nx = 10, - ny = 10, - layers = 1, - dx = 2e4, - dy = 2e4, - fUfile = 'input/fu.bin', - fVfile = 'input/fv.bin', - wetMaskFile = 'input/wetmask.bin', - / -! Inital conditions for u, v, and h - &INITIAL_CONDITONS - initUfile = '', - initVfile = '', - initHfile = 'input/initH.bin', - initEtaFile = '', - / - &EXTERNAL_FORCING - zonalWindFile = '', - meridionalWindFile = '', - DumpWind = .FALSE., - wind_mag_time_series_file = '', - / -! input/initH.bin -! - & diff --git a/test/output_preservation_test.py b/test/output_preservation_test.py index a4121113..2118e20d 100644 --- a/test/output_preservation_test.py +++ b/test/output_preservation_test.py @@ -96,18 +96,12 @@ def assert_volume_conservation(nx,ny,layers,rtol): ### The test cases themselves -def write_input_f_plane_red_grav(nx, ny, layers): - assert layers == 1 +def test_f_plane_red_grav(): xlen = 1e6 ylen = 1e6 - grid = aro.Grid(nx, ny, xlen / nx, ylen / ny) - aro.write_f_plane(nx, ny, 10e-4) - aro.write_rectangular_pool(nx, ny) - aro.write_initial_heights(grid, [400.0]) - -def test_f_plane_red_grav(): with working_directory(p.join(self_path, "f_plane_red_grav")): - run_experiment(write_input_f_plane_red_grav, 10, 10, 1) + drv.simulate(exe="aronnax_test", + nx=10, ny=10, dx=xlen/10, dy=ylen/10) assert_outputs_close(10, 10, 1, 1e-15) assert_volume_conservation(10, 10, 1, 1e-5) From 25ebd127002cfd527a2029b81a6f6198bb731c1b Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Tue, 18 Apr 2017 06:55:34 -0400 Subject: [PATCH 31/50] Rewrite test_f_plane in terms of the new driver. --- aronnax/core.py | 9 +--- test/f_plane/aronnax.conf | 59 +++++++++++++++++++++++ test/f_plane/parameters.in | 80 -------------------------------- test/output_preservation_test.py | 12 ++--- 4 files changed, 64 insertions(+), 96 deletions(-) create mode 100644 test/f_plane/aronnax.conf delete mode 100644 test/f_plane/parameters.in diff --git a/aronnax/core.py b/aronnax/core.py index e3f99788..30d0008b 100644 --- a/aronnax/core.py +++ b/aronnax/core.py @@ -131,18 +131,13 @@ def write_wind_y(grid, func): ### Specific construction helpers def f_plane_u(grid, coeff): + """Define an f-plane approximation to the Coriolis force (u component).""" return np.ones((grid.nx+1, grid.ny), dtype=np.float64) * coeff def f_plane_v(grid, coeff): + """Define an f-plane approximation to the Coriolis force (v component).""" return np.ones((grid.nx, grid.ny+1), dtype=np.float64) * coeff -def write_f_plane(nx, ny, coeff): - """Write files defining an f-plane approximation to the Coriolis force.""" - with fortran_file('fu.bin', 'w') as f: - f.write_record(np.ones((nx+1, ny), dtype=np.float64) * coeff) - with fortran_file('fv.bin', 'w') as f: - f.write_record(np.ones((nx, ny+1), dtype=np.float64) * coeff) - def beta_plane_u(grid, f0, beta): _, Y = np.meshgrid(grid.xp1, grid.y) fu = f0 + Y*beta diff --git a/test/f_plane/aronnax.conf b/test/f_plane/aronnax.conf new file mode 100644 index 00000000..8baf38cb --- /dev/null +++ b/test/f_plane/aronnax.conf @@ -0,0 +1,59 @@ +# Parameter file. Change the values, but not the names. +# +# au is viscosity +# ah is thickness diffusivity +# ar is linear drag between layers +# dt is time step +# slip is free-slip (=0), no-slip (=1), or partial slip (something in between) +# nTimeSteps: number of timesteps before stopping +# dumpFreq: frequency of snapshot output +# avFreq: frequency of averaged output +# hmin: minimum layer thickness allowed by model (for stability) +# maxits: maximum iterations for the successive over relaxation algorithm. Should be at least max(nx,ny), and probably nx*ny +# eps: convergence tolerance for SOR solver +# freesurfFac: 1. = linear implicit free surface, 0. = rigid lid. So far all tests using freesurfFac = 1. have failed +# g is the gravity at interfaces (including surface). must have as many entries as there are layers +# input files are where to look for the various inputs + +[numerics] +au = 500. +ah = 0.0 +ar = 1e-8 +botDrag = 1e-6 +dt = 100. +slip = 0.0 +nTimeSteps = 61 +dumpFreq = 2e3 +avFreq = 6e3 +hmin = 100 +maxits = 500 +eps = 1e-2 +freesurfFac = 0. +thickness_error = 1e-2 + +[model] +hmean = 400.,1600. +H0 = 2000. +RedGrav = no + +[physics] +g_vec = 9.8, 0.01 +rho0 = 1035. + +[grid] +nx = 10 +ny = 10 +layers = 2 +dx = 2e4 +dy = 2e4 +fUfile = :f_plane_u:10e-4 +fVfile = :f_plane_v:10e-4 +wetMaskFile = :rectangular_pool: + +# Inital conditions for h +[initial_conditons] +initHfile = :flat:400.0,1600.0 + +[external_forcing] +DumpWind = no + diff --git a/test/f_plane/parameters.in b/test/f_plane/parameters.in deleted file mode 100644 index 7a771650..00000000 --- a/test/f_plane/parameters.in +++ /dev/null @@ -1,80 +0,0 @@ -! Parameter file. Change the values, but not the names. -! -! Each namelist ends with a / -! This is important and should not be deleted. -! -! au is viscosity -! ah is thickness diffusivity -! ar is linear drag between layers -! dt is time step -! slip is free-slip (=0), no-slip (=1), or partial slip (something in between) -! nTimeSteps: number of timesteps before stopping -! dumpFreq: frequency of snapshot output -! avFreq: frequency of averaged output -! hmin: minimum layer thickness allowed by model (for stability) -! maxits: maximum iterations for the successive over relaxation algorithm. Should be at least max(nx,ny), and probably nx*ny -! eps: convergence tolerance for SOR solver -! freesurfFac: 1. = linear implicit free surface, 0. = rigid lid. So far all tests using freesurfFac = 1. have failed -! g is the gravity at interfaces (including surface). must have as many entries as there are layers -! input files are where to look for the various inputs -! - &NUMERICS - au = 500., - ah = 0.0, - ar = 1e-8, - botDrag = 1e-6, - dt = 100., - slip = 0.0, - nTimeSteps = 61, - dumpFreq = 2e3, - avFreq = 6e3, - hmin = 100, - maxits = 500, - eps = 1e-2, - freesurfFac = 0., - thickness_error = 1e-2, - / - &MODEL - hmean = 400.,1600., - depthFile = '', - H0 = 2000., - RedGrav = .FALSE., - / - &SPONGE - spongeHTimeScaleFile = '', - spongeUTimeScaleFile = '', - spongeVTimeScaleFile = '', - spongeHFile = '', - spongeUfile = '', - spongeVfile = '', - / - &PHYSICS - g_vec = 9.8, 0.01, - rho0 = 1035., - / - &GRID - nx = 10, - ny = 10, - layers = 2, - dx = 2e4, - dy = 2e4, - fUfile = 'input/fu.bin', - fVfile = 'input/fv.bin', - wetMaskFile = 'input/wetmask.bin', - / -! Inital conditions for u, v, and h - &INITIAL_CONDITONS - initUfile = '', - initVfile = '', - initHfile = 'input/initH.bin', - initEtaFile = '', - / - &EXTERNAL_FORCING - zonalWindFile = '', - meridionalWindFile = '', - DumpWind = .FALSE., - wind_mag_time_series_file = '', - / -! input/initH.bin -! - & diff --git a/test/output_preservation_test.py b/test/output_preservation_test.py index 2118e20d..eed03e38 100644 --- a/test/output_preservation_test.py +++ b/test/output_preservation_test.py @@ -105,18 +105,12 @@ def test_f_plane_red_grav(): assert_outputs_close(10, 10, 1, 1e-15) assert_volume_conservation(10, 10, 1, 1e-5) -def write_input_f_plane(nx, ny, layers): - assert layers == 2 +def test_f_plane(): xlen = 1e6 ylen = 1e6 - grid = aro.Grid(nx, ny, xlen / nx, ylen / ny) - aro.write_f_plane(nx, ny, 10e-4) - aro.write_rectangular_pool(nx, ny) - aro.write_initial_heights(grid, [400.0, 1600.0]) - -def test_f_plane(): with working_directory(p.join(self_path, "f_plane")): - run_experiment(write_input_f_plane, 10, 10, 2) + drv.simulate(exe="aronnax_test", + nx=10, ny=10, dx=xlen/10, dy=ylen/10) assert_outputs_close(10, 10, 2, 1e-15) assert_volume_conservation(10, 10, 2, 1e-5) From 1e963a0327c5e3e2cb4d9b7c441ebf1ec68cb303 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Tue, 18 Apr 2017 08:29:04 -0400 Subject: [PATCH 32/50] Port test_beta_plane_gyre_red_grav to the new driver. --- aronnax/core.py | 11 ++- aronnax/driver.py | 2 +- test/beta_plane_gyre_red_grav/aronnax.conf | 58 +++++++++++++++ test/beta_plane_gyre_red_grav/parameters.in | 79 --------------------- test/output_preservation_test.py | 14 ++-- 5 files changed, 72 insertions(+), 92 deletions(-) create mode 100644 test/beta_plane_gyre_red_grav/aronnax.conf delete mode 100644 test/beta_plane_gyre_red_grav/parameters.in diff --git a/aronnax/core.py b/aronnax/core.py index 30d0008b..faaac33c 100644 --- a/aronnax/core.py +++ b/aronnax/core.py @@ -110,14 +110,18 @@ def write_initial_heights(grid, h_funcs): with fortran_file('initH.bin', 'w') as f: f.write_record(initH.astype(np.float64)) -def write_wind_x(grid, func): +def wind_x(grid, func): X,Y = np.meshgrid(grid.xp1, grid.y) if isinstance(func, (int, long, float)): wind_x = np.ones(grid.ny, grid.nx+1) * func else: wind_x = func(X, Y) + return wind_x + +def write_wind_x(grid, func): + wind = wind_x(grid, func) with fortran_file('wind_x.bin', 'w') as f: - f.write_record(wind_x.astype(np.float64)) + f.write_record(wind.astype(np.float64)) def write_wind_y(grid, func): X,Y = np.meshgrid(grid.y, grid.xp1) @@ -187,6 +191,7 @@ def write_rectangular_pool(nx, ny): 'f_plane_u': f_plane_u, 'f_plane_v': f_plane_v, 'rectangular_pool': rectangular_pool, + 'wind_x': wind_x, } def interpret_data_specifier(string): @@ -233,5 +238,7 @@ def interpret_requested_data(requested_data, shape, config): else: if shape == "3d": return interpret_initial_heights(grid, *requested_data) + if shape == "2dx": + return wind_x(grid, requested_data) else: raise Exception("TODO implement custom generation for other input shapes") diff --git a/aronnax/driver.py b/aronnax/driver.py index 3a851f23..9838c3f6 100644 --- a/aronnax/driver.py +++ b/aronnax/driver.py @@ -127,7 +127,7 @@ def compile_core(config): "initVfile" : "3d", "initHfile" : "3d", "initEtaFile" : "2d", - "zonalWindFile" : "2d", + "zonalWindFile" : "2dx", "meridionalWindFile" : "2d", "wind_mag_time_series_file" : "time", } diff --git a/test/beta_plane_gyre_red_grav/aronnax.conf b/test/beta_plane_gyre_red_grav/aronnax.conf new file mode 100644 index 00000000..f670b6da --- /dev/null +++ b/test/beta_plane_gyre_red_grav/aronnax.conf @@ -0,0 +1,58 @@ +# Parameter file. Change the values, but not the names. +# +# au is viscosity +# ah is thickness diffusivity +# ar is linear drag between layers +# dt is time step +# slip is free-slip (=0), no-slip (=1), or partial slip (something in between) +# nTimeSteps: number of timesteps before stopping +# dumpFreq: frequency of snapshot output +# avFreq: frequency of averaged output +# hmin: minimum layer thickness allowed by model (for stability) +# maxits: maximum iterations for the successive over relaxation algorithm. Should be at least max(nx,ny), and probably nx*ny +# eps: convergence tolerance for SOR solver +# freesurfFac: 1. = linear implicit free surface, 0. = rigid lid. So far all tests using freesurfFac = 1. have failed +# g is the gravity at interfaces (including surface). must have as many entries as there are layers +# input files are where to look for the various inputs + +[numerics] +au = 500. +ah = 0.0 +ar = 1e-8 +dt = 600. +slip = 1.0 +nTimeSteps = 8001 +dumpFreq = 12e5 +avFreq = 48e5 +hmin = 100 +maxits = 1000 +eps = 1e-2 +freesurfFac = 0. +thickness_error = 1e-2 + +[model] +hmean = 400. +H0 = 2000. +RedGrav = yes + +[physics] +g_vec = 0.01 +rho0 = 1035. + +[grid] +nx = 10 +ny = 10 +layers = 1 +dx = 2e4 +dy = 2e4 +fUfile = :beta_plane_u:1e-5,2e-11 +fVfile = :beta_plane_v:1e-5,2e-11 +wetMaskFile = :rectangular_pool: + +# Inital conditions h +[initial_conditons] +initHfile = :flat:400.0 + +[external_forcing] +DumpWind = no + diff --git a/test/beta_plane_gyre_red_grav/parameters.in b/test/beta_plane_gyre_red_grav/parameters.in deleted file mode 100644 index 95ee246a..00000000 --- a/test/beta_plane_gyre_red_grav/parameters.in +++ /dev/null @@ -1,79 +0,0 @@ -! Parameter file. Change the values, but not the names. -! -! Each namelist ends with a / -! This is important and should not be deleted. -! -! au is viscosity -! ah is thickness diffusivity -! ar is linear drag between layers -! dt is time step -! slip is free-slip (=0), no-slip (=1), or partial slip (something in between) -! nTimeSteps: number of timesteps before stopping -! dumpFreq: frequency of snapshot output -! avFreq: frequency of averaged output -! hmin: minimum layer thickness allowed by model (for stability) -! maxits: maximum iterations for the successive over relaxation algorithm. Should be at least max(nx,ny), and probably nx*ny -! eps: convergence tolerance for SOR solver -! freesurfFac: 1. = linear implicit free surface, 0. = rigid lid. So far all tests using freesurfFac = 1. have failed -! g is the gravity at interfaces (including surface). must have as many entries as there are layers -! input files are where to look for the various inputs -! - &NUMERICS - au = 500., - ah = 0.0, - ar = 1e-8, - dt = 600., - slip = 1.0, - nTimeSteps = 8001, - dumpFreq = 12e5, - avFreq = 48e5, - hmin = 100, - maxits = 1000, - eps = 1e-2, - freesurfFac = 0., - thickness_error = 1e-2, - / - &MODEL - hmean = 400., - depthFile = '', - H0 = 2000., - RedGrav = .TRUE., - / - &SPONGE - spongeHTimeScaleFile = '', - spongeUTimeScaleFile = '', - spongeVTimeScaleFile = '', - spongeHFile = '', - spongeUfile = '', - spongeVfile = '', - / - &PHYSICS - g_vec = 0.01, - rho0 = 1035., - / - &GRID - nx = 10, - ny = 10, - layers = 1, - dx = 2e4, - dy = 2e4, - fUfile = 'input/fu.bin', - fVfile = 'input/fv.bin', - wetMaskFile = 'input/wetmask.bin', - / -! Inital conditions for u, v, and h - &INITIAL_CONDITONS - initUfile = '', - initVfile = '', - initHfile = 'input/initH.bin', - initEtaFile = '', - / - &EXTERNAL_FORCING - zonalWindFile = 'input/wind_x.bin', - meridionalWindFile = '', - DumpWind = .FALSE., - wind_mag_time_series_file = '', - / -! input/initH.bin -! - & diff --git a/test/output_preservation_test.py b/test/output_preservation_test.py index eed03e38..8420033b 100644 --- a/test/output_preservation_test.py +++ b/test/output_preservation_test.py @@ -135,22 +135,16 @@ def test_gaussian_bump(): assert_outputs_close(10, 10, 2, 2e-13) assert_volume_conservation(10, 10, 2, 1e-5) -def write_input_beta_plane_gyre_red_grav(nx, ny, layers): - assert layers == 1 +def test_beta_plane_gyre_red_grav(): xlen = 1e6 ylen = 2e6 + nx = 10; ny = 10 grid = aro.Grid(nx, ny, xlen / nx, ylen / ny) - - aro.write_beta_plane(grid, 1e-5, 2e-11) - aro.write_rectangular_pool(nx, ny) - aro.write_initial_heights(grid, [400.0]) def wind(_, Y): return 0.05 * (1 - np.cos(2*np.pi * Y/np.max(grid.y))) - aro.write_wind_x(grid, wind) - -def test_beta_plane_gyre_red_grav(): with working_directory(p.join(self_path, "beta_plane_gyre_red_grav")): - run_experiment(write_input_beta_plane_gyre_red_grav, 10, 10, 1, valgrind=True) + drv.simulate(zonalWindFile=wind, valgrind=True, + nx=10, ny=10, exe="aronnax_test", dx=xlen/10, dy=ylen/10) assert_outputs_close(10, 10, 1, 2e-13) assert_volume_conservation(10, 10, 1, 1e-5) From a9170b676fee7cb4e3a6214e69c4735780de3371 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Tue, 18 Apr 2017 08:35:52 -0400 Subject: [PATCH 33/50] Port test_beta_plane_gyre to new driver. --- test/beta_plane_gyre/aronnax.conf | 59 ++++++++++++++++++++++ test/beta_plane_gyre/parameters.in | 81 ------------------------------ test/output_preservation_test.py | 14 ++---- 3 files changed, 63 insertions(+), 91 deletions(-) create mode 100644 test/beta_plane_gyre/aronnax.conf delete mode 100644 test/beta_plane_gyre/parameters.in diff --git a/test/beta_plane_gyre/aronnax.conf b/test/beta_plane_gyre/aronnax.conf new file mode 100644 index 00000000..7c7159cf --- /dev/null +++ b/test/beta_plane_gyre/aronnax.conf @@ -0,0 +1,59 @@ +# Aronnax configuration file. Change the values, but not the names. +# +# au is viscosity +# ah is thickness diffusivity +# ar is linear drag between layers +# dt is time step +# slip is free-slip (=0), no-slip (=1), or partial slip (something in between) +# nTimeSteps: number of timesteps before stopping +# dumpFreq: frequency of snapshot output +# avFreq: frequency of averaged output +# hmin: minimum layer thickness allowed by model (for stability) +# maxits: maximum iterations for the successive over relaxation algorithm. Should be at least max(nx,ny), and probably nx*ny +# eps: convergence tolerance for SOR solver +# freesurfFac: 1. = linear implicit free surface, 0. = rigid lid. So far all tests using freesurfFac = 1. have failed +# g is the gravity at interfaces (including surface). must have as many entries as there are layers +# input files are where to look for the various inputs + +[numerics] +au = 500. +ah = 500.0,500. +ar = 1e-8 +botDrag = 1e-6 +dt = 600. +slip = 1.0 +nTimeSteps = 801 +dumpFreq = 12e4 +avFreq = 48e4 +hmin = 100 +maxits = 1000 +eps = 1e-2 +freesurfFac = 0. +thickness_error = 1e-2 + +[model] +hmean = 600.,1400. +H0 = 2000. +RedGrav = no + +[physics] +g_vec = 9.8, 0.01 +rho0 = 1035. + +[grid] +nx = 10 +ny = 10 +layers = 2 +dx = 2e4 +dy = 2e4 +fUfile = :beta_plane_u:1e-5,2e-11 +fVfile = :beta_plane_v:1e-5,2e-11 +wetMaskFile = :rectangular_pool: + +# Inital conditions for h +[initial_conditons] +initHfile = :flat:600.0,1400.0 + +[external_forcing] +DumpWind = yes + diff --git a/test/beta_plane_gyre/parameters.in b/test/beta_plane_gyre/parameters.in deleted file mode 100644 index e55102fe..00000000 --- a/test/beta_plane_gyre/parameters.in +++ /dev/null @@ -1,81 +0,0 @@ -! Parameter file. Change the values, but not the names. -! -! Each namelist ends with a / -! This is important and should not be deleted. -! -! au is viscosity -! ah is thickness diffusivity -! ar is linear drag between layers -! dt is time step -! slip is free-slip (=0), no-slip (=1), or partial slip (something in between) -! nTimeSteps: number of timesteps before stopping -! dumpFreq: frequency of snapshot output -! avFreq: frequency of averaged output -! hmin: minimum layer thickness allowed by model (for stability) -! maxits: maximum iterations for the successive over relaxation algorithm. Should be at least max(nx,ny), and probably nx*ny -! eps: convergence tolerance for SOR solver -! freesurfFac: 1. = linear implicit free surface, 0. = rigid lid. So far all tests using freesurfFac = 1. have failed -! g is the gravity at interfaces (including surface). must have as many entries as there are layers -! input files are where to look for the various inputs -! - &NUMERICS - au = 500., - ah = 500.0,500., - ar = 1e-8, - botDrag = 1e-6, - dt = 600., - slip = 1.0, - nTimeSteps = 801, - dumpFreq = 12e4, - avFreq = 48e4, - hmin = 100, - maxits = 1000, - eps = 1e-2, - freesurfFac = 0., - thickness_error = 1e-2, - / - &MODEL - hmean = 600.,1400., - depthFile = '', - H0 = 2000., - RedGrav = .FALSE., - / - &SPONGE - spongeHTimeScaleFile = '', - spongeUTimeScaleFile = '', - spongeVTimeScaleFile = '', - spongeHFile = '', - spongeUfile = '', - spongeVfile = '', - / - &PHYSICS - g_vec = 9.8, 0.01, - rho0 = 1035., - / - &GRID - nx = 10, - ny = 10, - layers = 2, - dx = 2e4, - dy = 2e4, - fUfile = 'input/fu.bin', - fVfile = 'input/fv.bin', - wetMaskFile = 'input/wetmask.bin', - / -! Inital conditions for u, v, and h - &INITIAL_CONDITONS - initUfile = '', - initVfile = '', - initHfile = '', -!'input/initH.bin', - initEtaFile = '', - / - &EXTERNAL_FORCING - zonalWindFile = 'input/wind_x.bin', - meridionalWindFile = '', - DumpWind = .TRUE., - wind_mag_time_series_file = '', - / -! input/initH.bin -! - & diff --git a/test/output_preservation_test.py b/test/output_preservation_test.py index 8420033b..6a1204b1 100644 --- a/test/output_preservation_test.py +++ b/test/output_preservation_test.py @@ -148,21 +148,15 @@ def wind(_, Y): assert_outputs_close(10, 10, 1, 2e-13) assert_volume_conservation(10, 10, 1, 1e-5) -def write_input_beta_plane_gyre(nx, ny, layers): - assert layers == 2 +def test_beta_plane_gyre(): xlen = 1e6 ylen = 2e6 + nx = 10; ny = 10 grid = aro.Grid(nx, ny, xlen / nx, ylen / ny) - - aro.write_beta_plane(grid, 1e-5, 2e-11) - aro.write_rectangular_pool(nx, ny) - aro.write_initial_heights(grid, [600.0, 1400.0]) def wind(_, Y): return 0.05 * (1 - np.cos(2*np.pi * Y/np.max(grid.y))) - aro.write_wind_x(grid, wind) - -def test_beta_plane_gyre(): with working_directory(p.join(self_path, "beta_plane_gyre")): - run_experiment(write_input_beta_plane_gyre, 10, 10, 2, valgrind=True) + drv.simulate(zonalWindFile=wind, valgrind=True, + nx=10, ny=10, exe="aronnax_test", dx=xlen/10, dy=ylen/10) assert_outputs_close(10, 10, 2, 3e-12) assert_volume_conservation(10, 10, 2, 1e-5) From 2b467ddc9ba152d688f668bb2e9da60a59dae37d Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Tue, 18 Apr 2017 08:38:01 -0400 Subject: [PATCH 34/50] This helper code has been superseded by the new driver. --- test/output_preservation_test.py | 40 -------------------------------- 1 file changed, 40 deletions(-) diff --git a/test/output_preservation_test.py b/test/output_preservation_test.py index 6a1204b1..16dc5381 100644 --- a/test/output_preservation_test.py +++ b/test/output_preservation_test.py @@ -12,49 +12,9 @@ from aronnax.utils import working_directory self_path = p.dirname(p.abspath(__file__)) -root_path = p.dirname(self_path) ### General helpers -def tweak_parameters(nx, ny, layers): - sub.check_call( - "cat parameters.in " + - "| sed 's/^ nx =.*,$/ nx = %d,/'" % (nx,) + - "| sed 's/^ ny =.*,$/ ny = %d,/'" % (ny,) + - "| sed 's/^ layers =.*,$/ layers = %d,/'" % (layers,) + - "> parameters.new", shell=True) - sub.check_call(["mv", "parameters.new", "parameters.in"]) - -def run_experiment(write_input, nx, ny, layers, aro_exec=None, valgrind=False, perf=False): - if aro_exec is None: - aro_exec = "aronnax_test" - sub.check_call(["rm", "-rf", "input/"]) - sub.check_call(["rm", "-rf", "output/"]) - sub.check_call(["mkdir", "-p", "output/"]) - with working_directory(root_path): - sub.check_call(["make", aro_exec]) - with working_directory("input"): - write_input(nx, ny, layers) - tweak_parameters(nx, ny, layers) - then = time.time() - env = dict(os.environ, GFORTRAN_STDERR_UNIT="17") - if valgrind or 'ARONNAX_TEST_VALGRIND_ALL' in os.environ: - assert not perf - sub.check_call(["valgrind", "--error-exitcode=5", p.join(root_path, aro_exec)], - env=env) - elif perf: - perf_cmds = ["perf", "stat", "-e", "r530010", # "flops", on my CPU. - "-e", "L1-dcache-loads", "-e", "L1-dcache-load-misses", - "-e", "L1-dcache-stores", "-e", "L1-dcache-store-misses", - "-e", "L1-icache-loads", "-e", "L1-icache-misses", - "-e", "L1-dcache-prefetches", - "-e", "branch-instructions", "-e", "branch-misses"] - sub.check_call(perf_cmds + [p.join(root_path, aro_exec)], env=env) - else: - sub.check_call([p.join(root_path, aro_exec)], env=env) - run_time = time.time() - then - return run_time - def array_relative_error(a1, a2): """Return the elementwise absolute difference between the inputs, scaled by the maximum value that occurs in the input.""" From 4b3ac7a3483b9ecf047bd82589df0d5f2a326c09 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Tue, 18 Apr 2017 08:41:12 -0400 Subject: [PATCH 35/50] All of these writer helpers are subsumed by the new driver too. --- aronnax/core.py | 39 +++++---------------------------------- 1 file changed, 5 insertions(+), 34 deletions(-) diff --git a/aronnax/core.py b/aronnax/core.py index faaac33c..2004a563 100644 --- a/aronnax/core.py +++ b/aronnax/core.py @@ -105,11 +105,6 @@ def interpret_initial_heights(grid, *h_funcs): initH[i,:,:] = f(X, Y) return initH -def write_initial_heights(grid, h_funcs): - initH = interpret_initial_heights(grid, *h_funcs) - with fortran_file('initH.bin', 'w') as f: - f.write_record(initH.astype(np.float64)) - def wind_x(grid, func): X,Y = np.meshgrid(grid.xp1, grid.y) if isinstance(func, (int, long, float)): @@ -118,19 +113,13 @@ def wind_x(grid, func): wind_x = func(X, Y) return wind_x -def write_wind_x(grid, func): - wind = wind_x(grid, func) - with fortran_file('wind_x.bin', 'w') as f: - f.write_record(wind.astype(np.float64)) - -def write_wind_y(grid, func): +def wind_y(grid, func): X,Y = np.meshgrid(grid.y, grid.xp1) if isinstance(func, (int, long, float)): wind_y = np.ones(grid.ny+1, grid.nx) * func else: wind_y = func(X, Y) - with fortran_file('wind_y.bin', 'w') as f: - f.write_record(wind_y.astype(np.float64)) + return wind_y ### Specific construction helpers @@ -143,27 +132,19 @@ def f_plane_v(grid, coeff): return np.ones((grid.nx, grid.ny+1), dtype=np.float64) * coeff def beta_plane_u(grid, f0, beta): + """Define a beta-plane approximation to the Coriolis force (u component).""" _, Y = np.meshgrid(grid.xp1, grid.y) fu = f0 + Y*beta return fu def beta_plane_v(grid, f0, beta): + """Define a beta-plane approximation to the Coriolis force (v component).""" _, Y = np.meshgrid(grid.x, grid.yp1) fv = f0 + Y*beta return fv -def write_beta_plane(grid, f0, beta): - """Write files defining a beta-plane approximation to the Coriolis force.""" - with fortran_file('fu.bin', 'w') as f: - _, Y = np.meshgrid(grid.xp1, grid.y) - fu = f0 + Y*beta - f.write_record(fu.astype(np.float64)) - with fortran_file('fv.bin', 'w') as f: - _, Y = np.meshgrid(grid.x, grid.yp1) - fv = f0 + Y*beta - f.write_record(fv.astype(np.float64)) - def rectangular_pool(grid): + """The wet mask file for a maximal rectangular pool.""" nx = grid.nx; ny = grid.ny wetmask = np.ones((nx, ny), dtype=np.float64) wetmask[ 0, :] = 0 @@ -172,16 +153,6 @@ def rectangular_pool(grid): wetmask[ :,-1] = 0 return wetmask -def write_rectangular_pool(nx, ny): - """Write the wet mask file for a maximal rectangular pool.""" - with fortran_file('wetmask.bin', 'w') as f: - wetmask = np.ones((nx, ny), dtype=np.float64) - wetmask[ 0, :] = 0 - wetmask[-1, :] = 0 - wetmask[ :, 0] = 0 - wetmask[ :,-1] = 0 - f.write_record(wetmask) - specifier_rx = re.compile(r':(.*):(.*)') ok_generators = { From f22c4e39dc0806b1227b22d0901ce0ffcdc01855 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Tue, 18 Apr 2017 08:45:13 -0400 Subject: [PATCH 36/50] Update documentation references to new input generators. --- aronnax/core.py | 1 + docs/input_generation.rst | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/aronnax/core.py b/aronnax/core.py index 2004a563..cd8a1b62 100644 --- a/aronnax/core.py +++ b/aronnax/core.py @@ -163,6 +163,7 @@ def rectangular_pool(grid): 'f_plane_v': f_plane_v, 'rectangular_pool': rectangular_pool, 'wind_x': wind_x, + 'wind_y': wind_y, } def interpret_data_specifier(string): diff --git a/docs/input_generation.rst b/docs/input_generation.rst index 4d67d404..14048fec 100644 --- a/docs/input_generation.rst +++ b/docs/input_generation.rst @@ -1,7 +1,9 @@ Input generators ******************* -Aronnax includes a number helper functions for generating input fields. +Aronnax includes a number of helper functions for generating input fields. +These can be called with numerical arguments (generating very simple input fields) +directory from the aronnax.conf file, using the syntax `:generator_name:arg1,arg2,...,argn`. Grid ===== @@ -14,22 +16,26 @@ Forcings ========== -.. autofunction:: aronnax.write_wind_x +.. autofunction:: aronnax.wind_x -.. autofunction:: aronnax.write_wind_y +.. autofunction:: aronnax.wind_y Initial conditions =================== -.. autofunction:: aronnax.write_initial_heights +.. autofunction:: aronnax.interpret_initial_heights Domain fields =============== -.. autofunction:: aronnax.write_f_plane +.. autofunction:: aronnax.f_plane_u -.. autofunction:: aronnax.write_beta_plane +.. autofunction:: aronnax.f_plane_v -.. autofunction:: aronnax.write_rectangular_pool \ No newline at end of file +.. autofunction:: aronnax.beta_plane_u + +.. autofunction:: aronnax.beta_plane_v + +.. autofunction:: aronnax.rectangular_pool From 9c8371f5115e434baa67393e5f8ab89e8cfba631 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Tue, 18 Apr 2017 08:48:18 -0400 Subject: [PATCH 37/50] Rename "interpret_initial_heights" to the less awkward "depths"; match its config file name to its new Python name. --- aronnax/core.py | 6 +++--- docs/input_generation.rst | 2 +- test/beta_plane_gyre/aronnax.conf | 2 +- test/beta_plane_gyre_red_grav/aronnax.conf | 2 +- test/f_plane/aronnax.conf | 4 ++-- test/f_plane_red_grav/aronnax.conf | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/aronnax/core.py b/aronnax/core.py index cd8a1b62..a64ddac6 100644 --- a/aronnax/core.py +++ b/aronnax/core.py @@ -95,7 +95,7 @@ def interpret_raw_file(name, nx, ny, layers): ### General input construction helpers -def interpret_initial_heights(grid, *h_funcs): +def depths(grid, *h_funcs): X,Y = np.meshgrid(grid.x, grid.y) initH = np.ones((len(h_funcs), grid.ny, grid.nx)) for i, f in enumerate(h_funcs): @@ -156,7 +156,7 @@ def rectangular_pool(grid): specifier_rx = re.compile(r':(.*):(.*)') ok_generators = { - 'flat': interpret_initial_heights, + 'depths': depths, 'beta_plane_u': beta_plane_u, 'beta_plane_v': beta_plane_v, 'f_plane_u': f_plane_u, @@ -209,7 +209,7 @@ def interpret_requested_data(requested_data, shape, config): return f.read_reals(dtype=np.float64) else: if shape == "3d": - return interpret_initial_heights(grid, *requested_data) + return depths(grid, *requested_data) if shape == "2dx": return wind_x(grid, requested_data) else: diff --git a/docs/input_generation.rst b/docs/input_generation.rst index 14048fec..7633c3d0 100644 --- a/docs/input_generation.rst +++ b/docs/input_generation.rst @@ -24,7 +24,7 @@ Forcings Initial conditions =================== -.. autofunction:: aronnax.interpret_initial_heights +.. autofunction:: aronnax.depths Domain fields diff --git a/test/beta_plane_gyre/aronnax.conf b/test/beta_plane_gyre/aronnax.conf index 7c7159cf..c74e75e0 100644 --- a/test/beta_plane_gyre/aronnax.conf +++ b/test/beta_plane_gyre/aronnax.conf @@ -52,7 +52,7 @@ wetMaskFile = :rectangular_pool: # Inital conditions for h [initial_conditons] -initHfile = :flat:600.0,1400.0 +initHfile = :depths:600.0,1400.0 [external_forcing] DumpWind = yes diff --git a/test/beta_plane_gyre_red_grav/aronnax.conf b/test/beta_plane_gyre_red_grav/aronnax.conf index f670b6da..ec8a6b65 100644 --- a/test/beta_plane_gyre_red_grav/aronnax.conf +++ b/test/beta_plane_gyre_red_grav/aronnax.conf @@ -51,7 +51,7 @@ wetMaskFile = :rectangular_pool: # Inital conditions h [initial_conditons] -initHfile = :flat:400.0 +initHfile = :depths:400.0 [external_forcing] DumpWind = no diff --git a/test/f_plane/aronnax.conf b/test/f_plane/aronnax.conf index 8baf38cb..686b907c 100644 --- a/test/f_plane/aronnax.conf +++ b/test/f_plane/aronnax.conf @@ -1,4 +1,4 @@ -# Parameter file. Change the values, but not the names. +# Aronnax configuration file. Change the values, but not the names. # # au is viscosity # ah is thickness diffusivity @@ -52,7 +52,7 @@ wetMaskFile = :rectangular_pool: # Inital conditions for h [initial_conditons] -initHfile = :flat:400.0,1600.0 +initHfile = :depths:400.0,1600.0 [external_forcing] DumpWind = no diff --git a/test/f_plane_red_grav/aronnax.conf b/test/f_plane_red_grav/aronnax.conf index f5da7127..399b99e7 100644 --- a/test/f_plane_red_grav/aronnax.conf +++ b/test/f_plane_red_grav/aronnax.conf @@ -1,4 +1,4 @@ -# Parameter file. Change the values, but not the names. +# Aronnax configuration file. Change the values, but not the names. # # au is viscosity # ah is thickness diffusivity @@ -51,7 +51,7 @@ wetMaskFile = :rectangular_pool: # Inital conditions for h [initial_conditons] -initHfile = :flat:400.0 +initHfile = :depths:400.0 [external_forcing] DumpWind = no From c54b7b925b79bf3a07aaeca145bd700a6cf41bd7 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Tue, 18 Apr 2017 08:50:36 -0400 Subject: [PATCH 38/50] Try to guess type annotations for some input files, but I am not sure of the right values. --- aronnax/driver.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aronnax/driver.py b/aronnax/driver.py index 9838c3f6..861b8d59 100644 --- a/aronnax/driver.py +++ b/aronnax/driver.py @@ -120,15 +120,15 @@ def compile_core(config): "spongeHFile" : "3d", "spongeUFile" : "3d", "spongeVFile" : "3d", - "fUfile" : "2d", - "fVfile" : "2d", + "fUfile" : "2dx", + "fVfile" : "2dy", "wetMaskFile" : "2d", "initUfile" : "3d", "initVfile" : "3d", "initHfile" : "3d", "initEtaFile" : "2d", "zonalWindFile" : "2dx", - "meridionalWindFile" : "2d", + "meridionalWindFile" : "2dy", "wind_mag_time_series_file" : "time", } From 91c1a60a2ee397ef769c8792b56f9ea65f82f143 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Tue, 18 Apr 2017 09:00:54 -0400 Subject: [PATCH 39/50] Stop working around #96, and update known-good outputs. Fixes #96. --- aronnax/driver.py | 2 -- .../good-output/av.eta.0000000001 | Bin 808 -> 808 bytes .../good-output/av.eta.0000000201 | Bin 808 -> 808 bytes .../good-output/av.eta.0000000401 | Bin 808 -> 808 bytes .../good-output/av.h.0000000001 | Bin 1608 -> 1608 bytes .../good-output/av.h.0000000201 | Bin 1608 -> 1608 bytes .../good-output/av.h.0000000401 | Bin 1608 -> 1608 bytes .../good-output/av.u.0000000001 | Bin 1768 -> 1768 bytes .../good-output/av.u.0000000201 | Bin 1768 -> 1768 bytes .../good-output/av.u.0000000401 | Bin 1768 -> 1768 bytes .../good-output/av.v.0000000001 | Bin 1768 -> 1768 bytes .../good-output/av.v.0000000201 | Bin 1768 -> 1768 bytes .../good-output/av.v.0000000401 | Bin 1768 -> 1768 bytes .../good-output/snap.eta.0000000001 | Bin 808 -> 808 bytes .../good-output/snap.eta.0000000201 | Bin 808 -> 808 bytes .../good-output/snap.eta.0000000401 | Bin 808 -> 808 bytes .../good-output/snap.h.0000000001 | Bin 1608 -> 1608 bytes .../good-output/snap.h.0000000201 | Bin 1608 -> 1608 bytes .../good-output/snap.h.0000000401 | Bin 1608 -> 1608 bytes .../good-output/snap.u.0000000001 | Bin 1768 -> 1768 bytes .../good-output/snap.u.0000000201 | Bin 1768 -> 1768 bytes .../good-output/snap.u.0000000401 | Bin 1768 -> 1768 bytes .../good-output/snap.v.0000000001 | Bin 1768 -> 1768 bytes .../good-output/snap.v.0000000201 | Bin 1768 -> 1768 bytes .../good-output/snap.v.0000000401 | Bin 1768 -> 1768 bytes .../good-output/av.h.0000000001 | Bin 808 -> 808 bytes .../good-output/av.h.0000000501 | Bin 808 -> 808 bytes .../good-output/av.u.0000000001 | Bin 888 -> 888 bytes .../good-output/av.u.0000000501 | Bin 888 -> 888 bytes .../good-output/av.v.0000000001 | Bin 888 -> 888 bytes .../good-output/av.v.0000000501 | Bin 888 -> 888 bytes .../good-output/snap.h.0000000001 | Bin 808 -> 808 bytes .../good-output/snap.h.0000000101 | Bin 808 -> 808 bytes .../good-output/snap.h.0000000201 | Bin 808 -> 808 bytes .../good-output/snap.h.0000000301 | Bin 808 -> 808 bytes .../good-output/snap.h.0000000401 | Bin 808 -> 808 bytes .../good-output/snap.h.0000000501 | Bin 808 -> 808 bytes .../good-output/snap.u.0000000001 | Bin 888 -> 888 bytes .../good-output/snap.u.0000000101 | Bin 888 -> 888 bytes .../good-output/snap.u.0000000201 | Bin 888 -> 888 bytes .../good-output/snap.u.0000000301 | Bin 888 -> 888 bytes .../good-output/snap.u.0000000401 | Bin 888 -> 888 bytes .../good-output/snap.u.0000000501 | Bin 888 -> 888 bytes .../good-output/snap.v.0000000001 | Bin 888 -> 888 bytes .../good-output/snap.v.0000000101 | Bin 888 -> 888 bytes .../good-output/snap.v.0000000201 | Bin 888 -> 888 bytes .../good-output/snap.v.0000000301 | Bin 888 -> 888 bytes .../good-output/snap.v.0000000401 | Bin 888 -> 888 bytes .../good-output/snap.v.0000000501 | Bin 888 -> 888 bytes .../good-output/av.eta.0000000001 | Bin 808 -> 808 bytes .../good-output/av.eta.0000000801 | Bin 808 -> 808 bytes .../good-output/av.h.0000000001 | Bin 1608 -> 1608 bytes .../good-output/av.h.0000000801 | Bin 1608 -> 1608 bytes .../good-output/av.u.0000000001 | Bin 1768 -> 1768 bytes .../good-output/av.u.0000000801 | Bin 1768 -> 1768 bytes .../good-output/av.v.0000000001 | Bin 1768 -> 1768 bytes .../good-output/av.v.0000000801 | Bin 1768 -> 1768 bytes .../good-output/snap.eta.0000000001 | Bin 808 -> 808 bytes .../good-output/snap.eta.0000000201 | Bin 808 -> 808 bytes .../good-output/snap.eta.0000000401 | Bin 808 -> 808 bytes .../good-output/snap.eta.0000000601 | Bin 808 -> 808 bytes .../good-output/snap.eta.0000000801 | Bin 808 -> 808 bytes .../good-output/snap.h.0000000001 | Bin 1608 -> 1608 bytes .../good-output/snap.h.0000000201 | Bin 1608 -> 1608 bytes .../good-output/snap.h.0000000401 | Bin 1608 -> 1608 bytes .../good-output/snap.h.0000000601 | Bin 1608 -> 1608 bytes .../good-output/snap.h.0000000801 | Bin 1608 -> 1608 bytes .../good-output/snap.u.0000000001 | Bin 1768 -> 1768 bytes .../good-output/snap.u.0000000201 | Bin 1768 -> 1768 bytes .../good-output/snap.u.0000000401 | Bin 1768 -> 1768 bytes .../good-output/snap.u.0000000601 | Bin 1768 -> 1768 bytes .../good-output/snap.u.0000000801 | Bin 1768 -> 1768 bytes .../good-output/snap.v.0000000001 | Bin 1768 -> 1768 bytes .../good-output/snap.v.0000000201 | Bin 1768 -> 1768 bytes .../good-output/snap.v.0000000401 | Bin 1768 -> 1768 bytes .../good-output/snap.v.0000000601 | Bin 1768 -> 1768 bytes .../good-output/snap.v.0000000801 | Bin 1768 -> 1768 bytes .../good-output/av.h.0000000001 | Bin 808 -> 808 bytes .../good-output/av.h.0000008001 | Bin 808 -> 808 bytes .../good-output/av.u.0000000001 | Bin 888 -> 888 bytes .../good-output/av.u.0000008001 | Bin 888 -> 888 bytes .../good-output/av.v.0000000001 | Bin 888 -> 888 bytes .../good-output/av.v.0000008001 | Bin 888 -> 888 bytes .../good-output/snap.h.0000000001 | Bin 808 -> 808 bytes .../good-output/snap.h.0000002001 | Bin 808 -> 808 bytes .../good-output/snap.h.0000004001 | Bin 808 -> 808 bytes .../good-output/snap.h.0000006001 | Bin 808 -> 808 bytes .../good-output/snap.h.0000008001 | Bin 808 -> 808 bytes .../good-output/snap.u.0000000001 | Bin 888 -> 888 bytes .../good-output/snap.u.0000002001 | Bin 888 -> 888 bytes .../good-output/snap.u.0000004001 | Bin 888 -> 888 bytes .../good-output/snap.u.0000006001 | Bin 888 -> 888 bytes .../good-output/snap.u.0000008001 | Bin 888 -> 888 bytes .../good-output/snap.v.0000000001 | Bin 888 -> 888 bytes .../good-output/snap.v.0000002001 | Bin 888 -> 888 bytes .../good-output/snap.v.0000004001 | Bin 888 -> 888 bytes .../good-output/snap.v.0000006001 | Bin 888 -> 888 bytes .../good-output/snap.v.0000008001 | Bin 888 -> 888 bytes 98 files changed, 2 deletions(-) diff --git a/aronnax/driver.py b/aronnax/driver.py index 861b8d59..50aad9f5 100644 --- a/aronnax/driver.py +++ b/aronnax/driver.py @@ -160,8 +160,6 @@ def fortran_option_string(section, name, config): return ".TRUE." else: return ".FALSE." - elif name in ["dx", "dy"]: # Horrible hack around Issue #96, to validate the rest of this refactoring. - return "2e4" else: if config.has_option(section, name): return config.get(section, name) diff --git a/test/beta_plane_bump/good-output/av.eta.0000000001 b/test/beta_plane_bump/good-output/av.eta.0000000001 index 3ddfc970d5b5ff492482335d9d947fee8b4e01f1..7add0c6b603e971c334bcdd35e86665a4f26bd0a 100644 GIT binary patch literal 808 zcmY#jW}q1eD~RR~N%*pl{qX&3BK%+WDZY5Zo4x<@zPSZ!zcz+{-j^7#cT@h2Px~@V zpBQz`{Iu_l^zzcm?oa!w!czXMbpEst-C>s*JN0M(`n>OoTJEVidp_?=t77=GmHYF) z*3_3xYqr1N_g3sz(3&}q_ti|E?iLjBc;A|3J)Kf}-|ai_AZm}^+m9ILtur%wym9*H zeaq8ow@tJ9ypOF>ll4*0`+ZMpcdfP8xM}z27Rx8;haC1RO0HhJc8kM4TDxZImX|l| zu5Bxe&JB2vVcuGkzN7Dqf&L1qI*>W*)4s(GpC$M;9`9TK);^s3Cx^ZC3aMF{FIDVM zhImdDd8A^0f6@j;-o+gDW)~-kSv`A-VV<^Tj7iwzPx~%kIB)zQ_|v|NMMq2HHayyA z8@Arylpv>lsjUMH?C;?q8%m<8)>yg%(@ei~G? yQ}xrnh~Q_t&OG?IuVteqf83>y`+Co#XSc)d?YAaDN^%NP5W-Ku<+k@RWb zM1QvA?;T(Ft@HO_*8lotU#d%)zS5sx`^5KO%d_6jwEr^iqv}h=EEwkb$nHL{>eb7A zUS{pinM>a7Yt~v>8+-f9KC8EJzIxX$>{H`=8^iSNzun6BS~{mM|F-*LDk^ew(}#Wk z%V&5l6~r_zxz^?M=7ul(p1mo2Rqye09|wnmgq`TueR*?ta^^-c*higtH~;TGMf)cn zEV9DhiuN+!*?v0LezUXK{a~x!WF`#vNiQv4Q6lkopUjFD<=ONexvzFz>ozx8m4Dk;Qzf1z z5YL9;KL6|q_v_{|?_Vf(?flkumi^lt%H6gzuWY9ZdUW`TRVl z{$<*4vhC{qf-1&ONe_8h%3p>iC xFJs$p<>7k3E0cYHvK?pP#S85F^@Qgx4CLY1@0C}^Y4`}!JoNNKE?)tdM*t9B{%!yO diff --git a/test/beta_plane_bump/good-output/av.eta.0000000201 b/test/beta_plane_bump/good-output/av.eta.0000000201 index fab17472eff636ecd1381557c425fcdd479bf1bb..4b99c0aa74cb37fb40a9cc706ff6cdcf1a36c012 100644 GIT binary patch literal 808 zcmY#jW`KbPD1#6UQxBtYs^_qY6yoiAzfb5zzvb%ixBHkcbmjT_Kizlhwt@P&gD3Z` zob|x-N7_ldX+jIE^SdtDwH`cjwshfweG|8PEckZ&!9J)3aPx(<#5whZ-|btHTequN z?D;;|OTEcIW$cvD|0Y-+TJdZk>+KH9dwWc0uo!I<-1Iv3quzXJ7j7 z<#sR!!_4(uI{R1C`&au8+itjLeE;UY9OkVFYa(yi`K&w??acYaj=yi&Z}FO4`+5(R z|90<<+vk;-WqjV^ja`wzwCFu`FEPvu)YW(@pZQ{6(X;6nAFn#IkJWx%sPy*Rc3)m8 z#J>8n)$WM8=c{c-&-XD0FuFx8e!TBl%F4^q-)`IWhOw`Vt^J5$-V4o>Oe?0o+_$;( zutHPw#eEL$>#Bab+_CeYce2p#>~*{5AnPT2Vz%vD^5wQvm8;IaAb}#;V>WOsMl7Yy@cq7UA`^yvLQwgJeLFYb zl9|2zqMbz{+wCb@_v~IsX%QK_rsb!v3ha;lsh-CqB(VR|&8?zp zlfLYmqqA|QsQJQu`S-id+_`#ZUvKxWhrz*5_My9@OE`KD)5{ljUd)~Ry&PZn9cJ>_ z7IL0%zq9)Jt=l5__ivWp=ym_w|9yO}mEAw2-|W*pxA`64-4FZD%u4Z%Z2XR4-rXMw z+m7ydzRycBY)xjsuYHUkj_oVeVB7EOwM9guoqa$5b8#c9H7xtDG;iiS7RkK-N^Z?f z{*O%i@9x;R@#0dJ{pjwKQLOuN&zN`r^etA-3!2&X8~^8S5DjD8-yl7a%|MoMf7GJj zwUx3Q`?oz__}l9s|9)O4>s|LQ3hXcS?R}~KSP;X!lUKF>-x3tse=VJ9kL^y*{r|!? zxdc`)?q73PxB93cEjIhdx{v1YB*T;FMj;?f8SJ&{RhrUesePB*k5j)c8!&jWq-!srQI9% z{NMM<`<&uVcLsF#G5GeZ{r|!7ogK47;)&C8&-eMSGhg=7k!$~qFQ>eodkF4-$X31b zq#?(CXNCjEpB?(TFJj}_s*74 zWq(ebZvMLOl=eq)Kd(>wIv&gMKdZR6Z$;UO%iEG)*rB_Jf8%Zc2|?TT@vl~RY3~1M zpNhqSmIhQ!>w@EC!r_aS| zA5yh!|FZ5YcFSs>-pOCev>)BPkZL#6%O{`it8V!_=@$Fbefbja8{aX$uoM4K^Kwly zk9}`w-eKlqA$z{R?+T(A1nh6s=cuSJ`C})(d3))afIk@S({leGA^ZKsJ~y4bIqGRo z_IaFCzV6)o%I><~svSF1dF;&?1LmlI5wvf3%5;85A-_HA#051b`~KQ}jJWD3!uJ=$ zyjH1w0Xt=0?7NYFvTx;;*ZaO)m5;wscz&OXFT3 zC(AYz*nWR$R~Wz9(&^8C4D){9FfDoe>B+tdZ$?SBgU|P^Tg3LtjOWe1jVxkpCU)2M z-Qn72{9*5PyY~W73s!zPZ?{9OYHoPcy?r|_1;}N-dWK~- zz7@?UUwW53-dF9n!c)Wc(>~?v+=0dGKJ5!CVcoeT?%lo{Rzf>1*{|+XyxX{Vw(ti# RSi(b(7c%*9;}n2-1ONfnB+UQ- literal 808 zcmY#jW}q3U;JN7i*YMoFX9`o67xvt?o1#?Qkl*mmE=P364|k~}cEShC9&gHjwC~n| zeNso(+}~I9xng(Ns?&CvWm_g^1$?(dci5$f>>2(=PwjfM(iYWlKDT@Gwd+qx><7D$ z6@gD)%6zsH+UT)^Iq{pFvmMi&-N8TYJX9NQXk~x5I}(s{{@J}>80Kw>isRX{`K#R& zRhDPR%fH!GU)<-s>F9sEBS$ZnU25mF{};XVoQsoyJ@Y|cU&kLj_J41D=XT}&Z&$Q% zqxNssXBg)BPARD_+xN?E%CU)SALTIEXG(rxEqcIa|2eDfn1_Rqy)IM3`;eL9_Oqs6 zne&5D*#3`2IP)$I2K(lz>PPilS74Y|w#emR<;H(@#=fPVJX4tL-#o8LXS~8@UwotF z=i;3L_C}fsI-&NW_RCaE_H&2{**}g=tFcI8w$Hr4aVvJuOAPaVD|}5o@s`1U_jdzF zza~ceoGrG`zAt39kFSs_RA=O{f7T%KApa?k{S)_`YwR*S_Md^N-X7A+uF)I8Y zqdj_jJP~xAleqVn-F&HK8Jo)g*ag~MJKkW)Xx|t;kLkfACi}eo@v0l5nCv~~&WYN8 zhS^@;T0>3o4U4@<*$>yPiL99BXd&%W10P_d{KiTk_ diff --git a/test/beta_plane_bump/good-output/av.h.0000000001 b/test/beta_plane_bump/good-output/av.h.0000000001 index 1c9ab43775b7ae2eb8d1a51c16f3f16e20fbb425..96ab4617861579a39f46c5f5e8a1bf9c3d9f2152 100644 GIT binary patch literal 1608 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 literal 1608 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 literal 1768 zcmdVb|5MX-90%~p1vqRV0f8m#%$+VSmp2ef)(c83<4(Q^ij8a%DuhfRJXyhp0y`*D z*@OZI>1 z7s7v5P45nhi|(?}OG$$s-wWG-xVaH-`RO6lOf6hVQGsNr{>s@uwNT2`sOBHK2~zt9=@pq2j5-o}}X=Vyq^L$ov8Pj{0IQ!U1sn zHoB@gpu%<2e%CF@cFIA^yd{cr>wuU(R*2|=1@$z$j`c>`(VKj!Xe?U;-r)@0G1@fr zD~%j}xeeDPkUc3VUkh{W)(ofX8Wf-3s2`I2fmrKbIoahw=-T6)9kSJ}1zMfyWnlQP`*t=Cu89ADD}%*sG^RrCPxKlY161tt*A59~1S zwL&);wXb*Wg!5mNAJ+H$h{Q{peFw2lT-Rv5Qz&@713YikayLBeh4HY;(=ko=V2{S^ z@HILh(cGS@z_bvQJ5@Zf@C#b&H4?$}9L063=e88N`>P?dkN?f?@*befY^_%OWd$0? zJ63L+0_Secv}AiR?edCZ-iAD;07-ItG*5gv%4An{a-p z@J5c88S)BGlxF!HM;xQH%}yLfLT<8AoqZiQ?}2%e)W2E^&oeAJS3jtOMg3lSiB1K( zDibD}o0LGdpLj9#Q~+AUxPuv+8c_13{mP^#VqDiSyw3L1QZgzi8(vWxFgOx59_3A| rg%-{VnH(eo+Cy61>anlD5GGRvVkw9@?BX0sFTr*Ht$Ta$&mZ?UFHXu8 diff --git a/test/beta_plane_bump/good-output/av.u.0000000201 b/test/beta_plane_bump/good-output/av.u.0000000201 index 55632b7f7faf7364bd6da57ebfd7a9599cdf1365..cd413b978394ad5038d6c7127bac94fcaf989221 100644 GIT binary patch delta 976 zcmW;J`%@DH8~||SA%og-h#g2G;~goG2Ll<~cd+ruL{}gZvK_Et119ojBnT*PXtM1T zC{zdy)HBb6rt$g)Vj?66tmffQ0iE@~#YN)&#%Q@4*dV(u`SbSfPeDqy^CcXlYLqRz z@%+1O(H6@Q*l|h7EjpWqu^u@Iipc_;`>3!dtoa*^J@TNQe1wZ;1xwXF$NcoRm&3g8 z+7X1c3MC1Y$ynhIai#essC`sNPOz6@$yfV{nwcu3dtV<^r|_{nz}DWSI!e{=hbONG$Zbhq!-h7?|trlg1G%k(z# ze8p5!i4&67mv3h%S;*AR807~!VDD+2{7P*$T=0C@YW-miyb(%Lk27RY+}XcMwLGo2 zT*;Q-{YWc}ev^^C?|!5Jt@BA~NIM7W!t&ZIDQR%ZRweQ9F9L~S`VzUR5N>G+4p!6@ zy*)Q75huk?FkJsmdy&I>!RWb@^Oln72;qS|(PyLkKvQ*YqOOt$Qnlqoeij!fnS_%$ z#1N2^jfSLlCcgbfMX5!x8b(lP^9LCoR$xvy%PZJUg#)}RFE72vhRqM%OX5oXL4IbW zq5IeZ!>3!vpUT{U{~zC44eZ(Kw-tgcmK-G~XfVkx2=8`24E*9Uo8UzOI1B!vh6lz0 zIA!xw2LphuYhq!equw&3)~}D<*abVSO0ooPZ$-A23tdlpDTePS z0)5APYt0-F2WFYKRj>GZdo?9jWNq#Vy-2*amUztY8C=z7TYUi!=-yqweK z5R-irt(qh^il>IyYtz{gauDj jjSfxMJFxMl`}PgeItw``1H_xIdE$S^LgT+S8yNfx+GfRr literal 1768 zcmd7T|5MWi7zc2W2_s5wT&(!!Zn!8=z-`y21U_srCZoalIuK|dzBC7t9-9HzammF{ z%Md5fDT)%XOBkF;CU$_&bcW#B6sfUBgH?xzX!0e$Fo~%D;NwqS&#%wj>)!W%es~=2 zF8|qdRK1}q>di(sYtE4KbtO_iwP;1Lg*bU{?95{GE~M(}MsGSZ(K`3kIA%;isu8|-4{#o($S@ZWtU2^{%cl~AgKi1Q+qe7g9|Vw zcuSWXMMmn{+rzZet=TA#>@LvWDaIld%XpTmLEUe+COto{z%^H2hfcL0uftwGjLIy|aI+g4XmHrQ;x$e=XKd{VbxLd}!YcjLP}=L56LUcBqk2AvxSG}XG!yzC=|?>i0+2Idw* zA!W7E^KSxjGicJF?_{JdS^xjH{e{QT*#SlY)cY5?uG~+Cs<=79og)%xn3%b_R3U)E zU^lNRaV#{bOFb@r#s^d7zUM104ALG3odU&fwFri9`&+*CNd?<`^K@NA8faR21N=hM zASQ!*nsqD%wpl9=(mch`GZ9u$(ZeNmbB|doOnpMobk}tH$EUz~z4`Z6XBNo)e)g?x zQ9x}sgI=f3fvbkK@Zu3ED7s{URO#EK?%X-OVW^)A=v7&#-kt!FTfJeqQ4RspYxml^ z-iNPzt5Qlv(xH4n_rXWzNN^Ag#TC6DlHD^Y)L3+)H3VjFG}kWbW5BlZXj*9(Lx}5Z zvxZNEusqKmEMMj073Rj&EQ1X7P4-)>LGh$+&obZB!s9^d=Yp|~N4J9;-~IA8mzi){ zTV20qjYB~?Wo9iR3s<^30#(O%;Xsq-X=tdF)NNQie2BdyfUD0G9Ir+(P;zBHIz|{g zob{M&w}_EA$)fF)W@7$raa!znIvUG~=d=X!yyJ0nUCm2L5L)?4QoAA@{G)R;)SftK qlTgQKJPuOXDLii?0X1UFs4_1e-8IV0whkU?Ub6mQbnp20$NdBJv#Hwv diff --git a/test/beta_plane_bump/good-output/av.u.0000000401 b/test/beta_plane_bump/good-output/av.u.0000000401 index 9cfc75a81a3010952bab62cf79c766a5bf1311ee..88d83b92b6212af4442219de922c81e868ef174a 100644 GIT binary patch literal 1768 zcmd7T{WIGK90%|?S60*R)}ZQPwdxR0ca_vrIv+}^R60UYrj3Lkm5GOV<~+rDYOm^H zq{=wkA+;=IHa7jp>gpCu8`@5%MOY2nRJyAk+HU{BcR%g+`SpGGy3c*?efL?=BmHMX zp_Sh}Rd)f!waWH5X)4M?=h9vV=HTSY-7hy*@~~SqRP5A~gAcP&hi#jLJNl~O-8Ci< zEf`n!#Mi+h0o60MC+E6F7`d!@!8(wS9Wrd(l$4@mxqyE9bTv-j^S^h#qzbj3zl86M zImWSS+S|^pIlT2Qb!8a6{t`hTA;PpqGw%m z&YF_gtuVOQi_?$l~P=t_$z>ibG>RMiw-c%kw~n#XqTt7j+SQL3i%xH189T`5i1E0VzRAZaWA zI~I`TpRuw!LI_==zWm>EPw6LEx#$a3ojxAfBjFHbSrO!+%La|KMSu8WEWBg7O9wqR z=vf^tOE?@1Z*Q1KoV$9A@D9IMhTYhdGr^Z-QemVgpZ^TmNA{VXE=e-Es(es&rBRgzpIIt%=98L-DQy?1wMucnwgH% zQ!r@4W|Ka~#kYQ%Em#16zLh>#mo;btxKCX5HS~ zC*`7cXMKly_hS@%J|C+*=7nUfV`lKG1)=*~%zLOmV-L$qU0Zn*RN%%fmROmY;*GSY q2KFt1`050O>UoHX0bPd9{Xf#s;IAc0Rh%oKOVpQtn=kzHueCF)i$ zyzoAlP4KfklL#zjyXE_jTR}1TAl+hQ z|3ytwI6QC)qZwuifd2OHtcs|bwo*M+h}1Rq@G2ZG$JlkFCL@o6Q6Mf1nydA zqQE~-p9@)}=at6mEQp7UV30Y(j8gS;aNSTH=19<(CGdoBay-(6z0 z_EqRh=Ye;8a6Cb+-sVODrM63VwoU@=`BnP77jf{brLlvxhJd;EP1xa^cS zw=n66rDWY-iVy13B?mfxXq)Ar%CK@U>vSNJn*TbU(P9n*ZNqh!Bz#!w60d@g2g(^= z$$G`7peX4riLaSa@AkfGyDxjCi-G5qH*_Z00a#^}-4xmA31MBb{SS|Xfh_Q=}Hzn;V9f8GdwT(J!S~xwz4e3 z--w`U*ztR1y%3C>MFTZVuGXe}-8svm*kjpXImJHK4V%98d*Y>UhmSpOj2hc~0;Hp< zx8Gh5f+4V6Exbhlf7*`LY5Ko4uwKfEuJpumgXtefGT5j(L7iS%;Gr4YtLaa;>l z|3upH!ao-oJr-0)@I6n}^=ow3<|dYmiLd9fk?QeTe@_5`Ygeu+gdO1+-JG?sjNzD> z-=J{48HVKAdwZhW{IS9Hu*=>J8{GYsfYJXQe~X899S#pV0!4V}zIzBiSA;A-hle9O z1e%|3DdtY_aQ+ojR&mG=t2q2>Spr3CTbI{I-j(suW}I?N^;m?G=iOGFPX(AFesP*{ mhmHLkKIwyF9ynzr_GqOT;pPE9-PcpL@ZZLXdb0*PI{yO539(-Q diff --git a/test/beta_plane_bump/good-output/av.v.0000000001 b/test/beta_plane_bump/good-output/av.v.0000000001 index d16bf26b631d401ec4edd75ab76ebd0245c33540..fe4ca24cf70f0744c1a3cd506891411304aad4a2 100644 GIT binary patch literal 1768 zcmeIzZ8Y0=6bJAPr-zmfRozLqSy@EY!$OHO@=L?iQ)^P;uO1I(be)>09E8!9An4|4 z!Dgb(n!lq{jkIE?y;V_^IMp&%iRw^nrP_(w8V}oR|5tmrowNJyzWJQ*z4yg^yzRCB zOo{O<|Dgp8{HthvWeLGR+Mn$1WSIbW7vC~8r3s*jm)qx}(+KbOU5YxO6afR*X2;GJ zf>SZ?zBR^%t%Fvadh=Gf7Y58`x2scC(eOsJbiSd!2>co%<@8Y*RCZpje5$8}o^aXn zi)RBsGF}%qv1CA5jCojRc81_FlhyZ>Tnxr;m}(qGQwNDK3OecbOXAdl&IfcPVmM~O^A9m$3T)o>aY|BLBpz7=?~UNzzMGN zhkbk?=CFz3#&b`|Q8Fl-jtJH@+Vn%2t}uAj#&SeUA$aFX-;TV!?I^6tUoD$^97Jx% z8Foz-)ksa;AUitFCPm zdZJ3s*?!>}1!(6H6He|q89LuFn{GTkfNs7s^q_or0Qs}B?I~m#iv8@> z+{bt>!RwzHDHG+=U|nK5si$>>QDfOBSPEFBR3kjBBZuo zU7H@{Bb(MT@AjX43EtMc|M&lF1I($SaPboix-##a)seG6p7fAJ?x4dl*Oa(jCr==U zVQEy>NICM!s@aFg7 zh6c=F2+Q&rxh@WcgYL|AoSqDvgnE-^MJ_~?Tv*hUrNgeLhl{OPsVL9xyOq#%9;$M~ zH$S4q5xgs3zxRP6DiCr~@}6G^!~okLT_Os}hkhBFPRefql0q#fXDFbt!{fYfLl?L? z*q%-Or3vPR$*zx_3t;QDQbRqsH>|vY)5Ej1_}w4Aec?CvYh@Z}hl2J%e?4?cT&$HI zZQ#~B^F{A%DTrrq+RFFefLCmx+^#W`;KeuI`E&PW8ua48cLaPNd_qY|s3k_O>NEZ|CKcbI$kS zJaH%dXKF`%dD(T->CU0L4sw**(?{hF9k*+JYpAcX^A}MS2&7c=!dEMfV^g zzrOS7VIjC|F_uT|a;;8w@V-JvBcK8uS zok!chxv}^q^*6LkAP#8KCy}J8#1dkvL~A|zO6?H=(!dUH$L)ixArPM1X7qDoLwM4C z!txyp>USQ5(RT<~@A=%HNHhW#dF87mGs%iRA&)ap2g-0>)rLIl_#PcJ>W4B%LkEDQ zZ!>oJ^uvv8R-k@X1zuNrRpsnEAluwjxIO9?`0q}p&@BR(dTvs>@EUOYQu@mMS~vB= zs%#g5E<&Kn!33<&2Lam~+eIsW0UUD17p@NpwBhlr>bxle?Tutp{(~VKRDS#W^d53Q z&U5p4dtyDW6UHKJuTJH(z}GW{iuo2bB$UkRuZB;QG#k6z9pgN7eic38dE8v(=Ft(299E?C-?Tk*>GEP9?1PQ0G@1gE0KAxrwVB zgp}YUy`WwJl#@Tqq!<`DZ*4yR_y6nyCuZm-;*t`GZOwrfHn)J6How!lqJm!$Ll*bx zO%Tfa+>-=%fqOs~<9S^J8EG7*y1pNLmCuFmF7j7JaWIt@H{lXu{Eb z=-IUqw9(^I%rIY!)~1y@DOy@A>jZLFVOaBEGicM7LaACFcwrxXIL948tqHcCx^N>J zZOqJ;^czt+`^C7c-vByb-meQ=C&YP9Ua_u_A%T(TqT$46xe%$*cse_3K@Tsh674(` s!A+7&6QxLNJ$jFJR*EX>Hl$s)h)|FquA$Vk6z8p-_utY#`TNKH1pze41^@s6 diff --git a/test/beta_plane_bump/good-output/av.v.0000000201 b/test/beta_plane_bump/good-output/av.v.0000000201 index 5a2c9446e9207842e0d0c2259712361b0cfcf5ff..fc935dab2e96e9ee0364a10d77609d0948443815 100644 GIT binary patch literal 1768 zcmeIzTTIgj6b5iWEq9!th;ol;#ziVOfk1m4ZMhXis0BtHU>FP-r4tB+f`Wn=xu&fO zBC`sW$u_Qau!;6;3@`&3;HVm`KuH-A)F_CQh2i$h|7mYqvh()6{E~CNhcivm`p-=5 z$&|&sWrbY-fNN-owl4bA_+GtQ$M!RQ(ed zVfZrk_Ofx~qCX$w^hVp;eAz6o#%_uUxiV$ zLzP%Gcte-8vlMycz#%Q2OoGSzy~lWIbvLxh7VQ|Wp`f`mq!N>oA>(=2cbOAOP-qxF zbvL2_&Dc7g&9!2jVjAsX#EP)l+BZO~E+lw#8zCda$paQg;zbi*BtRS0e8}f)A>4e3 z*5;j+kP>Ucs=8hTZ6Q5fO0QzvYbB3RWL9BUw591nejdTYC^Dnb$^*35zwe%lPJrJ= zgVN@^ilD`JGJK1(2pWoKIq|;;AtP`Q;wrhY_sV>_Rbw{hoU@#~r6k_3|CV6({xeHZ z*Y_0|Ix|6kTp(Lv^Wb&5VT}xmVQKi0?l^?~Z|G1@-Aedej>0Ej8?qU&mjr*n^Ry>2X;o9TF+; z+IfXBK(4(gB{Sn-`X2QHP0fPF)<~7|8HLbCFjJ(EkjJT2>}xll2dL$T3-p6J-dRBD z;-L4W*-_v>{k;EAej22VGz%RrX2JH}3ODu%E^K2Rca{dk5WMZ2))r&Znp}re=i=pe z0QVo%D`^xmG2*fPndw8JXg0d(>YIi{sO7Y`d=@SMS;gq-p~zfF4Wpg9LrEfdw<&Rz z=O%Yzh6~^Et``Hf9l7)m@;}9~j7LWNvMjV)7~iFGNk&d;OoTNr6=Z1^x=&WJ;6sVn z{YPm6!3!Q0+vl}g;F@*bvVIH$Khe?J;rB8L4U`{^c5KbXF|J*`&J{tm*Ac0=(lCCbkN(i&Zcq74U-1SzZ6N1;RSI|)0`j`RS%k$+#hFP zy7JBDS50xKEEg=VhnQfja41sq-VHalf3mfjHc1+jSJ1lmlzgR!yL#Ry*jTtD-RbH~ wO-U$@6lrefDxz) zG7Jv)9zErmil&Qpo%hu#>0;c%==0mOJrhwP@ zEfw*u7zczkv(a91+_hD}{PMXXOfP&kboz;$#G_n`81a~NLdIZKj>jD-I9R+rsu1VG zMmJ+)mSq8)tj;PH>7~FDcCBA%%tT5_ZH|7p5Rb%jXwz+EKi1p}U$_s8VPLV7^|DO{ za2(zk{6m)qrLpeya{giP(nr?EY4gBRxnjL)7Xh?<*X&MB0fFV6^F6rms%E~wJ05-fQY+3yNpUjHT<-g)7)Q5k2J-W;)`M@CqY41Vw=s10{4Wir3n+h=QHy r{**|ssNtcz<&Ql?N(j203{tP2VPnwh<{HmI4vA;V|F`6szkl3cXD5UWo{D2x($0#cHcHIiwb9 zt~JvUN^5lKusUmb>d4)6#uTR->5_Ws%uB88tTnd%o!?*kZ@b&`-}j%--Sd3^c=TkG z|I7rx)cHMni-o0q3X_usK`;~^!flxlK;`b{Fo!!iP`5J+(v1kWLhu}0>MO8Oz?mq|GvVb;|u zvL;my$(r+4#VbB&uwg##Dapm^r@bEcRQUvtExWlg-7EmNHdFrx^LfA@>GU*=%AxY` zHlGhQ#lU~LIDI))48KJNkI2Or5MGnSa|9RhmAUb$8%JdXZ}9zHJ*RDxfRsknrX9(G zv+R}#p_>#&!{2Lv5+nijz9H7qun^DYY2MBsRbXj-l)|#16sb)MWafzv2p;v*{-W8A zD6o4{H?xGu!aTH_94c)jsv@L=`#(=2%z`sYSQ+e#5>WxYP-rz?2q)I^BLI~pU$0E z=@T)H@|o!|Q7*wV_W#fS>;kVVy%?s?4uES-Z6~dliT498Ju^r`FwiR?Ao=lWRMp&N z(mJ^Kx%?qz+58k%+cYgVG642$+B+Rd3?=lDG8pD^TlKsr>*K2=bp{*Vt*5_@juqe> zDc;~+E-3^N181D=DO(fnIA-Rp&&iI4ru!RZzOV8KUPav}f3#== z(fNvY#LPDV*H_QP*7u~Ld|Q8ljWh$_IdnTg)WF6o%g=X<-VgvoGf>Ubi6B!E66d*@ zO7POnelBaA^T)x$Q@r+T5h(s4l%v%|VySKO_}YBm0q*LQe{9x8!dUHn?kKh^m|CX%(`^WtSNG!5p literal 1768 zcmeIzZ&1?(7zc1T1iayZ00*sNf&oWi4Z`4H_%Ij<$b=32$-fbcV=^`-f3#VQCVx&6 zM`UWtB;xNnImr;Fa3h|A(?lD{O>cnN=&JE??)?|ZaP-8&A;Ae}4@JchY)mbKj0{W0Q<+d1}Nk}7y#l^6#n*7w!Q3#zM zF1@Cl&H??gYntfR6cAU`sHVmUD^IHFI+}XoAOw@MeQ&Bu;g=*+mW!ec{%Eu@_b5vt ztj42iVYmPS2We`0xEJ`uRn5t_r=WItMSr>B+K}aZa@iMGLt+JRC3fLSg`^m2HR&A1 zP$?Lu?R=WHl)$i?>C=X!%e9WE>&sC0z9mhlcp*X@_{Kf$`rVyp3ZkIgV zEU2S?aGj6A{sJ#ob(WQ9ng9R(pKTzcX(Y2{A_`kG+my_P80>1KC6JfnP;rAxeSAM2 z*Q!RU3eRqKEoqyTH}Q5C z?E#04xv-U1Fv-Cd@~t3U?mmoLTY0uo_e@`(j)WqL>sjh%^RABb+SDaQI5zZT%m~&)P%Zmhq-uowV17%SABC1Gumd0Of; uKa_Qm-S^$`P}sO1@|LoK1q_C4h3*;;p-g{$_;aR}XPN)s($D<;o)g8~+fBEn-$Fob~_7`6B>0_{p+i&)$boUUit8~>)*4Q?e8<56q#BU zY=3=UN&eNc3=H@A8LbmhWz5@uLwUcAt6=W_e-(eGO@9}=f8$5ZI}@6k?L#l8G(?3h zu($PED6$}6f&IQuflf*G&Gto`7bV`6PQ)-TnBl@kv*z6WUfaF|@GZ{SpVrJWW3qAV z{)FEg-=0owwog?z((;U2V1GPjz2l+a1@=M_?>V=7G}~vHeL4Gy9n-uwDIqCmlydir zRW67Cb4?G>Iy$-IvYvH!nR z;^_|^O#d1^3%)<$Ue5k+=k9hq0Gg-&~w*Twgp0mI3qUz_sRXO|b^xwMBH#KMfmDYua zK1Sv2w|vC@#QuHu{y5c*-#6XJ-tW6eZH6RE&i-ZF%-If{z%&m%{gBI70Ok<@)M^`6 literal 808 zcmY#jW z&Yb<4?_yjTFBj~0sGG2>C%#~ReyYgUUm~UZr*!Gx^|7nnKht#L!yjMjG0c0cHz_UD zK4pK_qJuU?AJX@mY3gt#dKc_p9rPr^BEV}upYhBahCeFoZMqwGmF+FH_f<*MFBZ?* zUuXT#X;L(%d0!jPmi4d{>=$9we82cW@qRb9n@uw+3ikhDHH!D@t+e-%f9jdDYqtH9 zjbV3vS!dhx74}Nqomgn!uA=|v2Wu^c`~F7EQkLFbw*R&HDb-zymHQoxtS2!mmG1BR zzLG)3zRbR%ee-eohqLV8Ywzk!Ynf$llCv%2(B=aB9z*-j_q;H}@6^YF1Qo&R{jb6e z*4#F$+t1|m;l4G?18v2Y)$L#B7|+GV)v&)$i&wutqhY^|b-Z(ve#3t62dn?^eXZHg_wA>H z<(k_4k>BpAnY1+S_bJ+}+%vZc!@S)RnXxHm4f}8PZCPQV)v$kIZ_Xb^J)phU7xgo2 xYTTczV3y|O)wF-Fh5rKO*-iWZY;!s`|76pCt+o{ZZ7VR%Lr*{C@)dx21OWZ+503x< diff --git a/test/beta_plane_bump/good-output/snap.eta.0000000201 b/test/beta_plane_bump/good-output/snap.eta.0000000201 index c7dc102fff4279b1e367bf2ce7e53badf1f3089c..64fe68ce59c73102e9d59ad15f21f8ab2045f888 100644 GIT binary patch literal 808 zcmY#jW`KbPD1#6UQxBtYs{g_xR{C;D#Qt`j7=6~4Vf!;YS9XO@57@s(OkO1PfbssR zi*ETn)i<%PxutqkJK5Gg^+9UyvHh(3yB%#;FH-Z`548Ype)ii}8~4|Q?|-)czkm6^ z!2QpvJEEdXwf3*8SN?V=-NXL$GM?fu>%8q}JX3m|@ypLX>womS{MG*UDH6vs#Un-R zVGf3wyXWp#8F!Y@{m+>E>x!gY_8aGPss;48*b99B9+!06&t8(RTD)zV+Wr}J|K)x! z{It*JAZ=zj6JNojrgPWxv~PkuXfhP6Fg zT#*|?kh?vr`k9y7m)z~|hnvJ@m^<3v*VA1SAZ3JMo}rD)^`5H8{YRg(pLGYOo3jDa z7!;~Q_D6d4x=ozmvHwYn*{l7rw)=DHetr8X>9qexm(2#VMZWu)cZjMv>jmzI#VfUG I1z;Wl0BCans{jB1 literal 808 zcmY#jW-}B$I7x(Nc_6uj4tc^XJvEM>=>Gp#cLig`7`J<`wFmk`5U1nsKP!fiDr&2bY z$bJyG|I+OP`;EO)_B$?G{?$jKaDR=^rtLnKMf>MTCu_ZwDA>PTTkFu@_qqG^Zy!DX z=Wot_4dwafdb9E|%=5kO@056|Y=2pp3d_;{!u@Qk%YIciW$pi*Ev-LQJ!}7sz980u zy+!-C9?*_UoLsSAN+)sW?n9OPr)b25civu{ zvHu;9>f=e3nds&*2riTA^4J|=|H|TF_WYi}{ZY?Wmfy`O+3$Mb-u*i_tM)rOoeD16 zUbKJeweHJ&CldC5QL|cYWEZ&qt9r_M2>}lb^TG;DQ$GZz+E=ABU4465#s1mtg5>+b zCHpJ1L>2YBYWBZb`o~s3t6+bVtHj^1!y)^>{onmvn8|s6j0(So;!PWSwDbby!l?!{ Ld7}9Wz&ru~%zPH; diff --git a/test/beta_plane_bump/good-output/snap.eta.0000000401 b/test/beta_plane_bump/good-output/snap.eta.0000000401 index f9db8cb0279154fe5f481be78c13b6bd9a6fa2e2..d727d9ec1ded7ea87795b8eb2925cf7ea5c1196c 100644 GIT binary patch literal 808 zcmY#jW`KbPD1%%YW)6&Qs1@3oW9TNgUvfvwac(~2{jUrKYaTBT*zdnxZll=G`2DkP zCcTNflCZz#c)9GpoiY1U;@7T{4D#6Td7$i0<=G&6boabalrCgmCA;4u=fV#eH=q3; z0o)(UjAQn@i=MK$Ar`z};KD&Jv&G8x&KD)B{IwbP=cq1T)i*t2|HE0gXQ?nH?ngI| zb?L6Exq;668|51cb}kFu&);~buXu~+{w?<>nEp*pu}^uge9*g~*uL9n>uZ+E0{iWZ zXAl3K>|lS?A=i9~L@tJT7nshLTV4;?pAhE2q~{s1ze2lj^*@8S^GB$$MoR+pP63leKo^>|7HeL ziTmF}>`(Cf`@AtIvoBfm(K+!;wf#q<^CkB{eMOh0J8zi4qP_vHI&_P*OLi>n(I+xvB!Ycz8e+E*5~@2rjv zvEOn3_p>IEObqw!i2b?xlvlw16Ib)pv?d1am)^O6Yw7dQ{o5zcH|JD$+<#Vckxj=I zC;J1fA>zM6EbSBR_gpKP=e|Gaw!i6r#~=*z_U^wpZGNujen!8gKi(HP?r+?}zQ%fy z-~NbSOE>LX7_)yzU9#|0>)8FboW(-6ZVKNY!M$;dRIaxwBLL`^1bzSj literal 808 zcmY#jW*`+bKsCTrUy|f4M4SJ;Nu_9^GK618vHF`d;>H&K#1PYaeL8hx_<> zU9kvzQJa#_%gtl#XI3Sfx;Z4+hb<59K3JM$zq`I>rQpp(`HUA5675enKDzGmDc#r!?57NhmqKjj6G>U=_c;Z+)J~B2Z+nbo7IS z!~Pr$^F$K$f85SYwZCuQIGOEhntkkm%U1yA5dd`o;@$uN diff --git a/test/beta_plane_bump/good-output/snap.h.0000000001 b/test/beta_plane_bump/good-output/snap.h.0000000001 index 77d00e234f1969cdb061f673083a764b043ce19b..5ae422cf70406d9cbb3da92875d96e769a503bda 100644 GIT binary patch literal 1608 zcmb`Idn{D}9LKL}I$}cVR+P-m+El8AQR+0VR4R(;_V&8c1L+}BS4+as+O#_w~-rS!PBwjQkY+>IO6U8E4Xo!|HDY^VSG>$~$izu)KlzW4jvE^984yt9@_B&>?{ zC}yBtnXk;~IqzY&jI<@D)y9m|nJ(!aqeLpyg+5`f*ljd8-b=c`krqZOiKECp@Ovz$ zPX-coKAh&Xt~}HK!N7r#WHI;GT}j-eKzm? zO~20wv+^>1uYDlsD(zuuCtpbOGAT3rgkw58-!6A9scGZeMN~g5uX0M_`lJo{vSJZW z>)8WdaCjhix{Nj8o&K^NJd5y&;Q53Ug6Em`47|IQ-<-uf!LNJGC;0WBcLaXh7&rKB zP8kosj-_|tSN7u|{90@o4Zrso2RpG}ArEDN1M;xHl8HRrr7g%~x+)sn+=NZYV^@_8 z@+ikM;7(f0<ngTo9S!aj2i=kea? ztM#FI+kXAq*YRq$?Bu2A`rT@F{gzay@2E1=tES04sqdN76o$Sp>{)gEzJ~UyH9D=K zeQM15&~MW6 z>*jg7tvt`6#Qf@As*1N~74XkcVMv3i22VD@Gm*8+6FS`$H$V(_|I!-|^xw^sLoI)MFO+ zdWiE7?xmrIzn5*DO5}b_x((c0`i-~??d=NOiM6^0dTBu<>ce-O{<)X`ea|fSAMzL4 CVeAh8 literal 1608 zcmb`Ie^AVM7{|AwvLVxK*%+nKFBKQAOv>)p^h-5+`h~V*Po`$AQkx@U>buunMJd-c z<~t|0ETTyvE@Y5JMKb-EToRc^dsCDjwHu9EpXV{(neYAYuh)E@eV+F|?|nZrOPTX{ zFX!@jJc_1#)RxGhyr(AcE_yiZ41AE(GS7t2Wr=FgltZ@8_OWwnPczi9I_@z8<~{3M z)W9rZ{1raoM8*5uaKe3;Q`Aj_GXq2#V5nbfA=E{_z3tE!^q({l=Gtn+s29^&9}4e; z(tHL!7YQ0;>IwVI#Z%)!G)3ngNcEA>R8(^U4eXE)3iYJ!UGQ_rb<(F*mGxT?vU}!B z^2Wi}j>{!?!U#hq!wjI~Z;0)ux6{urC1)1ek45k-F@nvBor*rh2cX zEn7q8lFW_h^O*jX?@aRcX^A{^pKv?f8VP&2cJCCx{J~X%A>{%U6=|(-ODFt1F;5S5 zr)SLKc+xk&q1ai?(X*&-MZLYxw(*8M?j3p|0mU zNx6Eg-&3oT&~H?5F#2`udaMV(S+h^0-{z0z(J)_@8gL9a{7Qj-trNv&W*on49`Ua&8{%y{P4$_&Yvd`AH2q z``I*Ig`77U>BDdrN8=3Ta3^*ae7qaYNNpa}eXIWHfg2XjS&_qb1Tgv}_t-4{B>bj_w>h)t1DTVH8qwzoZD<|n zkF~vd0e;*Tw^hR)_2GjJFdwMfTiCpkq2l&OqySB{H*=tVeOB+jD$;i#sxPC5qbIVJ zpq_?rKt0>^`>3Zm7lwKrf43Ka&IRAfWMIytanuXEbxpz5WBm&2bm+IHb~*a>YdwN~ z2Lk4!-=6}r(XaINrQ@(yQ@#uOopSXSbN#Y;_}{a|JYwFsV;=uZ{)l;8aQK9I+zx8M zJfgQqFpsAvCoqo_%C$Of9_+mcUBBH+_}DtUm)!@SL_^LVyb8RFK7}dXi+^?&k_n2% SJF4q;_}{&J?|Y`mf5=w~N9t4n diff --git a/test/beta_plane_bump/good-output/snap.h.0000000201 b/test/beta_plane_bump/good-output/snap.h.0000000201 index 19b35322310ac3dd88bfb7dbb26ded87894a2893..1a744717daa4426354c6fea41faccf7b603085c5 100644 GIT binary patch literal 1608 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 Fz-sb=S diff --git a/test/beta_plane_bump/good-output/snap.h.0000000401 b/test/beta_plane_bump/good-output/snap.h.0000000401 index d61bbfc8d6de0dfa5dd3e078dd12b6a41afc35fd..a71bddd666cb5c5ccde652970594dd14a451c527 100644 GIT binary patch literal 1608 zcmb`I{ZG?Z6vm4nuT>BfEI1_$WeX^qL#JZe1JW|(ZGg-%S@sKlwJoj)cGGvHB%-jbI#mj>MFg>jhxgRm(s3p z2*7>){C}bd$P}CR=dU8*b51>W$CrR_(7R>N7ZP|Tbc^5XM_`9+)4La|2}IH_>QtEo zf}X^R4DYMX@r=Ax*@=OBkY}?c^z1$X0eN_Nr6<<4@gYFQBS1F`oXz40bo}Xc zQ$f%oA#h^U>9xEE^X3UvHCh4}_Vu5!8z5j8Hzn85k*S{s!+0T;y~&&o->nD5L> zCNNi5{`I~K$eTTAp`DL?>1?)g8tX=1r^kid#{{h98{g;MBJecphoy;S1QrV&yrSos zcud~eoo_7c0|?w@T?(tgywjv}vgHv3bY^)e`RKz;rnr}x8vqv1oB6G8hVond~KNbU;1_aDlyK#?yPcpQaJWolwH%xCm`rcXPv@17fd)zwL@JX zUsjysPrzRL*Jum+mmi(?xnr(rUq19cfAwCk*Jn`3QcoCFkWggQ6Jg!shVv4ws@0%h zzNr#SR_2_!$JEVU@;}eZL*W*&k-}#-(x#wv3UQ^i@$Sfx4=4j|w^4X4=@{LE%J*vd z?cr7mLxZA#J)0@`xMs-?CR6Y&9MKxyE1vnv=qJM?^<@I`bi>bQCP*kmpN&#?>6udMFhi$Xjv+!PTh^zEqCWY{xZ|7#>J2&TXtaZp^eD?e8yZB-g1<4`h zCmO8R)+gHpBUkC`Rw9X~KwjO9Zi+--=ao$nF%)FH8{D;G3O#?9pI*L`f~{liwo&AX zxmR=spS^jP?N*|;bFMlWRIACTixia0(Zber2x{P;iGM~H1)jit&vm@r0wpVW$!aDu2&;uVu zQLu6-pL%jFg@Tm$2{FExzv8h=)sLpU%sj3omi+Pn`{m{Rtf&sTu@$QokC4kz225#3 zZguxq|1|7Zx=yK3qgI7-UE*=RWeR&A5#DF!!R$*2tC4*QzYoa5-ixt*V1tKCDe@Pw sHRKM?x#~(QcLKHPcH!re3QUO%TfYsdGdefiM)4EP`NA7Vn|;s5{u literal 1608 zcmb_d_fwQ-5I)e*M8<$oAPAzA2mw@zB12dd2|9F$3MU}#4&e|R2n=Qcm00Ks?~PIt z1c?cjC>IDt1Y<$x5@ZNDh!d15mJm$@>ybS&-@qT>PtWZ8?LPZFyF2rN3Xk`v7LUgR z1p6|zDICq}R#L<{?T<_pcs=^oJS9TYrRhV;Gmv}d^0>M(%UM%A7Fz<3`z=K96g5i@ zFGIMmb;3aCg3#Wq0%{@fEwg^cnCKd12A!zQ@DHm@J{ZRw}_REdw%8Q|htU%eiIm7M$XDAh}>OKc+}5n7t|w$DF;aJXNy=t>2` zhTQtWUHJ%a{)k+t%}1CMq&IQN0im}p!D4fyz9ZddOQR9G)DnkFLd3N&2%Sj`f*K5XpW9WazUyP;g-e%`)hs( zx&>|Ry>uUq&%d^C^+r$;ua4u>ez|*j-}mhCc5-qufx#ZxyD4-JJvxP@Uf0JJ?|H-0 zMg^{#D0iQU+&h=Y)#=**&o@45amq54!IR4T&eB8%9&dYBo9!gN{FY}v6qlR)KGu@P zApT6T-6-Kf=hD?V`xpq0eRX9#o`Fr)=&+(+&iucp^n|5&-i_MBzefX_fl-8|K4JA`eY*m-IPWE%uoS_i{%s7xlSLnYAHbmBdf&^m4dky?C9Bn+ z!OOzS-^Ru;2nq_5nI$tw^}ClOo57cG=E$%0^j-P80si`Enxl=mEGnGlrr8$cM7j(+ zU(^_TGx(^m+4FWF1JxUShRu}MX`t+Jg7k5GoZtPy2mI4X*9z5cQ$GRuJueA66vd$6 zK&^>2=^RTkPd3=fAY*cDP7C4IHHmL0s9*X?ab_#!bAGvf81!cRwuAgu-Kq8gny-)8 zsLP7@WjFXwUy%-D;a^v>sqS`j#0?qsdAy}6D>RaUbkmP%s|dM$aQDJb8_!*w#K1w` zT{4gEB*AgWcOUUx3I>5O@p$iVSeZxt8u@u%?X)l7Ynvqrv|oA83e!>Q&)v)WzGt9+ F$bUSR<<0;A diff --git a/test/beta_plane_bump/good-output/snap.u.0000000001 b/test/beta_plane_bump/good-output/snap.u.0000000001 index e1ca9e51390bcd9ff11ac9dfe94a597720243798..07114b13e03585b72e048e9ae127b62467595c46 100644 GIT binary patch delta 970 zcmV;*12z2U4d@M!Y&Z;vbFH@9&A#hM)J(TV&Ax$LWPS4&)4mUo_J40#*S-QBZ4gZz z$G+;^OD-0zq`u7c4m9m!%D$2OAvd_{!CuJ5zG|dwuem_rzE9JKxmLXbzamYG^oPq4 zzhfmdWQZQQzCW`ifvdj|KV3K77j+W;K9T$&H;IcLp0*p&zTNp(Hpxx|zpU$jai%vg zzrADF+cEP$ziQ9b9|LcqJ`{#6WO(&IKjA4UyYLk-k^3PxJ)IZ%k2T!BPqP6Yhlm=# z1vXG70^mizHVsdf5|CBDDk-ROZ;r)2wB2Ku<)l?VgGYF;(;-HY`yn^rMF%8jT-v^- zk))^>X&S$<-}?(R+(o~WBKqIEkWRzXU6&zVbE#b2zfrz6WhpB+-%qznWk?vH(mGze1q)ETo);KDKxNua+Va zKawoIa@lqNK9T$&H0!U6zM@4~OddMHzUUpVk~uKbzOt6(!Ta>pzLESOIO2Z@h+5RczNq)SC|}C2 zz6@u~AY>rrKIkdiWhnCbJ}DkF7fim>KFq4gVJ$oLzP@}WgSdb0zLESOI21Otw+DT> zzI;&nTHIddJ`CqFlusNMKQbHx-FFlxKM!>{b(g*KK5*r}$@Iu0zqCnMwS}P+zmfbP zIN$(6kHkEPKDvCTNv*~JKcojKys4cnKj@@#_|QB)Kg6UA_Ym>$J`kbT6|S*7zx>Pf zhG^C+zmfbPI51d^Uz?btKA7oOmk6K$KM=X)r;Ot)KeVft)Zh9%Kh_!*{H3pWAa5u|cpEhasMDdiEc1L=i>~A?!?}{L@X4nFAiQ3J&cB`#FWlkduWjMCDoz7m)aSd0pJ9m=j<)J#9KLt?@nHa|EHES%j8ANpGmK7&9g z4z<}W?4^w9cZ0xCKJtTmRt%`So}B7xdmEwEal6qA0z?voSKi8tfE3SR7OScNGK6^? zQzOr2nF5-mN*WDQ59Y2>79vp4Tq&u0s2H`57H?D#g^2a3$JY7wFlb#!9}-~4AYg&W zm+n7cvtK}>b8cHO;6G`s&C_%w*sK_uJz0VX^-juJPa&!+_z}a|elUJT^4y1W49H^} zM(n#@+K%`m1R6$z;crNp>Cpkm`?|;@cH$k>+Wzkl!#N+-t1p`I{PnP89+jPUDu7+= z<>yV+Tw5+CWN1uA68Kd+&XF~4K)bYz>&ESnPSh_YxksVKPF{my#TDj-%{|}8#ly@; zzh__l+P3qiEML#NlnyDdQyMX!PSwrUNYM*!?mF(Y$wEf^o0KHSc; zBvo(B*%_YmSmx$XBMo$sDV$j{w>6&3bb@@~{T({IPE6Z-!qMLB#g|0W8klDGR5S=o@{!ca~rQow7~ zu|gx^!i`3*N5lG9cxE`n*w?=mO(`(D21TsR{@KM;2@l19tC%yZ^#Yh^tMccB^TA`b zPh}rk0Fr!{fr-Ir2)uCf>7qb@3`cwFPba3^Y`cEttHQK!FxyM}$_^(0#^}{X5O{FM zdd7V2Kt8zWN6IbDt4XexwcSS{MjV@2F&~XgMKRo(eZ9ZDY0I6wuH2b)+z+Uiz&E^W(g@60%aZ9bYHupUWY^V_Z qwyGh39J6*V9`uLW&ep+dodcBBSqH~18}Ll-L(Ap>dnBuMF8dFfPsZy2 diff --git a/test/beta_plane_bump/good-output/snap.u.0000000201 b/test/beta_plane_bump/good-output/snap.u.0000000201 index ceb904336a17acca565f13fd070aac7c45d55228..402516a430333b60b50a977babb24015bac37be0 100644 GIT binary patch delta 1007 zcmW;LjZ+f@7{~G1WP=dTVaLmP#ZZcOlNVv*?U6T$mx#&6%fSZneh?sR3=o0s6gU{n zje)!@X)bR;$hw3Rx;UPU5{f8N#)}ifkQkU0Xk^SF*&pz^`#tx)M`xxplN^!tk{o1m zqLnm;;;rr%sBWs|^V z+z4r~ik0eZX@0C$UO@l@wNBFmAwk9X_3C_kIKLK|a*|`=kOVjM6zwosf?ntRIWju| z_PZJBRpKC&22yE5?~MGSf0~X%l4;L&e<7xbrHa@-3A%;`hSW^9Vuam#RQPwDnAUoW zK5E~BiOkT!ao-|?on#!0>&wZ(R+q*+GOrrz_l>vordDI^ruOkqJ%zZnZ9M93B}L)u zL^`GY3NBgN$Y*QI40dhD{SiB!jh$1w3yTTaSn=XeWJ?4e9*h5-W5l$;fgdx4B4I7$ zDvwnWL<#6{FjxJ<@f_IOJg_j>bL}M!Q)V35pOKxxe5F$1(OV6|f@Iy4e;eFCT~?RY z(*cg=8q=D4QqV+acH~*q8SIVlGn@8~=CHmMKh`Y@hKlRW50iQeK{HlQVaw})=OeL= zx+j6?C|3br*$54qjhcO))dqX1JBxKzy%11OaMCItY>Y7OSlFDI@dD@N&Yw%u(qLR& zmR&980%gf*@fn#5pL{e+8dypNStHS2N;Q_rh*TMsm?{$yZD}Nz{mq(F7EpWE+WXx` zKd7h!OL-R)M8hVkgkMwO>ilnm9l3EJ4BSqbK5Pz^m7fNxef&`Rl1e+l?ewo|_JXaj zdfnt7@t_Mj+VDkmKGX@eRw%L(*lO}{o5|+Eb#=QU@<0ZdcSmh1JE(>m6ny``Cc+}% zel}D8T%83MzqhhJrz(NF)>&rhV-+y6`(=FB8$xiVxW7gJrW^(o%u^2cC7f4v0O9YWShE>}X^!kraAa;m`!*3>V*2kR0&e-Ofa7mtFcf9dK8QvAQ_g7LwS2tddUE?sb_v$80>@2x#n`p^RigD^ zhQTr(>W(t!mjfhL!OJ0@I|0tzWJ>ASVRZ6J($BV?#w3wrWGp)oIiA^K!o@`Fo)nvH W{1b+IyDhPy delta 1022 zcmXBR{ZkVJ7{KuzFB5rDgfrH*CJX9#ITL|^rTE0K1~PC1WXAyASS&`+8gufpHD-bv z80lPa5eHYdO^H&yr~GGL};QX#>*e@`Q`hawVSm&N6~Za^%Rof z4ACt>GiXecRjP9!d9Pw&J4p;7EdEsHP!2L}%hdCpI@Fi+UcPosgf1gP;WWWXh`$kM zUuvN;*qA#9XwDN8=zHUOf z$_hDNtOmzl6{lL?m2TJ+wuAE=)fv++EpeMF(&4Y30bcc$6sU0IRdbq>fEYf*6V9H5 z_m)@aPyWsW--hLpX|`g+dKXX8y{eDkzBbtv?QRM9On;mG*)PXIWWj8op38>eMb>I= zb1t0o@`~tvcna8$Nm|~5e9f-K(h8qdK9cx@{9-UoP?iq;@D4RUKL=Jy7NYlO@V4x9uy?j>9Wyk^$xS~QvS`qu{&MSlR|c^Bt&&_MdGPi4c9q$LfJUB3@+iMq==KdEkt8 zDtr_B){!#uKB8gJ;2W9b-}rd_2WtIOr60C4OC9@I!4Mn6lDAsNB6qx{vMfN1f}#5@ zclPr)ak)r0ulUa&hMpRWLTG#(naumt#U>ITFFns>+~Z*9PIuJ}I|;s0UubV#Ov4cF zO1IWbu!*f$e$}Nefsi}!dZULT3hlENWV;gLv3Ae{sOgEw7Wuo6UQNO3*J}5BWTc?( zzQ@6?3$g2Xt(dFRSmdo9Cc4Vn;u>m>A(f)?X}1+)>4fVl14L*CHiW(k0rD@_snj|l z)~r}6wuEjJThrCcCETyZ*eKnpoSkHf@q1J9^jxWQ)Y}@ dd6kdG215DG`Y>FZzei7T(|g)m5+;ZQ!vBwa*2@3@ diff --git a/test/beta_plane_bump/good-output/snap.u.0000000401 b/test/beta_plane_bump/good-output/snap.u.0000000401 index 538d9592b87b87d04b11720a099afda75384f9b2..f95455c0db775c29c7cefca75ab759fe333fb8dd 100644 GIT binary patch delta 1020 zcmXYueNYnw7{+m%h~j7iq1pJ@1%hFj#)!p`moLXa7~^9I4BK$94dj~uy@4+yWxm-BB+;G_D0UN4XdZ;%DN0IQ$jE35f z54ycuN)A9FXyj%|{1CBmHlfZ(T5cu)r+V#hicSvqhixY6?Zq%Fb4%Dm7hn-3uhk;U z3(2=F%mY@W7^-*O_DOiL5q8_bIp58WLt)_2suoHV8Wv`nNlOCIJok$)kQ@QJr+*+X zF#x-*yqH6od3cL)T4?z5)P^Y+HJeg%j7X{Zl*m#u=o_i|+SF3b*vd-wuf4dE$p`7+ zBN5eB07I=digVTepj2h-Q6Sr^_1qa_R(m3Q7SVub~r#I^TS4~>k*J6Pd3v%iwD}=^RDlx661~cN=FvU zIN@k#eFn*4N!Tm$n}6+kBxd=^%-7lyAwKBAPSSn}M9?w{pPF+(L3em|;!czicHFMx zq?3-|)N*?5N0k!vx+&W8jx-#U+3pEnFtcHZqbPb&CV@)gS1Zb!e7vO9#qFF7Hs07l zquFg;j74SczE)wc5XZvA71zdN;QW;mUDrW5kUi~5AIQCte1q@G2N{n1l)tO|PQ?EX z`beDB(QuTzhg{L!jYYcY`ssJ$-9aq-IeL~52aEk0a@}|sHdu%RJ?*hL`_Ca5l%?7FOJF`l*9dZ}7lf7xak*1~#a>8VdbXBJim1uIPj0 P4O6bKl)q6kX-fVVIDx^5 literal 1768 zcmbW2c}&x17{?15KyZqHid+hgW1Bcdm>h0TMJ%P1qexki!$P4H$GSS!3KgYT1S9LD z3TQ+QVFr!h#V8__2OJ2o5O8uhj*LaNaVA40AUHac(LaQcU$Xa~@B6;r=lwiy-g8KY z^nZ(Fao|#2kym23C*Nkr36NG*>$bdUyMP1rnVv~q`O}r*nsfv*6Mb;(Z`hx#I;h<~*%J_f?2R~w6-M*($=V)OS; z))-x37%gjO5OVW3Ja^)1$6{kUmYh_@U_&%j)MuoH%|T`4SPmO5jPDO@>NyO0gZe-G zKK&tlZS<(0lS4dT325tgY>B|E`(p?CM8T+RH4S*uOov}C3%Yg5Y)DY6t4C--AW)UO z@GaJXmz!?))($um&bLL~y!#6X!`Jooe=J!0qmS7Pd6hT_O52sawI{>jN|o0=RR$S$ zr1!0f7;-{ARk3kshXEn?T)X_DodXT`)$%_teCve?Mt1#@5eist_xs>fs2>RLobtH2 z%^S&#jI6&}TrvK$r^XQ#0kG^~z2716_MK_&m%B|;tiW`O%10>N3+p+@#lITt w!clVtMbXB_aNp!rJ#%|-qy0i~*8t)B`+gSEvU?<13|Oj~ahiV8(7QkGU!VHGZ~y=R diff --git a/test/beta_plane_bump/good-output/snap.v.0000000001 b/test/beta_plane_bump/good-output/snap.v.0000000001 index 5e23bd1bcbc2e717b496e397a0a74c16e30dd83c..77710e09890980978036f4c5900a8cc008008fde 100644 GIT binary patch literal 1768 zcmd^=TTIhu6u?V`GDNh(P`Nb06=iG%%9sJ8`+se+QWXVR0Bx+WIb;|WWH1cFDdRH1 zDM1+mL)n}#*0D;dok$tyt6W;KQcD$D(Q*$U6a~2|t;~l#wU6#)+4pjCUVizVeCN_f zA^m5b?7p9rT&n?zwkuZ{ssi_IM~S-3K4>jXb)lqNV{3n|T}q)V7MDacEkmw2sjR}= zSWU*!l<+FX?R#Ke=z%pM`Zk6Jl$;dT@F6Xn;3+3Ow=Ba+{I`NWxdi!9lrKM ze^hMg%x_pA%z5yMD&fz4Vjv2GRc^-Lz>5|jtX$tgkkSk8f7wk&#NOhHi%(rp;y|K_ zSMP!zxLu)jtF6#awNbudhng*T|L`;3Fq&)rZ}R3zXW43k6+v}y zY+%^4>d_!!lmwJ2Vn|4Ip?uyp%nG&G(}fglAbgjOZ8+!HX7L}{;#K_`I}OClXJpQm ztAMqaOJ%(Mh+t4>G`kH>i0^SVbhej)?h3N_POUzOGX8=8>Z5DX$U-}hyK~lp7ruur z4))MMKD}=zN>hUFwjhW3#6awxp6cC|Kt~^*2$XLh+lpA3Sr0A+5Xe&|dzpOK3#Cs; z$`+T~SoHIvL{2YvRzZWhx#u<8}yx@RaPagzp0JenWgX7MADym{UNq*ax}vn62YkGO)YOke%tzY3H>fw_Ky4ulnyp1>~}m;oG??@eE;?p z?dJ}BG1@O8^;q^Hv#|ZeOv&k`j-J`4XBvQU6>|d%9y0O5ea{ptdW49WTD)&DNpWofUkhGsY zytvx*n<|ERI!~AV6rW;me?n!(hYP-z_8$UwUcdI%)c#9<&Y#H=`t}|5mpM{C>f5(T zstP^(q-3x7pTSr*Sirt2es8enLvalMYIAW(%t=U_SxsG)?W6hvOjI!v@Sff%KpuZC4XgAQtW%}uL(1~H^ne-_6>;_em4#5lT5Ny=d)j zNBh0kRIOxQtJ{Y@e{eg?>6RUOd_egP6w)}19sa`2vv+H*T&8Qk=Rtg1lBc5mafNPf zEo*&y&8e&9thJQv=g)WAdso`rK5`?Iu5**M{Z|gX+ZNGg_HxnX^OY|vW5h3GeYjxe zBA)%+mB|jwk(%~P-PCs)H(S`7MXSz`R&}%AvW`R1ttZ?*?IQ0Q8{;thJ0XR}*99Ey zZKAXv8yab2n0Nem&foCE*7j0=is!~lJKJwk^-kIS($@aVj^A;gjt1J_YGXa}S2Wpv zU!26{$O*~zC6~Ens;&jvSDl|yR@{J@o-e*LcY4@oZ~yEFHy`gC3w!0-GnZ$X8`~Rb z9=RH!rD*^8Zs)zV+tloTZuorSfWD6XiJ7b1EG5+Jzpa_!TCrCF!+rm+9Z7f=Vq)Lt zG+}|j2~+zCuhY$xzBAZA@!vLKwwc@hd4Z3Vjm{_T?~8sR5_CUd|BkKK;~#~(?GHIP zhbM+rc0YOwtl!~f|n@|ODzSy7-cHiQ@pX6*7vKLW0 zxR;BQXa5nEH2Jbn)%^mhT~~INsqX(Yf0INAv*`XE+^dsM6f$6#M`1o|K=&`T_z!?} F8~}2mo6`UQ diff --git a/test/beta_plane_bump/good-output/snap.v.0000000201 b/test/beta_plane_bump/good-output/snap.v.0000000201 index 37d6c27c6494312812a98141ff07bd783481ae32..3350b76d1a1740aac583073ac3054afa832daa51 100644 GIT binary patch literal 1768 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 literal 1768 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 YWD!vPm-qkIe2qk;7iyUp0Of&G5C8xG diff --git a/test/beta_plane_bump_red_grav/good-output/av.u.0000000001 b/test/beta_plane_bump_red_grav/good-output/av.u.0000000001 index 953e7c2ac368e513cdcd1b419be9941097033fca..77e7a735afb21518f16f430cf8d92d3f3aaf35a9 100644 GIT binary patch delta 495 zcmV7EHdf!@ZJI^8>^82fpOuUmu%PG``)tz23zEMZPU)IpfVA z7`}0D^TYF&Aygn$BT?NUA{=`bqN}e%|7GPrqoZ;y*`ln`KEydzCMu= zAUM{Ss$jrdHNGv57GUSzdA=i2{@94CrM_ml_6|QywZ0z~rrUj$YCc43YkVtkwmtz{ z_+}(sraqAoAUHBtW%n$A2EP9P5Pd8>OTN?TloKSfcD@+NU@P6sg}$EA?=(a@Rz7pS zNVeLUi9WndaeZC{c|MU5AUKl|de_mEz`b2uOHz~v1iq)zvUjv@Fuod+6nVr;J-#zH lRdXc_DL!81o7J>7M?QvE495YgH9nIO17ndO1q5&d0084r^gI9n delta 495 zcmVR-XCh?Y&+(8dr`6F}{r?B6z7KT)r_jMWznFY`(k|M5vmb zKEBBc36o@jXFks)!0t5bSU!;vAUJP1*zDvBF~0Jh(>8HUbG`b9DjSSaJ~=kyEduntUi4qnjJUsoj#EfAUM$&I@jb&UcUW0C+QU&p}rFn^J$9% z%)T3u7h8|R+rEgtt8wITh`w<#Y-`20+CClTZE+deTo zEVLpV%s!D3AUN!#ft|e%Fupc)(R`^Ha=tH!thTaToxa7ZjFWivtGAeZz|CJ&2EWQX(Og^M6SH41^;rMK{c7t(e{ESFM$p_t%}(Oe4HWIe_v+X_c$c!Dd1t<`^NPm( z-`VBA`lSID+QNp6s}6+NEIMEpxxxUm)Bc^|s__CbCIrcIszvqi6w%8vrTh;TUtiM4Mq kv`<3@j_*PsSyMM7Jr){ui!hZYa zF14$QQTt1uMI71u+G9T<2cFFFN#K0vy#GqCb)f0_u>BpLsVe)`llQZ&KBQcmmbG6= zHMBQ1K4O3Ru#!ngh3yv$D`L7Xva*-u$NL> zv$pw5I6-qmxGJrrPxIUBXC0ou@3fu$LqFady6eO3TXy+0uG*VwznF=W_uAP^`za5L zX7|lXwvROXzP7$Qkf6Eh=|K}+yB+pl`DcCSz(TA2nW0i$!IMnwuf&wykPHj4Z`--@ jHB(%ay=BqD>vN9;*{4W&)g~HP5Hy!iI1wvf0L*g$Cp^~% diff --git a/test/beta_plane_bump_red_grav/good-output/av.v.0000000001 b/test/beta_plane_bump_red_grav/good-output/av.v.0000000001 index 54fe41da5d9d9585277b2fd5d0e4c680e96634be..0a13660c5bb217700b006a46b0ef8d117a006611 100644 GIT binary patch literal 888 zcmXS5W*9QSFg@%3%CKd7A3d~fTI|lcZ^674lZd0<`??i;?=rAd?dw0|>6U$B;=X4S zy_ySdP28u-Kl4FMLDjxJllA`QG5YR9_vk0VDQo8CUECX-w)pJhLc@J`K7Hk~kuTpT zwq4XY`1sO&Hu)dereE8;&!y=)*Vg}g_x)5jy!n&UvVAgZzb*-CufQ;`_|e{%oJ_a& z3f-*U?)lPw9}~Axh*DVFKI`%XE%V&1`)aae+TACf-KTil={n=xv-=uP`rdvPux;PL z-z*`yZ#po{lh>6LEh)ZdtMlvLCDsIGyJ(SwSuc(U+VP2-^D)b&+l9n7-(Ivg&aQH9 zLrVLRxP2=$PdZ(aOW(J|@7Im#Q~WW^#{OXGjwill}#^0LkW|y^uY2TapPCFLq z($c4y+w6XoM2jguJ!`juRU>|C$5}h3d=-iL!CUQmUxfPYvuLwJ4?k%m{}(+n_iRHq zTni|!GPRo`S)h0NM}^(pd08hvB`mY!n__FO%(>5w#dURM`RToOv0jyX+Ltf2v$lJ^ zz5RX}hIzS<6#soF-Dn%NbSD$P2dCW|HjM{WvwZCYoT`1YXII%ZWxZ3J{9vM8LGJX4 jvim36<=5U%vAR@gmr}QtGd;u`!#s5N4ikZmt literal 888 zcmXS5W*9PHWtm9s?hTjso-RGzF|SN--z7esD(`}#eP@4pmb9H;urFz!bmgfN+x9*B z-_p71{ zz3H6!gDd6qz6kCeC-2XAwC~=Q6Q8DSdbH0^TKDgZf2a4|Hrl9KdSpI^dDEZ2j6D;< zvF|&V@AMsZY5Ouw9j0h4T(eJooy6zM>u>E_6LInfzwM`ekGctli;?f-MOf_AdDW(DnC@Y>;Jae@ZksZ@Ws(!uwC?M%%YRkCk|x}2 z*ZN3%&R+56eN4A?ewrNU*>^QqRBz2LO#kYZsc1XClC)El*!@ssWu9G?*+toI^9^<> z3oAt{Ufs6Sd}^ShQ~1d)ZSyL=)#jhQ<9eVh^WNmCsSE)s6FoKg%qz^O>@(D?#Oq-4!e5o#i_o*;z#DU-~fdk)7MR$a9f4r|o9U zc3A&<{ag(5s&d|7HTNzmS#P+hGomA?%7oTPq+vV_HuREZ>&@Lfr@8t65+w30v lIXsJR?>0L%F7_0G4GZj^SzKk$vM9nZ58b_kgV^f?cZ~z zap_Fyi2bu>6-8ZbQQzO2ZF5|$KiwYPqgz-?y}J^_>;(?LKk`Z<&EE6RE3W#0e0#C2 z+x>YK=Gbo#YrpY*q1*lyFLp%7T`1qrx7kE}Wl-7vx9hrX{Vja;_H2Y(y%HUF)(x7oe$ z@g|*?{m*|nwfFN(*uQP%yd`@aS}@GJ^CQ;fTzQDS`wqqEeT5nJAD)}IE@f@Bk7kcw z+Sk`(|JF{XFzH^C{h|C6hsXRy`;UGymhXDsvcGSZ$BRSqRT$>2I(_)Vu3Az1#FNn? zle`1$9S>jjeC%CdUlq-nXx3Y2UmD=v@=LG6etJIJOKSzW{r^R(9@Ma9>}RxiUzv3! z1jD?WjJDaODen7uKWx7tHB)c@o$T1Jrs-bx(jJ0JtHP4)r!D!sG9@b6{^z$t-7RbZ e_O<1Dr&d;*+WW4sIw4>dYL6ZtgOy(Z%yR(t5!p2W literal 888 zcmXS5W*9QSB!Ydj;(0!Mg@dmxcnuxwdmoujPCwvke`TUc-=r){`>udxN$N{Y_J>VL zWv<@szh7k|lVrj5fc-4*L*HCE>bxJ_qpZC97V8{VwRg0d!J#7xTT=MeUM_XNihHtG_RSa!^UTjXpE}fLV$VF~ znZ4lL2zxPk)`(SClkIblF!%4YPPBiL>Y)(PYrfx1@y%tg*V+3Ef>S&m1{UtWT^X@& zL0~3^c||pD%@G%D?9J0`mDP?n|JZ~+y~x|YBjn-#+VdG0=6zVL-CK6!x!oGZX)OXT z1MNf0H^~QAC)o2n$nH@}PqhCoq{E}m>t(+s>@<_z>yZ8Hm@CcPIFt70otzUjAw3Gi zycOGwDpC~<_OA*usZ`r-X+PuQmFzQG-u4UDHCA2@^s;Y?wVeMUQ^Worr2?Xlrk)UB1k$R?4NsYnXqY%m9ZcUm zZJ?n*b+We-)9HXFn3-roGcCUmu<_PUsgbRv(*N$IopG$XdF$fcX+0} zdHtr@^$urJn>T~#sjhc)LE;ka&!$cTntN+|zAi{#D%*b+kh@Z*a4<0g>65QZ)j|Gx z_-x-KkUQorJ+}s=pHXq<_F9<+hZA3Z>;lp1mz%bM#Q)UU)|3L(iSO!DnTKTFnmTr{ zdD=R~VDmcvtOT29bg><5-pZY;z~*`MaP0<}rz3F}Y@Y6$uzF9Z@)|e5 z{@u^M0PJ5Wn;BsLwog{s0CLZ{wqUS-kKMZu_OH27#Vln1!s4T6Lp?Y?@)_j8@!=}} z6dWHFtG|QImEWlej*khk4B+@EYYqU%M>pf~I^_6(r5C3dNP2l0CIC(^jc@b7>BVK6 jD>z+*9X$t5Cp}(U!1Rh(Ij}hU=Y1&Yh1%&^0hpWtofkYM literal 808 zcmY#jW?;C-$H2hgQ14(mj{{7r2?Xlrk)UB1k$R?4NsYnXqY%m9ZcUm zZJ?n*b)U=ISU|MY-Y=^`wBrWXN^T%+lysxQA4vZSU!8dwNS~gtKMzD3er{+0iGQ24 ze>O;+%k#(-kiN5P?ZM{7?AP)K@eizJivY<>UzWJI7f8!2$(+^(`RA|k-xfb0UH9H{6G;90^!L&y zl7Q}b(Ge*!r{3X%vBwS&o%nn4GLZO`hQm!7Ky|ma=j&Pl^`)}?2m4cfg3Vc0Ab*P6 z>Pr`Zv<*k#Zjd`<+=T=|`ooW{eYQ!m!C}qLRaTpUv|`I2QBk0{q52fg^+0vvyZTh- zA(I;y0BKH$*K<1UT<;#K0`(3Oaj%*&x zzs;ZLgZ=wDpdajCsSV3FfczWi6DR}nmu-+~3dr2cs!Urz^jBuyriX~a(uwj zOI%SqI2>2y7_9-tvq-6OHOSol-+i^9bm3XBHye~rZa$R-r<XgM@}!) KPR|O!r2?Xlrk)UB1k$R?4NsYnXqY%m9ZcUm zZJ?n*b)A=zZ?XaD=(gQwJ%IG|XEUomIMzEXNN6;Vb+30=oaD6ZiC?{gurl8&7yo*P zyUc8Bz5&HMU;j1?b*gu8c^;VpGUx1Cd$4(l(iZVXKt7|q{KA7kbFS~ca{G)Y(4EWk z8IQ%*JMj0!ovkhc>Q@hXp-o|SlKy$38-n*{XT<;*T#Hlb~QoX|o_4dQuQ|cXRe)VQ-XsdVF z^scJM-obGTr^hwBn@>m4?qD)ne6sCN*m)xBge0~iiAOZUsv)jNpq>QkAAWL{uH{l-N=^LAdW zYG47HSKV46dI+e`zTd#Zc`{JHleMBQ(ERz_-|kwL0OKz+*(h#iy@U1++n^;42=ie6 zm56>dZ57b`k7*v>7hLNd{<@dnD}Xu4A5N{wCdff z+v^=#-s=1=N<;V;79T6t2Q$k8&70ldc`6C$&a+cj?LF>M?~uI5-#Gr2?Xlrk)UB1k$R?4NsYnXqY%m9ZcUm zZJ?n*bzcoqHZ!)@JM55cw^Q+`cW9du5v;FL@36p8QL#w7-XW!J%Iya>^$s^DHpezv z*E?`-Uc$}JQ}3{Ed5Q(cxjF}z=aDHObIz`{2b-rEd9gnsrQTsOM}Ut)Dp1|u{q@Be z^$y?8eg1b9D6aRW=FxPZxbMg4Wg$`Z4qM)vY+UD3@9_VtgYIo0eW+pfeRiOEFn4Y; z@zh%k{i$sKSwQY|;gr_Q(X4maoGMzLmR|4hXl_FLrU~^9ta%Fz zo=>WG5Z;(HeN}J0!(DOtHesNBFKk`rNrl%tOw~{n*D0)b5Z~3OG7rhTEBb3~6@cM% zRnjnK1<-zVjj5?zlj|M0Ri6mkP6LKpMdA*FiS-WtwHCF4K>g=6LLD7K>K%^XUmvBA zhA9kL}vl0O&J zJ8*OrIA?{`J4km1o?4ZN@GmSr1kT+ST~ku;u!_ac$PlPrg*&gf7RW#T=ba)mkoJ7$ z)IYBp7!J3p=Ia9aJB1urO9Ja1M4!n#NjE~o2Q0lTm7SQperml#Fwas+d;fX|yZkg? zUfp_!Xt%~0_I5!3Kc8_xDY@R^UbL|N-=cbl2MV75u3ObRNIIU6inxPFFVs%Y3c%zH E08LCqhX4Qo diff --git a/test/beta_plane_bump_red_grav/good-output/snap.h.0000000201 b/test/beta_plane_bump_red_grav/good-output/snap.h.0000000201 index 05cc370b04e534cd75e67aa9d6b11f06f905b7f7..ed6a543546bbb21402dc33ca3ca3bc7831fe21c2 100644 GIT binary patch literal 808 zcmY#jW?;C-$H2hgQ14(mj{{7r2?Xlrk)UB1k$R?4NsYnXqY%m9ZcUm zZJ?n*b+bLHJR2PA9o|^QXK1+9JD5!Ot7;CecVM5iElDb^-r;_JQvRjFdWRd;CK=Ub z^$ri1R=nDiU+*9uICD)}Y`ufa^T-sCIcL|}gUzeIrnviwOTELH)BhSj_}4pJeP_N~ zE4AJs;1W~d37|eJ2G7?Uf#zX-$<-? zcz(deD$BdxfrI;`+0npy2hoN~fwLh%eP^c~yBbmNpy9NYV^tN<-@E!$<{_EK(zB4y z-KXB+diKr4y+HTae0<*JkX-K|)pfFBSt!uFqo(4uK>zOD?$~)RquycK9sQ(hDZqHt zVi$<&M3@Kj?~QxE6$OF*C|xm0=Sf(-!`A}quE4B%hyJs+t3Lzv|Lxp|9pHsa>4CNMk$x9_~`3-tfmm~{3J@xXAs)$dUXr2?Xlrk)UB1k$R?4NsYnXqY%m9ZcUm zZJ?n*bs-xXLu<LVf!Nsrq(;SJdaEPnR9lnJ=nZ^QI}qp*ws7izNr&v2~=02#q&;O zX}!Y@DZz_hI_n+01)?Mk9P1rc{E<*1X<9ZtKaolGJ*K3p1DRxY%3oaHwJSeRiOE zFn8uYnRY%$r{3Y)fAu0(&w7XB-iP~lCIHQe=FU1EUhlxg$l}`OTJO*rKWXs?-+G6v zhkS~0S@jOfq-X!`ZL4>p=PZg(0*0!E&jUo z4i8SVrAMmQJCt5_X0rp@Bmcwx+4SOihld+jPWkoJJ6K7)cp5Rk-a&jg?36H|fA5)T@p=O7?YZZ!%U=Ps zzj$J5bPK{fn16q=ev+3K?Y3IZ^$u^oX-v4}RPV6=7Vol&!1y>J z^X|U9EzqCWW72K_<(qGCyXbo({0obZ_wUvU{&uN%STO(dZVr!nhgtnvi(K;S9qi%{ zgpP3 zYYEU?Z^isX@tS%EsTb2UFHEd=&=s@2I|b;^4J#-9Y>%pU*y6l8NfH>27xn90l4=p@ Lh1%&^0hpWtLAy(t diff --git a/test/beta_plane_bump_red_grav/good-output/snap.h.0000000301 b/test/beta_plane_bump_red_grav/good-output/snap.h.0000000301 index f70e60d8a6a5577302621217d905848eb841ba6e..f4ba0791ec7f624b1dc6b4a14e64fe3024a04003 100644 GIT binary patch literal 808 zcmY#jW?;C-$H2hgQ14(mj{{7r2?Xlrk)UB1k$R?4NsYnXqY%m9ZcUm zZJ?n*bxQYQ7MldrJ2=g7Qx=G-cSv+g|In3K?{J4HT9zrY-r-76a)N1ay~CTS?ZO*JCgo; z);mPia@I0g)H_VNAs7||RG;yzET+`C-r>^*PtPMx^$vl;b0vzy>KzU>%)ZYKl!v+V zfaRIJ(}C`?@-UNHw`nUHMMZt={2W{;jjFK>GQw zax>ux^$w*vm1}z*1H;+L)w%yhy+gCqVQt^?dI#l_jK#6i^$y~@`c&p2nKyNYOkAyB zy@RFBxBl&}^$r_2jF~xr?!2(KJ9h5udWYkWj;h{xU+>U)wI?a+X}!bmr<-3qZUxG3 zKB8-)i7*f5-{M7kN_&9%AEf;cm;&@)#I$PuOF;iTzwXCjnNaU=SR_?CWKO+ z)oJw(bLK9t){d=rhX-eVVpe_`?AJLO@YJuv*;?n|Us0Nwe7)g@5~Xs+bOUovUH za94XGH($gb=bys@VJJf$&wDmqvz5CJ6pA;$(@c~OO4ml$7qCox1Z)3UGL+Tyc z<~(Chjjng_xyTlB7ZeVC3u2ep1KsnI_m78dy~B>sI<+N0b&vBB?!4|oq!((ZX9Zw# F1^^J9O}795 literal 808 zcmY#jW?;C-$H2hgQ14(mj{{7r2?Xlrk)UB1k$R?4NsYnXqY%m9ZcUm zZJ?n*bpm(pKRnr2?_g=YTWC&xy+h5>hv|Qt>m9<+Jn*|Sq26Jhk5}f0`g#Y!mEXe3 ztLq)?`J#(f6x2I(CNSOIlv3~D@;ovHWX{>O_F(f~-#sQA4m9t?&g1VZfa(hB`kslF z)H}>Q9dwN`t={2e_UofEUiA**F4?UQBkLVBCuG{6si}8(bNFY&_v!TxhZ<(zX9t=G zbLX!@rhN+%>m44RJ+de|tlpu?+hW2DKVUephPTeq2D+zvd7Tkwy+hPNF&9%sU^s~S zasJ4tcX0ZZ<8gRxy~C~T`MOp>^HSOVvw+;$c=}B68OM5ui%T!gyX^v$S7FtjqEYW~ z=SgxV)4w{0==w=k%U{gMRS8t*^NjD@H`98D$Qg&`zU8QQ*x2>%kK(sF2l>SQwM@MA4j)Voh}`t8 zcX$x`$NNzS!aSINgC|titOJH?X49O;USRl1r5`o;lm!g8^GCn;yVpA~Pq>>LrdjWB z{#xBKHk*2f(8N=}qtb!?>J6xt0>%@}zp(h&w*8U@V_Ut$kC|~*+ZyT}RQ?uP+0G#ldukBlu@UxA1ZSb8~jwzO&%Fn$j_ zyXNIzRqt>`jn$&7wBF&%vB0StfwWJM`6QvbdWZYW3tt7zu6L-`bZQm?n)mhH#5@gP P{K3)-wbQc#FgXJN?)qG* diff --git a/test/beta_plane_bump_red_grav/good-output/snap.h.0000000401 b/test/beta_plane_bump_red_grav/good-output/snap.h.0000000401 index 7fe1a2e9a90ec6ddc286e776badcd3bff17fa775..62919ceaf31fefb07e77425a0da997f8a5ab6589 100644 GIT binary patch literal 808 zcmY#jW?;C-$H2hgQ14(mj{{7r2?Xlrk)UB1k$R?4NsYnXqY%m9ZcUm zZJ?n*b!v$}YoBJ+JLqpNn>y8_-a){Z?@PKuy@LuHuaT>8y+eEB@|!}^^$z!|rtIG# zSMMOt(&J~UQtwa@xjrY-zTUy*d1MO6oU?1~!RA?MZZWwNTJNwq^h3jE%X)|Tg8R)r znAJNtzW7?PFt*;|>fJi!vXXj-mkU@c&*#@WFlb~Rk_f1Gi2TUb5TH}t9O`@Sz^Jnv)-Yi>71hcs(J^x z$*24?>gpZ5w-zi3FsXOAwLM?g3TR#`+kY02JD+S{`cVbwp0u+%@BVt%J2db467{Yd zX#U0hB99N$J1|!|-K(GLt$Ai-Rqr6at50Pfl6eOO za%Wuz+Os`Yla0}*-r?DtAm=k(^$sg;TwSfar{2Np3;U(2iJ`D^PP z9!)n}aeW~${NyV?)mH-JC&Tj4CUJy+VeuibY41W&mwE?D3!V8v*1&lCnp8X)$S+TQ zd8jhA-eKP4y(uNY_?YRxaz#^Fy@Rvi#?>wH^$tPLSW73%AmRg-UitzKcnL?=JDf8& zy&3Hb3@7s)x2G7?JM8mG;jmHziW@Z@oCtJ(y0*953t+tFeF*$I7nr`7K3<$0oq|X& L)K1R|z~l@7C$3Mv literal 808 zcmY#jW?;C-$H2hgQ14(mj{{7r2?Xlrk)UB1k$R?4NsYnXqY%m9ZcUm zZJ?n*b?Xy5I802fcc?eyIu@5-@9_1k`O+mt^$rW>wY#O))jLGinCVDP zu6OX|cvx&wTkjB?CCITOvEISud1MO6oU?1~!RB%On=RJYSntpmmgOh}lwW)O^23#G z^$z!$t{?kmU+)n1z2s9&M7;ykccVzwf_jJG_UOlNr9S?tD+ij(mHnXn zvPZqclA`A<+pX&zZf(!kwE~)#%J!cHESy={D z|77#LbHVivS{qg`%>|mX^1&^&Vilmfiq^h92Xvo7|Ls#XQS}ZF4XaQ8O8~k<>eKY8 zg$VOt{xx{=%WzRfy~EZ?>N{420OiF#{bw_(cla^E&vre~-z;usKd0E#JEWId8JYXm zI~+Xsv9A&ser!$u#2J9$1oJN}K4!I^$<-(a#;45g3#anx9o}nwb4dZJzkTGSrvWg2 z4E`F4&IE>=fW@b-t6}vH6ZdHsJ<63&PS zLv6HqYUa#(hsvPMHw6~gJ3RI2yH(W$jNkf<$J*(@beY!CTb~R}KfkZNdH^&RmR_ix Jo)v(}82~n$Q?LL4 diff --git a/test/beta_plane_bump_red_grav/good-output/snap.h.0000000501 b/test/beta_plane_bump_red_grav/good-output/snap.h.0000000501 index c6ef3dbbe9484c5a1c0453884b1abd4f026ffcb7..9954877991241ca528cb0dc29a71d3a392103170 100644 GIT binary patch literal 808 zcmY#jW?;C-$H2hgQ14(mj{{7r2?Xlrk)UB1k$R?4NsYnXqY%m9ZcUm zZJ?n*b(JSRn!YlqcUZiILsLS#-a$f5FFM|;-XUq$AE5;QdWVg2Z&SW_)jPaw)D~nm zuXos^BO|RSQ18HhajT8|!#W3-=aDHObIz`{2b;I>vDHilwR(p;?)#+~gX$f^9?F@Q zR@6J_uKbd#UsCU&7btY7FS*`9+AOtib12Z=rtf_Oqv{>*Dec=7T3PRKsA2YfcA$AM zcZ%PhxHB2(KJ~P4;q3f+hc&UvpLTTDJ4}^R{ijl1@6hDYz))6D?@+Sxx3*~D*~UGK0dTq&!vs@`EfpOW>Z+Iok7TYpHiOs#iV_KSPL*_L_-zD+q3yHo2O z%GDycje+3;GY{t9C9fW@&G!VlBg4TlC8OSfmp5>eX>q+n#vfs~zBFKXHNT#hQdsYB zZtcx)WkCP3$hl8w0>)E9_UoCqf#C}CFDyPhRl+_#1)BHcg2=aj!1&0X61UeGXn)Qc z<;!n@>Nzi5&Rw5b?-1F4&?h6k-l6K;yx!lyc$pVCdup;BB0ga0CGYOrgq2Rf_&mZr z>AXh0!_4*R?fSsf-fi_K=&I|N%^-Ck5w?@(OzEkyyC OZeZz!+UZ#Vn4AG4k4(-0 literal 808 zcmY#jW?;C-$H2hgQ14(mj{{7r2?Xlrk)UB1k$R?4NsYnXqY%m9ZcUm zZJ?n*b*JZwuPBeHcc`EKEnUgB-r;)550$e9^$up!PqXEC)jKe*vlR}msds2~@_1a> zUhgnBVRsozSiOT*+HTH7oq7kC=aDHObIz`{2b=e)cz2$3b-lxk3ul|;lItDLy*Ux( z9a-=2yX5r)mYjMADYqkYL?_lebl#Jep4eCKkaN{$&pM!a+kT!s`x$8Op@!M_*@5Q4 z-1-0fNml3tslI}Ghw5+gvpTEl9c&X9+^m^e@9=K|^D`cxx@}Wz z&ISb3JLJv_I6uR%-r?5vd|fM`d8uswSwQYISh-&K2vC3i)vIok%jzB0h4Kg5<<&d9 zRhCN-D5`gG`ZkGsK_^iCpRyyijr9&so=x|<19bngtF0n+9`z35yZTh-A(@)9M{g zy6t`N5a@51c`*Mr>5Aw&1l2nv99$mu8fZ@Z;ied&=z52`W1Ta$$JIMrd+uu`3JhO{ zLd(Fv4fPIpC8Fl61FGYAH8Nc128_g)WrV(0s2Q|$pcrW z;ChD+>+|o=1I@ptEqEj-7U<7{H%SUWb1F_asH_8~2UvW-(#w{=!fQf->X#*-KAn&R zjL%8Srd9gXJG`IVVHIiuOh=c)7M<1tri=W;)vGn@9VQ=_Ra>VGbe}-LnGmG(Lhbad H08GvR_9{=n diff --git a/test/beta_plane_bump_red_grav/good-output/snap.u.0000000001 b/test/beta_plane_bump_red_grav/good-output/snap.u.0000000001 index 06c43bce973975f951d3a35b6f80c7ac41831310..12604f34ece06e5e5096061d6a23f2259eef072e 100644 GIT binary patch delta 486 zcmV%`g(zH+`f<)iFbwk2fvQ-*OZn+ z7{50OgDA=j+P-Myj-ze~7C)r>CaW!=20xKZAUFoF(=p6b#l9A(EQM~|3BMf}2SW_O zHNWd-Y**gIMZZ7`?FDWy^S&PE3jp8pL_hG{;PkFQH9wI|AULqExu?I$+`hgPTgLHm zA-{g6Yy~q_sWG!x7(T|a&o5S?IAO+S%L zAUH>uX5N|G#J<=D*7L1H3BNpB=%a%vHNOt=oRn|PM8BFbfav`7`98qrfOm@NML*w& zj*RuzH9wI|AUG%YnCUC|mA?L&B67o++P+w9A3OIc2ESp1T>KA86~DAHvYY0#);@U+V!Q%Q!kUrv+~{JuJUQV8kg z&Ay1#mN#7V_CE5XC$X_r=suB5AUGB%OOKtUz`j1HijSb#0>55dD1N*5F2C+m7J@5^NwT0fCYAUMfoaz1s>1HV-#Gnukl zM!y~vc5#nHa=(x~ZgA56fxoPSN>g#Q5x)>=--A%jfj_sH-5g#dazBwwAUHN)2dt@+?gOf$1O{TE9c#mW` z^W%AQTR)LZAUGU0p;x|MzrKBoo73qMX^ z?}kwGKR@0hy5|^!FF%n?AUD1z11PE?UM@wZB=pV1^@s6 diff --git a/test/beta_plane_bump_red_grav/good-output/snap.u.0000000101 b/test/beta_plane_bump_red_grav/good-output/snap.u.0000000101 index 8fc7b9c8f6a0f35161c1837df49f2bb5fe61a08d..12bb80b8e12441f7af88cce80e256c7543d7835b 100644 GIT binary patch literal 888 zcmXS5W`KbPD1%fQrXQWgFvowDRm=W0KlkbI=ki`~G(9|17`V`qhtK`-#S?iKWl` z37Y$Cy_bTff8c&KGZC|I|I7EAs`~0y6!h;G_^TAAb*Ov4)7ytP&OPt2Khv+)`A}+s zy-j7^gjMgR5;WIScWM0WPsaP};?{8;jEmmCv!X?Q+3f877rfsd3R#wIf9Xr>KYl6!E9ewKw@N`?&AbK7!`Hyt-Q1>DH5dX&J&(zi6@VpL^m-lq!#%eg68Y4(UGy z_OmW2t(*J1&Hh3`#95V;4tu911+O!fl@c-)09b}F`+cU`Byw7a(byI;*V z1^euZRTYkFyzL(cTu(iem1JMEj8VwqT#`LQmnp-gjlP7;#YlJ1bcrqw6~;+56ae!a E0RCw2WdHyG delta 522 zcmeyt_JeJL^yCO;iOJH;3KN4REk3fazn;5uiv0_j33hq+CfmOj5Dr_YP+-49R`FT# zp630B3ZB-gDoonX9~!tVAq`xSql zxqNU6-~VkNTkd(b*8SN!DdvqkzKI{K$tBtJ%`_s)Q6ic3I+JBjU-dQI1>iv`Ux3pEuX4*eG z!*9OmR5e8NglIvV`SlI<8?INHeL0wJAGXh$;qg*>USijk?(0_l_ z@8;d>@@x0^6g+1vZff6u^`Ugt2Alf*l~=@{INAi*gMvDCMyN+gd#}A~l6173N z-pX(0PcFAV@=j0Ab9wE4omCV1+><8nKgi(r^Qz+H{qpi*8&1lU0i#JB7TdfGP|#4o H%)kHuf+g;% diff --git a/test/beta_plane_bump_red_grav/good-output/snap.u.0000000201 b/test/beta_plane_bump_red_grav/good-output/snap.u.0000000201 index 04f23f326465af58797362d3a53a9ba633443b3f..57d565649324ee621fcf35f624b341ddc0e47ba0 100644 GIT binary patch literal 888 zcmXS5W`KbPD1%fQrXQWgFvm3FZHLA#kNqEx^v{3ak+J{yoDS~gJ~jJQ#TNRzO=#Nh zcBXN@rA_62p^0)Ld$$?w4_@9eOBwbN|&&tF+| zL3M|q{cU>@I{}+)`(11eyK?^4*o%K=IB=Au&VF9mS)pq>1q987`UfNZq4|>#x1j)- F=K#uv_QC)F literal 888 zcmXS5W`KbPC<8{r#L;P(JUUHKU2^JERfB+T`y)rEtG-g}vzPn2WBsQ674}j^S)WZ` zRP4WVS0&!0w|oDIe^(B+Yqson5YcV>@cPp}G=nkh27ubG_^RcT*) zSu!9dzr;SE<Jq(|E2D4{riXUU3nlOa~s|^ z?LKP}lW1S3)^&A_Uci3yM`s<>Cnnoh-_6{{akJ3At!b8|$bGB*HhWI)m?jvrKiALW zkMT@Pg68T-+brEQH`jidr0g5dGx7F5n#W&!udcQ~{F-yQT3wU<-JFUCa>q06w@mqe z*Iz(wze+>9qUn9Y=8DLs&CU4RYX2cY?-tLmE_)Hb6HW1lI_=LLJQ>Pf+-QH;$ueX) zf3p3=s~%G%TWt2LOl()xlGEHzAbcCvEz18isdIw;m7tZOb~~op`yc!qa(+jjJ?Gag zA^q=5?Std*eE!y#u>YSZ3;Tg%<@@8`)lBeOpGVMKuDylb?c7uC&vbTZ`Q4adFFk$s z*!?%Arh%ZjX#T;)ZGcLk(=hc7 I1;9K907WD7y8r+H diff --git a/test/beta_plane_bump_red_grav/good-output/snap.u.0000000301 b/test/beta_plane_bump_red_grav/good-output/snap.u.0000000301 index 76a181c35cc67ce8426fd691b31c41f13ea599ea..9988a5fd1c3bfa2bb8ba0c28aa92ce2f4912a3d2 100644 GIT binary patch delta 498 zcmVygTJYAo_X?7fxmhl zsD&|$fxl-uNl1cscfYwVb-^SHMn92EAUMfix!S1ncfW{p=~_1Ef4@cTCvXzibiaWl z=&aK-eZRMQxU#x5jlZ(5qx<$VlfSl_`4DyejK7ggAUKNP=`oh-YrjQ$UBY#DNIyGQ zBw1*%b3YttFN-frc)vqC5)4puk-ze@7W{|>n7@fvoazf%m%ot=AUNj$#<2PYS3fj> ztzjHfgFn;K0J?C)gg@*GU!|0>c)!=`-)froiNC8boI8n7kH5P}bsxJOl)sS-AUK0u zcoDE~Za?C(TZ5Tkia&e5+8&G#jX$Gh?2v`WR6iY8-kd9cVZYo%`~Uy| delta 503 zcmVsfi!h_1RaLIx>@M&rj3I3Z%cO^2q3;}>GTHtri^I$eOj3`Q#wde?-%kxU>sz)$~t#WZxkBN!2q zsbz%}^ zOrv4H-mTM+mBMPjjcI&$8pLS7OdR_I#%Nu?9@GJyg?B~2_BY1Gi*ZW7{TZFAVs}}; zkxU>sQ>Ep%%vN7NvpHw<(lByAXBzsFPj7fXa64zyIcj!4xn>X`#6@sFgx<+6gNI;0 zu*hKX3ehJ&kxU>s7@Sq){;PIB+LhZk8fk_<+YX3E!(xd)NQ|uQE+v6KlWO>Y;GJzh zSR}Xa_dOmz_}eX8(YH{)kxU>s^9s>}wu)6hC1^G!@D_kSYF6i~Xnlu274P>khM0ao zSiXeN`Cwc>oXXYQu|;pc#O6qAJb-h*kxU>rEJ<&6`PY8G%y{W;6E;G>??BjifFyiB twp^5Nrf7FRBHb;E{oOe~=P*!~t%QER8HCWa*gb)h3jHv zZPwlyTE$|&b^j%{r+j+9JtxEqZcc)~Gfhi)LN9^8kxU>sqA_$5*I;r#$j5@n8B>8j zt3T?)$H8ttn;$t~PZx5(3Qxo@3$}8<9lE=?{v{^A?l`zD(Kt^(kxU;s0HvNpd@_%M zKdsa4lLX#?KeI51BDu?Xzr6Yx4%&E+zjNxzFsprszsR=@&LFd1KW34p2}OZ~KamU{ zIRH7LIeMJvfIsiVr5Y8zWk1qlo{6K_iN9GSB31>bkG~JcYU#`kguloSjWKG0Yd=6Z z@#3;wi$9SJA2|Rbr@-)Ae|kTpZb;-)**ZV(?^73?DfF-zx13)QomNBO}_QjTBiwPjkX)37UPs3(5f|9JoNg z+=d@E=YNJj4kLmTD8i0E2h1nNLx6@qkqjU>fD5{7o(5$#oAIoy49NMG^j#9VzuC>woP%rkqjU=cYiWyo9t=7Bi=Kp{)Bhrf|b zAUG3qS;=regTIlgE%?h%cfYg$Uzii)b3eQ|tf~9`hCgJaRiIIwdp|Iu>)Q}$bHAg? zamM*MfWMJUAUN*(%jUM6bHDn%5p=-WV827Vj<;~JZa==nBxG~2f zZC!^0bw4mxP@n1J6Tgv6AUK~GY}+dwR=+k*lq_f|A-}fGtXtCJIzP6Zt@r$*XFp-l z)uTO!fj{FZ(>Mx7fj_8o{tA-WVLy>fAU6ijRIEvuZND56_T5cuZNEK|eEengbibXJ v%v2R#Zof9$eS;yAb3b10kJ?nnc|YFCFC^DoP?HM-IFnlg7?CRwlWPMF?V|e% diff --git a/test/beta_plane_bump_red_grav/good-output/snap.u.0000000501 b/test/beta_plane_bump_red_grav/good-output/snap.u.0000000501 index 280542057d517b974f11e85e23e33d38772bc2be..5abcb1cb44602413a7b8cd3d2f507ea459ce09af 100644 GIT binary patch delta 523 zcmeyt_JeJL^ki>lfr-(A6J_`zECEY~9uM`o4?p$T7kt&VH`(20AE>cx#*urm`}e*y z)Vi{|cE9eo4=3kzSMFa?^y;IlLiqmDhtER~1ccd7#=YK2M_7{)+CKFD2SG z`;YCBE;>KCdH+v?DbAlOTlbeTep~ajy>9=1H9g;mH*xmI9;`9%J=SDD(Fdq`HgD`S zF@~J|%*Ri0t?TXBud~oUwN$5j|5A;Nol9*y_wQe8)W&$Yb$?q`e3ZI(!v3PNDXQP@ zltMKB|HztE=GM6X)4@si{jYZKkKz6Nr09G7{u$o4o8~Pq+W%AE{lO9Wto?#oTMYaZ zg6)6K2;!b?k_FVPVA0<&@wUEP)Ba_1Oud`eDA_*n!smF6HJ$dVg^~x( zvrn+U;P-3#x0BuW6*m?gySuLrtk;5B>U!y;`u#q;-e~-N(71oWHCCzG<<<6kjf<~e zJUY!jd=-0k%Ar~It{Do~#P>|K|8e_k^oB)UV7=DKN^&-O`TI2;#NU2iUbg>7(>6!7 z3+eWI*E6c^S>0zZ>BRVX;gyN@0yXoqXUyrh|Gx0We1n5Mz@S#Jn4f9Mx#v=by}ZEL zFs}av_N&s$Bx0>h?f0yo8vQ0dW`DoI^G!1}tM-4m%5EydRlfh7EO*=SoGPGRb3}x* KHWV;3FaQ9GeDvV} delta 506 zcmV2>^%BAqa>+HCk&6XK|4~1kh;4*?5JM3j-lH@UttZ`RE`&WG4;M zwzqV@K9iBWM$Ll1Iv!a*9NKTc@F-+zAmVyIdBy@8Q3H%W*|Jc3dOV4f3j-lIcZBj% z_OEM>-2zfS zGhH$}N}Y5+C+Bjr^VWGkksKg6w#6dJXt8v^Uh6NMx>0SvyfrOyu1``w%StB3UWRc$ zs+sL^;xKwYMl`(}6oh_1xeyTh1o3e{ksKg5=YVp;MR1J20~{Vct;C7H024lbX=nmJ w3h~^Ay()!2*?IveOwfuyupX=9HIjut0n)X%O#yL}3j-*V8v`f-0Fzt;9G9cxD*ylh diff --git a/test/beta_plane_bump_red_grav/good-output/snap.v.0000000001 b/test/beta_plane_bump_red_grav/good-output/snap.v.0000000001 index bb1ae8461136775aeabda4d30766db5a0601f100..09311e8d29f0950e252e6925a321b32daa8a17c9 100644 GIT binary patch literal 888 zcmXS5W`KbPD1+KG%zPM4w)w|i=ssC^!F1pBJcG4gk5Ae6qRCTvhurObCjw<}yh!KV ze?)M}p&hY``>QXRJqXNK+<&Sfbn~u@ocrBs?32@i@9cv*0B(QV%#JT?Y>E5cPP|xV z!Fh0>w*Hny4O7_mpEhasU+!YMf8m*9HT}xI`^`$Ho!RE?yWhC4hdFVt>3-hV;#<|e zu(KeZ9%<;pKyBmaz}*TFyND z9Wv>gor-51mm%vryAv~2E#7dy+qbUBB2;q9w|!>{o_NY!zlY&p`9I5-CNwwLCB?8g zCi7ggn=qx%aP4sk`=ppHB3X}J?QH_CIv+8NwQm!BdoS^NjD5zG$+0UhyVy%Tt-q1E zS=1igzwg5C&U%=hYiGRTR{#J2 literal 888 zcmXS5W`KbPD1+KG%zRulx_#*C;PMZDw{lFkO5Vq@aoWXe`}gjvWb@y;l96fu8@ma< zE3*vtzY%xcCF`!u&4o09z1dcTlV+V3s=S^H-!_%dVR`NsV+ zW;$nP{B7L-RP>?1LY3_OPDMwqZ7{dTFfV7@VZG(EC)?f7SX-dPa>MSDw)khi?X31Z zn_Ij1gk>~@ou{!*d+56*_}-YhJ$|K4Q=RUa2-4D&K(D=s9#5r*&9r0-u!+>l>H}hRn0Shbui2;YhYJgTAytkRS G^Be#$ee19Q diff --git a/test/beta_plane_bump_red_grav/good-output/snap.v.0000000101 b/test/beta_plane_bump_red_grav/good-output/snap.v.0000000101 index 2d630f3ec6ddd79b8eefa7fb14e53db6ff5d101f..4047a80ba6a0267c373dcffd8d3cb8073753598c 100644 GIT binary patch literal 888 zcmXS5W`KbPC}Ysl^I{AqK74awUqH8N8zj!)N zr*^-(T80Yq@rM0x)|j31*j}{%yrIp>n_6M}(fv19|3Uh_o#*zQ-6-bVVa~sQ=BiZ@ z4J!ioOZYM7rD;^}KfL3U|Hajl_NU%ZV^-{(v44-$mzZzX6ZX%tn%x~)R)%gK!zK0N zR$n$j`^?qVtN*-pvful7l9K^zto4U8u&GshGzJBesnPPu>fzf>_ zfe!n?@A40rA9wB-Wu9Q7-8g0c@(2xuMN$nI<~_gfW)v%8V1LzyXX~;ZN%jHTE!Y2R zZ?|XMxVhAmX|8>y$rHV0j0^1NNZM-oJ?OAM{jkMr^3Ig~-#6Y0{Vd@QGY=Y!3=9!p z8a4khNZ5b>v`$~{ho3!<&+7#bu9w>Li%t0b-KO8((55~j@#s|hJ-VsE3`e`|4=$Z> z@S}95egCQ*)mJov?coMN8Ldm~t7kSov-{w`ccsuTW&0wZqXr`L1MNRf_GkTgG|xUG z;a<;EsVe*2*VEU2m{V*Yx1;EfLT{-3DU*NSw+q-{n1^mYh5QDnev0V=V4ed2e#Px< literal 888 zcmXS5W`KbPD1+8C%sygin0pv(f)f@gN%Yw3m!}rVsJ7T!XL-m9zmK-RBlDAMwMO3l ziq9_}HW(D{k6~1<%59dk_r9_^ntN@%eeOBV>2Dgl?9nY;Rnd7ea&4de^Bt#7?mpLM zf9es_x%pQs?Oh^ouZZ7YY_IY8-Oa~;O6+UX&&&TcXteig_Q;*Nx5wUALFmnc#}hHk zI}!cIZtJ!t`!9>$Zdf4GVE?r3la=UJpgyaLJ^J5U?7ujKn_qQmwqN&y<%inq2K%cw z&i>gktI2-V@_L19l5H5~nd=$+@BTT1pr{R<1fhUwSyT25`Q+|N~?aa=RG zY=4G+1ncDFwEb7Ng{UWe_1Hf#-jS)DKWYEvd;W6AKR52*{PglC=I{yoRkIa!zUfTD zFfU}Ieh2f@3H#G$)Gyq2s(pW3)^tW`wY>d%JYzl{I3H-=7B*3``+=9e#Q7idg6CE2 z-|^HkNQiI3{=ko&zRQnJ!7#5kemWQ4-c3C4jQHoCJp0L JOcwz28~`@n@tptw diff --git a/test/beta_plane_bump_red_grav/good-output/snap.v.0000000201 b/test/beta_plane_bump_red_grav/good-output/snap.v.0000000201 index 5c81c1bf90a71a1ea2e889615462eede293b79d0..4434bbc4080f2d780dc60b986da4f9fe53547754 100644 GIT binary patch literal 888 zcmXS5W`KbPC}YslUu+I(bT{klSN`&Prdc0R((%Rl-{j0~t z)d}_@)>ao|Zv6W4Nf_qEr1kANd@|AAJ>TIFS8kL2i)ZRFMz^Nezo;pj>hXG}y{>!Iw=}&L zdlUKli#hI2*q>hVgzIR}?EPlkIR%iRnTza+_hT!1OIE) vwrS+pr!#+@rjZl4pX~!%dxN3FekP|jQNzV080MjyPa(ens-I%I0GQ_h{uk*{ literal 888 zcmXS5W`KbPD1+WK%zhY+%YKHcd)H2+<`vsNi06H9u_eWRhk}Et)q_ZT6CNdH^@tSv z!?6NV7hQ_%w{SO{yr$e}-*1&>`Tl#Cy?JfrU3IGo_Am=z^pr;}S6Y`h*l$voa+tTb z#C~t%)w>rChS)E;e!o8Aa=87S;MmJ^Cl}f~oG{fm7gcSq8g}!&D=qz2UG3RF_4tgFXX48D@7lfc<;ULa{olD1LYd1O_dj~P zTg!X%g#Dj?9&`HWK4bs&`D)JdFVDs>Z;!RQ)A`W8{aeoOy^7U5Vi@3V%#RHxKGuI0bVzT!2Id MOh3hR0Wi-20D+M9@&Et; diff --git a/test/beta_plane_bump_red_grav/good-output/snap.v.0000000301 b/test/beta_plane_bump_red_grav/good-output/snap.v.0000000301 index 16ff9616f4d77b3fabb49d9ee7ed505a0f59ced5..51200d429853b51b20d7bdb2e63f50f3ad214577 100644 GIT binary patch literal 888 zcmXS5W`KbPC}Ysl8i$_!?XM5pKiyOD`Ule>`)TLTeUs{_u>Zxl)K|c~%YMc_kGnQs z`s_9AFWJ{TYqx*K-8M%`C*M9OXszY5z~uet{# zJ;9z~LXE2Xl45{qDG@kEd!*u=kPRTa(vYVsCZtM#SU&$@_nZYz+(u z_1M4Txo?r?qC|A}F*uypSsx)$Y=5Bdo}kXAMtftP#;||U&Gt`t&ZjI_tG7=$sm@VS z=WTzW)5>2tzhS@NjVIZm;m!LG&u=ViHfhB$@36EtdvwLV_zvHO$Vzq@Jo)aXn(>uV1;2+BCK;m-EY;t}?$#}9d>o=Uf0lX~d$f?F>3W=64>?iW_=e?Now z_Ra@w`&)SU%NIUs+n?rq_Z+)!>Hgc&cijv=w_uouZaxlv15_MF<50!`lc$(20OmOW DfvfC{ literal 888 zcmXS5W`KbPC}Yslho4*RnD#t*|J6$Mh1Kch_9{m&$$9X#+Uu`!)GMf}vA=mz`CV&n z(EjZk&j{s()$M=bSarKazjFU8NzuzT3GVyR{U__X&%VUUdB5gX@7#jU8hhE$zq@#J zJM4?^2z6EIwAd%i6ra#@GRMB^{`YKUjp+SMw>(lJ?0oGv9aT}PJX@Bh2*W)sj{Y5D5z=_{M;+02g_|65jSFDJ`zA@yLT z{pxNrkJJkt80PJg_KPk_PPTVqQmDUBS7E<2oPX~T&klQKw*A-KO#1A1ec8uiaJkjq zotJy&hqN?%>#1V>YAT`omvz?M7Wxr{Vcyih|7&fuJ?)nUe|yL#P-6cgYpVXU8Ey98 zle5ffD!T2}1a2xkPOY<7;{C1AqM5P(fX!NK&y<$^T$j(j_WaR;9)1kjc^$bmTbk_; ze_wPwqqW|CP2qt>%R?0tKea8HqO!0<0TVyMGtfEq(FT>#8;0H9mmlK=n! diff --git a/test/beta_plane_bump_red_grav/good-output/snap.v.0000000401 b/test/beta_plane_bump_red_grav/good-output/snap.v.0000000401 index 2324183049908b70b9968fbcc46b0778414326ee..a69bd5937c1a2f445734150ae500827678b1c13c 100644 GIT binary patch literal 888 zcmXS5W`KbPD1+8C%sygin0pu;^dBX2?RK^2`Il1mxTMiOL{Nn+%y3J%etGxbfa{o17Pvz?m*?ccF?aInqD+@D{ic)IFm)_&jfe|u~{mfLfzzA_=<#6*~R zaQCG>JKfm&x6popo2+bmK%)Iwqnet~pOX9i>@V%UkQ-`$cQcRW-xB-%L2RYpi@Tck zXD^&6y8C<6{xq#A@)yr%?uWV$ZXWZ|O?iLrC)pQm+T0UW=eK{8##1?;<}`a=hAx$h zD?03rTW{`A{M%?BxL_@}#+l0f$Jm6_zZ`1Y|51v`e0@_3x_J#gs#iC?6lU13Hre5V zv{S}@)@#hNdUmOH7kw_>-toE0H^!j&{Z9h+2z>b8 z1Tzm7j18gJ3sSeP3ETf&qw|iNMaBNc))tY+(s}z;yq)BCRW{jYcxi?&gR{!gy z{Y!o0Cx)%YG|wp4`}8K&(*0j1us$*Q61IN=2jd}u6(4gq zXH+}9?Cjgt{ZYxv=})#a?O);QcJ%t33Uv1|EM4Y*b4P56{qh;R7M@^jwg0Bu|MG8o zhkf4PUn$z_%It-n=da^9nZJJ?|H|nR3##|;^Ig=CaZKKxBTK{nMqraYH2mNcPs`iQ zZI(^;TY}Q}+cNgpCp=F&TeYv>-v5qwclm)9dkKS^E4X4@?d6Xe7>6ko?zfzgZdiXk zbieH5EsafcvoXxO!FfK~Yi+%K(&35c-Q*kX?}$`?blh8Szd)GvhlEav{e`7}GvXdA t*dJOW{eJ)I^!+wE1>NCh1^YcrcK3FclwkN5?ojG58lc8dOcwz2902cn@|XYs diff --git a/test/beta_plane_bump_red_grav/good-output/snap.v.0000000501 b/test/beta_plane_bump_red_grav/good-output/snap.v.0000000501 index 51e89e4204d843eab0f43802eb392d0693c7b4c6..0154000d86d4286608a89238c3e54c93fbcfbff0 100644 GIT binary patch literal 888 zcmXS5W`KbPD1+KG%zShj-5zv#7$2sNp*;NR1>HAQ_9kl%M?`sN?!T70O?>XR?)~*1 zuF+LLChmW^^v5U9tcm+2jb^Op7SGb{tB)# z`=o!$E=#3L_gAgc6TNk-X+Nv3bm!t*<@*=dOcc4FTfKjK!mh&QpWFA(<~nj+E~INe zZ}0u*^Mi{p%)4awx!>b@g8lLKo#%zZ%=dp^ydma%cCEdoE7!e!O1<`sF7G~m45_kj z)n8iom!WBYvC>xFE&09sze+9d{xvZT!@T5!I%db@{Om6(B{o$^71=MboTW0EWrF>N zn!K4jg466x#0;1>Z*H>B+4b(zgZQrfU4qe7j(OAebNDQoC;zJj-MofL%vGH+UatFZ zbM;?OdRlIOlqH|}#nuV-Vn*}VoamTr|3q0;`bBw-y;za;57#YS``@e|n z;lt9E9We9Y@lx~P*}AwJ#rw0Agshd{6xo|EY!upPHPK#3?_b=l-bwb+m(IWQX>PEu zyK6bU>T}tCHva3SYuq~bGnGnpZ*i%|Fz@>7iiQU^wfkqy7koD{$iiN&>Yk4oM~D3- zZnINS3KQ(>({=48h_=})aK!a4-kxLs#>DSiEl=8h_pM3AGuxYB=E36^ExuvmFd8b2 PlR{Sq<5Nr*0P`FGo_XzE literal 888 zcmXS5W`KbPD1%ls%pMp`$Q}%Ja&MpXZTs21zhnA>`nvf|`*kPSo)TPFw*SmYaq-zR ztM)J3J#Cr&=BE8DEp=&=nVR=cTfD-g@k{ys>IIogcW#f^4>b^O?@fo@Z(dBDvj6JE zb+2T@+xIVUWYURj%-Y}dDv?F%iNStB&F7mpnndjXC!@3Ul405YN~K(l!ovFf{1KN0 z#GaO8n0KQxXZ!KzJ^NQ4^WAs!T-pA`&n7%RBwlFmZXuD?W7=xJu-`7mWm1cMWMZ)+ zPjiC3$?rdT=KE{+iwbR?al5_^!#pGVxq_DusMxo!^gH(CYnJ`?;s>i`;u`EfPnl_9 z+t+Fz{^|D}e!&KNyPJmfO&enEmCwrO2&iZ6_gHoEw#&^jbn_S%yg$Qg+cm+SdDoOz z%ac0nPh1Wu__3hTeyRL|M+ym5_J_7Ej17F2Z?B~7n;CH+&pt-0N-~G9+@AOK^M8{U zm)XN21V&c`C;zYRon_CuKk0)X+eCZQT|zs94%geq&(i+1)u_~-^-fOA#RK*B#$tcg z-#^o7U$Iw|{Zwne{j|?n++8X?80H1P{V?BX$rO8b1*4D(>_#6dSe#R<_c?S#}3 JEnfi4a{vwe@P_~Z diff --git a/test/beta_plane_gyre/good-output/av.eta.0000000001 b/test/beta_plane_gyre/good-output/av.eta.0000000001 index 4b5852ddb75a591722e0d01a85ae6817dac61376..19ee1b1cbaf525a0167f2973041ac12e3496ed46 100644 GIT binary patch literal 808 zcmY#jW}q2}{>x!{zx?#R9qn&a-ZmcFmlKk7{3G|leK$_;ZSR`3ZQrgXWnpt4EZx@= zX_x-=Qi5Ih?g_eo&MvdtJK127jMG*-bcb11tv;^oe`%lRTazG#>NEQ$FNpWfEk3fZ z@#pocEt;LWx8HQpK9S<*nh&LB+nv)rl74L8Haovb?^rkr4`Z0e@VEE{)3R&( z@(+iEKbN|=Zy{UUgov}p_bqwP6#2Y&_dbu6^-nuE=kH_IDNAQ*TVbcQN3TGu@qpbo zmsP^2+D>DbClYz|M?d?`eG=-&xZmx$v`<2s{eASUllz`JZVmm>v3H;0;#-F<+@7~@ z#<{RG`6p}a*yeR!zI64FU8Ykn=d9H880Mw1a8#^ny|It!poaGLrc3*hy_WuD0Giiq z6kTr?vTxrk))`BWwJ+K?=iH>tA=WGG{L&V$54SmJSHCRopqcww4D&SGc1-#jdUapO z_gO!TIxg&+vea~*>%HUqzDeBq>veALzHet7|8%ph*cWen_|^K0)9pSzzHIj;dxu?~ zooed*2S+i?yW3t{kbCOFzD(um(|)>~-q)b=$Nc}%Bm0ccFHGDKxo6)Wy&nY^Ro3m} z)ZZ6mqEx%D$jiw`b;2?`9ixZebi{UGn780g^zFIXC-)WqUmq3u>FB}yybIP=A2hkY)Y!Kxo#&&DthJ^hf&R{-V_ E0OUs(mH+?% literal 808 zcmY#jW}q2xdMVdFqkX}?@Htvv@BWywZ*!uH)C;breSI_6C3oLRu#>(}|L=lIm)(JR zPd@qz&#+_ss@j|xxX{k{&FN%orDb;L4*T=z?FG%Fi}w9@5W9COYx+K2EmwBwlGc4f z^H)v$vpCqUO=Zi3uzg*2=X=>d#qFDEC(bb4;e^#^=>Ejv}78P~!yy6wtW zpBG?um~9t*B#+HScB!4?JdUKh^VVXRr@+gypzQS0efABxH1Qa?*_md~mVph|u5KG&W5 zOD37m+;`yZV(x~X&V83+c@n)psM*D8{5#{ZqQh>zO@`y|b2IENYqBxtzF1_pIq2{N ziI7v-s@%ed4CCIW{Uy+sDu4c<*sj>pqsXEvJRIXxV*VcR=yj&o(=@wBGuJ z#nbGzr2c4rd~t!@@6zc$%e64$ch9zu{~Xw6?YmmHXrjg3N&6oDkkk1zxoO|Q&F4}s z3pm?VyxMQMxvkYMxct}iAA6?Q@hP;XCH$Uimmo5uGxXsijPOHGKjiWifO!M}&}RZq diff --git a/test/beta_plane_gyre/good-output/av.eta.0000000801 b/test/beta_plane_gyre/good-output/av.eta.0000000801 index 8f9e58e874fbe55ba04834b87d82476febbc6ab1..8ae443d0e1dc1ece43f8f5de2201322dc38dcb2d 100644 GIT binary patch literal 808 zcmY#jW}p>lc(wLV^nA?;`&3@s*I2@F%r4JrLzDQSOLmR3{z_NQxM9~NVeOhW|Bju% zOwB7}-n(`osak1fYIp4>d4HT=Zg4DpZ@`ddC&L)?)33q+t*S4Fn3wRseQ6xb{lW|9oSc^wk#rH$DVylPMAF1YP@@& z{}`{r5?kdBTBx>xv!MO?Fv@;XatT Kl+p^oJOTi5NFkX3 literal 808 zcmY#jW`KbPC<8{r#L1-_Do&It{WEB@V~uW^koxhwWm5y=o_k9ka`ifAj7BhU0cINzpequ%56(v$)}4=!4X_tQNcC2xoEGhuiJM zXRKG~zIn(lcK;RE{F38#Yc3Qo4!d&7Zo#drBfT%r*cs1ZX4B_BYuB*8;LO4P(-`K3 zF#DS?UOr=A?zvz!waXjrG^)NE?1(yG$ND=pY-Zt6J6@ZQ$2@CK+C9u=cW$jYV;5^T zWe>}_vv%=v$L}|Aox?Ei&6ambbAE5x=XrqqI!sPEw$EBQ z@ykUZ?Qh%UwkPA@zRwrDUc8atyst<%VOcSAw%vhu{i@-YcGykX)K#)}-$@Mfx>%#w z(_;_s^Ni=pJ$U89zP1&HB5(Fz+86cnYR9vN3;XiZjrOcmIGi7q;&UlDm4d zYwbL{2cLsXX6-tPVP5r-YwxBc^!ywh?;{xI{TKhgML%@mKF@>J^4d0=_9b8U z%9#0n!#?}>Pv1 P0|6Q>nPGAjfO!M}BDxZA diff --git a/test/beta_plane_gyre/good-output/av.h.0000000001 b/test/beta_plane_gyre/good-output/av.h.0000000001 index 19f8c67c3dcf37a42f002977ec5fc4c2e6dae5a5..09aec92a129e54e3885b196dd55b1b2a4dfac152 100644 GIT binary patch literal 1608 zcmZ=@V}ODe_7Dd3=v42R`v3o*+Xvk+WMp7?VZY#l5tv?#MlXT#dyg7}<-?uwnn3E& z-Se)z`}9Acc?-ES!RiicWP|AwX!Kbq-`F}AEbn7C)r=8~d1_xKDT2&nh_3*vyKGVo zrthH9kD>gQFSTI#UuTv+z-C@F`-u~Of#%&m^#JJf7xucfkHNGV8f_2dFA#bLkyq-q zV8Y@)W|iJ&AoHwup8XFBM~A=1TxRa%noecjH9+-dKMZz8_J&^4w0{S_+o|4JYe90!^;c5`U}orb<DULRQ_<)|D1ZI89r-_5*pM1~yjLp2DrI$~D{rhndSlxkz5PB~fy$i~p6%LVa3{bGZ=3gV<#vG7& z9rB=Z;E#Q?1%$3gqido3Gl3BKwD!wWu$lL#^^_dQoR?1?fXy?OeTbJf34zETxZnB+ Qn|VOZVEvTR4!}AD06sr#_5c6? literal 1608 zcmb`HUr19?9LKM7Q#ad`2osmk&|nWSkRF1R?#u$CSqwvFG%B(YRFe|2hI`ONgK+9Y zQfWwkFjFBCX-gcTE^@{S$*`hYt)kIzF?DP1UhnPv5#o&V*7ow*_x^t8bMN`>-03rz z^-qw+UsA_WNni7t_>*@S%ld2kJ9rnox?)*Bvt+LS@@4Vfa3V!+o?H-LPqdp_iwW?m8Wm~mdn zj^sk$S-svOr})kZ=A{+j+pjf&sRmh2`85kN!%i|kgmYCVo=cxLQjksY&3ucuM1ilz z^^_9WI?udTxU~Id_93!aU87Q*M2PmJsUMu%aDibNvhpA zHyz52!n&+fc#%o*%@@hs9H=X;)r+vt=qV3F)`dwL^Y@_ZR{f6OupW^d*GehAQf1k5 z0o21zE$W}?I*r)YN3voNXOCeR)eXPwThl1Mu`z`$>P0ctn)}5$c zxxG8eQ+y-UnS)Z`8~2SMpG|iY_4kW62o}!aoM&tQ1MfHM_Zv8h&&$lU$$;-;=nW71 z(l2*{bIq~#a*_=SoJ}q~m(err7ZMbo+Hqw!^gSsmk}!ZBjwLV>p3OQ!a%mgRvg=bK zyx+6C!6}+=%+b1-4%VB?c4b0OV|^`nk9oGHlH_>}&K2((Ww729V7Acax7ljfz~6(b ztdYaMg+f30Kj2wk7RiO>&*=K>F$>~V;dN+@vfq=dCvL;_^7|pw*Xw+VIPsXIe;DWf V+96c`pqQ+O`%XSDsmgjVrN5k1besSH diff --git a/test/beta_plane_gyre/good-output/av.h.0000000801 b/test/beta_plane_gyre/good-output/av.h.0000000801 index 8cf34b8f7730da76a859ed1200098e8e90011b61..56437ae4a4a6c6092c0bc616573a0a5728074023 100644 GIT binary patch literal 1608 zcmb`|e^AqP9LMpA1W}TU)@7pTgr#yPx&yikS$yC+MA*$Aw8Amqh9!bG>4&iLK(8kkPxs8<;VEp%)BPZ8t17&uhBod!C&R~pT|Di_xt?3 zzn_0b+!+5}I*QDFc!ruTjFttXR~cRS>a>9(o;-Pt%N2@z(JwNjU!{oK(#*;RBSk`+ zAFEtCDRR3t`?y<2i)1iO_YeBZEjf9NTabdE#$W6tx5+j-^C zl0W+?3;W#Hlm-^UyvU~Ce`}{mbjPqX0P`~Jm&19f%tL0;CEUmTe6>YGk*6P;E5a~u zSKf+G0%6gwlXda%?MK;aJ>27-){=_n{ce8UrNn#KbB?{5BN|R_3q`h_JUmRJ8y@Oj zE`zDl#UTVxFk@Mk%OS`~o22~kKHqpVb5CP_d(N?Uqy9DZ0D974eg_9Go($RT z1G91-=vF|HcIB7$^})3bagop?QLPlC8}*q^6o>P%=Nx+nycvVZYMi@3A(+DbtE{XD z8%&?LY4N~w5kHt1UQqI8P7w=^y&EGu44GRrs+P+XvF99n?Fk37_u}04()=VP-sAr0 z(228f$)?mr4KTUxZ~7`!vU0cGg;wM1KSknxrM|ILvp~f_D2^YQ)%D7^~KChe!-g5~yiQiblg73+h9rrM&^LefJ zeEDeK7)`=b4Cx-|KIVIF8o|6Jtq&vb!XVn+zYh*B4qsCNW1mL*Uc21aKt)wBdx4&F|G%yY{zLu& DdCY(@ literal 1608 zcmb`|e^8Tk90za)YBF0QP+(#StB30tc?t#?>K6xs$qy$#2MHILM7Nl7G9)1IJ2%A~ z!Qms|Y1h2+$0d0fICTvg3i%^AIVst-F)8SD@}m^Ura*7?pKka3RqmhnzR&Y~U(fsd z*&icwoSuHZr{u|(XPB@0imkg1lz5-)$ct#Bq_H!~^AGs^iEsF&?Ub}d6?EObNQvF$ z-ocO#O6n5tr$uy9(#*UlHX$ARxK)%(QsCW6xvfrs!}Bzi6~Hkp`)a-WB}&Rmr;E13 znJL`*=K<`W>@U}+{6NX7BlgP;NJlR$aHUJsca-=o4hTMoe*6#jC;w=qgt!@Oa`gII z_?OBIH}av^VIe%{CpO2rXBq!mXdoi+!`PSbF{%&#f^$0yB zLU|AChIusG%&yzukG-FrrNTVsF!4XR9>3T8jM}isWa8;r5P& z*sWNvc&{O~4)OMCm;P%OL)rX}G!F;_=#WJz4tD>zTRphvs|&ku}LC?}9& ze%0SEVUFFJzNJc>bLK$rD1$lHEqdgUh=;!GFuk|hVY2Rm#Sh74tooF?)=vljW}JpbzR zU=6vM1h1<1)9^kxJcWm`6Z@Imz+Wb@zs=|r8I7FP5xb`a`&Dk_Xc97~i7pD_@HXGc z{=@?BqwTh#V7zDYYS>Q;;aZEd{1~`z-lME7z=6A+7dM)e_-y}dXG31PHXwXUf4?g|W_5SU7&%4LH-gmFN z*R;FKfA)wm|AnT#3ZO|Y=|joEwAxVog)$2^7G|eC#mRzo^(9%~6gYDm*ECQo2aYUZ zDZEGlOarFuZr<~03k91!o)u4Q1a-trBMn@w_J8)^ivRc zxB>q>PcgdW(GLHblu9tC`wa!IR>EXc(4aKM0G2Wn?XNR{T_w>>NDNTpYY}FyGl0PD z*O}Mlm5grGvYX$nNFyw3lpSQd5snk<*WS2i1WV-n&F!vLux(XZG49N#?t1m0*$D04 z(Wzv#kevG`6w<6}>nshsz87?!w9}wc@O=J0NJHP1 zb9a`)XhyeZC3fMoyB;nEpDC$U=waonHbX#@9`+s@6SP|Nz!~9)O!ayQp6wnilIkHO z@_wD}VF{yK+|oQ`>Lr0Tv%3u{68dfH#VK(lbP8WBE)OH2AwJYIj8DQZmRRe`E)qKW zLb|*fNk-SrcT2%Gb0V-mS#tl~Ap+g)=T3d>5d(>R73T)tih@7h)a7iC6GHD6e&8HW z1d1BrC52MV=rZl$|E;&l*~1T7WynA6_`p`a59fbe5T_o^#NmV&wEat&SP|lyEih&x zYqNvvnZFOuCe^tq%4Ep&k1Bq_&(AmJ;tISB97@}rW!{(LGA{pB-BWfNMohf>2q2ee3X zjz9g^s1~Pd?FqzK9_DXtvez}|GrC0Rhq~}a9f~dtI5x2I@OozB{q_x7)T$>v=Lekg zP5Dtf1GRWftrG5;q;b_FZJR z64^nbBXPeean5coEKXNp=d9HwG+fQ-b{&h!?z$w$>0WKk0~LWi@8#==8w4KvD30}L zmB5$N#4ET+;9RnI>5JbI*!#nYsCxkfqw8ia=iCmKV0zY>t3zvPxZlH@CzzC?qdeBT obY}+o?2iwSIHbsazcS`0SvtN;&9YOi5=NJ45C3gH?YwdS0BM7{MF0Q* literal 1768 zcmd7T>rayh6b5kCxDljUZh?X$L2!jC7!j2+SQz{gwD9y&Ljm0J_u%T5KWd>V-vTEwHX#F!trv!5Ug+dO}Ja>^S{Hl6!R>#GL98#7))0 z$=f~dEtEP!cVFNy38O46uvRgRl?6H|X0f+dRO#R|M{qgsln!=Y^S}E6R|h|rMMhrd z=s>kUIDDo@OX%(lwDVzE4{;;+^HL@Zpd)qkc1IeaDsJ2H{*6W;XDwRxCK@4&m#?j{ z7@%4HRRJs3K&4B0y)rVa)aj zuzGs%d;Me?ipNq)V!C)pbVqnn+Bf!ADb{c|o*14Mqi0*O-4rXrW8Klamb4;luYO#) zI$Derf4pjGUW~UADVm8VB0`tP=#UKhnq;^|9Y zfLDTy5OA&vl49FdHq9I_Cv@wYzMcKDQHkV(WT$F}3_C~kOv4r_QrXYhH8&+Vs2Yn| za!GL1JU>crlVJ{{cIw<~N57}oG`omYxw!EVmhLIt6_Th;1ijg}+h?w-X4mKdp=r+;Ou%kg#QfSF-AuE7^QBnYpezzw>d| j>CFCc6(1d!);KKvT%^9upRC9)C3J~;_;2$EuYTM=sFk;* diff --git a/test/beta_plane_gyre/good-output/av.u.0000000801 b/test/beta_plane_gyre/good-output/av.u.0000000801 index 582c937afa0603a76ca9b40e11ac5f9b9e0558a9..46e4a498370971c8615b19406547796bbdf6ce53 100644 GIT binary patch literal 1768 zcmd7T|5MX-90zcz0b-hkNaGM9kX(f#Fc1du+J+m9ePDwzBpA4FAJ_6J6C5Dn~1u=V}+ z0tt_Lw;no9%cpcVEjKIk6AIwHlAE^6xg^9(Y1Vdn5!5a|+0Oi=5ClEpWg<@!sy{nu zS(s5kXkYtPB8ECI?M&gdKU_Sh9$`GRm5bqZmZoy~mrMwMt^UmSTO=^H5@OicmI1@A z5`i!*4J?l61~xk3vCQ|*|@1yC@MsVeLhb-XAi;D0iW7XQPqGJ4cyt(Fxv=|+pn+NYk zXz)4jv2PpqsL?UBUlH~okJ6>u`+u9S_L-Abk4kX6U3Gw{lcUf!FeOb^qxUl$rd>wj zcPrl9Sh^Z_x;0M9FUirQw)~m8l115rvE-qv^7%wG)s8O?-AKkyOHaq|8y8}&VC(1! z1A)EQYsmPpR5a_l9#v|2XwtuLD$)s zGwmUVs>0y~4kHhSG6J)1jb(yT+%&Zm#-VhX0YBwJun0&d$1C!F4wwkywq;cY3yXKE z)4FBQq^}Q9mFB?S7FvUpl>rBgUkai(u_@i2L;VszemwZ|oG%(4C&BuP=;8D3d>FI6 zI-05GK}7g{{c&Kw$nG zXN^QKfi3OhVwNNYcjfvrhy@PT7SwsRS)-7u-ya{R&=PssXgYSKD=uGw6C=BZu3u51 snZqtWVpO4hNb>m;Uj=qXB-9x{d<&@4ubT{d42~21;w5M*si- delta 976 zcmXBRi&ql_6bA5dCZxi&0YTCj6B!&(V2gMhgk5J0sKnBcKn)n%h;)LBcnt^`jF1k- zVnPYW#0~~1bcjG1ZkLCn01*^)r2_Iw7)@q89K^9?{Q$H_#hMeT5l=|{-;q!rukV! z92fFFJ&I=?67#LKJcL%(dUKTkWwM-W0p0=}nJM=tK8r*CZIwAG^kba5oHkMHd(dbp z6fOVEf)IdEcWoj%6+{mnvj1sI2j(`ln3a(Zgva!yaA7K($gT{wqkaaY`vz^Ih7TLL z(*Cm^Tu}ztz8`z6O_dLJgS{N(s1$ln)n0FuOQHLcuRi*GK9n(r{;1iN12=wK)5tSK zMoaM*riQRnf$X6S2zSbZ;mM>b!-@plx6WVWc1z&a<$AKeRUU+SR`tDhAQJ+c2iMIp z(P+h9oBbY2k3qIeF;RS%2Nc#$Zc4iVvJzUJd}t7WLr=BIw%_^CNxq;_w{t$6xMibD)^B zrjNyqz9(8p@~x&B*kaSy#9fkLMUX+!JyU=Q%JWSfbp@CmxA4R;F2TY5-_LRcU!eO$ zTx@-e2+PRCei_Zw?`AyYnFi6Y{ukz7e>b|IPt+ZDL$M3C_g*UYY4XHptnAHRd?wzH zKes(--){Ulu;!6`&fb_UEz(~Z8K7XczLwl?PDK&#ZF=849d+s#VtZQ#ZW(3KUCkNj zswRB|yIgVQYQ_49^!5Mm?pMEcaqqBdAWi9dvSfwD&g}Xox;>V-IIoyy zAF{@=q0&xm)TN`d!JJmzCsrU~c#0;+m3h$jq3j=MM p9WD4Ju6TPP+hh#srn{7>q-}fiQIK0hYkVK*wO?eQg6~?na0mxDo8|$YfKH z03C_)CdBckmI0dbkeCzbB$a?LUYjonfs6q( zG!m0tzcXq*B)HmWv9GehVm=<$G%u(%T|7`c8x?3`d||xjgHunP`VD_>Fp*uC zotL;{FBZPGE!bccg^Jci#)ASefv3Au-EbqC3+2}0O^3WZf&J)8x=b<6)b1lc4<@-` zzlI!@&jGZQNG|DULD>C5uJ>l~u-D&9(jjaDg+u-Y$sF6Ss^J`UGfCr((^ zy_$>CeZQ8$!-2Nyq1q$wqonm4`@Zh&Xc8`Sanm_M0IA@mW8QU-#%zC!--$$DviVsqD~7sdf0r(xV%YK z(j+GEDy63<6If#0*D%{yPLD)So-1QQ8-k4WjR$o*cj3a}Zf50|RooBnE zm_VcIxi)iM}M;2De^7fWp<=-F74nbIRbZ%TOJT5b>?S@?r4o1h@)c746w zIy#(8OP}m#g+iC+iFf+dC~#=pvb3BnCGa-K3#q$XL^xEmp<=*10)3dHPhwmG@p{&B w(c&Z(W908HbWlB@JfG&3V9o(y)8xw>l>m-cWwgy&6Z5-zKmQgz_Ugy|4g8_D9RL6T literal 1768 zcmeIzTTByX6bEp^Hsv-qY)6HS5h+lh9TVwVu7{R_7FLAPLTj-FR7e;%5hFORQoJBA z1QzR%Izfh37y==~%=Lic=0HWtt%C&$8bm;uh)yy<=5zbBw=LQCc3ytx`=5MY&g2H8 z|IEqIkRq6)0@!=z^!xJ50Wgr5H@y_kgttCA_QBc_J5c|A)k}AUhM{z6{C=}QjPhm3 zNX|m^G`}>K+Z%)WL6<+-$VaUZ7THdkzNG*-Wf3ddSh5Y&>C*!dDqC!5sBDh1^u^u; zuf%oFVEiyiRapEi9E+6Wr(T|r8hBGf{WsiizcBT(16mhkZKfLi__o0p%QV4ch6c$%<`37EGOw(M!U!j<>IhIw|!o|$R!Vc>t zHf~o+Ow4b4bRvY3>l7AvYIe&{QB|Xy1hCws=kW;vfkMZOnv5e%_N2Z zC)NGYQdNwBXKAc`y1KFl=LBSHw=MyW?3XJ!v_KRoNC44e@U*e!e4_ra@zO#<5{BP(U&WHWHol%G?mLxzuWWICmoYZM6jiu{6$$F4}201 zEZAz;&`V_7ckQOY#r$*)=fzfRtIy{3O8hZrWImr3#l@Af^H=u`NesNw@VAwH*`ZK# z^lo=&5es$;vVQ2g;SQId#Zr>uKZZF%)|s0_??6=0iL$$4UIMoSKS#q)Y zH3nSIh$i~pW*NM{Rk=f>S}Vq|gE8WZH9=TDOIKEpxMABR!D{Uxdu;uw;O;b;1{LHj zik3ZWXlFcqFihD6E7h8iVY$S>V-FHIifS1KH(ki34#4jpOk5l6m{K=q zP$tCnpMo&6dXSV92=`rzaJ*gsosX9871zWWc%^-bqfEDG+2h{I}GTZ+6_@?i#Dd diff --git a/test/beta_plane_gyre/good-output/av.v.0000000801 b/test/beta_plane_gyre/good-output/av.v.0000000801 index b547e6ebdfc0614d5aaf358dc67a14d382763a77..654d7fa9b6d1540734e0e7d1f312bfc6ceed4d8e 100644 GIT binary patch literal 1768 zcmeIzTTIh;6bEp_D6-6fI&nCtEy$%cT+6TsgF~S(86aR=EtE@JdVzwJQka)4Y*Q{W zvXY6W35bG7kO6xDF_RjOVnI;i0@zUj$rSZJ7`Jyk3O$<+;<+J}EZPoz9vl8R&MJ z9sQeUCgx9Ci0!Y-(L889Vd+}0jY>Z`_vvZt=+7nKC>y5B*@uyq8uhUv=V-;*KLqNM;8IoP_qc}G`> z3h$4{B`>Asp|5Qtx4$|M*`+yxyWT3)f46(XB$g1oIym}%i+>h2``DxRKrYg&+PW)a zmDuhVJ67>F8?8UOWTAU^|3j9lLr2cUA+-a2u`C@gcg@-aH!#3F?_5pySZVihRJ{ov zxlK~zCa71N%CnJu!^6ciD#btg>n6^;5TdJ{ENI&dAMeODA6IP&#})syKP6ll!FzW1 zfketViTbC#WNm6L>hw{+vdW~`)Hv5$drN>TF-QN>Xyb6wx3t1m;fKo?Gpe5`BS8Ds zCX&KX61>D|-2#WFLfJ|&lsJg7#=%MM<-7h#657vQ?s)Cd9M#S{1~WQ~E3$5-pn11NC(mHYTo$bDmD5)4$zgf8aHs7z zBG{|n>Y^&*gZ7g6jq~eRI6aa+iK6wa zeI@}XXTv$;10h_SXa0Bq1wbnuoHykj27V2LI>m{Hl`tPxBq;~#qQ7oKbGixm<)d%OFszmpYs{tu8571q9E0-~X0+>fImrH#4}e(f|Me literal 1768 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 literal 808 zcmY#jW`KbPC<7M_Q%5Y_aCXV6QpIal`#HG(uU%}bwcjK#V2YLct9=hva=iUMOUd3) zZ0{QF^G5b{d!8+>bhoxY_&#*!UL!~QTc;Jz)nz%`qgm9zakAz$1Czu4E7Ojc&wix1 zzrQ%;bj2=N`}UVl-<|X_wokaXK{Wn`t$oh5t&9=@&h~4M9u_>!;%;C3XMNt04o?j8 z_^0*=aJ+We9~`{!>FJ5u`z<=2o|wTdV(*-~yfWI)$o|rz>5rP{*xAo)__gTfX&3tw zdoR5BRqJKnv7skb-82BhyaPvlW*b>~?(bfH_=2aP)qacMMJkiomG-9#bFr>b6tut6 zq7Zc4!N{JawdtI>uY>*Ge2v(&5KsHQo7<{_6N50!Tka#gwavn7Kf7#QO35nc{i`~j zJ#$!Tz5nz|(VV?E_4iL&v31E|qc8h@dHtCxCSYK{s!1Y@)z-znDe}wC(`}gME$h)g zbaIK?{=%OV`szE~_WP;wHaD+x-hW>8J}=V&+x^`q*wP=C>Ful}!q~Dd~6bQs{pVsf|Vh7{x_RqDy7V^Z|X@CFXeO)ed9QH4f)-P4;w%GsvtCexi zJ@x%rDO!~rOhWb>p3OeFF4D%HGklWs?8|-_=9OK}cp4C)wcr2oxtol7TKn7fPYd0g zBfh_MVy1?`1VQ`UXZ(NM>hIB2La JVM+m*M*u)?`04-v diff --git a/test/beta_plane_gyre/good-output/snap.eta.0000000401 b/test/beta_plane_gyre/good-output/snap.eta.0000000401 index fc2f1fb03525c0418d4fa91c1041465387d1d2a1..73a442ac95ca013a5c70247c0dc45792a2b3b6fe 100644 GIT binary patch literal 808 zcmY#jW`KbP7=uc5!=t3I5YKZ?`CK<{dw-kSPb)u>Xxy3 z?hD!Pq~*SD58Kmyr8zkVAL?4zGu*qCo4?52e%fs}9ji5g_H!Tn^tkO8V*jzbUDz%; z#Qtr=s^-r#qcF@{_NeR*`{{)J7yQ;;nEy9u|HS#<_}yCl_p{_{x>Y@J+rRF9n(%KI z)BP7>f_S~vZrTNX-Y@H1WNH6!R^EO#{s;{79&9{V6}B~Xzrxjskd~{-`~NWCK70&F zKj&Dwfzc#sfAE17w%SW#_aDeK|7NozWdF3ETnQW-?DvPJ^ZYV66^vnC$hrShBRSLd zzum@Nqokj;zq(+;iIcCh_iOK8q@r{uYyX?FnpdL9>HCX!$R5+ak+@&Y>C-Q@+M8&?r#6kU-(2pqnAD3iWL`6&Gofk7*QO!XnBDB zq)@#Gv4$WF^Lihh+S&TVX#d~z_l-6Ce(t;4bjNAc7Df9fSNjDSFX`Lc?0r9JW45_{ z?*Xri9seEd9kttKO%{3B@0l=V;W=$g_vPHv%Q*PPe*e@1pF4L;Iqp~gA$#+Ls>A*s zh14(1%dPec?^Wa2^4(xR58JNwQoFwF>$vL!ObIk2utG(^MGQkDIJZSo9AV8xfGfb`m HFpmHLIZ*a9 diff --git a/test/beta_plane_gyre/good-output/snap.eta.0000000601 b/test/beta_plane_gyre/good-output/snap.eta.0000000601 index 580a97e000e63a7a6dcdd5e23e752ab748bb6793..aea5083588f8f5068f631165bc194250adc729f1 100644 GIT binary patch literal 808 zcmY#jW}p>lSiEoI^yL34`zQa1zoeSsYH#c|eYr_QkiDaxD>v8WQ2SEv!&%W2BJEe- z>X~$Dd4j#Uq?4S?iWGbHRVT9U>ZRMGIjo`XWzY_d?GF20=7q0jObW5z@qgj+C4GtZ zFW297nlnAcURm2>i}cGBd!_?DX;IQ?_B$8P{~Q^SZhu+VSF}Yi1H-&(hMBkfe}wOk z3Oc$_F3Z$jP|N!5*^i<2Tle_XvOkNrKX|(~vwVG`eebP3y+RX{?bEkL3t0l~5%_iB z$^WIP80IO<&7J&WOVa*jpSujDl_K^>JKs`rUVqC4 zag8Q-d#A%T*|vp2_V*u_-@SS*4#T`hm((9P`lRj8=V|%9bY1rTgl|XoMzZJb-}v;n z#f~?b`zOn1GliR_?mr`|^UB9EZvV1|U)@Vm{P){kiN7op;E7@0yWfkox5}jN_n&@b zM^sYL{>@2&M-~Z}?w{%Ur66`i$^H^e+n+iqMf+7wJzgi0ox7i>Wh+k?fAW6SNzo~C zENmF&-Tm^!&3{|+{?l94*_UoF*xzRR)9bly@&2a*D(5a~7Vr1FbL-h@kHY=-Cp=8n zKFQwC-l4I6=Bvd0`sq(@yIFm+LyzCx&+oD^KMC5u-#Xvu!t2=mQf|(6GArWutH>Qu zTGJ7`Ka*z_8{eUb{ktD>h~~@=++TM-bMeX_4*MMh^=CZSalmjN)cgiYX$4>&0RV=g B|Fr-B literal 808 zcmY#jW`KbPCn%{^ey_g0A*$9agUY-}=};5d8;zDKzWXm3&y4C+b=_}t z{<~YZyTShNe=0AymzdhWndpDg`DXySe;Jf()H!)p>e$=p^PJ0n&S>wgf7)irMh<%| zKCT@(Vvd?|Cec<{_)V;{@)E2h0d&C4D-;^57}G=U>*Sg DZAt7U diff --git a/test/beta_plane_gyre/good-output/snap.eta.0000000801 b/test/beta_plane_gyre/good-output/snap.eta.0000000801 index 701e440e06e8e355ffc717d1ac2e6239df0da3c2..7d4b46b0215bc0c47fde78dccdf825ebc0bdfdd1 100644 GIT binary patch literal 808 zcmY#jW}p>l*m0<2N57%u{z!HOgHM)$_6z)1B%BV9wYMu3OtY~~wm<@n*EWS z6`$I7q}gv}RL`wDk!G*IqcP~pymWgshc$f2$~x@f#w#Gh%; zEbh2G%RJY<*yo@5o0NQehN+za&CU7tVrLi6|H+nbpLtco;mnOZ4D;Tu)AL>`;l2NA z!MRC34+HH@)cCGT3B}uQsc<_bXPamrAe7Qyn38B;o^wQvT)tMf8v_d zHXVcgCnQT|)p5Jnvp9V));|=FVP5F{ol8XZv-jI5SMF^yF4%u6jOSI9eE$C8{0UB} zT{-*T8z1?)^jyaN!m2+#=awh#pSVrgX5luk{cXXDyEbx#V3@Z@D(gVZi=6$=%@4eE zRm=BxuRT)|vcF>gR@v(fJM7B$`*poLp2btLKepoRp$YTz_FJuGyDq*haX;ge$gLZU ztTD`6KjG8rAnDZoYo@w=sj(~FUv$fy%f78*KX1oQ)u+G8_cPo-wCaOx>HY=nNAmJ@ z3imVpyQG@+AZ`DhivLd=7!3DAZI(3uI@JWjeK2z=r4@jA1OWe{ B{JsDH literal 808 zcmY#jW`KbPC<8{r#L1-_LM)3K7aIxK`$orXF1==AA2sWM{)AtS_GOa|HO*Q*>_2|C z+VWe*&ptM9%F6%tf%dO{8JPdC3$mZQA>;n!eL?nU7B}p8yKFb}PF{Of0d}^^ZYO(# zlPNo&#`)UYWvfW8_6@Rk=RO&^{A-B4vXkhllhecOuS`;y{b7BW{SWo@xCt$x80Kv{ ze6nuNVdedstR8tct+KXHelepkwBFNRTElc^!Ttby+x$J>`QHWG|K0sxQrbPt-qq;h zz5_nt_KR)O6rw7_G0aOp#LfP zvu%>2{SA})@?VnP_ID0GPKq@PvY(%{d&2$KVHoBKsqCLIQO$e5X5=-lRqcWMU)1c5 zdD{}Wf6G*n!>Oj;`I-Cr>Gdg!<9-|aLyu8Hodakk&UVZQpOW(bCPU0YY( z>k07N-?%66NPlqD{=bbE(nA7c_p9ZYcKV-+-0$L-7clK=(EdfD;p_NXo%Sa*Gi{AY z)v&)_X0Ni6GZ4ePA4Yjm)_QLHrM4W~qfrsIUu>uPmTv)(`}Zb#ZJsL?wx4YyLxJ2; z|NRmhIUagXvE6@E^g`aJBpv%H=7ryHUh~H=ucqGgX|=NUe&>XuY^gSz{m+>S-%KyH z+JE9I+Xw#y?frYy@+TS_@Y^rElvAg<$HG4GXxwinc@O&yXYD)BKE-q&H2pLXpwW^U JCRYKNM*u5m_Zt8J diff --git a/test/beta_plane_gyre/good-output/snap.h.0000000001 b/test/beta_plane_gyre/good-output/snap.h.0000000001 index f5a32e7da53ab827332d8646f26c8bb528f6159d..183afec7846a618618fce5ee7f8cc5dabe4c3dec 100644 GIT binary patch literal 1608 zcmZ=@V}O7IO%7lN73t?v4YU962b%lw9RmZ<+`pUNgX#ZhG{a_ycv#T~u>2L}XQ?3d z=&*dHc>;b^QaHXThZgR_E%d z0j7P>=s+l+JzWbduiVjC&WOc*`(5w2fXu6#w;t?|(>phU=}TzzO(?&2-)6A`8t8;k_ zp}o*(KPX=zoC&PXtjX5`n|aCKOT$3!+ATNtABf)meGZu3iAL{%@{KM)2B8~p&{vPOgVl+><2egb5B3j|d(>NND?sLzelG&66H$TC!f3Q0l>Z>4 z5Ug(1=Cy6u%v(6)(JqjAkALNW)y3V<2Gdb!bU2h>eI^Sm|K8f(1)F(_cPHKjnRn1& z1z4Sw@^UaOjz)_>`8ySsf#nz9d!dNUymxm$Tm+f7WU(*yF8 zYNECtHuE$hpUwf9v)ZQ~Y)%{>gpNU@Bcc3)D|KLXPwj3dV>8d658k(% zfeDK{;-~uu{05qLpZhOZ-M(-UZjgEJ+ED4ITOoXf6iptG{3R{l11wm~bL}nJ`2%QP z-@k`o^OBcO0Gl`C11jxkIT0-G5NN{-GB3pFQ8+sm^N!|4#(oEyS9$*n3rO9YOYhl0 z^jggiDD>)j2>*-x3vjsXO6OV2fyKNpg+b>)=9x;Y{PQ13J2STa1JNPDsPy(F5WdFu zcm|Mt+Z#*tv6;vE@WGv*K>h0&w|)VcbInoY8;Jf@hf43=4dF}fEBOwRmzifL!iL3t z|CraT{sYploB0u>EusWHI zj$qnz7b;zH7{dQ~xfCqV9iQ|Nfq}b z2&Rk7QR&&b5I(zwI9UFg!lM8Gfa<~SLvl}`$&GL(AYZVG5v)$(O6f0zA^E%n`l+l?6mMA3&uQ z7D4!57Px}tKW=#N6`OyV{%Nja1nOtW^kxT{6X5@j4Mab%L!}$^ApC2;`oZ$I>Z}s5 y#qZUwFI6D@>JmS|>I&8GgX!B!sI;3LgwG;&6f9qL!LJ|WZ}jv+ExrS=4gmlRPJZ(M diff --git a/test/beta_plane_gyre/good-output/snap.h.0000000201 b/test/beta_plane_gyre/good-output/snap.h.0000000201 index b763c465c188b9f3ac26b0738c2ac5ae0aa9663d..ac1628ad648dba5c7a46957b375db7deebac769b 100644 GIT binary patch literal 1608 zcmb`|YfMvT9LMnjvs^@0#CE~y#LL(aJE|j2%b<_AWC@^vYz`L$%3uR@io)CwHk$`f zO4G>1gH{}uMD1`*5GyJ{3Jk#s8{kTX5-xJlNmGJTsLDvUU)`Gq`fBsM`ShIje9!+m z=OiU;*1uaLB`-d_MDKXTOgG-3jSCEluc zU00&3jH>V!LBFRd2Xye*_?W*IJu!EwH2GIbEII3*q2-Mga`b)-T-C6qo|24&&ng^o zJ&vQ3BnNg3I!zYCBp#n}!~H1GYU_v5eYD{9sB#5fH^x1N*=IjjSPa}9=4y}UW;CU)9fx~9olY}jUQ5op=g`lckl?zWBC#7D_$PO@9?LpP(YYy#>ZtgrO6(VN@hJ94lqQqcI>-ecupYAy9U`y49|Svo9DDa;r;XH>2p~S z6+6lh&XYfddh{ehhch3bm%xTE0e~ERsY~SuTi#aoA{}O4SqA)A}3j8f2rREzbB3dV?E$f0HR;3D&_W5!GsK+`moZ z!LC{81pX2lB!u3A!5U}S$s~5MVN-RO+M@W5{<#@FX>MDp47TmayT!u1bKeiM`&UvC zzE6+ul-9$27dVD)sFwMt^zcH5hkqYb9wM4S*x?n>*#&i%bL&EEyk{qh{3GjeTvlUV zGzIUTTCZf|_v>m+P0p}8;^J`^xIBM$*&_JNnJcgyFLM3DH{C{W?!5nXpWr{_A7O@m Al>h($ literal 1608 zcmb`_e^AqP9LMo7<`|_U%)z+k$3h$1`Z_4N9_rZM0g1=UXIb}m| z*oK>w6kY6@>PKTaM}wqY&R!i;yu11uCFi~E{786%wro~8Jj;Au@kV$at+A75;2kpE z8fbviueEhBx+xhFdrzD*IeQKJJxz*MN?O~dro0*ok(k#h3nSGi%!6K86ry_7w*kj zS?pH0Qso#kvWt@R!v{0eF1(O0Zwu?N??Oh|+zc8qT{P7K*N^M}ofU4~t_xom!>uu% z575K)Iy+SzfW3nT-j!}~;mvQ$|45IyYQCd}j}HC5{iV;)nQaec^6x33=8|9*_7@&o z5Iu%h;Mn@-6YOpM&D3@12j_id>qdJf@P4~oo#;Tf&&qoTFz><5yYme0$?=|vlBAXY zxk*ij;MjEDIurJFul=B4hYOFf@~qW;9#fE~-Wpab*~^F+R}eSTCmQh`1!>r|r%46h zBGq2-L$`crFa7qmg4hl!&HK>JV@nC+w-m&Y$(Cr*)#vHe$EQ}p<1Z!q@!>VT-!d$K z)6J_I%)xvVoeBK|bK$ysC-P9^D+0MMI+C9-{o|;!cX>%-51&vF;e6@o6nL9_x(oNh z6R=`BbKxxpy|=-H`61O8n|7dIh5D$A;Z#X-z1l`xc*zU?SK-w^Qf6{j_D(BfEyH`n z$$ohsS`cP@cpR>Ki|(BYcyp;2RhjTOvTrO8Y|h@<{IJq?c)#*eCe83P_RtsE=(6A6 zNr^Zwi4)D0$sbFhJAco_3~&;FsspM3v$?epyUzMs$M zx!sNU`~3UpDS7c>5tSrtot7bQqNMO8ZVx4G&L4w?21*R3K5nIvlJ|WxBS*}XRFB2` zvTsu2G#o8g{6Wd_JeOb!diS%{%<&EEqGU2raijY;N_gD0>N9ZPm8GZE*C^@y#+W6( zPRRzax2kv423ESEGjs6=r1} z6sOL7d={Qx;*hI)%Io<~RMu7wAv6t@qWLHcI%}gRCsxJ zyKYe#mqL|`l!w8P+h=s&!K3TV{rR|0PkZy{-S_t9TodN(`XtD*0**A)MY3VxFMr-z z2a|j3FH7Ku>3)(U@NwgV)T^+gQyOi>eS6~O=PhbI#E=(xi>S?F_t#k&a#EZioqfQN z@POzqa_%#vI%L)CmO+NxIbnWOHo%Y=h3&*#KSKhlle8k#27}zehTi?yE1y085_$6b zqBU!g_xbEpR1EA7D`>fh+;j0&rr~=GaS6vA1JE+G&QywZ_3pEKen;({m-47KBn|W0 zKhu{cSQs*vxIEC4zosZvZ-NJFuQX>s4S&$|0j%B`87wC*jjP%{wey%xv=Zlg=Y`12ClwDF z(i#yE+ku?(l~KQ@VSm1R$9@yc?Ugz1L08*gvlF_hmH#R1k*tYtKAM)}{E8L!b zA|f{xE8$nH;GAMuQz2Yk05$S-t*5W!!OeBCFv-RHJ`wlmJ#Sh@ZtrQ#soMFpVg|nQ thUUl|?A}nqxZvH_xX*`R%1w8M5wZnAAE@AZzCLI9BK~f@`y%)c`3LnnhQ$B? literal 1608 zcmb`^ZA?>F90u@$yb3mB)D-a@E06IXposq&&)ThU=C``7$*`(2MNkTV zG_qHPT%*Xbz15mw$Z$SO`sDVkQ}tmjnd@%9h&)Y*mb()BvZc{HDf}T;Z>@lR>_6MC zKu<&3(b(%0xmo;csRBCVmgX(rwRmKOiXxl&T8HQ=MU+-=t_is{()hCd0~ASM9(YQ_ z4E=r?6M1d9p>b32^F92XPu%1M*(UAwD-?PE+gBsJk^9u5d&olHm^(aAIsCvP)%fH0 zSW_Im!3Xz^hNs8}ai1WNAti3|yzI#X@jVpzN*Fp60J#}C*7Z=gtvI3_ZWCBCdBMJ0t1-VbZfRa)Np){1zE3$)$dO>K?ayrW za=2l-^Qsr#Yj3pIUWZZK%*;XbYTr0SXJW2H`RS^|Zt`67|JV9=n!Gsw61_Rg2@sFc zq(&imrRW|_j#c-5G;gMfqvLt(IP|OAe83Eq-FJ=saP2om_5!F*-}2o`=-NlT`je(6 z2!Z9bj_Q8?|AZ2 z%xjg@pBOjq8z6|iL7^BHs zafc-($gQZVlh2~>1GeqC66%@4kk6nkDesX3_pqk##&eeWdQW4HFQmsGIR8J_ywmzIbr$wL z(G`i$;hg-LNAx1}7<@g_2&Z4GGw8K`it~m6^QH*iZqm5PbM50p#kpcuPP=PW+i7zG0Vc1Q31PbEA5pZQ77z)LJpr9%Fih#F8STKi- z(-@FAU@Rh~cBKIiOv-S_*>nK{JM z`sZq5^!UdUWKudsK9DdcDiL~~PL9xWL(j^cyn;{K8O1vem%4(y#1yx7 zcq#de3Qv{c8IE*ZeC-kJmpz zdNhUmu@R2mD3#y;euyLG*P?bFxcXAJ*_oZ^U0}LXR5d{9RnV46g1ji=V+QAlNXEG-)W*jI>1qu z`&{%l^5wqqlh>vbZ*VkY8Cc$cp4*zc7e?T<8+*9pGCW?uC5ax&%!`I zzkiscS#SFA1pJ!5^=sA&$KeUo6I*|Ai=%g+Yix^AaHM;pro00)KUZJs4u)9;cy=In zwNHX^B6#Idj{GokG<|)1ZNVgb19KPn!SKWn)$+=e9EndlU+)7qB?x}(1iO!K+Ft=$ z#zqA>gR%+TBfi*&rqA5w$o*Z&v)MT05|19OX1#w_ifWhtv@b$)&Vm~mu YNXLH{SQ2s|>%A5BtJ(Lz&V+Bs--6(OrvLx| literal 1608 zcmb`EZA_C_7>0|RXc%KsBTPO542nv%cEqt_-8_I0*%WbuAS9!)AQ~fd<3qrJghQ}6 z1Oo0=r%ag)umdt=j4!LwfzY|3brmNTMS)5wV|+TXOx<1g2eH2v&Y$Z&=RD^+_j6ui z&iZe(Q1aqq9{F`lX5URYCD-Ffruq^knznt*(&4ufsJ$~3lsI=AHuZyVr<;As{+SZ9 z=(D*3aFslvj1SJu)0*))&-x-IrRV)-I^da!jP`bIrQ~4qLtbPXC3Q>E+OLC|WU8tU z4Ev;(TMSy?xXKws9m_ao^(Q|pS+@)M-nUqS68Gljm{Wwm-A_$MZ} zKbN9kMR>lg4e~T)C5;ZWAzwwLLDNnNY%lqW&C=8tn9W-F zu-^M@xpW%$-I%<$@e=MC60dhDKz`<*0*+e;B}U!se%*)m*ojb|UQJ3DHc+BoRrgEI zPn1XwxN_dDr({hN`w6d+lGhg|E<24n>!QPJtB~8pF8*Bt4|?1VYVZU_nvs*X;9HKt zBd*}we1;z`EDh;nh_J9z;|H(Upe@Qq{^aU%i(dH6&BIt5KxegJDiQa%e(0Z*2TyX9 zYC%!Yt3J=?J~rRNr?vL~Bes@7%sD00GDPVc7dwdg-qQV9I`|Jh^?$@i-L#ibCqv$` ziFU5kgzwBy#acJ?`K6z{OM-KIbL>++;OSg6Suue5vpTkZG1%~3&u%H|CU*R(-vnPm z<{9-DCVZ{-)tx)Bzw*7%S|{|w{h&)`q|P=fLW%W=%@&o$_q*9W>MlZ`kM&v8T)baE V;OW(B&8zP>_y7FgIWcFk{skH`NxRa$mlC{&UZF&VODm zIN1IFG!S_GvWOhLTrb(8CeW{m@GWd3aMJNXyR3r%^M=uBO&0-0m}t7?0fB_ZEeeAC zV6RKh0?Bv7Khg{?^i8&>9j&S-5XP+xq_q-wKTs}ogxM$w~ z5YO%N6b#L60&TrSpI=AdNvErOKIRpwgqSP$2v~I1zVP+eT^w%_pzqtGmER<=S;%Me zu`a}PF>eR*Rj{u zJK3#c)DpNqRjs9=?-$Kb;sK<#s`t_@Wb>CSWhC-!NXH#DGRwDz_7dl`=&XJ5{yJl+ ziomcgY_t}=(VTIG3-XL)qcK83Aokt4Y!Bq<39p|nApQK8WRzpxSaWoC9`|U`S^E|> zeoVn@-y$-{TXI7IEPlAqmsM2X#lrg@)U!V^;e2z)DrmXLL!seu-waW3K1siO+n*Hd_p2za z!`MCjT1?&GR`Dz!EBMcM_}5&w!V{|WoP5@du5F=`^q>4LFd*^mFOujjBYBa#PjF! z?a@I$LJFmjvqISP~h0TA=wl6ZtGL>ot;eB@9@9o6Q|MRno-I$Avtc#H9g2e z7Q^ovvZUFt+7dTLxvsMGQ;jf84p?XFyC0KFuf%;U&+UIxhWUNRoTbyq7S1zz1kSN% if+#;n=4d8-{E;IuW>q=nGi7_zmtdW(Z?R&)f5?9@V1vK_ literal 1608 zcmb`IYfO_@7{|FxW!Wf0!^$?MYz$CmveFGiv(e+mZMCR%W+3A_3ylLNicBLJ#8X7G zWF#HDV_XU~Tmo1rg%uhor7D&IGAhVGTeKFCWt)r02%KkkcZ`f2n1@_Wz8d4A9T zJnx5>tabYL(Nps1z&>j)K|G#qWCzUTIu=? z{f-ikl?bO@1C*RSwW~H9JSaR^)q#C`-^WD**K>O)k(|}(e?-3Gs!sxBeUuC~i}svC z9zRa_D}TZpDc_&%508@zPuC7!$v0c4SJ$i0WAiE%-dLnvldQ^ zpjsE=?yaFjz&iS^XE!Bo>Iaw1=o64D4)_#v$Ak3ZHVNnvz1TM#9HEZiKZ;LXkV$d8y6K!S|3pyP0D`j=N7QtrhK* z?49x~jf3ZW4BfGab?X*e|1$dJ`15RR`}3_8}-ps!J-yeqgUG<0|gSHlK70TFT3Z%IPaC_@?{ZdGF~)lu%GE0#Fycox$9%f1n`Wy Y+*glbjtN1rr6~@4_Idy7n&2Pu4`u^^b^rhX diff --git a/test/beta_plane_gyre/good-output/snap.u.0000000001 b/test/beta_plane_gyre/good-output/snap.u.0000000001 index b82b9b870baa204585e6743c15aced2834d7b478..925a4b43c318313c58ace505c5719db8e8ad8758 100644 GIT binary patch delta 981 zcmW;J{WF^f8~|{UZV3_cqVsZsYdAR(FHJ|NKHr>{I~7+djwvlO`Xb4kZeuQox!5`{ zt$69nyv()gr5x?lTW`x(ovo|tb|Xp0=!UkTXLgj1WUaN&AMp9q}=B8^YFqrror9ov4ZTq4Q6s=N0%l4EE z^~CP|RltLU^G|;`63+v-)MaOXHs9U6~TA9>&(Ic5&RvcV63S9 zNP9Coki9VN3!1cD{qcoDcy4)*%QFZef&b`o{JIdHsUw^7^+FhNyz}UOfe`%ZjTQTi zzN9r-w34tYKJ;xom{ia3;VgwXHS>-aFn6ZS6C5un`cm~I!`chFlV>g2Q+#;bHPz`> z$|r5E;|2NA<6O9MX&`3EnG2yNrTEY~2R=?>{QPi%1B~v~lV%eKUXFgf^n%KTr6a20 zh;S}xHK|OO>;MztH#ZXofqxQq;SuXG)2#dEKjR+w#Z9_wGU!m75x!?(OC=-!i| z37fIP5U$7K&i0PZd}GvEzx|)?ZFLO&gDu$#4Hp|OTIw5U7`)T7fBrNL`!hr7RS7ig znT=|aCeyGfDLf_ea~jGIyR=OX(eSN3`9N91kg>2t?>-{EVvlk~Rn|WROq`iCb-i+C zV&&C(UzUoAsu!l3jADBXmf7{Ti&>ZVHqB;Z7A5$OO+JUT_h0AFrggJX#$o*aehv#+4%;C_jsqIb|f^yftY}T0c|lPg9Bwo!Muidp2ZCXIL%kbWAquKz4Az l$e?z?$Fwr#I{D|NZLq9 z?a7bI?+o4HVUxCIs7X~)W!d8oEQ7qHsJLq&GqUj=zQMA|*K z-`vY1?4=3kljpgi$PnCIo>D48?|qSE*L90f=HW&5f>ngB<|f)Q8$_s;dhA+_R)lhI zPoDb297@>aXmJ_2S&U*&yu9wSwjGga#A?Ag~+eRjr$p&nYGJVYu+{Ug_7LTbgRdR-efR4zshFURtZ=8KV@KUY!j zEk?XN;iqQ5Fv1!*1Ng%lAsT0EMCYf4h;^^;L7hQ}_Ej&XY@-Ju0UnyMcT$K3tdc}& zlMtCoUXN9V2nnlisT>}`y^s=PHCQ6J$ga<4m1($WNbV{qS zkK8K}yl?>(+go0gih*%6dq=ftV?Rnb8I?f?kFh)U;ChU(0iPTw@z%OQo#IHbP{D+$ zryVL%G6S|QWw&*tF`#MGcxCo613q3MX*anu!6#*+HDaGDVcVJbmS5aCFco*v==X>P zuKQhlXA+p8(IfQv5Ci&-FT~xRVn7>(m8AZT4fBUh{G+iRgvElf$Bh+k!22OS=7xp| zoDUWi_Z19?A0_?1yN&@q<9c1qA_IQDd*<9~HVf?k^!=%N)19zcg_&#@cLw-d1~>KG z#UP=^xFQ;)L#;LC{b?BnH_S1viSrmJugs`2XXsF%Hby@&F$t@pFk<&u$( v(01v|kZU3eypgY98`>!#EB#A}(kM{bA~U_~Btg#}^6=kUC;lqA4omtUx~9Ei diff --git a/test/beta_plane_gyre/good-output/snap.u.0000000201 b/test/beta_plane_gyre/good-output/snap.u.0000000201 index 50205893329da51231540b46fc4aaed69af8a9fb..3682b9bf522448ff71fc05484310efc5bb1221e6 100644 GIT binary patch literal 1768 zcmciDYfO`86bEn^LoOL*g_XpiA``hc6e`#ax6@$@u2gt?r59RS5!r}PE=^?41Q4di z85m_iF^Wi~fCEw4mcU?#n{(jCML`iAv^Ha#gG>Pz5rO%^?{Bg#d%m0xPx8yj|2Zd* zWrN-ScCNb2Z2a+2EE4k3!;*AwtlREBe4PCzEJdyaxGeiXZvKc(oE`-F{l)D3wqSU? z#GW89BB?Sz_B_VRp5tL%8O(U1lEmY+z#;L;*r(Lk9bA9(b8R)(cB)3b3ylf zXpIDxE$EGxKbDcYs|nSq7n)QEwi5m6Ka@Bgm%BAjufX)5^~$e<6zF{T`JGmS0xRcj zGoSY>ajoUnucj6yshbk8g`pP8QMh=lqDG~{BX?G_Jy+Do)^mvLz!WU)b(pr_sYd>e z4GoJg+^M1oT1B6f)UDRggTMSrgn8FmygECS_?;;-dZ;J`PsE(=x#6k7@Qtp0XX4aY zMk|9YjtcC|lT_zgM5OM^c`5vdm2BMpbNAV_qw81!56}L zToY+=^mt-~Te1dYBCVRnIR##GyPmWzNFdE&;mM}KE1VE4d4pyRGx5+nY??a36`<+S z<99D~3Gh?S{vPQBfdg!ZGyF z3N<+$4CA5{{4XZn&{ayHn3tdS;Gqa;-|vfPB7~%Fo}@dfQ6vZV9Sj!buVnCG#9ys4 zsKLiA^Rvv~)j&<`wUp+l;DBwkC!|LK_LN}fLaLP1{j>IYyF60}o4#S0?skY_u!vsg zbyNbQrKv=Dl>{P|ti1k*VwkN6YcUjv;Joo-syv<`b$3nqqdkQQEM_DJFKvUa#D=6q zF%@`FFWxof1S>09+Trb9;Lci@HQV{a*;kZVu3vJ3GB{>0; wMiCBn9=sW~SB#fLz5-{15dG&*Rjr!&c#xBkbt*m@$=>bd{lDG|%ZoqmZ-0=mIRF3v delta 1010 zcmXBTeNYm17zc1B&YFoyPQ_UQGJ!%j)aBGEkCB?Fd19Dm(^ES&z}jZ0%$KFREp6%? z+S`TLE_<6VSR0u+<5%R;lL^?(!f`rv8HveqY|&EMl>PPm^||N!-1nX*xF@)8C@u9^ zdW#TC3dcM;5mnw&Bt&|ju?h1T5!&KDI-ngaL&q&ksTW7ZC?}UGZTA!5Gv+UeFc&k<=AITEHXiCQ`m3t9j1+30rwL-XA9}!}GM*t8$ zm1txa!eg_{=^tx0tnH0U9g7n)4*~7n3)VPU3Fza4Lk1Sgpim@h>xvSCk<)gv$g>Oz ze5blSF(Qb)_2c@iA->(}14$#TL3~IsbPf|6iouW0d0cT;1Zg*}-%lcxKz>qPK@P#qjL5<9#yW`p*66mf+ws)3XAUvrjgtFBT#(qv=YrR)`Fv zpPw6#;G?_J3}?k3d1&TRqEOD;gVye?pJ}?M3Hk`Vz?qcucrhBe8jri;Qi&+ou*&Z4 zN|bL)?p8Zgp!V3Nz!WG&y?O<^)I+#xX{$wZC8Tw$gRt5+q2&OU9QH+T9eT8zfgEKu ze%B6BQT4;%?+InIN(NuceKXw^TAg3_DHVD{)dcg-;>GpQ*RG+;Bc_#WQD~hjt{b^D z)F?TX_9>T$Zg&y0K5n-tNu>Cf2^KR;TpdB>46Fm)LDSIlbgIiM5|mndnS( z+U?ug(6PimYGk36B}hM}xM5ggVg9E4`FqEZ(xova-8|`zW)i;ku4&$E zw~?`mfEb-8nxhkG%NR%0DJxUhO7OtEADp~+*bDMPUmd~Dc){DQnNkOuBM|1ZM+8x` Ttp6)_Tl;MZ3GX=Vgu(m=0$ItI diff --git a/test/beta_plane_gyre/good-output/snap.u.0000000401 b/test/beta_plane_gyre/good-output/snap.u.0000000401 index 4aa873ef18d6761a091661edb6be7f337863b9c3..31a0be442eed1c458414a18c760eaec7dd252d5d 100644 GIT binary patch literal 1768 zcmciDdrZ?;6bEpqv?34N;$S*$=L$N}A&>A792{qaQcyz!xK>JODTP9Ll=29RWdlUl z3?G1$IbMpORW=yRschIC9EhS&CXbm-jMRz<7(wE+fQ;=A{x!d3TXz3Bf85;9J^7y8 z+!2b||F#B_S4s+Ka?C5U5%OsnXv|b)hosECX_7xwj z>Z3^4XiZv>PsWp;P?F7NLN)hs7M=IV=b~l7FB&m z$;g6()_rjf<;jF@;MqXG{we|7OAMhMrzb$AU5|NjsSGs96SX-%%D~*$IO(}U2JJaE zTkpP>LbvY0+=4uc&~@rGD{{6CL+`hzquRHGW7l#Y?J`LO9%%6OqW6WP*76a@&BVpc znrU01^IlAys9%#`ABaTxMt2JBnjm4rsVsP7qDvc1fzxSOWt)NHl=gYe zSE11IcyXPBfDa2fV#Ma(4{F5){`tPs!43%$Lz1rMSloZf9g#7NP8@|7d>e)xf8n2w(LE9d!CFl zm#bu7C$i9s^w9m*OFGtlQKxLKUWL?KZUVz~Cp=l&c)`u+f#sDBiDSkO2;H$yYcEsQ zcq5ZD+*2ZFBRlw;0R7}{95VDWrqcJIrkkE1>*AnV?|+S#u@eg|T^oeyZiMdY_@p1M z9F0KgFO5PQjtJW{rrl3BN^n`}&`fZU1X~9v_j1j}n9~2sGc}fvzgLts-Jc33beG2W LuiwSU-+$a+w$ruo delta 994 zcmXBRjWgSK9Kdm|O52T9l~$4~^%N{bJ?uo)w~}9i-mDr?cF|GuRdn0-GF6Kj> zqZ>t{IT2*{UqB)tD?wuqmkrOmmj0Qr;Q->j>Ip%PSk^HKi!x_xiI7a`$lEB5+nDLS3?Q>|dA6ousGe1mDlh*Lju#6AG|F{| zm7=&gFP472&|>K&tK%luVnpp4&dX-YQ15_)=T&VbdVeNh>M-uU=`Rt*z?ov5RJju)tjcTYv|DWX|^#h zh5-ipv(y<82FgU5e&XRV2>!c)mB1lw&e@C|ClgKvX+mM+%6;L@JgF(Ak_g`71?h6sVT(N~Yi1tG_JEP}DsTJ4AwUQ$A6`?1 z!R-qpX6&E)4}l9-LjdL!DtBZbn>am%u5~A7XcKY)Xtl4(=kXAtrA@G tW5BMHcJdGw1MZ?7PhAT!(CoiM!5u;HN*7d6qkZ&l=-4*pvYqE*{1hj6F2Q!(@ z0v#qdvkovPg(eS)T=F3lqsiqHLr`L~Ws5cKAVfif`lI^ycjt9||M~v$y?fpJzTeOL zz9xrN|JyP$oX$&s&qszw`QxVsC03~aXj-dLVXi1}mEK8-CePt&QGpEm=isbgSUPT% zm6q3J01^c}Dr)MU4`zWUX(EYnArqcx`jihmWx!&Vn)GidfbvVTZLdTMyVCq3Io2$g z3~n?G0SAcOhjF{3ZFxDcbH2FdR=NUm*0@nuv?U;U&$p4=UIr@Co=r6Occ3g|=HxyX zDcqw?CMwASLN~IaZsWcBOmK2~Bi*vUlp?jq+lrrmzH%d+{ zTRVMl**5;=j;jp9yxszh`>DlLNYlT1+(J!&@F|V&*Qrr3!^*2B*M`A{s{Ya8$}k|+ z(h}?|X;8_1A?o|`WI~tRo9NHKNd+dwgO_Aah1E}7+U$~IAl22g_pO*Wp_D&W*s>50 z_4I_DDONVP;l*mEf=%e2elTt?;tFvitHx)0yBIsd&b0EsmEZ(m(SoIF_)*RgUXQ z-1Xb!a#S~!7=4rEI1n|zdD|li9<*N4RIL{f-ov}5*--j5CWcJAT;D&*!?sYxcb_;4 zQGNIuJE1xUX~BjZ+$F$(h_PjhR89w`U$$7~} z1(|R%s+b-C=Ki4xXpR8~zE{_g*m$^mIbG!A6-hV`M+=@tue4@E#1%8;?C1Hwtluzm zt2-Z5m&a@>y$l)}J0*^Hq(Cw-jBYV`a8ALyzMaM;baSV57XN1g82w4i&JHbr2~+Fb z@S!3IcsO@4_s2p=ugOy}%nJBn*)KeKKn!1yEemzWhZ=Hji-xb_210J{O##XY zjjN-X2kj!kr5pEo;N3E4vipz=%~j&DST+;J`*oBxAH7DHcjV=3UVZ+%@p!DUL~IeD zblBdlS1UwzL!+;=Sco0%Z3j!&W@8}rB}cX>1J&_Ca6pnw_-^}4Lk^tc<>04vXTs}G zE0ELR+){U>2=h(eMcSkye8oHMu;rKnr?0N}f2I`U9dkkA$(w0}?sN9+pC0|&H`8B# F+@Iwbvc>=a delta 1003 zcmXBReJ~pa7{_rht57sAUMgNHlqB`qb>+O(MV7ZHyo;D#?b+F zJKDKZ_XWsGI<2|WU5XB-9lmp)OOaNx`HDoB;z^H5$+EB%?@{Yj`wGPP^tK}*iC2IX zWLkhl_2Cywx)juo-r+}yvrtpQ>1Rx3BhhZo>6tnkWxQC^n+;j`gXnVc(?UL)V~DHK z5w6}QnmF3$8RkOz(tL*juNZz7A5e^QO2AY2=+@w>0LGLbqz0TQf^J@;&)*^W@I};l z!dPW0?Cq8t{pf3YTnHwS^5Ku`%3$GKe>AJ99Ew&#H?P0>8a85r54W|-K-gBRjtRd8 zF^l#54so8|UggYNT8$M$1}D;k^G7MX9sg^-QX~V?{Mv_)_sf6+b=;}2QW%v+Y(E+i z!Vou@l}^po+sHFkcfD+qpk5Jb*VvT~D+vm!PueBd1x75brVjv}~#nYZsSA?AyioTS$w4 z#Be@Fb;li&2d82M**Q><7B*44!W5wu&yR8j%kWQS_HY`p9M@8$rxM>?#~Qbhc-vp4 zc$d$V1v9UqfS>tYRzm(RX6!|-pb>Ttvx;v_tDu<$SpV)a6t-%Oy`rtzohBD-co{c8 zO`~B^LfWfJ3p!>O`a5oCIN=j_#rXCy6JWIrn5ey+^>2i4pD-A7q9FS-`OSWUIr_{7 zPPDGla9A}}dC}7w!?)}-@$GKNkW2i!c_gG&D@-ZND@T(5` zTtjN})PhaGOGx9S0JeoT-X?f<+CFpKia6_X z|1AU4!GiZ$VQhO4UO2lM##{};R8ESq`=ns`mCLe$P+a0O7)Pfs%e`7w;wCYfXJ` I(!{{vKV3G{0{Q5%uHBegl7Us_IqBsFsn}GIL7RHW zL81#L(F;#33arprdTHm5P&cG%(APRE&Y_1h^>!_pjX^htav0`kP=b@e(ZiOozevNj z&&36ZxK_P%Q{>0M3%YMPtsnuoD@SLj&5_{M`ZT+H&KJaSv*GtFB0#F&^vrc727YSa zIbW7cvnQVi zGd=hF@_Qo*xrSFJf)7x(VKrIZY>c!IYLa<}On&tN8sqQwe3~!x3rGI67oG-}09|>w zy|~T(yrXr<`fMAKzjv>j7djV3;dTyl=G%m1oD`=nSn+xIKyxKcx|fIJt?z?IUvP1O zG(&&)c`Q!dQ~he+F+bek3YGC24{1lF$+_5GoM|)iIvwNam%iao@X>nN|GmeBEOhpi zzFn%jh&{FsTCe4$;+m8>DAtcxaFt;d`--}oRYkrs-7HTLuZ*VxtJ?MMdTd;AQ_~e| zBqI5jt#m`3WLyH?xI>gl0`HHWXdE}SK}T|&Nu>~!&O%C5ZcB#&@jD*SNojE`3xULz z;<28GQBZqiw90f>Ed2cH-1hIjh=qBTf&`u$8wO7f=#$M^@O9bI#?Y#hpw!rn1E-{k zD?X#4Am0*4@@7OrU6QecBMyfaW8JqfuV zU|4R0mp?rEgeCZRR~Q_aF*;E>9R$C3>-qdp9RPOOW1e>$SnwIs=&h{O4=hbDv(j~l zxnwOT&HdBIF<~fqHR>=8y;5&3KC*Pjg=t|1r^yvf%%0b-4%uN{zE9x5k_AQ?8;#tJ zFjw?V>AdZ^pD6d=5{-X2EdHpL%f;SL3tX7d$*6a$=;^!~7vC-HIprziU}wLm#-*N( c2W5uwhyNm;vkjXSbvLUU=_)EC|NU|Q0?v%R)Bpeg delta 994 zcmXBRjWZi|9LI4h!x5dZ(PPzAR6Q?6An(kN^VqK(v!0Y?H&%GDz7VRXi)#c{V6z+VU zx8YH6Da>5whv~x0;VIYJv3*Ac43cJ^r!p@>L#E2zd|eDt%J0rgmiZ9E|E9(IL;*;# zdnnvXJ>3B(m(oD^8T|B1Ik7A1w^c ziBX(-brvJxm@KZb_Tb=6K6>cMvfiRg(9;rB*7{6};wd*aK2MS&%Y}1x(cDT@TDct3 zi4mdc*uqHeaDmAVtYkqZBLmguQATonbJ2d)%LnfDc}V^jKVMBcgHl|yL#;|S`kI@b zwxP^HTH-wSUe9rpJtxX0AD5qnW2DLtW?6igcw>Lf=(qs7w!-SzF?`6)2yz}K@?cpd zYt85{1lgteDN$-VZ0}vfJhuI3nh(Wx37hT0DzGWRy8fY-z}oy3@|WXP;4#@jn*OsK zuH9}9T}~FjXu?Q6kCkt<1Y_kGDbDJ3?B}%Zm8@V2tR0KDNa4_ccY_@7_9-2B4z>4j zE+OFb_)f%d4-I5}R0Yn00;BfSUU%$1;~iscLYU#1=5ipMJ(D|B)lLPuhm%J-o&gG~ zp?2nDCX~d=R76}Vli+I1E4VrJ1; zs4KKCy}h%bc`wut^x=N!*#|63Pp?Xh2W<3f@uyw)nyiz~BW^I~9bl?6Ixx-$AYJS$ z%rEta!!>eEEck<_Pd|K$=m#gmYqOihK7ciom2r0BO}22_W<9ds4`Od-n&~Ap2+(v3 zuO4K8<5En=ks>-2Hz*zk^&^;_kiNTH;0KYK-nvlg>%GLRd;0K|Lm;wJ8FUVG&y7r$WtGDU+tYe(|;r-C7`v}#9@w=dWSluZ1re#`iGJN8EwzgwD_{SOcE;lTg^ diff --git a/test/beta_plane_gyre/good-output/snap.v.0000000001 b/test/beta_plane_gyre/good-output/snap.v.0000000001 index 2c662ffd0acb5bc709d51e570be75ffcf97c576a..20d551d24b84ccdd17facb5f97881bfbce3aa751 100644 GIT binary patch literal 1768 zcmchYdrZ?;6vxqt!p1C*fWRm+K!<_4u}LtZCx8q@k%1dwL$DeYa7fn$Cx#fMFqMsW zOUWRD#cAUZdFhz4aF^b3$ta(hV^_pz;9>HS&fy(nU@~j9@6WR` z;B?oV!E`#9r$xe|v=hC5%*+jZ&Ibd0L}~V=6%a(#!6S|wxr*>P-Y=wp#1=z*s`wRhuBd}Haqto<>(}VXWeG% zKGI}xiQGD>cqzkvY*;ZImr8q@NO4EalSceXY zEf@H(Jl{Q*Uxd_`s8Q#hO}06sLRYsPK1NZa$cf|cDM;=^zmLOGPn~T-nR3L;j>`v; zZRIO($Q1hU;mr`juevE^tzd9`gR z76rt%#r)C@qjlFvjd>G5bJ@NNNIC-V1KrQ|yjU%E8rt1E>7>HzFHG8 zT8eil{?936Rp9S4`w47*3|H52$~;&T!1DA+Fy?6pyruk8-cXm9?@c)?#VzOm-~Maw z^^MT*dHJvohSGoS>B^abls?C<;5CC#dDz0#vR?=X(;DJgxdJTHmsdp}9>5QKwanad zC9c=-NzA9j_pv*A_4e^JEtH+y6>20?!m|x*zl_@oSTFUU>%SI5BTHhC%e{wA7gMJ> z4suLX7kU^|rcm8+E6`e?!Q}<=R9NVP3?|^Nk~;V7GX>;J&2Me6mqB-GZijYnGZ={? z7~T>(`dyWlvMU}SFFbjiAJ>EL>rxjN_`?JqHB4cY(ASK|OEZ1#j{S~%se%K$*SMo~ zpy%J38#N$OBSq-d0IsJWbe=jUgv1y5g80840_>I@cl!r8I!PzV&!AiFh}623OT;4 zyE;s#9kB^8of01ITu{)00EyV|9F3eT!ZKvJAHo&)#9UrWlME44DOOq}V@W zR8QdH>9p^n7Bpz&X*uQ{G>sjxn+^LzpP-j-@e5{BBT~3bP8C%IC;rH02(lCqA3nWt gx=9JzVvUI0e+xymh`M-bMKg|{Zg#Z8m literal 1768 zcmchYe^3)-7{?`yUpw(6#L!?|DaIvKAc3%+YDIuGf)Ny)njtg-L%3!j3Je8yw+U!; z0Seg2g9HS*h%K29!ZsXmImeG3$i{vOIDRceen{@(59AMaoL=Yk{_}mF_r3S?{J8hI zS7ou`$zrS+&r6?h*VAW>vwHs{pMd0V%%@>dukQSGw*u9H*dlVbxmY8eX9bi15p9v zM}CEHzkZL+1ObM5l9=0$OYtzxpHBR+ACtiTw$Y{^t@njnUX9VA-fL(s)@dX_rwe2T6JDFBU{`(HBm9!I%e_3>fQKHv+88i0hIW)}H_w7TjPD+Fvf0#% zbY^kZ&B9wi?5O^OU#Wwg6*BhEwF@S^@VZF`>PugCeX`%jDayw9IC z&(*kUie4v9HGpsaXWaA!HI$6(j5lr>1fo$Qh*WjLV=;B9jMIoY9>>h?7ki(khBuWOs|AkkaZeTZ<^99ZRtz0OS z6WD@=nK@oTBM6b&b+@Ju!H4U84swnG}n=P3L!|pNw^MZM*+BU$y+l{R{Jo`dI(~ diff --git a/test/beta_plane_gyre/good-output/snap.v.0000000201 b/test/beta_plane_gyre/good-output/snap.v.0000000201 index a4d99c020a9dc9630a072591af490a513f3d15c3..ba2ba7e34618d1819b865c3cdfaf239ed7b2eb5d 100644 GIT binary patch literal 1768 zcmaFB#z1e-0JV@<8t%T0YW}us&qUfE>s=q-#1XsSbAcK=_n(aYS7jf+=DMA;f7!nR zk5140{TrLtWOL6h*k5)jrMh!l!Tyb|Wj-sT^7fFlM(+P8?5Uf$qhkNu|8En|tfC7E*3RU~}{+g{6#Z?RRxBI8ne6{->|0Zt^ zUQx6EwN=R${jJseEz7qp$@^Ef|NdgN+H9q04EL?@4ergUE8Kr!srSrdmrM4GOV#n+ zk1W|gp~TZW_I1(z-+NBJv}-NgFI&YLH2p;W{$0OYHnW$d?_Y3E`O1_tF81(3e{bJ{zcYV3?LTaDDW6?fXMfjB zm8(BF#O*8eoG$&Wv9OmDNw0kJ$j$yK!>@&Nmc^l)2Xk%%ltC&D(?8T{vi)7e_PzGW z%t-q=j2DDWynyj#I4>ajYMg!8iS)=@nNjvP=dC^a^kJxds73GD#`OXAhmJW-S|j6V zFIMHbYTj*Q^z_HTqs5Y5^)Siat>{&Um{69z&Qeahv^$yh6|YoEp9G}a-}HeCs{80qC-gG!^zdVl-v zNB6$Dq?T;|W{*KGmtea6%&hMnCZQSjB~5u;;bNKgSN}9BP4dsQ*ZHqstDcu;f1YjI zcO%JAbn_a5QrzZAmRsx>Fkn=S{OxH!W1`@jEfL}Ne#>2!6+MZymyhc1y|q5kUMU XAQ0U=SUw>&y}{JO^i!RF0IcHxOnSk= literal 1768 zcmaFB#xPKz0ctTJ8t%SCyVsNL4U6o5hJL$b+m~c7oPOo)o4Wz_&R(L3BUv$6Y6T7qJQv&zzJ1tmi=9h+H-s`&u zrI(2n+P{*{yg!dC**<1tK9AkMV0%3$#e*|@yzFzkUPV6Rbhp1@zs>%AfU7-|z}5hv z&t~?alZz|P$5>#PH@hzE&6{Eu`{qRqKTokb*e^MC*Ye0t2m1zlU4`&UH~W*TeQpae z1=^PfZ+KwK8D*cK{HK&FA=y4VC)mw(Lxw#(;2?|!tyjtJB|Pc-FKO-(QMV7>pUC3V zwZUI!f9kabr!TCux918un8Nxy*nXq=%l9vU;rr!J-mL_d0{gFO?7Odalw+6|sP?cwOV*s_V1_ac_&x|*=t7cJ8&a1$)3}==hCrP z1@`Y2cYb{wUxi^_=d&q3%!%3iV^(o33p)_8e-UH)%f~X-`{zG?_%B*j%|1!;__^QC zZuWFz+`&8R#@jex%Uo{>R0Kg-64Mg6vn* zb8YtD;#hm4^`X&zvx9QAE^6BQ`)<$upL|kt|BgxDc;=~V@Bb6GsZvo_Z+~FbZ#}md zgZ)7kwF**O)b>LSg4@G1hhtu@rThMC2B(sCW!mpoIr`#fo`CuOUmkZ{<{vZJ-+kcj z{F=+A`{$l$E}2ziwcqT2>6sU^?e;gF-xBaq%NoPHDW42&w@3QypO&g}C!ybYzi;HE z-)`a7`{&)*9;zW|zQ5{yfPdazi~S{wGt<57?DucK%=>44ip%~P3>S|ajdsN_Z^5wx zQq!LM?q`16|3i0?%l@#k_AU`!>-~9p9rc-WP4^ev(Rs5d)O`OLk+)a!we9z>zwE%2 zG|_c`pK>4@ubmf$d3@>DI)pxW?vE9*T4=b`X@8NH_u}J%7W)s^PuHARVYELe)227U z&UpW{|BD`NF1FlX#VzsXn!EG<3vH4wd~ai#w>ItJSH0(s`&ZQ0=wCW-y`T5zsYIDp zqy2G=S?20;+WW=Z)B>06)81dLy!y=@aijgQY*)^(tg+d@=!tIU%WAj>+Vl15m2jqqOw2FWU;AFh2s80zXDyfrYr3Ku%x)-%rlk!nWtawz7=7x b-^lRn#G|t?;sc&;(BmB@F;MgaU>yelVhz76 diff --git a/test/beta_plane_gyre/good-output/snap.v.0000000401 b/test/beta_plane_gyre/good-output/snap.v.0000000401 index 11bd2ca8e99d824d54bbe597a355707bd75d5d9b..e19b103d79768ca65f5f66393976174cce4cba8c 100644 GIT binary patch literal 1768 zcmaFB#y~I70JVrz8t%TUXaBuC%2s0EG&A%4UZzm{^JW!dDR&+BKQR~Uae5NBf8uqw z2i9{^_bbG&VKFhv*e}o~VDQK>YrkH`ojL7BIs4J;n&6N}jFw6@$ zuvEpX$={y!+1JP~CDfbV5rd2Hm^{oeiba_`Nds_lE?$+o7Aef5t>7k^XbB`&Tcid@e2$vY%nK z#Dz!k{`;4l@?7k+%6GrrYgUmvM#202b*?<E{SV%`r#jV@ z?f>)Y>9w-`1^eYM@|?^&n7My#uAA@2hLrtIYv#58-IlPw_I>|-!R(0rQ{Slkw$Dt& zFt20Em7vE9Yxc|hNLKk`Rla|v?L`&N=%W3X+=Vk0zvt`^IwG2JVs6_0U%6AKZ(EtL ze~x7@Lvc^Q{u5T0HXHxQz%cJ$?CVGg$>RM!%r-OFRkQbBchcpSzL&E9e!>2Ho*VJ| zz1+^td-^$Szs}poE90!a_x~{cknm9RupR4KixlJFbaeAz-fw_1NTp%=hbm2~e_`t3 z{#`4jz2(e-Wc!Rl20{Jo82bc6-#?WrgY0u&JDgen&(nTJV{h!Xg_ic6hm`+R9#Gpq zrP?T^W|zbsGuGj3RiCglr?VBF83$i68+4G-1P$GIM$bO6N<++Ko z9qiv;Q+QOeUwpsI#jh`oA9?K0Jdw6QYFFrf7wbhvZ+FFEm^W>PmBOr;WcwtiX5 zBJI7}gUVcLo$Z%zkMKJoEoz^5{$AnT2IKvw-+Vu^{l3foz23Q5?pHka-};*2$eS04 zVczzL$DJJ)4DH!mO0P{)cCnv#;PRnc4{Yr1AD+E<@r<3loug`{imkJ~%Aal( literal 1768 zcmaFB#z1S(0JVTz8t%UDjPA$%@0Hv4t;x--4@|e;9(nDzdV{ZhL0j#@E!{Hqd@74l zlb>7eXL@zMvDGVh|Gph%`|=N^?(fXecDWTqZ{kHpOo1aVAbR=T`Wq~AI>+T)i@7ZK>&9J; z|N1>_|Gc*9jncWv=;k#rx}&Cr>VZSi9N?WYs;p{82itH3tuQTXWP$k zsy!2EP;Q@Mqka0sjam%z>J$8Z74@t3*Et?3dU!8u{|eC^kq^%K?`Lmiw9xR>wAXuf zKDCEC(Ei^2W4Z_$e)Dd;r`#x z$(kJH$7sLV=cVJ%w=DLnT95wnY5BD8-}Pyy%IAviFNr@VSMpkJ|FrM?Px}&7_QyV# zWr$j&y+7e2U&<0W-ThF5VD>Ta%q>!s+b(49!MjgFb&`Pn!D&14e%3PXZ@(D*_{j;m z{m<{r^Q+_4*k3L7^W@iF!~GVF?e58bX8Sk1Hnp46YmQ;w4wrh?Ni1*e4m|mH()ZST zyOOC7uE_JU?^m%ZcYK&Fx4-84A=8&STKl8_m`z`M#Bl%AitXV7{O0>PgsSG|W?P_} z*Wi`-^p@x*rTsgSqZvbHOYCoQU+baDBeegA?(b^p2U7e0X!Wb;y;I)*#JBZIQ>fPd z75jE?b_~(qZ*pt@FXo$u80K+_ad~kj8tpHbx>`{>L~B3a7V$eTR!i;Qm96nV^MdI9 zGw(OlKTH+dAF==9$=QoV_8&R0c+WjmiT(dg0}~foD`J>;zVt!#4l~pJ8n65uHq6x9 zAF0csm^M>(|KpBo&AWjD`x^s%TWV{W_Vbn8Iq=Wq*1og=$0r%@KiFBM2{>7{J>Q2G z9}QLs!fU6uRGOl8t3<<{hE@tJ1-?9?nkqq;nZ%1{ga$)?Eh9L-yd-4 z{DRvCdHY{5I|iowDBhocpkB{rSJ{5AV>Q36QY-f_{<8Db=9Z(pszW5R{|x2H;(8T~KXfBNyfFXn-z`xk1gKXYPX`TlQH zyj?ePmhab_vokU~u4w;vPo;dvJ<0n$ruLlLZ5w0{4>$;;;SGb-#je(d{Tur0pY9aO z-+$WdSvsRz^!}rVAM5#+x$kE^sZ;ClSIIs;O{P(JcBuVo57`w*_0#MpX_2+L(DLcmFo~ysEAMul<^(mft!$z3jtw?B!o47H@BOKKQHO#5DVz zk9JMJA(3kzFz@FjC@^TH2@OkZ)WVn5H{){1W*Gxu}%ZO-Ic9KAn&!OnmFf-d`e zUi@6NEJ(>dsdjGSZc8_NiQ>n>yH zcf8COV}6}u&-mFTdNy;4eZ-4>=MqCh?4L#4kDu{K%Km#xz)970p8KygTN?cj3g6$8 z7A(lelC=Lqo92RmkevNcgW%>e>$U4#TV8BG_hv;$iDQAi!8EJ>`)kte?HA@s^{2+# zFXDZtcgV=cUdYTqe$FaR`$^Z;R3AJI*nj@dg7Z@~Q!&h|do1|W>ut7u<>c&4fqgml z#u^>-7U<^KH*9=hRGFJ)Z&m)~|Euq5_F};&Bc_@r+DDvdYt;$zx6i(^y?LRF3x;_% zD>nNV-jcU}yCyD7+{w@0VA2A!ymvA7w~n=XE32f~znaqFBN3NoUlAK3uQ55rK5KD= z!6y57dy|Ffht`?+pr^lv8Pi&oMYwbJKkXC={eL@Qzv0K5U)93g_WRymFh^~IgMEL8 z(Y7bgL+wrWXTRKL9%p~gq@kJLEy-T^)B1d+sss%4a>LGC?$a&ZpBOvSd3s{z{(Vbj z1)AoC?JxLsho9v--~MHuJ3h?|39!%R_*~UGGu~cEtV>TfIo+#^=Q)_#uSl$WPw1lu2%3_kAX5pVx^bxp|~ g{Z#wsFN&>K?@2~C50-9V@l7fX(@%B!0kDn(00i5_9RL6T literal 1768 zcmaFB#y~I70JVrz8t%Rcht5C#yP(0|<&*nz5uZYPA3fofj>kjnFGyv&H{0CbSO0u- zfpDYue!-`&zbNcT*k9*tQ?5RvVE>Mtaj#ZPD&LQ0KZE|eqyyo-cqhBh1>pBzS_sgq@eu{GpZ+r2&V6^;d$Eq%d>3%i}&q6cSzS^nAh-o z;#zjaa{JS^DK9^CW!STw;^Sjw54878TKm`Um5KdMeenx6McVuMOAa07_Yd0N!z!lo z*o7b?m;E4Vw*WCSos+|t#pHJK`$fzHmx!!vJjOWW_w>rApf3#w6 zKiMB{A2Y=k8tkjtS14WF(S%{1-5dj*YsF3bmp#_ovSw$|{yrCn7rr)u``=u9cgEqIi@nQg zw@E9)W9=txb7>Il$+S=7&N!;yTw-5+M|%&`lL~b6(7Zq5xD8MrlS;z^s)3b7Z@Y-O z#(t44N4)nM3-3?VJMrPt5|RB5e{=Y&8m0F~w%^|Qm0xoI-_yO1Jp;t|e+*>ui}@w6 z|4x9>u6HaF=<(5DU|W>ex<`9|OYCpU0A;ED?20XmZl09gf8e5*OH-}F{s)I9O+3F> zaliGQm~D4&sqL3)HV=$Vt@P>t_{se%KOzL^($5zXzf3=-Y<657v249xZgGWA(e)3020k^__bCJ#iPmXBpPfPsqtXo}w zzt)yF%>e~!80MY55+1zcui<_ZaC Tf4)W^4FAH?&7h+n0P8pa*DAWD diff --git a/test/beta_plane_gyre/good-output/snap.v.0000000801 b/test/beta_plane_gyre/good-output/snap.v.0000000801 index 0438824b6b277523d2bd45f6c961e7ee6c573248..a52d1184e521a7d76023b72ece3041caf1f7174f 100644 GIT binary patch literal 1768 zcmaFB#y~I70JVrz8ty))5HCZ6?QQm}wPzX17AM)W#UK9Erj@XNh3>16+jk51-(CHZ zIl!-c|CP27y+g_s`(@=Sil!8l?f)YD?$fHMlKp7*Gi=x^AL#$H+1@oiVZE+skiFm% zz4mD@6Zfy%DHJXep0|I;!9QPlyNdT)Ez*5wx3hHrt$j%qk26d5?{qnI(4svP!@U37 zXMJ3+pJ6{Qtoi2ZD{FNUsJOGZPTG1J;BobbCcY@iTf7pZ=IW#_cT9w|H{u> zV_bA%_s>oana5q8w4dig-nTcMG5e2(P5nPxEYThwa1chr0*j9w^N7`$NBWDD3Pi+Ane2*T6h9cmIm6GR{hep#6H^Haqs z?eetNV@o^sD>%)J*?GNe|An3N`m>|6_A9)wid>T)zdwE5`D*rPkNtCZi6w_EakYPV zzkBoAu5|m=XS~lcXfiXdboe* zaD?{E7cR2Db)-TxG9lCc=<&HLIXn~WHFA^^z0ZW$8!l{+PRVz%pZ|UpR?<{#(t^`c=G}YLb25o?|_QzgMK{v1A zQ0t$9{yD1q*SDSu@)Gd1&r0+v-_Q|a|NX{WxGebL(%V(RJTH;(v)n#4`&Y=BOph?k+23

eioa3Hz@$X}p_w!)O12j1MnXE8N_7u~*XJ@KX=_lj#ZF hvJ6r7p7LBN>;95k8BaLDg(z7NJL=P#gCdoM^PHa#As>N!cu;HyQA*qFHhDBy zYoCPTlTv`B=2bQ@x zHG&AKc z)rQhg<7`W#OZ;1?a^EcZ^mQL-*D|(uabsb58I!cpnE@KfT*S6+rXi2tHnPLUgvAD2 zh`Xb@>3z83tE!K#c?}enl<&o1RCFubEnBELf+UA0inhe3qG$0d8?A1oqn>vx{YLMn zq4mN29q=byRhY&>pKRiOBT9LKS?S zg_iQ2`e(UZ6nP>1uE&A^-HR`%_U|t=;%(8Fo|@_sg5r9)FjAfiOp1OeWG)JrHsh+4 zrDznC$a-%clY$~f)E3mwGg061^!~cRJT$El*My~V40&tq^H+oC=~~|ZMW5H_KRsWY z1HUEwvje$Dw?aN%8F;zI6d1hn4|(6ZKpy*dn~am*Ff?)X3!fxEIQoZk94-9~_=rGS zR7CBBG^$V+!^6WWXuYnOqhw}EeSzjly3<|Z0BMSj`e}j}>>f_2i!8>&*bG@|7ej!P zrL3DI#vZtznVYF`wG2#ia#J1r~GMN7$wyvxQ0Jp$h&2=F- zkT1UcWsj{3qzBX-$vNu_n$5wks*(WsWfy)3-@X@wK^arE!Nxr1-GUwFLJ9~cNh!|o zCOnn7cH(GWFgITL)Smb%*xeo>a~ka6lh!-i263LivT@7vYbLC)W+>;f>h`d3*yI1k>fdvFRpQ96cA9si)RFiH8Q@A8qq3SYlP}Hj# z3-As!;+2fy8KZdtVBz+?u diff --git a/test/beta_plane_gyre_red_grav/good-output/av.h.0000000001 b/test/beta_plane_gyre_red_grav/good-output/av.h.0000000001 index 0487e5cee97aff8852c4b94cf8f4e31cd12a4244..9c7c343831fbc47976c9f8f36c343872cfcb2410 100644 GIT binary patch literal 808 zcmY#jW?+~#69iV;Q=2}cFtK`c)r42a9$T_`~X&$688s8 zXQI)0Q2w~lf>xSeDEWG)u-3LIoQrvSxSW2eprse3nNA(;M*M*o2F<#N}8<&U{3 zubqd*Jl!MeXF=v&{;U9wpVmWKV7d#9?uYWf*qVUl*Egr8Vl!{U>@H?d_{A5lnFexS zrQ#+qU5iFHK=~@mwu9yQXZvbn^Y6;IDJ!P~&AG?YITd8y!#iDI`Y{^)6v{uox(6&T zcd4U!Hc&l!dfUo$od;x&*qte0bvx>?(>tN!lT{${mGMyu*wPES`Q-8yfO!M}3N^G8 literal 808 zcmY#jW?+~#69iV;Q=3i-RCzWTXzt6Zznehji>>;<1w;$%M5TWmhw#5I{3krK?w+~dot}0B#q%Ytw}RB&`_8fpM4y#rMWMayA$*_zC-#BlSM~SQEeF!*=Iy(w z72E<8msRBgyKBMRg54nXwO3JTH=aVU`1R7Whd}b0CMSi~V==G(KvZM{Q2a%i)>4o< z3Dsw7L3C_7Dy_Hz!j~4G4)*V+6#pNau$WiWw{meKP+Z@erx#?-!y?zIAi8HGDt-4I zgddz-J{KfE^Q1`UMj(yu-)Dwa%iDqC2`SZOAax1WlWRcq-%M2c#&igO_2-pMAo;J; zsuNZNX>{|-Meg6}2a0R#Ih6}i_hKSfA(&o;N^dv};qU78Edj|tlJ1mTjKw_hRZC7z w1BzGZH5Gu=t=yIZHgCaRRC@9e2;VKyy9lK2(C%j4Iatg?cQ3ho1z;Wl05{ID=Kufz diff --git a/test/beta_plane_gyre_red_grav/good-output/av.h.0000008001 b/test/beta_plane_gyre_red_grav/good-output/av.h.0000008001 index f70246d6813b82dd06705481671d6d722990ad51..1ac620800f37846c840bdfe464452dbf6e864352 100644 GIT binary patch literal 808 zcmY#jW`Kf92MB|DG?&$}3j$G<4oA-I+cl-L(qVnpr!0;8Dji<>xc@Z+ z(!uAI^=5TdI@~H@t(w|Y>2SqKU9`Cj(;cben)?nGRXX?xKD^p_uF_$jPSYdV!<7yJ zZ)5I7?yhvGW-!!a-&*NVSbI(4<;qHjSz8o7?4Mrgu=#}Rb@zHq^X^7go||A*>Ckk} ztI4LY(&2rKBok8t(7kDgwNhg$9kwZ*+nEI93p9x=yO>((VEgx~-mdIQhs8ULRMdd# z(Zj3aiVK6n(+Y>JKHpYezEt5b_v0-Ywu==GOV%u??6_IsaJ}sA8TS_z4*t_L8Z{Uy z9dsNS6`rY9I?NL&XYGiR*WU0va@w)*nFe4sng&6^y} zvPFAkg~Qp$sjnxRRyasUJwKT0UEz>fy!wZ=SA~Q8`ynN+{ z`#^WTbo~2nk`$(SN82U#8ZuWpFvm18X&tX{Xktv=v*>(8d%R zl@9A(eC14(sC2mK{JPRas?y=^pIets18H>kuzaxU^!{Jrpb>9l9w<=hAap&{XfIG* z@#9lYQ{*ch65@3CW++xV2q%l2N(9pG-Aw*RfZ_#>*S4g{Vwxv4*L}s7Ulk52D(64V z;;VG{xPF4u6rgzrcR61bQ>b*<{!XC(HP9R-gPl9)1L^H}9F@aYG%#Eih)L%kVFa4vcQn-j zi+Km%FAZ$~#>eV{j7z;AD;$D&E_iJK(mLC#3;MrTI0W4FeWDF?kKfC59$jE~{_wV6 aoW@`2u$tjR3XwNILoP004rUN1pAo>WDZidoqo8N)uqgrpB0;wnDK=Hr% z7u2W3+ihC)GW8RXo+vJt4x;Zv>1j~Is>9<^|L2 z%l|{|b}rjJmxUqB?#HB5Fs(NkLjQvC`S*au#rrG2fz%T+_o~(0qQ+?!b}x)hnoR=I i%zHMOf@nJ^4dXL>I0lxV7yn8Nq@Iwu)RHd%<~aaaM$gv( literal 888 zcmXS5W}q8jwD=nq7w%=}!7KJ7Ior!lo9RJ)I*=9*c@L&bcp!X_&n3S=@&%E{jq-r% z2|19X=b*r)ns~c?S-*d+ni6lfA=%MjJ&=BQG8jyo&WG^zr|e@~4HUnf={EBgP(2}Y z-ygeY<&d0VXC9uTx3)CH?hJ2f-Uc8o9nlP?4g4Yetg03>kh~wust4{s^@Plg;VzwN8-yOdl299H4qa=Gq)S{=Vfys9iwK*7oBJ zVRi+dH%6QS(kTb_f$0+ho51ud?Ppye`HNOF6T5)w37N}P`KZ^l!@_QIWa|Z^Sr&Hh oQfEIl1=20cSAyx}EC~NRQ{_dF{8{$2E@hy4LgrFSz5tl#0K`AZumAu6 diff --git a/test/beta_plane_gyre_red_grav/good-output/av.u.0000008001 b/test/beta_plane_gyre_red_grav/good-output/av.u.0000008001 index 6614796e4a08afa274fef49c37a742fa451a716c..4865b64a24a333b16b0f8684bd4cc39dcc59ae48 100644 GIT binary patch literal 888 zcmXS5W}q9`vc75mI-v#oUH?4i*Zwwl|HCRHwYTZB_aAcA3RF8aV?TfFyh<(Zsr%pF zx&F4Xtbf0O*Uy^|zBlYAM!#x!ljOCuHt)Gu}nn+0*Rz&;FnkEI-x$#;Vo)Jx!DB z-6AjTjb1vzUWMq}jdpI|8TQ=XCD1ufOQ@OJsSsy>VuriUUWx{gRz0Is9s>37V@a$!D=Eu-V>4 zKC9q?cCGzx$H=w}(FXgUhfjA-Pi?dh+OYWF#@&tfeeSbvZjNcNS9Q+>+bHKQi1#9xOc=nXmH=JzC*fiqn*wEJv)uA9z3OQzpZ!TvC~Px_9rhs zp4Go3oS?b6RYt3yaOUn$R`7|~dNOc-Q%9Pi(mluhXB4g-sIxQQzt8nZ`Y$$d`vv!| z+0JhBvM<`;eBl;nC_!_lu@&k3W}Uh}8;x_;Q delta 495 zcmV8aAUGI$)Zxi9i$7)g8 zlRpJYNt)ErkUz{pkjqW^ia%Gk^7n>FgFpT@sSSJ_b3c(0AUHLrwVfj^NE zAUL#QMe8&=bU#PA^9@^0eLr1{=b)qjfIq!$MfKtQe?N9he(YQ`d_SBvZb%t^bUzIM zQ*`X!V?U7*AUNS5!Qr2zlD{qSO6+A)oxi7VzM|g~oxj&J$lKy6n7>!4S%xk(lE3yN z&XC@`hreO-2fka)bia`iAUKI0QhLhwmcN$z1*eLAp}&@@#=8oLp}$|derF12p1-p3 lt>5)Mn7`g!v#vwjkiR|8hF=sFfWMOw17ndO1q5&d000p%@a6yj diff --git a/test/beta_plane_gyre_red_grav/good-output/av.v.0000000001 b/test/beta_plane_gyre_red_grav/good-output/av.v.0000000001 index 3e87eea7896fab3ecb194ec6cda7e9439d3dcbf3..41ce1b046f64efb7a10cdd57dba9efebd8ab111c 100644 GIT binary patch literal 888 zcmXS5W*9QSC_b(%sPFk+p_cq?gF9dLif?=269S|kUuX42rti&u2^MGmlK%vxj`e5b z_Xh`_??w0MhVCMn1MhzBJ(}`c;pYpseSWRa7s$P2+b8*ueIYWv%km{yd|fTiZjd^j z+Wk`(vHij@uT}Yt@bXxeeGKwfHW&R6+?S^IO1%$Ar|x6cK&CyOzXpp>^i#Gk2Fi!N z(Q&(*4Ah4PPA>Q`Bl7~szJn8X9RKq`bYH+4Zfog>qWiL*Xra*mUh{(aTT-Uv{{^a> zCy`R^c8&wXyrUgvjw+AX_m%GWzOvu_TFXXY(b_!-!ifT@ePk_E}MS) z%ijBW=dD(Bz1fTI(Va1NrH7|~-^+00!H2jfZ2LB~Z=U-91>3$1bH2yObkO3CX&}CZ z{?niLfa?04i<|b^{lPHL+UA<#-EGYKuFf!S`twO}U&STsFIC?J_f0&?Y*>v%_i&4U z1&Kdj8NEaPv*14U3+(o>Z&>!ByD!VUB vzD=|K?VZ2#;#XvP@=V8m5I<7!gjDMkpt_(2{nN4UFyaF}JO>NE0GQ_h%4_$` diff --git a/test/beta_plane_gyre_red_grav/good-output/av.v.0000008001 b/test/beta_plane_gyre_red_grav/good-output/av.v.0000008001 index 25498c48fddf0eeaa1158b200ed19a055bc3bc07..aa82ba4f0d6458b751b13fc39f4f6dc369b8bd1f 100644 GIT binary patch literal 888 zcmXS5W*9QSP1AbSud4O-%ktJuZmuog|DSh*TU~PX{%dQ39lKa+_8)(_-|Ayk(|#uA znJSKD9s9dvJKUBp@82JEj@5Ca%%uJ39?d%)lT&QB(tcU%;<%6NdiU=?7;SC-s&oI& z)IDBbs~h)QUh}k9%52y!*kX_F-_4eVjQcHC?SHkWU#T|K#D44BJX3*rrTbIW z+IAeUDcx`4G-vhFTdDhh+WO@=IH%aF&iA>arPXfVv6sJn`ROSb<~fEha=ko%<^ENl zqPVu5s<1Df{9o$T+wA@F`9)8D7iRCzba(h&=^eK}jcJQ*x^a^IuRAM^z7@3F8@T>n z8elmc!#ue^Zg*}OF5Mq=*Qtb|I?sN?g#4}Ea}xH;PPmnk{3Lk4N7IBO<-At=8}0;2 j?~zKi{~GvadLUc7z0qRnRO6(X80Mk-f3WZifO!r8f>`31 literal 888 zcmXS5W*9P{`Sq{)Y^_u5-+i3V%rU*qe(zr?&2@i6?Q5;0&wRDY+RrOx6FYlV>Hf*9 zi~ip=soB51?$q3x1&#aLBu_uCF>KtA?$Ik&dvlj5%(uVfGb4B6fQ(H02Qz-Lt6TG@)zxgp< zABBU{_Me}&-EqYtG5dKht}guiqsd-talgiGu?~Cx#R@4`qr2_Xt)(_PeCxAs3%pz; z(bk1w-iHM;KCXYJ?Y~|;*ZrqR$9~;=a$%ECNbg_2Vt32M&LaD1AM3;`CRW&oy}QN6 iQ(tQzX&s)sbZMjgS$4kz%cL7H%tQD8VBr@4^Be%3Cf$et diff --git a/test/beta_plane_gyre_red_grav/good-output/snap.h.0000000001 b/test/beta_plane_gyre_red_grav/good-output/snap.h.0000000001 index 083ce22f338dbb26f706447ebab0a88e4af67d22..e86dbd0ccb432e736740faf57d4429b108b5cf85 100644 GIT binary patch literal 808 zcmY#jW`Kf92MB|DH2bdG5B~kHaBzrS$;7}=>G1f@8Zi9?jeZ8@zYEy_mOpq$S(y>2 z9^E}3d29Xu0?oU#O$q4gN{8S@T3|X1jgElwo$`&q@_N6VwlZNc@7)RUE5Cu}Jymgr zs4MXU)5d7DIh230E)p#7r*O}J1&euar#F;?ciiE{Tq#DI0O-IV3`Y+pQ*&U9-DbwF{Sl?faYvZ zQ~3)rZ^IW&Fueth-VWv4N9cp)b5DBKFk|s=;gea?p!hv_j{OhFye+di!SpsXdIyw$ zAf6j6Z#cL39=7;h`lGW9WX{_-VX(Rb%-HFJQ1KnBg}~};9A`9x!W%ukP>ZhsjCBBp CRS4t& literal 808 zcmY#jW`Kf92MB|DbXEEOykGw-95}j8OE550I!LZLC|_Pf=*Fg7b4?)%(}7sq1W?kj$k?|}N*8n)a8ne*rP^2Z>$@hd9rsk8zt{`LFJ zmmvAIw%OH`taFTI)ul^-tG3TbZC|TQ#3E8 z(jh5yWt?_Gr9(qs7U!yvN{2qH@(d9lOn3Ntq({t_uXO1DVP7mCTj?Om&)51TqtfA> zT7a8mTBSqL>7MzG(UlG_oyso13a@n78fM5`6j|x8C3RU~Gmww&ziypKzQ4aK9K4%2 zb6%=dI=m6k<(Oqq>F~q;cW$paP`$^8(@!ia9XvxHefM*%bZ`(enCux=>0rV*NyZ0g zAG&$hAC+e@M_($V;VDw%=dBP$!IV2Ej6+@5=rwx6$XIDPH6%lQKp4l@$?1(NqvIQ;z;+q!vcg~Q2B z<@qLSD;$zCDvx+5;qJg$jo^Iy3yIsAHNJ^G}}PHqe~PHz##`mQ^@RY5!{7 z4AlSb=KsfMf#zkMPBYuKy~2SZ_=!pKHek4XI6aO11d#tosmTu*kLdp0IWMh}cRKvF!a*oL?yM|O-yETpe>GSu e9n8*0ZDC`tbeK??D4XSsX&$l2m^9TSb3I99* literal 808 zcmY#jW`Kf92MB|D^m^^v^B(-JaJa}cafU2&r30s}h4w~{N{6&cUL`x8N{26sJjOYE zl@6BY|6aY!U+M5~+rP{Xfl7za+uFJHKpNdWa%cRny!>0?u#~U%TqIDR_tqc}E{RHq zHw)eyD#%ni9A#2k`WHwST==v6j&!BN;c)QjeKmKsN(cWdW^)99_N)kR_T3{?=@4AK zZe724rNa%r{I_{Pccc5a#7y~D>az-m=v=p?6W1#o{;qg)QtVoVgAunK=gs>S4i5{K zCT@6J;c&U`&*NEtDjcRROxdOl4A%f-uT{xF|D&77wD#E6=EoHdfnD(iGDj*LVtCAN z-rZf{&~w}2M$xefhdrsbPXcdLIBufIJ1}qQ1)x9o cTHTtpQ>@bA@bdqfJ;3-ucOSL*3cx%90C6t^NdN!< diff --git a/test/beta_plane_gyre_red_grav/good-output/snap.h.0000004001 b/test/beta_plane_gyre_red_grav/good-output/snap.h.0000004001 index 9c86635cb8b4cb5a9c7816e1ae73d43090d49fd1..3bed314d53cadfbeb5fe6cc6e2d2444772f6f2de 100644 GIT binary patch literal 808 zcmY#jW`Kf92MB|D^wn6cT?;BI9iA=vW%Yl4rNgiO=WFx0f!ibV%Th+LE-g z(t$m-w0GIeN(X`3D=ij{l@4LdPn#1mFx_D}XVO8pj!FlcwR4>3U8;0A%l+A}`dFpI z$x?&#&I6SWhVDvF#rIV@q%!x;J-@ZmfyLPIvD(~9hiyycEfjMx&HLj$?c+PmN{7&0 zyMMFARXW^xWf{{NQ|VCK$S}7rzS7}p{QR|-f%J;tikF8oD;;8==q>wGR_Rdr&-TaN zLQM0TK1_ca{iL^V$FVBmo8N}JhzGZboY9N!=lHBxI`aRIK)IRUnTId z!r^?Z)#iV~l@5X~J?q1rFwK*lU$kS@_6mn2!H9}Oi4_hu0#QDaSrraC7T?ZKt*CJ5 z^DKRPucyMn-t21q)5R4I3*2tST>#qWRk~04pa!OSi$0s&TerKyVb?mICtu7f9O5oN z2*|Ria7c_Rp7&N8=q{t|Reb6d4pNJp?@YI@aQNoDHT73(g~PKKCok*qVw$&7=b_%; z`4tWm-ZvLo>s2`1-?-q_J+BIfy6KIQYXd7Bsyx)2tAZ;We)BxxP>HK>2zZm;w_`$u zgJ{9LmrJ-X&C{qlw#QYz(!qLOY?0iV3I{{&8SVP}DjYW5EtV@gTj8Ll@;2wejS7bz juA`qtu2nclTz(L7{C$Ok@bn7D`-Yh2Q7b(w0P_d{+yf4V literal 808 zcmY#jW`Kf92MB|DG)u|*^{)Ra9JcmNZQI3G>5x-0LF7DdrNh>a3YU*Ul@8K5jIVc# zRXPYyu+>eItaMOFIsM|ERHcK8*U}pX(wOeJCH_oHm!Z-jK56djJ3#$BOEPMOWoy{xrdYx+VRhNBqFWUXvkq$tiR`R!h+^B)@M2?y1FMyh zA>)Ax2f4|g{)%3$a45Xx_B8c%g~R5bM^6Sz ZHUq=4Y45wEva*=&LyvEA`3k^10syOc`fUIJ diff --git a/test/beta_plane_gyre_red_grav/good-output/snap.h.0000006001 b/test/beta_plane_gyre_red_grav/good-output/snap.h.0000006001 index b1ec13c2524399d2395f3d3cd92d733124f93068..158b9a11bc5ee13d88e427697c93d4f2d31fb000 100644 GIT binary patch literal 808 zcmY#jW`Kf92MB|D^ko~_H~teV9e(h%b??4Z>EK!?f7R(+rGw$E`sbn-Dji~^r8^X_ zRyqhsWSI7!taNaEG;KoG`bvk%MgnX5Ctjkt8~~Nn7@}{4W@bT>h%>K$5uMr z4z=}GSzGCFI)3^d=Bbqq-C93?+VodCEd9PCySum2;d{gD8F4^=Xgk?>C`_w#sNh(89!~i4r=`NdXrJ_=4Noc@^uzpeSyD00OD}x$p)wR`o?ma9;lXl;*#};q zcllQC@H6QBjP)PN9VW1y(q(*E?r_5PZ7UaVg+uTCcdw)CDjaOh(mwN>Vw!iP|B3CT z>Iw&A`)~K(ohWyxn5>oEc(>eP`6K38OKy}q7+v;M4trnjAmcMZG*zm?A>H@ww&i6N z4$V7WSUPKCnm29!G-vA{6%H30ZkPO@QQ@%E@y_9EM=KosRvQJ}x?kZSoiHeqaOBPq9gL1X&;*2Ux^Qe`c6@YmJ0H4|pmjD0& literal 808 zcmY#jW`Kf92MB|Dbcw=qlbsBe4t5b|UdVD*I`Hg_G-ed2bU0F0p>bZM(jkc3XSKaV zrNd9Ns}k#^Djh5xmbr+@R66J?Ong%Sq|x1TPEr0;HdCcT*I!eWe?a}_Ym-{u$yYku zPqFr~RjG8~)VRHZU$xR<>X(jCRv>>`pUBpQij@vdJ;J}P%3+!}>%VQx|34KDUv-u$ z^9xrx{ONAu`~o!ZZaR{z``@`TuXS0o|W`{LNo& zp#Q_?805df;@`u3N0=@>tZ?|QuGt@Pslp*3H@nUEVui!hid!)U?^HNk*j=Hs{dI-I zx7}Zs_5G@FFw(o4QvkHb$7OB9XK_sT1+Sjwl?K$O&9babY*&SYhSH`p8k;H{CgiJ! z_3p25P%}@McKmXM!_(Vq_VT~1aA24(X!HGFg+uwwHEb(@;e+nqlR7t3s-9IiR4@Br z>V3SzL3!rCxk(2q944*KjA}St;b6JD&^8%ppM*W@(W-Y94qN0u2&4eRV_G0jmKGNC zB6ph~fBvJwVUfJoewOzY4h;e;B*TI9E}qN265lEuT(T#9?gY9=Yh$4*AA6-kPkpgr Y4KO_Setw+&QVi35=&=0Ba@tg#Z8m diff --git a/test/beta_plane_gyre_red_grav/good-output/snap.h.0000008001 b/test/beta_plane_gyre_red_grav/good-output/snap.h.0000008001 index 620a31221bb0572b7eaebb8c035796d4f577d848..8d978e05221cfd26e1ae46b8db598395d55366d8 100644 GIT binary patch literal 808 zcmY#jW`Kf92MB|DbjPk5le#;V4!XrX^{O&e4%4sP3vl4CaxiF5I($l~%3;S$$1OHI zRSu^uRjg$`S2|?nZVvf$ywV~2`SV+c*I>G1=GK1~iL~m?H5)#eBbxxxK&P- z!z=F}Q~ScJ9H!Mi&|B_M<-ojSg=nsPm4oy~rk6WDR64YBy$IfT7}LCr-7GN=W>q>o z4qN;5%9l!qBYbB0wtFfaegv&3j@w@8kavYg{r%obhv!Sbo;bO`(m}-k0n?S8l@2ko zY;E^fVVbw0%zeU?(-jUsrZs(Gn^57P8Ir$ObxwuD#S67d{SQ<)9ONt9x#4YvL(7HA z?IBu~4w6ddN;bKb4llZUE-smiX`XkG!p0K63J0fCiF#(U%N-)!zdoCFz1-nhk3spN zkL3SoyTZXzJoEh41r-hjkzOU8!IpHZ6;Tdku)UCr)>F~ME>g|S1O!KIfo)v(31ORyl3PAt> literal 808 zcmY#jW`Kf92MB|DbY)_jaqRyJ2i_$UdAGAyI^={rV(jOubm&z+v^GY#(t)d7b^8sm zN(V)by~$ycl@1p=m?BR}RXPMb|K^}Ajp>fr{If0=FjhLOlmEf`AE^K2VzFb7Eh4!bY;s;&XLS1$JJHZ#sj2fxZAfhzo!4vimfU7HVdzl`KQ zf%W2*4j-q!V$GDnG;cb8hs*y*6%L25sBG}NT;Z@w_qYnfr3!}&TJ04YcPku9j#WIm z_PWA>p~Cc4*{=$Rmv8{)Kg7-+3VY-?^n9MBBSSXa*>KMJg36ZR5#SaOT`A!3>CuHu`M3=?kUybdxEYDTX1Jb9qUIWv=q4XIjJyY)z zSiIsXi%tYk9U*hWuO}?MQmtx#(SfsxrAF1h&2VcYh~5pQJD~LCWf1v2TQ~g!sV8J^ zN%z~#UrZeK+p8N+axrt*&+aZb0iv%$X&67jtqv@o@bHB)NIfBQ(d5bHHWUE!901w2 B)JFgS literal 888 zcmXS5W`KbP7=ubQ%sd#)u+ihQLeNf0`yU;y3+|thw3j>dKgv?zj zqIv0Ij;ei{b^EPDHLCWzkI$WT6i7dEUj?RebyR=JN}W3j5Bw6^oxA zsIf2S;as{$t=3*}T9wxB-F5cj?9Q^SH!AHVbU!(4J(FP%(+{OF%>AhG;j=SijlI3w z%r(=_HQ8G;d#+k))n+gEJ0*XPaHsvEO^y9wtK04Uz8y+)(rdEc{<&Qz<#8cFbI<0? z4y-k4v}b#w4YU~wy=0~em*4z7j$XQeIy4t=-zh`sEfol8t2Y0>K zwl5`UuC*3t*eQ!T`~951>#v`wwU=zsef?0q!Tzfo<1d>nE%q~vxMRJhx7sHkpU-Th z+F`%`xif#q{APmYD#$afxv!hC|BtQw(Ke@w{ikpJy;S(Me1D1lCGQrEqW!-ND*AFJ z6zxwFdGk7dL(cx$YGtK!J%jcW3g7FeicYji1lT7ro#QOlkGFqacd|6E%hldaB%_<( z$7%mVuYGn;=LPQnI{*9fYUSwtzt45w>HHr+$lQh>pM&khz7_4iP^4~dyUxR&Kb+^} zK7`DLc?XtG(D^WNTr^yL I0Wi-209d=|x&QzG delta 512 zcmV+b0{{K^2KWY$8dFVOG!0nd4<0x3=MOrqjSHJ{2(`eNr(wg z(u_ZxB@6CF(v?3|7l7y%oj>786`)~Yr$4?D&7)vYs6WWqk8_Gjr9W2Wm+KO)pg&31;EqQ}mOo6H z__{IegOU3oHx8irny_1$KhQ?%jZ#~rKegWtHRyAtKb+pdO$I8XKkhaa-^hWUKRP&Q z@cw_4KaZmz85mH4k^3Pyd&BpLMaOhMjppMV7Xg1iu#EWM_OyXN^iqf8`%r>E(vTs2 z)@^`4m^2GMsv5#pw`XpLq+kxU>sxfw&@xWtmbDE9aOr`PVaLPuZ8hLqii3Hz=aNs9`Pc z;9H`NBVqsayspaqJ5Jv@bZuez{_Qd5 zye(Ea`!Bp=Fy*?Dxc|cnZ&S^M{`(1pZ^P!)ScQ%MZ0xJ@FTT{ah_|0tmKAvZM23Cb zo_x=pPPO(8=N~KXX=<`RA$L4Y?tg{7ko=#Yzt?3GbZ^ayivotXrtc3~AETA@zHR^i z#*>+43!C?67oTFR=$yPid*P>?yS>x)UkpiU+i`pH{`6(nuYXw6MaaD{?=(Oeq|$Kx I1;9K905Z_@7ytkO delta 494 zcmVILoa^l|MwP{AGE{kw2d;9zggnj6ZVg-@a7*gFi-KkBS$UbCLTYH=pHZ zWp!GhKj(>jfgnh#KPwfmDe1zhKd^jxb9$ksKZFpSn}jBzKU+qEewTTcKL#5GHOCf& zk^3Px6}2WD8s?lo{TOih^fsqI6@|KWlH#X7izcQqWO}4O&08F5t2m!O``Bky#8Q+$ zJ)mLeG3SAi`yn?Nx&%j1y^ll)vhihEC0Ipuddh{5*{wpua#Pbp|7Bn!nhs zM9${3lfN3yfBBSziN9U&LBuP_n7=rJ9pd@!qQBT^BU3TgqQ3@) k`}h?ypuepO7wX=$nZLlhV}Og^k-tilbTZo^fs+dZZH0#X@&Et; diff --git a/test/beta_plane_gyre_red_grav/good-output/snap.u.0000006001 b/test/beta_plane_gyre_red_grav/good-output/snap.u.0000006001 index 950a75fdbdc7d035dfbd4fc0730147ef1f0bd5df..aad9cf1980084e260313f2bf2487c897285fee0b 100644 GIT binary patch literal 888 zcmXS5W`KbP7=ubQ%se z>l&`lu~%34yh&}sRQschjQ1A3m}I|U`f+P6(JA(pmWJtk2~+L6v4K+tG&o|&09zBmf8QlKWC%0V~zc+(qG%3Pj0Zkkp1e)))fu*vw!XF zm-$*_-ySyg+M|bggv@R5S<10%lBD_mc4xWoQjJ;rI}awFUz!%ZpWo7L{*Rpz_9-1j zv46Kl+IPH`kF71%*v}=$Q{l5QXg`7QZFt2W`kt?=ZhtPrVmDLW!2Je39p3MQa_yhi zUF_|=TVbE{Ui-rm`AYlyllO?OtgW(tHpM@quey|=dv$Z-`)kh5*uPSOYpY7>l>L`q zZ+Uw_a^8Mf=?0?`h6Vd~&8}WQ?c~h;zkJq4*zK9V|H`YU4Tno65pplgI}K08YmcNOn@(4Scp}(B=oMX5oqQ66C z-)7(jpufI*?Nno|nZF;Wna_>qk-w$F?oK&TfxnUbAUIzPFig1@smm3QFOZNHPO0UOFj8o$KLR60Saiv%KW=T#(_@LIKa7V|kRSn}KUqT3-XxyGZpv%$x`VEvn zJI+qQ^`n82`yn^L?U7hn9Ckl@DRnnLxPLz`jS3rT5P?4mbh#R0%78zaam04)|9n3? z^XuLQhjc%NFR>JiOkFm017ht=-1`zU5b2U)HSNziIEUZHGiw?C(_0jL$4zyuW{% z$&Iv@+51D?moG_Tn|!=+^g;rmkq9!)uK7-+w1>b9ke z_T|}U9o>2Fka&^3#g>ZwpB*y^nrmYD$GmYz#r|UzlIPakOt;_Ioc3z}iY)t^ue2r0 z{)O9fh4w_0UrMu2Rl51;C{wY$!`uDqrf(=FXzrg~1>B5`EB2rNbG2SQZt?yftDo*l znzLYk)GPjP8ZT$;*HHbHE;@JGeuk-0#Sd1`*njy@ysgW%?)?PP15COB${>}7>n{N2 FIRFnI@}B?z delta 502 zcmV35_lE2*bpBEIBfs+dZAvezgM6w)PiNAiEc%WIfmA~ZR zv`O1mm%nt^=bwE>l)oh>+x7BLj=!Wfq!8oNg1_}PD{zdCZj%cGAvmTTf+7FzjX&2u zTz$3?mOmEiVT|AU8+Cs5EZ!NKXgnWHFc$QKW;&p(;a?eKa>AUH#QqZ)gAmA}lj7h22GpuhJeor?!>puYvY zB#NlMn!h4|ri5jX9>rnZHXM)YW`nqrXDB sa}*9Aqrd67H=~sZXz~kd6blHs6V1C4_Z*|*&@>~b% zuM}9`z%XxuV2~B@@>v?UUsu{*t9QY)-tQy*dzObyaMiAO+2!1*ZB_$*O2Io zEBAuM+s?R16vZ9c=Qb(NGvog5eNYF$&Fg(u_rQef_`VO5thcj7U)$FbWH_TU{@Om7 zN4p;*({=fbGeLaW3!DcUf$DzsrwF=EJ&j@BB{S~NlN~Pab4XU3?$!QqUuSlc(3Y-; z`#!9@>x)dgH%179_-~pyf8_wxxh?GFznpgk!#ugVuUF-wZ|rNYHN2A?_H^Gl@7Edm zQBU`sGBMwXOpBlUn+f92D(e!D0jj(5byoC(PuDTb^Im>4X}!vgeM&dGABDF)**EL^ zuCFRxPxiS98C$C&(RH13zJbL34`=&n0@d*fr>$rWyoO=kT`P^UHs4G8o-u#PmC(4i zZ(YNuf)3q#`)($mxQ0xtyuDBe;!i6pUo=(y-o6Wt6KZo-p2sk+?-cVAncs)@Ej#<` z-HW?t_pRDc6EF1m>^|4?d`FP!U;NL&;u8zh|8N4;y$VRqnX!B?hI!;BI5d6m^a2&9 Jm|p@SAcSo`|?e}i;GMaa(X1{);+Y^~PCHsSyhTm1TF5X|zHnI2Fx#Im#q~pR4vDILh zr$1$vaRPU#eUQqU_iBe5_VfA4-ka*tvOhcPYqytZhI0 zZKFHUHdXrtEu*?KYXi{DYxpSJBk}A*%l*yV->BMFgMZOvbd@+=VQ8k^qe2MArq49 zweJ7demznoekXo-B`~-kh#p>z2kdP&epl;?nCoFLjzO*Mx)CU;=}Y&Ocwz2 F8~`QwdPQfvkMy9^~UAnJ! zExyo&VcyTGuj2a?CfMJd5kK{ef4hC)ZLQAiEk*WSCp1gXPBz^C$UNA*bbG=6``=b> zczL3Be@BGL&Ls8b{ncLgmcHw4KsT@9r08YVI}Elaxi|mayEiJgZCEMO+#pS6-bkgmAYG&6m{7STk2ONaaaMg9Hng+|_ z{Xf;~UfhkEx<4}~qx*}cmHpNq3cEM$YqnPm@D*&E(qX?oHsOugye|7k+`BjLTH0fO zY}@MdoeSGB%zLfBDfU;*(*2R|58aknIeq_AbM3l@qmKLA?%w3*U}?5LW*{9rpRdc_ zrqHy;dRL$Q5<`gs^|Xoh1qoblRxRkoFt5QaD=$i`CRl>u;qT~ z-T!qaJ}RrbYYo~&OCWA`7ZIF)I-Du2Iu>D6Uz#%cSL z19fUvI27)W(&J$4&8XSG_w>#4pKCk!-wHH2wl{Oiel-6vY|(#edFSpj`?*DuLHy1g z`@hL^*F_ig?%y@ZPVOpm`~KILCVsG8(X#)r?W@e_;I{n>5*)55{_EQR?D;vnpK=q? z&1>ksw|@1sKUw=#w|-nXYx0!+fw~8T+$&jWV*%6k(W`eMMFM&7_6T}-6EnwNmkxV)z(E)dkG`?Yu)nfme@J`9 z<~>U??D_Y2KQeopXZWn^W4ZmV`?3s8 zhZ^mV33#kX>Y8Mq7H(2sRyYsCymQQ|v%eo$vOih#(sBDBxBZ`wO#dwNw{-u%t=rQ0 z9_H=eYTqEgp(10yeOQmVpH1@qk{k0_FNjyz7ivUXHs?%1HxJGG6muJ(CQwWl0P`FG D&>Qz9 literal 888 zcmXS5W`KbPD1%xw%v^MuRP*8b^M8CQ-G6zSeSfFr`s*Q`_KH7$&gj|`Y~NPH_VV!2 zg8ff_*Q1Kg!>(Jg%$XFH-jI zSGq;>{^H#i_fA~jykEN7VOv099lCi9%fATBklE0_zvT>X?D@Eo{T8cyllDExu%9_4 zYueXXV{Autl-kylxRPb`ADNWORBy7{N!U!9VzzkfP*j^y0csk>)J2b z-}dpyo21HV`#*^2A6Ypk*1qGbjYS!AyM3Yj%nAMdo%Yj>PRS%|blI;BY>y}q?6I%> z+IsFrSUZM!9cSO`+y7p+-`+QO!a#!a|Kg{$HzwHE%sFt!v9SlkJf22n)ulIQ>|Y}0nvwFabAMH0=bwO|Huk@s zD)NS}FSD;L$zXaNS7SfH_}3ri#0LAbJ2NkfNi^HP-R>zPl-h`H9?bjj_=X9PNyE&c Jm@WY3IRFFv^x^;j diff --git a/test/beta_plane_gyre_red_grav/good-output/snap.v.0000006001 b/test/beta_plane_gyre_red_grav/good-output/snap.v.0000006001 index 86222fdd0ea33034e7312d5630ab2220f411b364..6f561580b7b457fa720c04306ab3a28ba0a5062b 100644 GIT binary patch literal 888 zcmXS5W`KbPD1%xwwakT?!{8p|{`m2-9rpRxD&sHyYTEC9O8bXGZ~gv^mBqF~ZYBE_ zRx|ikgx2ntGW_qe!>Dur7n59*SH+X|mmiv3`u_Tq{b>GUSkA-n^tkm_`vqKES`3y< z+<)(3_C&RS&i!JSDp%+`m+u$27=3;2{)YXxPUfcnDDB$6-RX^3U*v@SyQW{zQ}&sN zVcxO5H<&qRG}_G#+J0d!C|{Vx#k@^%@iM(bd4nY z8((=deofD{f6SmhFMX1qJ=~)ZM#H4{W!cfC%l2PnU&(CxIAVX;2j%#l<+=N>KI`e; zx}$1;);9~C6W5FOzpYIaQs|1cpTM)F>S<$>y@vJr%Wc|i80JYboL#$V-Io26*Z#kd zR-b9Vd{dg#CezXUC@QPcU5c8E zli%*0GGnTJk%_HS?4wlsldFCN@VeISudMw0PF1me|NUvT+ak=m_b+j8KEZ#lcmILY zi;u-hc4C;f_MCvstzL{o6oL=_WALL(l{hCysy|wet=P|N*`&B;iST#?r-*2+0 zXUcK&=KWbZ>K9)9Y~F7(ORYrPupZsKhRIKx-yPi1v42XOWI)uO(*1w?q@Jz4nr^=! z#m!1)Pm#UQ*(ZCPFK5^Ie^gxepx z>_6C^K2W`<6~ny0B}v8_G0XQqW-{I?v%h$kmFuW%jeW+En>8Uf>+LtB{andm-ejNH6O(9ju^!z#H1AW)ZGf6U JF)t_a)^Y*j6m??IfqkjL7$%bqXp4RQZ z-O$FgHoa%R!{U2lmtIZYzt%!`{hxQ!_D@%k*r4}$(tb4mF>Kq{$FIw_&ptQ0YDV;# zMf)Fpjo`?gJ#GKGS$l&{OSbO6e$9xz*uQIk*oo6I-KG=wo0x?BR7jt^KhIQnS(wH| z4D%9>%d`LZ)M>9FP@0+6ICKAW?h4kko7?w`sR`wXhS%+96$w~gP}Haf6mu9gy? zlwb~@L0Np$^?^DcefSN!tT>#8; E09p$2`~Uy| literal 888 zcmXS5W`KbPD1%xw%v=~vuDLM%3^OOB88ly;W-mG?Ooqq3(|()I52onMAo~mNk54kX zS+GB=G)PW-O6C4A?Pp;uCiVNjG6p+4Pi@-2>`Q{6MpNT{s6jAyFysqm@M#`eXn(|| z>%q*mQ|*68tyNYJNwfDU$n&4bQM*6#pyq78Uv2xB=C<-q;OO4pyOpKo-qzmz8|O!6 zhl_P$n0IJu*5}~%Dfa7SErfW5dhKUTXUY08DbGHG<$QzdjNJXgV(tQOt?Kv3-p%~u z@~>$>!&>d6!~@OygCoOttFYIjo7a#cb@_qh>5l!HPiDlIOfB6Xr>3{{k5z`fHFJ;EEqUlxap$9psFCp>;W_t@z~`#VgQlgxCJ?JrbY@M&ly+QS15!f2>>yJqCEbIJaa zC;zwhew?=dv$k-~`TMc<5r+(-)3V#`*^jQg;(fW(eo55Z9P2Ng_Wlc2+)^~_w&w_U z2~~aFiecVPmZ>qewafSGE_mG=8$WaZG{(u9J|Bba?_PL(cInb~`(vxGFXI#Ju`iol z8mq0@XaDAw&J&4{3HBVj9S_bp(S>2&EOyTKRZTPZdt^?j(XZ^lM$ F0{{m^;AQ{- From dbdabd2b49810d923a346385efaa34e924cf56c8 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Tue, 18 Apr 2017 22:16:23 -0400 Subject: [PATCH 40/50] Document the Aronnax driver functions. --- aronnax/driver.py | 50 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/aronnax/driver.py b/aronnax/driver.py index 50aad9f5..c34f68ed 100644 --- a/aronnax/driver.py +++ b/aronnax/driver.py @@ -12,6 +12,40 @@ root_path = p.dirname(self_path) def simulate(work_dir=".", config_path="aronnax.conf", **options): + """Main entry point for running an Aronnax simulation. + + A simulation occurs in the working directory given by the + `work_dir` parameter, which defaults to the current directory when + `simulate` is invoked. The default arrangement of the working + directory is as follows: + - aronnax.conf - configuration file for that run + - aronnax-merged.conf - file to save effective configuration, including + effects of options passed to `simulate` + - parameters.in - relevant portions of aronnax-merged.conf in Fortran + namelist format + - input/ - subdirectory where Aronnax will save input field files + in Fortran raw array format + - output/ - subdirectory where Aronnax will save output field files + in Fortran raw array format + + The process for a simulation is to + 1. Compute the configuration + 2. Recompile the Fortran core if necessary + 3. Save the computed configuration in aronnax-merged.conf + 4. Write raw-format input fields into input/ + 5. Write parameters.in + 6. Execute the Fortran core, which writes progress messages + to standard output and raw-format output fields into output/ + + All the simulation parameters can be controlled from the + configuration file aronnax.conf, and additionally can be + overridden by passing them as optional arguments to `simulate`. + + Calling `simulate` directly provides one capability that cannot be + accessed from the configuration file: custom idealized input + generators. + + """ config_file = p.join(work_dir, config_path) config = default_configuration() config.read(config_file) @@ -36,6 +70,9 @@ def simulate(work_dir=".", config_path="aronnax.conf", **options): return core_run_time def default_configuration(): + """Configuration defaults before parsing aronnax.conf. + + The configuration is represented as a ConfigParser.RawConfigParser instance.""" config = par.RawConfigParser() for section in sections: config.add_section(section) @@ -96,6 +133,9 @@ def default_configuration(): } def merge_config(config, options): + """Merge the options given in the `options` dict into the RawConfigParser instance `config`. + + Mutates the given config instance.""" for k, v in options.iteritems(): if k in section_map: section = section_map[k] @@ -108,6 +148,7 @@ def merge_config(config, options): raise Exception("Unrecognized option", k) def compile_core(config): + """Compile the Aronnax core, if needed.""" core_name = config.get("executable", "exe") with working_directory(root_path): sub.check_call(["make", core_name]) @@ -149,6 +190,14 @@ def generate_input_data_files(config): f.write_record(generated_data) def fortran_option_string(section, name, config): + """Convert option values to strings that Fortran namelists will understand correctly. + + Two conversions are of interest: Booleans are rendered as + .TRUE. or .FALSE., and options that are input fields are rendered + as the file names where `generate_input_data_files` has written + those data, or the Fortran empty string `''` if no file is written + (which means the core should use its internal default). + """ if is_file_name_option(name): if config.has_option(section, name): # A file was generated @@ -180,6 +229,7 @@ def generate_parameters_file(config): f.write(' /\n') def run_executable(config): + """Run the compiled Fortran core, possibly in a test or debug regime.""" core_name = config.get("executable", "exe") env = dict(os.environ, GFORTRAN_STDERR_UNIT="17") if config.getboolean("executable", "valgrind") \ From 997816ab887b6deabf0974a4c7faf099751143d5 Mon Sep 17 00:00:00 2001 From: Alexey Radul Date: Tue, 18 Apr 2017 22:25:35 -0400 Subject: [PATCH 41/50] Marginally better documentation of the idealized data generation pipeline. This whole thing looks like something of a mess, but now it should at least be a navigable mess. --- aronnax/core.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/aronnax/core.py b/aronnax/core.py index a64ddac6..10fcceb4 100644 --- a/aronnax/core.py +++ b/aronnax/core.py @@ -193,8 +193,18 @@ def interpret_requested_data(requested_data, shape, config): - TODO A numpy array in memory, whose content will be used as-is, or TODO interpolated; or - - A specifier for auto-generating the required data, in this format: + - A string specifying auto-generation of the required data, in this format: ::arg1,arg2,...argn + + - Python objects specifying auto-generation of the required data. + In this case, `interpret_requested_data` will construct the + appropriate `Grid` instance and pass it, together with the + `requested_data`, to an appropriate meta-generator for the array + shape of the needful datum (determined by the `shape` argument). + The exact API varies with the meta-generator, but they typically + interpret numbers as that constant and functions as an analytic + definition of the field, which is evaluated on appropriate numpy + arrays to produce the needed numerical values. """ grid = Grid(config.getint("grid", "nx"), config.getint("grid", "ny"), config.getfloat("grid", "dx"), config.getfloat("grid", "dy")) From 6150c8227a627b3fc9773d43df2def576358c084 Mon Sep 17 00:00:00 2001 From: Ed Doddridge Date: Wed, 19 Apr 2017 09:52:12 -0400 Subject: [PATCH 42/50] rename Coriolis field generators to include "f" --- aronnax/core.py | 16 ++++++++-------- test/beta_plane_bump/aronnax.conf | 4 ++-- test/beta_plane_bump_red_grav/aronnax.conf | 4 ++-- test/beta_plane_gyre/aronnax.conf | 4 ++-- test/beta_plane_gyre_red_grav/aronnax.conf | 4 ++-- test/f_plane/aronnax.conf | 4 ++-- test/f_plane_red_grav/aronnax.conf | 4 ++-- 7 files changed, 20 insertions(+), 20 deletions(-) diff --git a/aronnax/core.py b/aronnax/core.py index 10fcceb4..e124eaf5 100644 --- a/aronnax/core.py +++ b/aronnax/core.py @@ -123,21 +123,21 @@ def wind_y(grid, func): ### Specific construction helpers -def f_plane_u(grid, coeff): +def f_plane_f_u(grid, coeff): """Define an f-plane approximation to the Coriolis force (u component).""" return np.ones((grid.nx+1, grid.ny), dtype=np.float64) * coeff -def f_plane_v(grid, coeff): +def f_plane_f_v(grid, coeff): """Define an f-plane approximation to the Coriolis force (v component).""" return np.ones((grid.nx, grid.ny+1), dtype=np.float64) * coeff -def beta_plane_u(grid, f0, beta): +def beta_plane_f_u(grid, f0, beta): """Define a beta-plane approximation to the Coriolis force (u component).""" _, Y = np.meshgrid(grid.xp1, grid.y) fu = f0 + Y*beta return fu -def beta_plane_v(grid, f0, beta): +def beta_plane_f_v(grid, f0, beta): """Define a beta-plane approximation to the Coriolis force (v component).""" _, Y = np.meshgrid(grid.x, grid.yp1) fv = f0 + Y*beta @@ -157,10 +157,10 @@ def rectangular_pool(grid): ok_generators = { 'depths': depths, - 'beta_plane_u': beta_plane_u, - 'beta_plane_v': beta_plane_v, - 'f_plane_u': f_plane_u, - 'f_plane_v': f_plane_v, + 'beta_plane_f_u': beta_plane_f_u, + 'beta_plane_f_v': beta_plane_f_v, + 'f_plane_f_u': f_plane_f_u, + 'f_plane_f_v': f_plane_f_v, 'rectangular_pool': rectangular_pool, 'wind_x': wind_x, 'wind_y': wind_y, diff --git a/test/beta_plane_bump/aronnax.conf b/test/beta_plane_bump/aronnax.conf index 647bdb9a..22bb90d8 100644 --- a/test/beta_plane_bump/aronnax.conf +++ b/test/beta_plane_bump/aronnax.conf @@ -46,8 +46,8 @@ ny = 10 layers = 2 dx = 2e4 dy = 2e4 -fUfile = :beta_plane_u:1e-5,2e-11 -fVfile = :beta_plane_v:1e-5,2e-11 +fUfile = :beta_plane_f_u:1e-5,2e-11 +fVfile = :beta_plane_f_v:1e-5,2e-11 wetMaskFile = :rectangular_pool: [external_forcing] diff --git a/test/beta_plane_bump_red_grav/aronnax.conf b/test/beta_plane_bump_red_grav/aronnax.conf index bff350a2..88343d76 100644 --- a/test/beta_plane_bump_red_grav/aronnax.conf +++ b/test/beta_plane_bump_red_grav/aronnax.conf @@ -45,8 +45,8 @@ ny = 10 layers = 1 dx = 2e4 dy = 2e4 -fUfile = :beta_plane_u:1e-5,2e-11 -fVfile = :beta_plane_v:1e-5,2e-11 +fUfile = :beta_plane_f_u:1e-5,2e-11 +fVfile = :beta_plane_f_v:1e-5,2e-11 wetMaskFile = :rectangular_pool: [external_forcing] diff --git a/test/beta_plane_gyre/aronnax.conf b/test/beta_plane_gyre/aronnax.conf index c74e75e0..0150a13c 100644 --- a/test/beta_plane_gyre/aronnax.conf +++ b/test/beta_plane_gyre/aronnax.conf @@ -46,8 +46,8 @@ ny = 10 layers = 2 dx = 2e4 dy = 2e4 -fUfile = :beta_plane_u:1e-5,2e-11 -fVfile = :beta_plane_v:1e-5,2e-11 +fUfile = :beta_plane_f_u:1e-5,2e-11 +fVfile = :beta_plane_f_v:1e-5,2e-11 wetMaskFile = :rectangular_pool: # Inital conditions for h diff --git a/test/beta_plane_gyre_red_grav/aronnax.conf b/test/beta_plane_gyre_red_grav/aronnax.conf index ec8a6b65..7cb6d806 100644 --- a/test/beta_plane_gyre_red_grav/aronnax.conf +++ b/test/beta_plane_gyre_red_grav/aronnax.conf @@ -45,8 +45,8 @@ ny = 10 layers = 1 dx = 2e4 dy = 2e4 -fUfile = :beta_plane_u:1e-5,2e-11 -fVfile = :beta_plane_v:1e-5,2e-11 +fUfile = :beta_plane_f_u:1e-5,2e-11 +fVfile = :beta_plane_f_v:1e-5,2e-11 wetMaskFile = :rectangular_pool: # Inital conditions h diff --git a/test/f_plane/aronnax.conf b/test/f_plane/aronnax.conf index 686b907c..ac46d35e 100644 --- a/test/f_plane/aronnax.conf +++ b/test/f_plane/aronnax.conf @@ -46,8 +46,8 @@ ny = 10 layers = 2 dx = 2e4 dy = 2e4 -fUfile = :f_plane_u:10e-4 -fVfile = :f_plane_v:10e-4 +fUfile = :f_plane_f_u:10e-4 +fVfile = :f_plane_f_v:10e-4 wetMaskFile = :rectangular_pool: # Inital conditions for h diff --git a/test/f_plane_red_grav/aronnax.conf b/test/f_plane_red_grav/aronnax.conf index 399b99e7..e58e04a3 100644 --- a/test/f_plane_red_grav/aronnax.conf +++ b/test/f_plane_red_grav/aronnax.conf @@ -45,8 +45,8 @@ ny = 10 layers = 1 dx = 2e4 dy = 2e4 -fUfile = :f_plane_u:10e-4 -fVfile = :f_plane_v:10e-4 +fUfile = :f_plane_f_u:10e-4 +fVfile = :f_plane_f_v:10e-4 wetMaskFile = :rectangular_pool: # Inital conditions for h From 392d68b53ad609b2f8bcb717321f5d2059085f48 Mon Sep 17 00:00:00 2001 From: Ed Doddridge Date: Wed, 19 Apr 2017 10:17:17 -0400 Subject: [PATCH 43/50] make Travis install package in such a way that the test suite works. This is a work around and needs a better long term fix. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8d7303f6..4bfea1b0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ before_install: - pip install sphinx_rtd_theme - pip install recommonmark - pip install matplotlib - - python setup.py install + - pip install -e . install: From 8456a68386b3e46703813616ff500ecc8132ad1b Mon Sep 17 00:00:00 2001 From: Ed Doddridge Date: Wed, 19 Apr 2017 10:25:17 -0400 Subject: [PATCH 44/50] change Coriolis function names in documentation too. --- docs/input_generation.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/input_generation.rst b/docs/input_generation.rst index 7633c3d0..c392643a 100644 --- a/docs/input_generation.rst +++ b/docs/input_generation.rst @@ -30,12 +30,12 @@ Initial conditions Domain fields =============== -.. autofunction:: aronnax.f_plane_u +.. autofunction:: aronnax.f_plane_f_u -.. autofunction:: aronnax.f_plane_v +.. autofunction:: aronnax.f_plane_f_v -.. autofunction:: aronnax.beta_plane_u +.. autofunction:: aronnax.beta_plane_f_u -.. autofunction:: aronnax.beta_plane_v +.. autofunction:: aronnax.beta_plane_f_v .. autofunction:: aronnax.rectangular_pool From f7dd2a73cd4079ccb0a93a5b372868e97182542d Mon Sep 17 00:00:00 2001 From: Ed Doddridge Date: Wed, 19 Apr 2017 10:26:10 -0400 Subject: [PATCH 45/50] edit Coriolis function docstrings to say u or v location, rather than component - it is a scalar field, not a vector field --- aronnax/core.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/aronnax/core.py b/aronnax/core.py index e124eaf5..039aed94 100644 --- a/aronnax/core.py +++ b/aronnax/core.py @@ -124,21 +124,21 @@ def wind_y(grid, func): ### Specific construction helpers def f_plane_f_u(grid, coeff): - """Define an f-plane approximation to the Coriolis force (u component).""" + """Define an f-plane approximation to the Coriolis force (u location).""" return np.ones((grid.nx+1, grid.ny), dtype=np.float64) * coeff def f_plane_f_v(grid, coeff): - """Define an f-plane approximation to the Coriolis force (v component).""" + """Define an f-plane approximation to the Coriolis force (v location).""" return np.ones((grid.nx, grid.ny+1), dtype=np.float64) * coeff def beta_plane_f_u(grid, f0, beta): - """Define a beta-plane approximation to the Coriolis force (u component).""" + """Define a beta-plane approximation to the Coriolis force (u location).""" _, Y = np.meshgrid(grid.xp1, grid.y) fu = f0 + Y*beta return fu def beta_plane_f_v(grid, f0, beta): - """Define a beta-plane approximation to the Coriolis force (v component).""" + """Define a beta-plane approximation to the Coriolis force (v location).""" _, Y = np.meshgrid(grid.x, grid.yp1) fv = f0 + Y*beta return fv From 9748b2a9f4fd41b0c6c69341fb54554776f67fed Mon Sep 17 00:00:00 2001 From: Ed Doddridge Date: Wed, 19 Apr 2017 10:30:15 -0400 Subject: [PATCH 46/50] direcotry -> directly --- docs/input_generation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/input_generation.rst b/docs/input_generation.rst index c392643a..2f4924af 100644 --- a/docs/input_generation.rst +++ b/docs/input_generation.rst @@ -3,7 +3,7 @@ Input generators Aronnax includes a number of helper functions for generating input fields. These can be called with numerical arguments (generating very simple input fields) -directory from the aronnax.conf file, using the syntax `:generator_name:arg1,arg2,...,argn`. +directly from the aronnax.conf file, using the syntax `:generator_name:arg1,arg2,...,argn`. Grid ===== From 0a3b8d82d995967c70d6444e215f37cd5af6e527 Mon Sep 17 00:00:00 2001 From: Ed Doddridge Date: Wed, 19 Apr 2017 10:33:01 -0400 Subject: [PATCH 47/50] put Coriolis functions in separate section from wetmask function --- docs/input_generation.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/input_generation.rst b/docs/input_generation.rst index 2f4924af..f2ff14ed 100644 --- a/docs/input_generation.rst +++ b/docs/input_generation.rst @@ -27,7 +27,7 @@ Initial conditions .. autofunction:: aronnax.depths -Domain fields +Coriolis fields =============== .. autofunction:: aronnax.f_plane_f_u @@ -38,4 +38,8 @@ Domain fields .. autofunction:: aronnax.beta_plane_f_v + +Domain shape +============ + .. autofunction:: aronnax.rectangular_pool From c5b97f01ec9e0ce83a39fd2168e0f01310cbc8f7 Mon Sep 17 00:00:00 2001 From: Ed Doddridge Date: Wed, 19 Apr 2017 10:43:17 -0400 Subject: [PATCH 48/50] state which configuration files are automatically generated. --- aronnax/driver.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/aronnax/driver.py b/aronnax/driver.py index c34f68ed..919aab87 100644 --- a/aronnax/driver.py +++ b/aronnax/driver.py @@ -20,9 +20,11 @@ def simulate(work_dir=".", config_path="aronnax.conf", **options): directory is as follows: - aronnax.conf - configuration file for that run - aronnax-merged.conf - file to save effective configuration, including - effects of options passed to `simulate` + effects of options passed to `simulate`. This file is automatically + generated by merging the aronnax.conf file with the options passed to + this function - parameters.in - relevant portions of aronnax-merged.conf in Fortran - namelist format + namelist format. Also generated automatically - input/ - subdirectory where Aronnax will save input field files in Fortran raw array format - output/ - subdirectory where Aronnax will save output field files From 04e67271f8417be55b2a21ff32015c4984ec626f Mon Sep 17 00:00:00 2001 From: Ed Doddridge Date: Wed, 19 Apr 2017 10:51:50 -0400 Subject: [PATCH 49/50] add "running Aronnax" section to docs and modify driver.simulate() docstring --- aronnax/driver.py | 38 ++++++++++++++++++++------------------ docs/index.rst | 1 + docs/running_aronnax.rst | 5 +++++ 3 files changed, 26 insertions(+), 18 deletions(-) create mode 100644 docs/running_aronnax.rst diff --git a/aronnax/driver.py b/aronnax/driver.py index 919aab87..2353e0e8 100644 --- a/aronnax/driver.py +++ b/aronnax/driver.py @@ -18,26 +18,28 @@ def simulate(work_dir=".", config_path="aronnax.conf", **options): `work_dir` parameter, which defaults to the current directory when `simulate` is invoked. The default arrangement of the working directory is as follows: - - aronnax.conf - configuration file for that run - - aronnax-merged.conf - file to save effective configuration, including - effects of options passed to `simulate`. This file is automatically - generated by merging the aronnax.conf file with the options passed to - this function - - parameters.in - relevant portions of aronnax-merged.conf in Fortran - namelist format. Also generated automatically - - input/ - subdirectory where Aronnax will save input field files - in Fortran raw array format - - output/ - subdirectory where Aronnax will save output field files - in Fortran raw array format + + - aronnax.conf - configuration file for that run + - aronnax-merged.conf - file to save effective configuration, including + effects of options passed to `simulate`. This file is automatically + generated by merging the aronnax.conf file with the options passed to + this function + - parameters.in - relevant portions of aronnax-merged.conf in Fortran + namelist format. Also generated automatically + - input/ - subdirectory where Aronnax will save input field files + in Fortran raw array format + - output/ - subdirectory where Aronnax will save output field files + in Fortran raw array format The process for a simulation is to - 1. Compute the configuration - 2. Recompile the Fortran core if necessary - 3. Save the computed configuration in aronnax-merged.conf - 4. Write raw-format input fields into input/ - 5. Write parameters.in - 6. Execute the Fortran core, which writes progress messages - to standard output and raw-format output fields into output/ + + 1. Compute the configuration + 2. Recompile the Fortran core if necessary + 3. Save the computed configuration in aronnax-merged.conf + 4. Write raw-format input fields into input/ + 5. Write parameters.in + 6. Execute the Fortran core, which writes progress messages + to standard output and raw-format output fields into output/ All the simulation parameters can be controlled from the configuration file aronnax.conf, and additionally can be diff --git a/docs/index.rst b/docs/index.rst index 243ae5a8..405b71ad 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -44,6 +44,7 @@ Aronnax is examples aronnax_model input_generation + running_aronnax output_helpers verification benchmarks diff --git a/docs/running_aronnax.rst b/docs/running_aronnax.rst new file mode 100644 index 00000000..7fddf217 --- /dev/null +++ b/docs/running_aronnax.rst @@ -0,0 +1,5 @@ +Running Aronnax +******************* + + +.. autofunction:: aronnax.driver.simulate From 3a113eb8e0a0ce8397d38ee570c9c9abb6a293e2 Mon Sep 17 00:00:00 2001 From: Ed Doddridge Date: Wed, 19 Apr 2017 11:03:19 -0400 Subject: [PATCH 50/50] rename coriolis functions in benchmark simulations --- benchmarks/beta_plane_bump/aronnax.conf | 4 ++-- benchmarks/beta_plane_bump_red_grav/aronnax.conf | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/benchmarks/beta_plane_bump/aronnax.conf b/benchmarks/beta_plane_bump/aronnax.conf index 647bdb9a..22bb90d8 100644 --- a/benchmarks/beta_plane_bump/aronnax.conf +++ b/benchmarks/beta_plane_bump/aronnax.conf @@ -46,8 +46,8 @@ ny = 10 layers = 2 dx = 2e4 dy = 2e4 -fUfile = :beta_plane_u:1e-5,2e-11 -fVfile = :beta_plane_v:1e-5,2e-11 +fUfile = :beta_plane_f_u:1e-5,2e-11 +fVfile = :beta_plane_f_v:1e-5,2e-11 wetMaskFile = :rectangular_pool: [external_forcing] diff --git a/benchmarks/beta_plane_bump_red_grav/aronnax.conf b/benchmarks/beta_plane_bump_red_grav/aronnax.conf index 774f600d..476a767b 100644 --- a/benchmarks/beta_plane_bump_red_grav/aronnax.conf +++ b/benchmarks/beta_plane_bump_red_grav/aronnax.conf @@ -45,8 +45,8 @@ ny = 500 layers = 1 dx = 2e4 dy = 2e4 -fUfile = :beta_plane_u:1e-5,2e-11 -fVfile = :beta_plane_v:1e-5,2e-11 +fUfile = :beta_plane_f_u:1e-5,2e-11 +fVfile = :beta_plane_f_v:1e-5,2e-11 wetMaskFile = :rectangular_pool: [external_forcing]