Ejemplo n.º 1
0
    def __init__(self, degree):

        b_degree = degree - 3
        x = Symbol('x')
        poly_set = leg.basis_functions(deg=degree)
        pts0 = gauss_legendre_points(b_degree+1)[1:-1]
        pts1 = np.array([-1., 1.])
        # The coefficient matrix
        B = np.zeros((degree+1, degree+1))
        B[:, 0] = [(-1)**k for k in range(degree+1)] # Values are (-1)
        B[:, 1] = np.ones(degree+1)                  # Values at (1)

        # Val at -1, val at 1, dval at -1, dval at 1, the rest of polyevaluas.
        for row, f in enumerate(poly_set):
            vals = lambdify(x, f, 'numpy')(pts0)
            if isinstance(vals, (int, float)): vals = vals*np.ones(len(pts0))
            dvals = lambdify(x, f.diff(x, 1), 'numpy')(pts1)
            if isinstance(dvals, (int, float)): dvals = dvals*np.ones(len(pts1))

            B[row, 2:4] = dvals
            B[row, 4:] = vals

        # Invert to get the coefficients of the nodal basis
        self.alpha = np.linalg.inv(B)
        # Having coeffcient comes in handy if some matrix M is given w.r.t
        # poly_set basis then alpha.M.alpha.T is the matrix represented in
        # nodal basis

        # Symbolic nodal basis
        self.sym_basis = [sum(c*f for c, f in zip(row, poly_set))
                          for row in self.alpha]
        # For numerical evaluation the row in alpha are coeffcients of Legendre
        # polynomials so we can use legval
        
        # Finally remember the dofs as coordinates val, val, dval, dval
        self.dofs = np.hstack([pts1, pts1, pts0])

        # And my finite element
        self.cell = ReferenceIntervalCell()

        # HACK computing df/dx without the derivatives. This is exact for P3 and
        # lower. Represent the L(f) = df/dx(p) = \int Riesz(L) * f dx
        # Riesz(L) = l is a polynomial of degree 3-compute its coeficients
        # They are given by mass matrix of the nodal basis
        xq, wq = np.polynomial.legendre.leggauss(degree+1)
        M = self.alpha.dot(leg.mass_matrix(degree).dot(self.alpha.T))
        beta = np.linalg.inv(M)
        # Now I have expansion w.r.t nodal. Combine with alpha to get Legendre
        # beta = beta.dot(self.alpha)
        # beta[2:4] are the coefs of df/dx eval at -1 and 1. Need them only at
        # quadrature points
        self.riesz = (np.polynomial.legendre.legval(xq, beta[2].dot(self.alpha)),
                      np.polynomial.legendre.legval(xq, beta[3].dot(self.alpha)))
        # Remember these for later evaluations
        self.quad = xq, wq
Ejemplo n.º 2
0
def solve(n_cells, degree=3, with_plot=False):
    # Space
    # element = HermiteElement(degree)
    poly_set = leg.basis_functions(degree)
    dof_set = equidistant_points(degree)
    element = LagrangeElement(poly_set, dof_set)

    a, b = -1., 1.
    mesh = IntervalMesh(a=a, b=b, n_cells=n_cells)
    V = FunctionSpace(mesh, element)

    # Need mass matrix to intefrate the rhs
    Mget_geom_tensor = lambda cell: 1./cell.Jac
    M = assemble_matrix(V, 'mass', Mget_geom_tensor, timer=0)
    
    # Stiffness matrix for Laplacian
    Aget_geom_tensor = lambda cell: cell.Jac
    A = assemble_matrix(V, 'stiff', Aget_geom_tensor, timer=0)

    print 'M sym', is_symmetric(M)
    print 'A sym', is_symmetric(A)

    ew, ev = eigh(A.toarray(), M.toarray())
    ew = np.abs(ew)

    # Now add inner(dot(grad(u), n), v)*ds
    G = get_G(V)
    # A = A - G

    # print 'A sym', is_symmetric(A)
    # ew, ev = eig(A.toarray())#, M.toarray())
    # ew = np.sort(np.abs(ew))[:3]
    # print ew

    # from sympy import symbols, sqrt, S

    # x = symbols('x')
    # nullspace = map(Expression, [S(1/2.), sqrt(3/2.)*x])

    # Z = [V.interpolate(f).vector for f in nullspace]

    # print [np.inner(pi_z, A.dot(pi_z)) for pi_z in Z]

    print 'xxx'
    print M.toarray()
    print
    print A.toarray()
    print
    print G.toarray()
Ejemplo n.º 3
0
def get_bubble(deg):
    x = Symbol('x')
    poly_set = leg.basis_functions(deg=deg)
    pts = np.r_[-1, 1, chebyshev_points(deg)[1:-1]]
    
    A = np.zeros((deg+1, deg+1))
    for col, f in enumerate(poly_set):
        A[:, col] = lambdify(x, poly_set[col], 'numpy')(pts)
    b = np.zeros(deg+1)
    nodal_pt_index = -1 if deg % 2 else -deg/2
    b[nodal_pt_index] = 1

    bubble = np.linalg.solve(A, b)
    bubble_dof = pts[nodal_pt_index]  # Point eval here
    # Return coefs of bubble w.r.t legendre and the node
    return bubble, bubble_dof
Ejemplo n.º 4
0
from __future__ import division
import sys
sys.path.append('../')
import polynomials.legendre_basis as leg
from points import chebyshev_points
from sympy import lambdify, Symbol, integrate
from sympy.plotting import plot
import numpy as np

deg = 10
# Suppose I want to find some polynomial of degree 2 over -1, 1 that has
# 0 boundary values

x = Symbol('x')
poly_set = leg.basis_functions(deg=deg)

# f = a*l0 + b*l1 + c*l2
# Suppose we reure that the L-2 norm is 1
# [f(-1)=0] = [l0(-1), l1(-1), l2(-1) ] [a]
# [f(1)=0 ] = [l0(1), l1(1), l2(1) ] [b]
# [norm=1 ] = [(l0, l0), ...            [c]    
# suppose instead nodality at 0
# [f(0) = 1] = .....

A = np.zeros((deg+1, deg+1))

pts = np.r_[-1, 1, chebyshev_points(deg)[1:-1]]

for col, f in enumerate(poly_set):
    A[:, col] = lambdify(x, poly_set[col], 'numpy')(pts)
Ejemplo n.º 5
0
            return f.eval_cell(cell.map_from_reference(self.dofs[i]), cell)

    def eval_dofs(self, f, cell=None):
        '''Evaluate all dofs'''
        return np.vstack([self.eval_dof(i, f, cell) for i in range(self.dim)])

# -----------------------------------------------------------------------------

if __name__ == '__main__':
    from sympy import integrate
    from numpy.polynomial.legendre import leggauss
    from function import Expression

    degree = 4
    element = HermiteElement(degree)
    poly_set = leg.basis_functions(degree)
    x = Symbol('x')

    from mesh import IntervalCell
    import matplotlib.pyplot as plt

    fig, (ax0, ax1) = plt.subplots(2, 1, sharex=True)

    # Funcions and derivatives. Check continuity
    for a, b in [(-1.4, -1), (-1, 1), (1, 2), (2, 4)]:
        x = np.linspace(a, b, 100)
        cell = IntervalCell(np.array([[a], [b]]))
        for i, color in zip(range(element.dim), ['r', 'b', 'g', 'c', 'm', 'k']):

            y = element.eval_basis(i, x, cell)
            ax0.plot(x, y, color=color)
Ejemplo n.º 6
0
def cg_optimal_dofs_restricted(deg, vary=0):
    '''
    What are optimal dofs that give smallest condition number in L^2 norm.
    By CG I mean that I constraint two dofs to be at (-1, 1). The remaining
    deg-1 points are to be determined. For even degrees symmetry is dof at 0 is
    also forced
    
    For vary None: the symmetry is used and `all` the points are used for
    search, i.e. this is multi-d problem.

    For vary=int: that guy and its mirror are changed, i.e. this is
    1-d optimization problem.
    '''
    poly_set = leg.basis_functions(deg)
    M = leg.mass_matrix(deg)

    # Only allow negative (make life easier for mirroring) and not midpoint or -1
    if vary: assert 0 < vary < (deg/2 + 1 if deg % 2 else deg/2)

    # Want to minimize this
    def cond_number(x):
        # 2: [-1, y0, -1]
        # (3, 4): [-1, y0, -y0, -1], [-1, -y0, 0, y0, 1],
        # (5, 6): [-1, y0, y1, -y1, -y0, -1], [-1, y0, y1, 0, -y1, -y0, -1]
        # One-d optimzation
        if vary:
            x_ = chebyshev_points(deg)
            x_[vary] = x
            x_[deg-vary] = -x
            dof_set = x_
        # Multi-d optimization
        else:
            if deg == 2:
                dof_set = np.r_[-1, x, 1]
            # Combine no zero
            elif deg % 2 == 1:
                dof_set = np.r_[-1, x, -x[::-1], 1]
            # Combine w/ zero
            else:
                dof_set = np.r_[-1, x, 0, -x[::-1], 1]

        element = LagrangeElement(poly_set, dof_set)
        alpha = element.alpha
        M_  = alpha.dot(M.dot(alpha.T))
        return np.linalg.cond(M_)

    # Initial guess
    # 1d optim
    x0 = chebyshev_points(deg)
    if vary:
        x0 = x0[vary]
    else:
        # Multi-d optim
        if deg == 2:
            x0 = x0[1]
        # Combine no zero
        elif deg % 2 == 1:
            x0 = x0[1:deg/2+1]
        else:
            x0 = x0[1:deg/2]
    
    # Optimize
    res = minimize(cond_number, x0)

    return res, x0, cond_number(x0)
Ejemplo n.º 7
0
def _solve(mode, points, degree, n_cells, u, f):
    '''
    In mode == convergence:
    Solve -u`` = f with dirichet bcs bdry of (-1, 1) given by exact solution.
    The Vh space is CG_space of degree elements and n_cells. Return hmin, error
    for convergence computation.

    In mode == cond:
    Just return h and the matrix A.
    '''
    # Element. The polynomial space is spanned by Legendre basis
    poly_set = leg.basis_functions(degree)
    dof_set = points(degree)
    element = LagrangeElement(poly_set, dof_set)

    # Mesh
    mesh = IntervalMesh(a=-1, b=1, n_cells=n_cells)

    # Space
    V = FunctionSpace(mesh, element)
    bc = DirichletBC(V, u)

    # Need mass matrix to intefrate the rhs
    Mpoly_matrix = leg.mass_matrix(degree)
    Mget_geom_tensor = lambda cell: 1./cell.Jac
    M = assemble_matrix(V, Mpoly_matrix, Mget_geom_tensor, timer=0)
    
    # Stiffness matrix for Laplacian
    Apoly_matrix = leg.stiffness_matrix(degree)
    Aget_geom_tensor = lambda cell: cell.Jac
    A = assemble_matrix(V, Apoly_matrix, Aget_geom_tensor, timer=0)
   
    # Interpolant of source
    fV = V.interpolate(f)
    # Integrate in L2 to get the vector
    b = M.dot(fV.vector)
    
    # Apply boundary conditions
    bc.apply(A, b, True)
    x = spsolve(A, b)

    if mode == 'condition':
        return mesh.hmin(), A

    # As function
    uh = Function(V, x)
   
    # Error norm
    # Higher order DG element
    fine_degree = degree + 3
    poly_set = leg.basis_functions(fine_degree)
    dof_set = chebyshev_points(fine_degree)
    element = LagrangeElement(poly_set, dof_set)
    # THe space
    V_fine = FunctionSpace(mesh, element, 'L2')
    # Interpolate exact solution to fine
    u_fine = V_fine.interpolate(u)
    # Interpolate approx solution fine
    uh_fine = V_fine.interpolate(uh)

    # Difference vector
    e = u_fine.vector - uh_fine.vector
    # Need matrix for integration of H10 norm
    Apoly_matrix = leg.stiffness_matrix(fine_degree)
    A_fine = assemble_matrix(V_fine, Apoly_matrix, Aget_geom_tensor, timer=1)
    # Integrate the error
    e = sqrt(np.sum(e*A_fine.dot(e)))
    # Mesh size
    hmin = mesh.hmin()

    return hmin, e
Ejemplo n.º 8
0
def solve(n_cells, degree=3, with_plot=False):
    # Problem
    w = 3 * np.pi
    x = Symbol("x")
    u = sin(w * x)
    f = -u.diff(x, 2)

    # As Expr
    u = Expression(u)
    f = Expression(f)

    # Space
    # element = HermiteElement(degree)
    poly_set = leg.basis_functions(degree)
    dof_set = chebyshev_points(degree)
    element = LagrangeElement(poly_set, dof_set)

    mesh = IntervalMesh(a=-1, b=1, n_cells=n_cells)
    V = FunctionSpace(mesh, element)
    bc = DirichletBC(V, u)

    # Need mass matrix to intefrate the rhs
    M = assemble_matrix(V, "mass", get_geom_tensor=None, timer=0)
    # NOTE We cannot you apply the alpha transform idea because the functions
    # are mapped with this selective weight on 2nd, 3rd functions. So some rows
    # of alpha would have to be multiplied by weights which are cell specific.
    # And then on top of this there would be a dx = J*dy term. Better just to
    # use the qudrature representations
    # Mpoly_matrix = leg.mass_matrix(degree)
    # M_ = assemble_matrix(V, Mpoly_matrix, Mget_geom_tensor, timer=0)

    # Stiffness matrix for Laplacian
    A = assemble_matrix(V, "stiffness", get_geom_tensor=None, timer=0)
    # NOTE the above
    # Apoly_matrix = leg.stiffness_matrix(degree)
    # A_ = assemble_matrix(V, Apoly_matrix, Aget_geom_tensor, timer=0)

    # Interpolant of source
    fV = V.interpolate(f)
    # Integrate in L2 to get the vector
    b = M.dot(fV.vector)

    # Apply boundary conditions
    bc.apply(A, b, True)
    x = spsolve(A, b)

    # As function
    uh = Function(V, x)

    # This is a (slow) way of plotting the high order
    if with_plot:
        fig = plt.figure()
        ax = fig.gca()
        uV = V.interpolate(u)

        for cell in Cells(mesh):
            a, b = cell.vertices[0, 0], cell.vertices[1, 0]
            x = np.linspace(a, b, 100)

            y = uh.eval_cell(x, cell)
            ax.plot(x, y, color=random.choice(["b", "g", "m", "c"]))

            y = uV.eval_cell(x, cell)
            ax.plot(x, y, color="r")

            y = u.eval_cell(x, cell)
            ax.plot(x, y, color="k")

        plt.show()

    # Error norm in CG high order
    fine_degree = degree + 3
    poly_set = leg.basis_functions(fine_degree)
    dof_set = chebyshev_points(fine_degree)
    element = LagrangeElement(poly_set, dof_set)

    V_fine = FunctionSpace(mesh, element)
    # Interpolate exact solution to fine
    u_fine = V_fine.interpolate(u)
    # Interpolate approx solution fine
    uh_fine = V_fine.interpolate(uh)

    # Difference vector
    e = u_fine.vector - uh_fine.vector

    # L2
    if False:
        Apoly_matrix = leg.mass_matrix(fine_degree)
        get_geom_tensor = lambda cell: 1.0 / cell.Jac

    # Need matrix for integration of H10 norm
    else:
        Apoly_matrix = leg.stiffness_matrix(fine_degree)
        get_geom_tensor = lambda cell: cell.Jac

    A_fine = assemble_matrix(V_fine, Apoly_matrix, get_geom_tensor, timer=0)

    # Integrate the error
    e = sqrt(np.sum(e * A_fine.dot(e)))
    # Mesh size
    hmin = mesh.hmin()

    # Add the cond number
    kappa = np.linalg.cond(A.toarray())

    return hmin, e, kappa, A.shape[0]