def _initialize(self): self.cont = Controller(self.params) # self.cont.deriv.reconstructor = WENO(self.cont.mesh) et = ErrorTracker(self.cont.mesh, self.cont.analytical, self.params) soln_plot = UpdatePlotter(self.params.plotter) soln_plot.add_line(self.cont.mesh.x, self.cont.init[2:-2], "+") soln_plot.add_line(self.cont.mesh.x, self.cont.init[2:-2], "-") self.cont.observers.append(soln_plot) self.cont.observers.append(et)
def __init__(self, mesh, exact, params): # Defaults self.error_norm = 1 self.params_plotter = None self.mesh = mesh if params is not None: self.handle_params(params) self.exact_soln = exact self.error = [0.0] self.current_plot = UpdatePlotter(self.params_plotter) self.current_plot.add_line(self.mesh.x, np.zeros_like(self.mesh.x), '*') self.all_time_plot = UpdatePlotter(self.params_plotter) self.all_time_plot.add_line([0], [0], '-')
class ErrorTracker(object): """ Error analysis and tracking tools. The "exact" parameter to the constructor should be a function that accepts one parameter: time. and produces the exact result. """ def __init__(self, mesh, exact, params): # Defaults self.error_norm = 1 self.params_plotter = None self.mesh = mesh if params is not None: self.handle_params(params) self.exact_soln = exact self.error = [0.0] self.current_plot = UpdatePlotter(self.params_plotter) self.current_plot.add_line(self.mesh.x, np.zeros_like(self.mesh.x), '*') self.all_time_plot = UpdatePlotter(self.params_plotter) self.all_time_plot.add_line([0], [0], '-') def handle_params(self, params): if 'error_norm' in params: self.error_norm = params.error_norm if 'plotter' in params: self.params_plotter = params.plotter @staticmethod def calc_norm(vector, norm): if norm is np.Inf: return abs(np.max(vector)) err = np.sum(abs(vector) ** norm) ** \ (1.0 / norm) return err def get_final_error(self): return self.error[-1] def update(self, y, t, dt): exact = self.exact_soln(t) diff = y - exact e = ErrorTracker.calc_norm(diff * self.mesh.delta_x, self.error_norm) self.error.append(e) self.current_plot.update(diff, t, dt) self.all_time_plot.update(self.error, t, dt, x=np.arange(0, len(self.error)))
def _test_controller_helper(wave, t_max, delta_x, error_bound, always=False, setup_callback=None): # Simple test to make sure the code works right my_params = Data() my_params.delta_x = delta_x my_params.plotter = Data() my_params.plotter.always_plot = always my_params.plotter.never_plot = not interactive_test my_params.plotter.plot_interval = 0.5 my_params.t_max = t_max my_params.analytical = wave cont = Controller(my_params) if setup_callback is not None: setup_callback(cont) et = ErrorTracker(cont.mesh, cont.analytical, my_params) soln_plot = UpdatePlotter(my_params.plotter) soln_plot.add_line(cont.mesh.x, cont.init, '+') soln_plot.add_line(cont.mesh.x, cont.init, '-') cont.observers.append(soln_plot) cont.observers.append(et) result = cont.compute() soln_plot.add_line(cont.mesh.x, cont.exact) # check essentially non-oscillatoriness # total variation <= initial_tv + O(h^2) init_tv = Controller.total_variation(cont.init) result_tv = Controller.total_variation(result) if interactive_test is True: pyp.show() assert(result_tv < init_tv + error_bound) # check error assert(et.error[-1] < error_bound) return et, soln_plot