Ejemplo n.º 1
0
coeff_calc = None
for total_steps, (xs, xs_mesh, exp, var, quadrature_nodes_count, coeffs) \
        in zip(accumulate(steps_list), galerkin_approximation(trial, max_poly_degree, domain,
                                                              grid_size, start_time, steps_list,
                                                              delta_time, wave_weight,
                                                              quadrature_method, quadrature_param,
                                                              retrieve_coeffs=True)):
    if not coeff_calc:
        coeff_calc = solution_coefficients_calculator(trial, max_poly_degree,
                                                      quadrature_method,
                                                      quadrature_param)
    stop_time = total_steps * delta_time

    reference_coeffs = coeff_calc(stop_time, xs_mesh)

    coeffs_norm = error_l2(coeffs, reference_coeffs,
                           axis=0)**2  # errors for each degree
    assert len(coeffs_norm) == max_poly_degree + 1  # in 1d
    coeffs_norm = np.sum(coeffs_norm)  # sum over all degrees
    errors_coeffs.append(coeffs_norm)

    stop_times.append(stop_time)
    error_var = None

    trial_exp = trial.obtain_evaluated_expectancy(xs, xs_mesh, stop_time)
    trial_var = trial.obtain_evaluated_variance(xs, xs_mesh, stop_time)
    error_exp = error_l2(exp, trial_exp)
    errors_exp.append(error_exp)
    if var is not None and trial_var is not None:
        error_var = error_l2(var, trial_var)
        errors_var.append(error_var)
    print("Error for ", trial.name, "dt=", delta_time, "stop_time=", stop_time,
Ejemplo n.º 2
0
     plt.ylim((0, plt.ylim()[1]))
     plt.legend()
     plt.show()
 elif test == "pdf":
     from scipy.stats import gamma as test_distr
     shape, rate = 0.5, 0.2  # >0
     loc, scale = 0., 1. / rate
     a = shape
     own_distr = make_gamma(shape, rate)
     x_data = np.arange(-0.999, 0.999, 0.01)
     y_data = np.arange(0.001, 1, 0.001)
     plt.figure()
     from util.analysis import error_l2
     res1 = test_distr.pdf(x_data, a, loc=loc, scale=scale)
     res2 = np.vectorize(own_distr.weight)(x_data)
     print(error_l2(res2, res1))
     plt.plot(x_data, res1, 'x', label="pdf scipy")
     plt.plot(x_data, res2, label="pdf own")
     #plt.plot(y_data, test_distr.ppf(y_data, a, loc=loc, scale=scale), label='ppf scipy')
     plt.legend()
     plt.show()
 elif test == "ppf":
     # test if the inverse_distribution really produces the same distribution using uniformly distributed data
     # by the inversion method
     uniform_data = [random.uniform(0, 1) for _ in range(10000)]
     shape, rate = 0.33, 1
     distr = make_gamma(shape, rate)
     inverted_data = list(map(distr.inverse_distribution, uniform_data))
     hist, bin_edges = np.histogram(inverted_data,
                                    bins='auto',
                                    density=True)
Ejemplo n.º 3
0
import numpy as np
import demo.stochastic_trials as st
import matplotlib.pyplot as plt
import diff_equation.solver_config as config
trial = st.trial_3
stop_time = 2.

plt.figure()
xs, xs_mesh = config.SolverConfig.make_spatial_discretization(
    [[-np.pi, np.pi]], [128])
expectancy = trial.obtain_evaluated_expectancy(xs, xs_mesh, stop_time)
exact_variance = None
if trial.has_parameter("variance"):
    exact_variance = trial.variance(xs_mesh, stop_time)
calculated_variance = trial.calculate_variance(xs, stop_time,
                                               trial.raw_reference, expectancy)

plt.plot(xs[0],
         trial.raw_reference(xs_mesh, stop_time, [0]),
         label="Reference at expected y")
plt.plot(xs[0], expectancy, label="obtained Expectancy")
if exact_variance is not None:
    plt.plot(xs[0], exact_variance, label="exact Variance")
plt.plot(xs[0], calculated_variance, label="calculated Variance")
if exact_variance is not None:
    from util.analysis import error_l2
    print("Error in variances:", error_l2(calculated_variance, exact_variance))
plt.legend()
plt.show()
Ejemplo n.º 4
0
def simulate(stochastic_trial,
             simulations_count,
             keep_solutions_at_steps,
             domain,
             grid_size_N,
             start_time,
             stop_time,
             delta_time,
             eval_time=None,
             heartbeat=100,
             do_calculate_expectancy=True,
             order_factor=2,
             quasi_monte_carlo=False,
             wave_weight=0.5):
    """
    Monte Carlo simulation for the stochastic Klein-Gordon equation using a splitting method to solve the equation
    for randomly generated values of the trial's distributions. Calculates the expectancy by calculating the mean
    value of the simulations. Takes quite some time for high simulations_count. Convergence is of
    order 1/sqrt(simulations_count), though the random character makes this not perfectly visible. Offers
    an estimation of the convergence order (should be 0.5), but as the convergence might switch from coming from above
    or from below, this is mostly not super accurate if no reference solution is available for the trial.
    If a setting of randomized values fails for some reason (result blows up, NaN or Inf appears), the simulation is
    repeated, but in total only the double amount of simulations will be done.
    :param stochastic_trial: The stochastic trial to get starting values and data from.
    :param simulations_count: (int) The amount (>0) of simulations to use. 1000 is ok and fast, 100,000 offers ca.
    error in range of O(10^-3) to O(10^-4) for most examples.
    :param keep_solutions_at_steps: A list of integers of solutions to keep (if intermediate estimates of expectancy
    are wanted).
    :param domain: The domain to solve the Klein-Gordon equation on. List of intervals.
    :param grid_size_N: The grid size(s) to discretize each spatial dimension into. Should be power of 2.
    For spatial dimension 1, this can be higher (like 512), for higher dimensions should be low. The higher this is,
    the lower lower the delta_time parameter should be (CFL-condition).
    :param start_time: The starting time to use. Does not really matter, mostly 0.
    :param stop_time: The stop time. Will stop when the splitting time is bigger than or equal to this time for the
    first time, so after (stop_time-start_time) / delta_time steps.
    :param delta_time: The delta time increment to use for splitting.
    :param eval_time: The time to evaluate the solution at. So the expectancy is calculated at this time only. If None,
    then stop_time is used.
    :param heartbeat: (int) if positive then every heartbeat steps a small print will be made to console.
    :param do_calculate_expectancy: If there is no expectancy set for the trial but it has a reference set, uses this
    reference to calculate the exact expectancy and later returns it. Can take some time but useful for error analysis.
    :param order_factor: Factor between the steps of the simulations used to approximate the order. Can be 2, default is
    10. Should not be changed though.
    :return: xs: A list of 1d nd-arrays of the spatial discretization
             xs_mesh: A list of the sparse mesh grids belong to xs.
             expectancy: The trial's evaluated expectancy, the calculated expectancy or None
             variance: The trial's evaluated variance or None
             expectancy_errors: 1d nd-array how the error to expectancy (if given) evolved over the simulations
             variance_errors: Same as expectancy_errors just for the variance (if given)
             solutions: The solutions that we should save which are approximations to the expectancy, a tuple
             consisting of the step index, the expectancy and the variance
             expectancies_for_order_estimate: The 3 solutions for the order estimate (if possible)
    """
    xs, xs_mesh = None, None
    eval_solution_index = None
    expectancy, variance = None, None
    if eval_time is None:
        eval_time = stop_time
    solutions = []
    expectancy_errors, variance_errors = [], []
    order_factor = order_factor
    steps_for_order_estimate = [
        int(simulations_count / (order_factor**i)) for i in range(3)
    ]
    expectancies_for_order_estimate = []
    random_dimension = len(stochastic_trial.variable_distributions)
    actual_solutions_count = 0
    fail_count = 0
    running_estimator = running_mean_variance()

    # HINT: To estimate sample variance, you would need to sum the squares of the simulation solution minus the
    # estimated expectancy and then divide this by either: simulations_count, or simulations_count-1 (to eliminate bias)
    # see: https://en.wikipedia.org/wiki/Variance#Population_variance_and_sample_variance
    # comparsion: http://www.johndcook.com/blog/2008/09/26/comparing-three-methods-of-computing-standard-deviation/
    # stable calculation: http://math.stackexchange.com/questions/20593/calculate-variance-from-a-stream-of-sample-values
    while actual_solutions_count < simulations_count:
        if heartbeat > 0 and actual_solutions_count % heartbeat == 0:
            print("Simulation", actual_solutions_count)
        if not quasi_monte_carlo:
            stochastic_trial.randomize()
        else:
            # do not use the sequence's first element as this all zeros
            if random_dimension <= 6:  # by recommendation (of whom again...?)
                quasi_uniform = halton(actual_solutions_count + 1,
                                       random_dimension)
            else:
                quasi_uniform, _ = i4_sobol(random_dimension,
                                            actual_solutions_count + 1)
            quasi_random = [
                distribution.inverse_distribution(value)
                for value, distribution in zip(
                    quasi_uniform, stochastic_trial.variable_distributions)
            ]
            stochastic_trial.set_random_values(quasi_random)

        # If the time step size is too small leapfrog is unstable and we should use wave_linhyp configs
        # but they are slower about a factor 3-4
        # configs = kg.make_klein_gordon_wave_linhyp_configs(domain, [grid_size_N], stochastic_trial.alpha,
        #                                                    stochastic_trial.beta, wave_weight)
        configs = kg.make_klein_gordon_leapfrog_configs(
            domain, [grid_size_N], stochastic_trial.alpha,
            stochastic_trial.beta)
        splitting = Splitting.make_fast_strang(*configs, "FastStrang",
                                               start_time,
                                               stochastic_trial.start_position,
                                               stochastic_trial.start_velocity,
                                               delta_time)
        splitting.progress(
            splitting.approx_steps_to_end_time(stop_time, delta_time),
            delta_time, 0)
        if xs is None:
            xs = splitting.get_xs()
            xs_mesh = splitting.get_xs_mesh()
            eval_solution_index = next(
                (i for i, t in enumerate(splitting.times()) if t >= eval_time),
                -1)

        solution = splitting.solutions()[eval_solution_index]
        test_summed = np.sum(solution)
        if np.isnan(test_summed) or np.isinf(
                test_summed) or np.abs(test_summed) > 1E5:
            fail_count += 1
            print("Simulation", actual_solutions_count,
                  "got a invalid result, NaN or Inf or too big:", test_summed,
                  "Skipping", "Random parameters:", stochastic_trial.rvalues,
                  stochastic_trial.name)
            if not quasi_monte_carlo and fail_count < simulations_count:
                continue
            else:
                break  # to make simulation stop at maximum of twice the runtime or if it is not (pseudo)random
        actual_solutions_count += 1
        current_expectancy_estimate, current_variance_estimate = running_estimator.send(
            solution)
        next(running_estimator)
        if expectancy is None and stochastic_trial.has_parameter("expectancy"):
            expectancy = stochastic_trial.expectancy(xs_mesh, eval_time)
        elif expectancy is None and stochastic_trial.raw_reference is not None and do_calculate_expectancy:
            expectancy = stochastic_trial.calculate_expectancy(
                xs, eval_time, stochastic_trial.raw_reference)
        if variance is None and stochastic_trial.has_parameter("variance"):
            variance = stochastic_trial.variance(xs_mesh, eval_time)
        if actual_solutions_count in keep_solutions_at_steps:
            solutions.append(
                (actual_solutions_count, current_expectancy_estimate,
                 current_variance_estimate))
        if actual_solutions_count in steps_for_order_estimate:
            expectancies_for_order_estimate.append(current_variance_estimate)
        if expectancy is not None:
            expectancy_errors.append(
                error_l2(expectancy, current_expectancy_estimate))
        if variance is not None:
            variance_errors.append(
                error_l2(variance, current_variance_estimate))
    return (xs, xs_mesh, expectancy, variance, expectancy_errors,
            variance_errors, solutions, expectancies_for_order_estimate)
Ejemplo n.º 5
0
trial = trial_1

wave_config = WaveSolverConfig(domain, [grid_n], trial.wave_speed)
wave_config.init_solver(0, trial.start_position, trial.start_velocity)

if trial.has_parameter("show_times"):
    show_times = trial.show_times
if trial.has_parameter("do_animate"):
    do_animate = trial.do_animate
wave_config.solve(show_times)

if show_errors and has_reference(trial, dimension):
    print("Showing error...")
    errors = [
        error_l2(y, reference(trial, wave_config.xs_mesh, t))
        for t, y in wave_config.timed_solutions()
    ]
    plt.figure()
    print("Errors=", errors)
    plt.plot(wave_config.times(), errors, label="Errors in discrete L2-norm")
    plt.xlabel("Time")
    plt.yscale('log')
    plt.ylabel("Error")

if dimension == 1:
    if do_animate:
        animate_1d(wave_config.xs[0], [wave_config.solutions()], show_times,
                   100)  # pause between frames in ms
    else:
        # all times in one figure
Ejemplo n.º 6
0
    plt.xlabel("Anzahl an Durchläufen", fontsize="x-large")
    plt.ylabel("Fehler in diskreter L2-Norm", fontsize="x-large")
    plt.xscale('log')
    plt.yscale('log')
    plt.legend(loc='best', fontsize="x-large")

if len(solutions_for_order_estimate) == 3:
    if expectancy is None:
        order = np.log(
            (solutions_for_order_estimate[0] - solutions_for_order_estimate[1])
            / (solutions_for_order_estimate[1] -
               solutions_for_order_estimate[2])) / np.log(order_factor)
        total_order = np.log(
            np.sum(1. / order_factor**(order * 2)) /
            order.size) / (np.log(1 / order_factor) * 2)
        print("Total convergence order without expectancy:", total_order)
    else:
        err_order = [
            error_l2(sol_order, expectancy)
            for sol_order in solutions_for_order_estimate
        ]
        print("Errors for order:", err_order)
        total_order = np.log(
            (err_order[0] - err_order[1]) /
            (err_order[1] - err_order[2])) / np.log(order_factor)
        print("Total convergence order of error (estimate using expectancy):",
              total_order)

plt.show()