From e6f8d15a614d42e0b7c6f6ef3590b5886702aa7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=BChle=2C=20Laura=20Christine=20=28lakue103=29?= <laura.kuehle@uni-duesseldorf.de> Date: Sun, 12 Mar 2023 00:13:51 +0100 Subject: [PATCH] Added 'solve_exactly()' for Burgers class. --- Snakefile | 7 ++- scripts/tcd/Equation.py | 102 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 106 insertions(+), 3 deletions(-) diff --git a/Snakefile b/Snakefile index 6616d90..c4dceb2 100644 --- a/Snakefile +++ b/Snakefile @@ -23,18 +23,23 @@ TODO: Contemplate allowing vector input for ICs TODO: Discuss how wavelet details should be plotted TODO: Ask whether we are dealing with inviscid Burgers only TODO: Ask whether it is helpful to enforce boundary at every SSPRK3 step + -> Done (should be not needed as we enforce for RHS) TODO: Ask why we limit the initial time step TODO: Ask whether cfl number should be absolute value TODO: Ask why cells 1 and -2 are adjusted for Dirichlet boundary +TODO: Ask about introducing subclasses of Burgers -> Done (do) Urgent: TODO: Add Burgers class completely TODO: Add 'update_time_step()' to Burgers -> Done TODO: Add derivative basis to Basis class -> Done TODO: Fix wrong type for number of quadrature nodes -> Done -TODO: Add 'solve_exactly()' to Burgers +TODO: Add 'solve_exactly()' to Burgers -> Done TODO: Add 'update_right_hand_side()' to Burgers -> Done TODO: Add Dirichlet boundary -> Done +TODO: Clean up exact solution for Burgers +TODO: Add subclasses of Burgers +TODO: Ignore ghost domains by flagging all cells with it for extreme outlier TODO: Add functions to create each object from dict TODO: Initialize boundary config properly TODO: Test Burgers diff --git a/scripts/tcd/Equation.py b/scripts/tcd/Equation.py index 5298b04..6b170e2 100644 --- a/scripts/tcd/Equation.py +++ b/scripts/tcd/Equation.py @@ -460,8 +460,8 @@ class Burgers(Equation): """ pass - # num_periods = np.floor(self.wave_speed * self.final_time / - # mesh.interval_len) + num_periods = np.floor(self.wave_speed * self.final_time / + mesh.interval_len) # # grid = np.repeat(mesh.non_ghost_cells, self._quadrature.num_nodes) + \ # mesh.cell_len / 2 * np.tile(self._quadrature.nodes, mesh.num_cells) @@ -483,6 +483,104 @@ class Burgers(Equation): # exact = np.reshape(exact, (1, exact.size)) # # return grid, exact + grid = [] + exact = [] + + for cell in range(len(mesh)): + eval_points = mesh[cell] + cell_len / 2 * self._quadrature.get_eval_points() + grid.append(eval_points) + eval_values = [] + if scheme_label == 'Linear': + for point in range(len(eval_points)): + new_entry = self._init_cond.calculate(eval_points[point] - self._wave_speed * self._final_time + + num_periods * self._interval_len) + eval_values.append(new_entry) + exact.append(eval_values) + + grid = np.reshape(np.array(grid), (1, len(grid) * len(grid[0]))) + + if scheme_label == 'Linear': + # u(x,t) = u(x - wavespeed*time, 0) + exact = np.reshape(np.array(exact), (1, len(exact) * len(exact[0]))) + + if scheme_label == 'Burgers' and initial_condition == 'Sine': + # u(x,t) = u(x - u0*time, 0) + exact = self._init_cond._height_adjustment + \ + self._init_cond._stretch_factor * \ + self.implicit_burgers_solver( + grid, self._final_time) + elif scheme_label == 'Burgers' and initial_condition == 'DiscontinuousConstant': + # u(x,t) = u(x - u0*time, 0) + exact = self.rarefaction_wave(grid, self._final_time) + + def rarefaction_wave(self, grid_values, final_time): + uexact = 0 * grid_values + N = np.size(grid_values) + + for i in range(N): + if grid_values[0, i] <= - final_time: + uexact[0, i] = -1 + elif - final_time < grid_values[0, i] < final_time: + uexact[0, i] = grid_values[0, i] / final_time + else: + uexact[0, i] = 1 + + return uexact + + def implicit_burgers_solver(self, grid_values, final_time): + + ## Code Adapted from Hesthaven DG Code + + sspeed = self._init_cond._height_adjustment + uexact = np.zeros(np.size(grid_values)) + + # initialize values + xx = np.linspace(0, 1, 200) + uu = np.sin(self._init_cond._factor * np.pi * xx) + + te = final_time * (2 / self._interval_len) + xt0 = (2 / self._interval_len) * ( + grid_values-sspeed * final_time).reshape( + np.size(grid_values)) + for ix in range(len(xt0)): + if xt0[ix] > 1: + xt0[ix] -= 2 * np.floor(0.5 * (xt0[ix]+1)) + elif xt0[ix] < -1: + xt0[ix] += 2 * np.floor(0.5 * (1-xt0[ix])) + + ay = abs(xt0[ix]) + # Finding the closest characteristic + i0 = 0 + for j in range(200): + xt = xx[j]+uu[j] * te + if ay < xt: + break + else: + i0 = j + + # This is our initial guess + us = uu[i0] + un = us + for k in range(400): + us = un + x0 = ay-us * te + un = us-(us-np.sin(self._init_cond._factor * np.pi * x0)) / ( + 1+self._init_cond._factor * np.pi * np.cos( + self._init_cond._factor * np.pi * x0) * te) + + if abs(un-us) < 1e-15: + break + + y = np.sign(xt0[ix]) * un + if abs(ay-1) < 1e-15: + y = 0 + if abs(final_time) < 1e-15: + y = np.sin(self._init_cond._factor * np.pi * xt0[ix]) + uexact[ix] = y + + burgers_exact = uexact.reshape((1, np.size(grid_values))) + + return burgers_exact @enforce_boundary() def update_right_hand_side(self, projection: ndarray) -> ndarray: -- GitLab