Example #1
0
    def step(self, u_start: VectorHeat1D2Pts, t_start: float,
             t_stop: float) -> VectorHeat1D2Pts:
        """
        Time integration routine for 1D heat equation example problem:
            Backward Euler (BDF1)

        One-step method
           u_i = (I + dt*L)^{-1} * (u_{i-1} + dt*b_i),
        where L = self.space_disc is the spatial discretization operator

        Note: step takes two BDF1 steps
          * one step from (t_start + dtau) to t_stop
          * one step from t_stop to (t_stop + dtau)

        :param u_start: approximate solution for the input time t_start
        :param t_start: time associated with the input approximate solution u_start
        :param t_stop: time to evolve the input approximate solution to
        :return: approximate solution at input time t_stop
        """
        first, second, dtau = u_start.get_values()
        tmp1 = spsolve(
            (t_stop - t_start - dtau) * self.space_disc + self.identity,
            second + self.rhs(self.x, t_stop) * (t_stop - t_start - dtau))

        tmp2 = spsolve(dtau * self.space_disc + self.identity,
                       tmp1 + self.rhs(self.x, t_stop + dtau) * dtau)

        ret = VectorHeat1D2Pts(u_start.size, u_start.dtau)
        ret.set_values(first_time_point=tmp1,
                       second_time_point=tmp2,
                       dtau=dtau)
        return ret
Example #2
0
    def __init__(self,
                 x_start: float,
                 x_end: float,
                 nx: int,
                 dtau: float,
                 a: float,
                 init_cond: Callable = lambda x: x * 0,
                 rhs: Callable = lambda x, t: x * 0,
                 *args,
                 **kwargs):
        """
        Constructor.

        :param x_start: left interval bound of spatial domain
        :param x_end: right interval bound of spatial domain
        :param nx: number of spatial degrees of freedom
        :param dtau: time-step size within pair
        :param a: thermal conductivity
        :param init_cond: initial condition
        :param rhs: right-hand side
        """

        super().__init__(*args, **kwargs)
        # Spatial domain with homogeneous Dirichlet boundary conditions
        self.x_start = x_start
        self.x_end = x_end
        self.x = np.linspace(self.x_start, self.x_end, nx)
        self.x = self.x[1:-1]
        self.nx = nx - 2
        self.dx = self.x[1] - self.x[0]

        # Thermal conductivity
        self.a = a

        # (Spatial) identity matrix and spatial discretization matrix
        self.identity = identity(self.nx, dtype='float', format='csr')
        self.space_disc = self.compute_matrix()

        # Set right-hand side routine
        self.rhs = rhs

        # Set the data structure for any user-defined time-point pairs
        self.vector_template = VectorHeat1D2Pts(self.nx, dtau)

        # Set initial condition
        self.init_cond = init_cond
        self.vector_t_start = VectorHeat1D2Pts(self.nx, dtau)
        tmp1 = self.init_cond(self.x)
        # Use trapezoidal rule to get value at time dtau
        tmp2 = spsolve(
            (dtau / 2) * self.space_disc + self.identity,
            (self.identity -
             (dtau / 2) * self.space_disc) * tmp1 + (dtau / 2) *
            (self.rhs(self.x, self.t[0]) + self.rhs(self.x, self.t[0] + dtau)))
        self.vector_t_start.set_values(first_time_point=tmp1,
                                       second_time_point=tmp2,
                                       dtau=dtau)
Example #3
0
    def step(self, u_start: VectorHeat1D2Pts, t_start: float,
             t_stop: float) -> VectorHeat1D2Pts:
        """
        Time integration routine for 1D heat equation:
            BDF2

        Two-step method on variably spaced grid with spacing tau_i = t_i - t_{i-1}.
        In time-based stencil notation, we have at time point t_i
           [r_i^2/(tau_i*(1+r_i))*I,  -((1+r_i)/tau_i)*I,  (1+2r_i)/(tau_i*(1+r_i))*I + L,  0,  0],
        where L = self.space_disc is the spatial discretization operator and r_i = tau_i/tau_{i-1}

        Note: For the pair associated with input time t_stop
          * update at t_stop involves values at t_start and (t_start + dtau)
          * update at t_stop + dtau involves values at (t_start + dtau) and t_stop

        :param u_start: approximate solution for the input time t_start
        :param t_start: time associated with the input approximate solution u_start
        :param t_stop: time to evolve the input approximate solution to
        :return: approximate solution for the input time t_stop
        """
        first, second, dtau = u_start.get_values()

        # Update value at t_i = t_stop
        tau_i = t_stop - t_start - dtau
        tau_im1 = dtau
        r_i = tau_i / tau_im1
        coeffm2 = (r_i**2) / (tau_i * (1 + r_i))
        coeffm1 = (1 + r_i) / tau_i
        coeff = (1 + 2 * r_i) / (tau_i * (1 + r_i))
        rhs = self.rhs(self.x, t_stop) - coeffm2 * first + coeffm1 * second

        tmp1 = spsolve(self.space_disc + coeff * self.identity, rhs)

        # Update value at t_i = t_stop + dtau
        tau_im1 = tau_i
        tau_i = dtau
        r_i = tau_i / tau_im1
        coeffm2 = (r_i**2) / (tau_i * (1 + r_i))
        coeffm1 = (1 + r_i) / tau_i
        coeff = (1 + 2 * r_i) / (tau_i * (1 + r_i))
        rhs = self.rhs(self.x,
                       t_stop + dtau) - coeffm2 * second + coeffm1 * tmp1

        tmp2 = spsolve(self.space_disc + coeff * self.identity, rhs)

        ret = VectorHeat1D2Pts(u_start.size, u_start.dtau)
        ret.set_values(first_time_point=tmp1,
                       second_time_point=tmp2,
                       dtau=dtau)

        return ret
Example #4
0
def test_vector_heat_1d_2pts_sub():
    """
    Test __sub__
    """
    vector_heat_1d_2pts_1 = VectorHeat1D2Pts(size=3, dtau=0.1)
    vector_heat_1d_2pts_1.values_first_time_point = np.ones(3)
    vector_heat_1d_2pts_1.values_second_time_point = np.ones(3)
    vector_heat_1d_2pts_2 = VectorHeat1D2Pts(size=3, dtau=0.1)
    vector_heat_1d_2pts_2.values_first_time_point = 2 * np.ones(3)
    vector_heat_1d_2pts_2.values_second_time_point = 2 * np.ones(3)

    vector_heat_1d_2pts_res = vector_heat_1d_2pts_2 - vector_heat_1d_2pts_1
    np.testing.assert_equal(vector_heat_1d_2pts_res.values_first_time_point,
                            np.ones(3))
    np.testing.assert_equal(vector_heat_1d_2pts_res.values_second_time_point,
                            np.ones(3))
Example #5
0
def test_vector_heat_1d_2pts_get_values():
    """
    Test get_values()
    """
    vector_heat_1d_2pts = VectorHeat1D2Pts(size=5, dtau=0.1)
    np.testing.assert_equal(vector_heat_1d_2pts.get_values()[0], np.zeros(5))
    np.testing.assert_equal(vector_heat_1d_2pts.get_values()[1], np.zeros(5))
    np.testing.assert_equal(vector_heat_1d_2pts.get_values()[2], 0.1)
Example #6
0
def test_vector_heat_1d_2pts_norm():
    """
    Test norm()
    """
    vector_heat_1d_2pts = VectorHeat1D2Pts(size=5, dtau=0.1)
    vector_heat_1d_2pts.values_first_time_point = np.array([1, 2, 3, 4, 5])
    vector_heat_1d_2pts.values_second_time_point = np.array([1, 2, 3, 4, 5])
    np.testing.assert_equal(np.linalg.norm(np.append(np.array([1, 2, 3, 4, 5]), np.array([1, 2, 3, 4, 5]))),
                            vector_heat_1d_2pts.norm())
Example #7
0
def test_vector_heat_1d_2pts_set_values():
    """
    Test the set_values()
    """
    vector_heat_1d_2pts = VectorHeat1D2Pts(size=2, dtau=0.1)
    vector_heat_1d_2pts.set_values(first_time_point=np.array([1, 2]), second_time_point=np.array([2, 3]), dtau=0.1)
    np.testing.assert_equal(vector_heat_1d_2pts.values_first_time_point, np.array([1, 2]))
    np.testing.assert_equal(vector_heat_1d_2pts.values_second_time_point, np.array([2, 3]))
    np.testing.assert_equal(vector_heat_1d_2pts.dtau, 0.1)
Example #8
0
def test_vector_heat_1d_2pts_clone_rand():
    """
    Test clone_rand()
    """
    vector_heat_1d_2pts = VectorHeat1D2Pts(size=2, dtau=0.1)

    vector_heat_1d_2pts_clone = vector_heat_1d_2pts.clone_rand()

    np.testing.assert_equal(True, isinstance(vector_heat_1d_2pts_clone, VectorHeat1D2Pts))
    np.testing.assert_equal(vector_heat_1d_2pts_clone.size, 2)
    np.testing.assert_equal(vector_heat_1d_2pts_clone.dtau, 0.1)
    np.testing.assert_equal(len(vector_heat_1d_2pts_clone.values_first_time_point), 2)
    np.testing.assert_equal(len(vector_heat_1d_2pts_clone.values_second_time_point), 2)
Example #9
0
def test_vector_heat_1d_2pts_constructor():
    """
    Test constructor
    """
    vector_heat_1d_2pts = VectorHeat1D2Pts(size=3, dtau=0.1)
    np.testing.assert_equal(vector_heat_1d_2pts.size, 3)
    np.testing.assert_equal(vector_heat_1d_2pts.dtau, 0.1)

    np.testing.assert_equal(vector_heat_1d_2pts.values_first_time_point[0], 0)
    np.testing.assert_equal(vector_heat_1d_2pts.values_first_time_point[1], 0)
    np.testing.assert_equal(vector_heat_1d_2pts.values_first_time_point[2], 0)

    np.testing.assert_equal(vector_heat_1d_2pts.values_second_time_point[0], 0)
    np.testing.assert_equal(vector_heat_1d_2pts.values_second_time_point[1], 0)
    np.testing.assert_equal(vector_heat_1d_2pts.values_second_time_point[2], 0)
Example #10
0
def test_vector_heat_1d_2pts_mul():
    """
    Test __mul__
    """
    vector_heat_1d_2pts_1 = VectorHeat1D2Pts(size=3, dtau=0.1)
    vector_heat_1d_2pts_1.values_first_time_point = np.ones(3)
    vector_heat_1d_2pts_1.values_second_time_point = np.ones(3)

    vector_heat_1d_2pts_res = vector_heat_1d_2pts_1 * 3
    np.testing.assert_equal(vector_heat_1d_2pts_res.values_first_time_point, np.ones(3)*3)
    np.testing.assert_equal(vector_heat_1d_2pts_res.values_second_time_point, np.ones(3)*3)

    vector_heat_1d_2pts_res = 5 * vector_heat_1d_2pts_1
    np.testing.assert_equal(vector_heat_1d_2pts_res.values_first_time_point, np.ones(3)*5)
    np.testing.assert_equal(vector_heat_1d_2pts_res.values_second_time_point, np.ones(3)*5)

    vector_heat_1d_2pts_res *= 4
    np.testing.assert_equal(vector_heat_1d_2pts_res.values_first_time_point, np.ones(3)*20)
    np.testing.assert_equal(vector_heat_1d_2pts_res.values_second_time_point, np.ones(3)*20)