Example #1
0
    def solve_at_T(self, T, mx, mt, plot=False, animate=False):
        xs, u = tsunami_solve(mx, mt, self.L, T, self.h0, self.h, self.wave)

        if plot:
            plot_solution(xs, u[-1], uexact=self.seabed, style='r-')
        if animate:
            animate_tsunami(xs, u, self.L)

        return u[-1]
Example #2
0
def backwardeuler(mx, mt, L, T, kappa, source, ic, lbc, rbc, lbctype, rbctype):
    """Backward Euler finite-difference scheme (implicit) for solving 
    parabolic PDE problems. Unconditionally stable"""

    # initialise
    xs, ts, deltax, deltat, lmbda = initialise(mx, mt, L, T, kappa)

    ic, lbc, rbc, source = numpify_many((ic, 'x'), (lbc, 'x'), (rbc, 'x'),
                                        (source, 'x t'))

    u_j = ic(xs)
    print(type(u_j))
    plot_solution(xs, u_j)
    # if boundary conditions don't match initial conditions
    if lbctype == 'Dirichlet':
        u_j[0] = lbc(0)
    if rbctype == 'Dirichlet':
        u_j[mx] = rbc(0)

    u_jp1 = np.zeros(xs.size)

    # Construct forward Euler matrix
    B_FE = tridiag(mx + 1, -lmbda, 1 + 2 * lmbda, -lmbda)

    # modify first and last row for Neumann conditions
    B_FE[0, 1] *= 2
    B_FE[mx, mx - 1] *= 2

    # range of rows of B_FE to use
    a, b = matrixrowrange(mx, lbctype, rbctype)
    print(a, b)
    # Solve the PDE at each time step
    for t in ts[:-1]:
        addboundaries(u_j, lbctype, rbctype, lmbda * lbc(t + deltat),
                      lmbda * rbc(t + deltat),
                      -2 * lmbda * deltax * lbc(t + deltat),
                      2 * lmbda * deltax * rbc(t + deltat))

        u_jp1[a:b] = spsolve(B_FE[a:b, a:b], u_j[a:b])

        # fix Dirichlet boundary conditions
        if lbctype == 'Dirichlet':
            u_jp1[0] = lbc(t + deltat)
        if rbctype == 'Dirichlet':
            u_jp1[mx] = rbc(t + deltat)

        # add source to inner terms
        u_jp1[1:-1] += deltat * source(xs[1:-1], t + deltat)

        u_j[:] = u_jp1[:]

    return xs, u_j
Example #3
0
def solver_demonstration():
    mx = 30
    mt = 1000
    L = 1
    T = 0.5

    def uI(x):
        return np.sin(np.pi * x / L)

    xs, uT, lmbda = backwardeuler(mx, mt, L, T, 1, 0, uI, 0, 0, 'Dirichlet',
                                  'Dirichlet')

    plot_solution(xs, uT)
Example #4
0
    def solve_at_T(self,
                   T,
                   mx,
                   mt,
                   scheme,
                   u_exact=None,
                   plot=True,
                   norm='L2',
                   title=''):
        """
        Solve the diffusion equation at time T with grid spacing mx x mt.
        
        Parameters
        T        time to stop the integration
        mx       number of grid points in space
        mt       number of grid points in time
        scheme   the solver to use e.g. forwardeuler, cranknicholson
        u_exact  the exact solution (sympy expression)
        plot     plot the results if True
        title    title for the plot
        
        Returns
        uT       the solution at time T
        err      the absolute error (if u_exact is given)
        """

        # solve the PDE by the given scheme
        xs, uT, lmbda = (SCHEMES[scheme])(mx, mt, self.L, T, self.kappa,
                                          self.source, self.ic, self.lbc.rhs,
                                          self.rbc.rhs, self.lbc.type,
                                          self.rbc.type)

        if u_exact:
            # substitute in the values of kappa, L and T
            uTsym = u_exact.subs({kappa: self.kappa, L: self.L, t: T})
            # calculate absolute error
            error = get_error(xs, uT, uTsym, norm=norm)
            if plot:
                plot_solution(xs,
                              uT,
                              uTsym,
                              title=title,
                              uexacttitle=r'${}$'.format(sp.latex(uTsym)))
        else:
            error = None
            if plot:
                plot_solution(xs, uT, title=title)

        return uT, error, lmbda
Example #5
0
    def solve_at_T(self, T, mx, mt, scheme, plot=True, u_exact=None, title=''):
        xs, uT = scheme(mx, mt, self.L, T, self.c, self.source, self.ix,
                        self.iv, self.lbc.apply_rhs, self.rbc.apply_rhs,
                        self.lbc.get_type(), self.rbc.get_type())
        if u_exact:
            uTsym = u_exact.subs({c: self.c, L: self.L, t: T})
            #u = sp.lambdify(x, uTsym)
            u = numpify((uTsym, 'x'))
            error = np.linalg.norm(u(xs) - uT)
            if plot:
                plot_solution(xs,
                              uT,
                              u,
                              title=title,
                              uexacttitle=r'${}$'.format(sp.latex(uTsym)))
        else:
            error = None
            if plot:
                plot_solution(xs, uT, title=title)

        return uT, error