Exemple #1
0
    def solve_states(self, left_state, right_state, x, t):
        f_min = lambda s: np.min(
            [self.flux_function.q_derivative(s, x, t), 0.0])
        f_max = lambda s: np.max(
            [self.flux_function.q_derivative(s, x, t), 0.0])

        f_min_integral = math_utils.quadrature(f_min, 0.0, right_state)
        f_max_integral = math_utils.quadrature(f_max, 0.0, left_state)

        numerical_flux = f_min_integral + f_max_integral + self.flux_function(
            0.0, x, t)

        return numerical_flux
def test_quadrature():
    f = lambda x: np.cos(x)
    int_f = lambda x: np.sin(x)
    x_left = 0.0
    x_right = 1.0
    approx_int = math_utils.quadrature(f, x_left, x_right)
    exact_int = int_f(x_right) - int_f(x_left)
    assert np.abs(approx_int - exact_int) <= tolerance

    for p in range(10):
        f = lambda x: np.power(x, p)
        int_f = lambda x: 1 / (p + 1) * np.power(x, p + 1)
        approx_int = math_utils.quadrature(f, x_left, x_right)
        exact_int = int_f(x_right) - int_f(x_left)
        assert np.abs(approx_int - exact_int) <= tolerance
Exemple #3
0
    def solve_states(self, left_state, right_state, x, t, n):
        # Nonconservative Flux
        # min_speed = s_l, max_speed = s_r
        # Let G = 1/2 \dintt{0}{1}{g(\psi(\tau, Q_l, Q_r))\psi_{\tau}}{\tau}
        # Let Q^* = (s_r Q_r - s_l Q_l + f(Q_l) - f(Q_r))/(s_r - s_l) - 1/(s_r - s_l) G
        # if min_speed = s_l > 0,
        # F = f(Q_l) - G
        # if min_speed = s_l < 0 and max_speed = s_r > 0
        # F = 1/2 (f(Q_l) + f(Q_r)) + 1/2(s_r Q^* + s_l Q^* - s_l Q_l - s_r Q_r)
        # if max_speed = s_r < 0
        # F = f(Q_r) + G
        tuple_ = self.problem.app_.wavespeeds_hlle(left_state, right_state, x,
                                                   t, n)
        min_speed = tuple_[0]
        max_speed = tuple_[1]

        quad_func = self._get_quad_func(left_state, right_state)
        G = math_utils.quadrature(quad_func, 0.0, 1.0)
        if min_speed > 0:
            return self.flux_function(left_state) - G
        if max_speed < 0:
            return self.flux_function(right_state) + G
        else:
            f_r = self.flux_function(right_state)
            f_l = self.flux_function(left_state)
            q_star = (max_speed * right_state - min_speed * left_state + f_l -
                      f_r - G) / (max_speed - min_speed)

            return 0.5 * (f_l + f_r) + 0.5 * (
                (max_speed + min_speed) * q_star - min_speed * left_state -
                max_speed * right_state)
Exemple #4
0
def compute_quadrature_strong(dg_solution, t, flux_function, i):
    # quadrature_function = M^{-1} \dintt{D_i}{f(Q_i, x, t)_x \Phi}{x}
    # M^{-1} \dintt{D_i}{f(Q_i(x), x, t)_x \Phi(xi(x))}{x}
    # M^{-1} \dintt{D_i}{(f_q(Q_i(x), x, t) (Q_i(x))_x + f_x(Q_i(x), x, t))
    #   \phi(xi(x))}{x}
    # M^{-1} \dintt{-1}{1}{(f_q(Q_i(xi), x(xi), t) (Q_i(xi))_x + f_x(Q_i(xi), x(xi), t))
    #   \phi(xi) dx/dxi}{xi}
    basis_ = dg_solution.basis
    mesh_ = dg_solution.mesh
    result = np.zeros(basis_.num_basis_cpts)

    # if first order then will be zero
    # if basis_.num_basis_cpts == 1:
    #     return 0.0

    for l in range(basis_.num_basis_cpts):

        def quadrature_function(xi):
            x = dg_solution.mesh.transform_to_mesh(xi, i)
            q = dg_solution.evaluate_canonical(xi, i)
            f_q = flux_function.q_derivative(q, x, t)
            q_x = dg_solution.x_derivative_canonical(xi, i)
            f_x = flux_function.x_derivative(q, x, t)
            phi = basis_(xi, l)
            # elem_metrics[i] = dx/dxi
            return (f_q * q_x + f_x) * phi * mesh_.elem_metrics[i]

        result[l] = math_utils.quadrature(quadrature_function, -1.0, 1.0)

    result = np.matmul(basis_.mass_matrix_inverse, result)

    return result
Exemple #5
0
def flux_basis_derivative_quadrature(dg_solution, flux_function, t, i):
    # \dintt{-1}{1}{\v{f}(\m{Q}_i \v{\Phi}, x_i(xi), t) \v{\phi}_{\xi}^T}{xi}
    mesh_ = dg_solution.mesh_
    basis_ = dg_solution.basis_

    def quad_func(xi):
        return np.outer(
            flux_function(dg_solution(xi, i), mesh_.transform_to_mesh(xi, i),
                          t),
            basis_.derivative(xi),
        )

    return math_utils.quadrature(quad_func, -1.0, 1.0, basis_.num_basis_cpts)
Exemple #6
0
def test_compute_quadrature_matrix():
    squared = flux_functions.Polynomial(degree=2)
    cubed = flux_functions.Polynomial(degree=3)
    initial_condition = functions.Sine()
    t = 0.0
    x_left = 0.0
    x_right = 1.0
    for f in [squared, cubed]:
        for basis_class in basis.BASIS_LIST:
            for num_basis_cpts in range(1, 6):
                error_list = []
                basis_ = basis_class(num_basis_cpts)
                for num_elems in [10, 20]:
                    mesh_ = mesh.Mesh1DUniform(x_left, x_right, num_elems)
                    dg_solution = basis_.project(initial_condition, mesh_)
                    quadrature_matrix = ldg_utils.compute_quadrature_matrix(
                        dg_solution, t, f)
                    result = solution.DGSolution(None, basis_, mesh_)
                    direct_quadrature = solution.DGSolution(
                        None, basis_, mesh_)
                    for i in range(mesh_.num_elems):
                        # compute value as B_i Q_i
                        result[i] = np.matmul(quadrature_matrix[i],
                                              dg_solution[i])
                        # also compute quadrature directly
                        for l in range(basis_.num_basis_cpts):
                            quadrature_function = (lambda xi: f(
                                initial_condition(
                                    mesh_.transform_to_mesh(xi, i)),
                                xi,
                            ) * initial_condition(
                                mesh_.transform_to_mesh(xi, i)) * basis_.
                                                   derivative(xi, l))
                            direct_quadrature[i, l] = math_utils.quadrature(
                                quadrature_function, -1.0, 1.0)
                        # need to multiply by mass inverse
                        direct_quadrature[i] = np.matmul(
                            basis_.mass_matrix_inverse, direct_quadrature[i])
                    error = (result - direct_quadrature).norm()
                    error_list.append(error)
                if error_list[-1] != 0.0:
                    order = utils.convergence_order(error_list)
                    assert order >= (num_basis_cpts - 1)
Exemple #7
0
def compute_quadrature_matrix_weak(basis_, mesh_, t, flux_function, i):
    # function to compute quadrature_matrix B_i, useful for using dg_weak_form_matrix
    # B_i = M^{-1}\dintt{D_i}{a(x, t) \Phi(xi(x))_x \Phi^T(xi(x))}{x}
    # B_i = M^{-1}\dintt{-1}{1}{a(x(xi), t) \Phi(xi)_x \Phi^T(xi) dx/dxi}{xi}
    # B_i = M^{-1}\dintt{-1}{1}{a(x(xi), t) \Phi_xi(xi) dxi/dx \Phi^T(xi) dx/dxi}{xi}
    # B_i = M^{-1}\dintt{-1}{1}{a(x(xi), t) \Phi_xi(xi) \Phi^T(xi)}{xi}
    # f(Q, x, t) = a(x, t) Q
    num_basis_cpts = basis_.num_basis_cpts

    B = np.zeros((num_basis_cpts, num_basis_cpts))
    for j in range(num_basis_cpts):
        for k in range(num_basis_cpts):

            def quadrature_function(xi):
                x = mesh_.transform_to_mesh(xi, i)
                phi_xi_j = basis_.derivative(xi, j)
                phi_k = basis_(xi, k)
                a = flux_function.q_derivative(0.0, x, t)
                return a * phi_xi_j * phi_k

            B[j, k] = math_utils.quadrature(quadrature_function, -1.0, 1.0)

    B = np.matmul(basis_.mass_matrix_inverse, B)
    return B
Exemple #8
0
def compute_quadrature_weak(dg_solution, t, flux_function, i):
    # quadrature_function(i) =
    # \dintt{-1}{1}{\v{f}(\m{Q}_i \v{\Phi}, x, t) \v{\phi}_{\xi}^T}{x} M^{-1}
    basis_ = dg_solution.basis_
    mesh_ = dg_solution.mesh_

    # if first order then will be zero
    # phi_xi(xi) = 0 for 1st basis_cpt
    # assume basis has more than one component

    def quadrature_function(xi):
        x = mesh_.transform_to_mesh(xi, i)
        q = dg_solution.evaluate_canonical(xi, i)
        phi_xi = basis_.derivative(xi)
        return flux_function(q, x, t) * phi_xi

    result = math_utils.quadrature(quadrature_function,
                                   -1.0,
                                   1.0,
                                   quad_order=basis_.num_basis_cpts)

    result = np.matmul(result, basis_.mass_matrix_inverse)

    return result
Exemple #9
0
    def limit_solution(self, problem, dg_solution):
        # update dg_solution to limited solution
        # also return limited solution
        num_elems = dg_solution.mesh_.num_elems
        mesh_ = dg_solution.mesh_
        basis_ = dg_solution.basis_

        # Step 1
        # elem_min[i_elem, i_eqn] = min value of i_eqn on i_elem
        # elem_min[i, l] = w^l_{m_i}
        # elem_max[i_elem, i_eqn] = max value of i_eqn on i_elem
        # elem_max[i, l] = w^l_{M_i}
        if self.variable_transformation is None:
            elem_min = np.array(
                [
                    np.min(dg_solution.evaluate_canonical(self.xi_points, i), axis=1)
                    for i in range(num_elems)
                ]
            )
            elem_max = np.array(
                [
                    np.max(dg_solution.evaluate_canonical(self.xi_points, i), axis=1)
                    for i in range(num_elems)
                ]
            )
            elem_ave = np.array([dg_solution.elem_average(i) for i in range(num_elems)])
        else:
            elem_min = np.array(
                [
                    np.min(
                        self.variable_transformation(
                            dg_solution.evaluate_canonical(self.xi_points, i)
                        ),
                        axis=1,
                    )
                    for i in range(num_elems)
                ]
            )
            elem_max = np.array(
                [
                    np.max(
                        self.variable_transformation(
                            dg_solution.evaluate_canonical(self.xi_points, i)
                        ),
                        axis=1,
                    )
                    for i in range(num_elems)
                ]
            )

            elem_ave = np.zeros(elem_max.shape)
            for i in range(num_elems):

                def quadrature_function(xi):
                    return self.variable_transformation(
                        dg_solution.evaluate_canonical(xi, i)
                    )

                elem_ave[i] = 0.5 * math_utils.quadrature(
                    quadrature_function, -1, 1, basis_.num_basis_cpts
                )

        num_eqns = elem_min.shape[1]

        # Step 2
        # upper_bounds[i, l] = M_i^l = max{\bar{w}_i^l + \alpha(h), max_{N}{w_{M_j}^l}}
        upper_bounds = np.zeros((num_elems, num_eqns))
        # lower_bounds[i, l] = m_i^l = min{\bar{w}_i^l - \alpha(h), min_{N}{w_{m_j}^l}}
        lower_bounds = np.zeros((num_elems, num_eqns))
        for i_elem in mesh_.boundary_elems:
            h = mesh_.elem_volumes[i_elem]
            alpha_h = self._alpha_function(h)
            neighbors = problem.boundary_condition.get_neighbors_indices(mesh_, i_elem)
            neighbor_max = np.max([elem_max[j] for j in neighbors], axis=0)
            neighbor_min = np.min([elem_min[j] for j in neighbors], axis=0)
            upper_bounds[i_elem] = np.maximum(elem_ave[i_elem] + alpha_h, neighbor_max)
            lower_bounds[i_elem] = np.minimum(elem_ave[i_elem] - alpha_h, neighbor_min)

        for i_elem in mesh_.interior_elems:
            h = mesh_.elem_volumes[i_elem]
            alpha_h = self._alpha_function(h)
            neighbors = mesh_.get_neighbors_indices(i_elem)
            neighbor_max = np.max([elem_max[j] for j in neighbors], axis=0)
            neighbor_min = np.min([elem_min[j] for j in neighbors], axis=0)
            upper_bounds[i_elem] = np.maximum(elem_ave[i_elem] + alpha_h, neighbor_max)
            lower_bounds[i_elem] = np.minimum(elem_ave[i_elem] - alpha_h, neighbor_min)

        # Step 3
        # \theta_{M_i} = \min_l{\phi((M_i^l - \bar{w}_i^l)/(w_{M_i}^l - \bar{w}_i^l))}
        # max_limiting[i] = min[l]{_phi((upper_bounds[i] - elem_ave[i])
        #   /(elem_max[i] - elem_ave[i]))}
        # \theta_{m_i} = \min_l{\phi((m_i^l - \bar{w}_i^l)/(w_{m_i}^l - \bar{w}_i^l))}
        # min_limiting[i] = min[l]{_phi((lower_bounds[i] - elem_ave[i])
        #   /(elem_min[i] - elem_ave[i]))}
        # Step 4
        # \theta_i = min{1, \theta_{m_i}, \theta_{M_i}}
        # limiting[i] = min{1, min_limiting[i], max_limiting[i]}
        max_limiting = np.zeros(num_elems)
        min_limiting = np.zeros(num_elems)
        limiting = np.zeros(num_elems)
        for i_elem in range(num_elems):
            max_limiting[i_elem] = np.min(
                self._phi(
                    np.abs((upper_bounds[i_elem] - elem_ave[i_elem]))
                    / (np.abs((elem_max[i_elem] - elem_ave[i_elem])) + 1e-10)
                )
            )
            min_limiting[i_elem] = np.min(
                self._phi(
                    np.abs((lower_bounds[i_elem] - elem_ave[i_elem]))
                    / (np.abs((elem_min[i_elem] - elem_ave[i_elem])) + 1e-10)
                )
            )
            limiting[i_elem] = min(1, min_limiting[i_elem], max_limiting[i_elem])

        # Step 5
        # Limit Solution
        # \tilde{q}^h(x) = \bar{q}_i + \theta_i (q^h(x) - \bar{q}_i)
        basis_.limit_higher_moments(dg_solution, limiting)
        return dg_solution