In [ ]:
import sys
sys.path.append('../')
sys.path.append('../tests/python-support/')
%matplotlib notebook
In [ ]:
import matplotlib
import experiments
import itertools
import util
import numpy as np
import json
from collections import defaultdict
import matplotlib.pyplot as plt
from pprint import pprint
In [ ]:
# Whether to only run the offline part of the experiment,
# or both offline and online
offline_only = False
# Whether to import/export homogenized basis
import_basis = False
export_basis = False
# Names of experiments to run
experiment_names = [ "homogenized_l_shaped_amg" ]
# Offline parameters.
# Use integer exponents so that we can have reliable filenames
h_base = 0.5
h_exponent = [ 6 ]
oversampling = [ 2 ]
dense_fallback_threshold = [ 300 ]
corrector_iterative_tolerance = [ 1e-12 ]
# Online parameters
end_time = [0.01]
sample_count = [ 101 ]
integrator = [ "iterative_leapfrog" ]
use_coarse_rhs = [ True ]
use_coarse_mass_matrix = [ True ]
integrator_iterative_tolerance = [ 1e-8 ]
measure_error = False
In [ ]:
def make_offline_param(h_exponent, oversampling, threshold, iterative_tol):
p = {
'mesh_resolution': h_base ** h_exponent,
'oversampling': oversampling,
'dense_fallback_threshold': threshold,
'iterative_tolerance': iterative_tol
}
basis_file = 'basis_{}_{}.h5'.format(h_exponent, oversampling)
if import_basis:
p['basis_import_file'] = basis_file
if export_basis:
p['basis_export_file'] = basis_file
return p
def make_online_param(end_time, sample_count, integrator,
use_coarse_rhs, use_coarse_mass_matrix,
iterative_tol):
return {
'end_time': end_time,
'sample_count': sample_count,
'integrator': integrator,
'load_quadrature_strength': 2,
'use_coarse_rhs': use_coarse_rhs,
'use_coarse_mass_matrix': use_coarse_mass_matrix,
'iterative_tolerance': iterative_tol,
'measure_error': measure_error
}
def aggregate_offline_params():
offline_param_product = itertools.product(h_exponent, oversampling,
dense_fallback_threshold,
corrector_iterative_tolerance)
return [ make_offline_param(h_exp, ovs, threshold, tol)
for (h_exp, ovs, threshold, tol)
in offline_param_product]
def aggregate_online_params():
online_param_product = itertools.product(end_time, sample_count,
integrator, use_coarse_rhs, use_coarse_mass_matrix,
integrator_iterative_tolerance)
return [ make_online_param(e, s, i, rhs, mm, tol)
for (e, s, i, rhs, mm, tol)
in online_param_product ]
def aggregate_input():
offline_params = aggregate_offline_params()
online_params = aggregate_online_params()
if offline_only:
return [{
'experiment': experiment,
'offline': offline
}
for (experiment, offline)
in itertools.product(experiment_names, offline_params)
]
else:
return [{
'experiment': experiment,
'offline': offline,
'online': online
}
for (experiment, offline, online)
in itertools.product(experiment_names, offline_params, online_params)
]
experiment_input = aggregate_input()
In [ ]:
# Run experiments and collect results
results = experiments.run_experiments(experiment_input)
In [ ]:
# Uncomment to inspect raw results
pprint(results)
In [ ]:
def is_successful(result):
return 'error' not in result
def key(experiment):
name = experiment['experiment']
offline_params = experiment['offline']['parameters']
corrector_iterative_tol = offline_params['iterative_tolerance']
oversampling = offline_params['oversampling']
if offline_only:
return (name, "no integration", oversampling, corrector_iterative_tol, None, None, None)
else:
online_params = experiment['online']['parameters']
integrator = online_params['integrator']
use_coarse_rhs = online_params['use_coarse_rhs']
use_coarse_mass_matrix = online_params['use_coarse_mass_matrix']
integrator_tol = online_params['iterative_tolerance']
return (name, integrator, oversampling, corrector_iterative_tol,
use_coarse_rhs, use_coarse_mass_matrix, integrator_tol)
def flatten_timing(timing):
flattened_timing = defaultdict(list)
for experiment_timing in timing:
for k, v in experiment_timing.items():
flattened_timing[k].append(v)
return flattened_timing
def print_timing(flattened_timing):
timing_pad = len(max(flattened_timing.keys(), key = lambda s: len(s)))
for timing_name, values in sorted(flattened_timing.items(), key=lambda pair: pair[0]):
padded_name = str("{}:".format(timing_name).ljust(timing_pad + 1))
formatted_values = ", ".join([ "{:10.4g}".format(val) for val in values])
print("{} [ {} ]".format(padded_name, formatted_values))
success_results = [ result for result in results if is_successful(result) ]
failure_results = [ result for result in results if not is_successful(result) ]
success_results = sorted(success_results, key = key)
grouped_results = itertools.groupby(success_results, key = key)
for (name, integrator, oversampling, corrector_iterative_tol,
use_coarse_rhs, use_coarse_mass_matrix, integrator_tol), result in grouped_results:
result = list(result)
offline_results = [ result['offline']['result'] for result in result ]
coarse_dof = [ result['mesh_details']['num_coarse_vertices'] for result in offline_results ]
fine_dof = [ result['mesh_details']['num_fine_vertices'] for result in offline_results ]
offline_timings = [ result['offline']['result']['timing'] for result in result ]
offline_timings = flatten_timing(offline_timings)
print("=============================================")
print("Experiment name: {name}".format(name=name))
print("Integrator: {}".format(integrator))
print("Oversampling: {}".format(oversampling))
print("Corrector iterative tol: {}".format(corrector_iterative_tol))
print("Coarse dof: {}".format(coarse_dof))
print("Fine dof: {}".format(fine_dof))
if not offline_only:
online_results = [ result['online']['result'] for result in result ]
l2_error = [ result['error_summary']['l2'] for result in online_results ]
h1_error = [ result['error_summary']['h1'] for result in online_results ]
h1_semi_error = [ result['error_summary']['h1_semi'] for result in online_results ]
l2_coarse_slope = util.estimate_slope(coarse_dof, l2_error)
h1_coarse_slope = util.estimate_slope(coarse_dof, h1_error)
l2_fine_slope = util.estimate_slope(fine_dof, l2_error)
h1_fine_slope = util.estimate_slope(fine_dof, h1_error)
print("Use coarse rhs: {}".format(use_coarse_rhs))
print("Use coarse mass: {}".format(use_coarse_mass_matrix))
print("Integrator iterative tol: {}".format(integrator_tol))
online_timings = [ result['online']['result']['timing'] for result in result ]
online_timings = flatten_timing(online_timings)
convergence = [ result['converged'] for result in online_results ]
print("")
print("Convergence: {}".format(convergence))
print("H1 semi: {}".format(h1_semi_error))
print("H1: {}".format(h1_error))
print("L2: {}".format(l2_error))
print("")
print("H1 coarse slope: {}".format(h1_coarse_slope))
print("L2 coarse slope: {}".format(l2_coarse_slope))
print("H1 fine slope: {}".format(h1_fine_slope))
print("L2 fine slope: {}".format(l2_fine_slope))
print("")
print("Timing (online):")
print("---------------------------------------------")
print_timing(online_timings)
print("")
print("Timing (offline):")
print("---------------------------------------------")
print_timing(offline_timings)
print("=============================================")
print("")
In [ ]:
def visualize_statistics(summary):
for name, summary in summary.items():
histogram = summary['distribution']
groups = np.arange(0, len(histogram))
proportions = [ entry['accumulated'] for entry in histogram ]
plt.figure()
plt.title("{}".format(name))
plt.bar(groups, proportions)
plt.show()
grouped_results = itertools.groupby(success_results, key = key)
for (name, integrator, oversampling), result in grouped_results:
offline_results = [ result['offline']['result'] for result in result ]
coarse_dof = [ result['mesh_details']['num_coarse_vertices'] for result in offline_results ]
fine_dof = [ result['mesh_details']['num_fine_vertices'] for result in offline_results ]
print("=============================================")
print("Experiment name: {name}".format(name=name))
print("Oversampling: {}".format(oversampling))
print("Coarse dof: {}".format(coarse_dof))
print("Fine dof: {}".format(fine_dof))
for statistic in [ result['stats'] for result in offline_results ]:
for name, summary in statistic.items():
# print("{} max: {}".format(name, summary['max']))
# print("{} median: {}".format(name, summary['median']))
# print("{} mean: {}".format(name, summary['mean']))
pprint(summary['distribution'])
visualize_statistics(statistic)
print("=============================================")