예제 #1
0
    def test_assemble_iiform(self):

        mesh = Mesh1D(resolution=(1, ))

        Q1 = QuadFE(1, 'DQ1')
        dofhandler = DofHandler(mesh, Q1)
        dofhandler.distribute_dofs()

        phi = Basis(dofhandler, 'u')

        k = Explicit(lambda x, y: x * y, n_variables=2, dim=1)
        kernel = Kernel(k)

        form = IIForm(kernel, test=phi, trial=phi)

        assembler = Assembler(form, mesh)
        assembler.assemble()
        Ku = Nodal(lambda x: 1 / 3 * x, basis=phi)

        #af = assembler.af[0]['bilinear']
        M = assembler.get_matrix().toarray()

        u = Nodal(lambda x: x, basis=phi)
        u_vec = u.data()
        self.assertTrue(np.allclose(M.dot(u_vec), Ku.data()))
예제 #2
0
    def test_assemble_ipform(self):
        # =====================================================================
        # Test 7: Assemble Kernel
        # =====================================================================
        mesh = Mesh1D(resolution=(10, ))

        Q1 = QuadFE(1, 'DQ1')
        dofhandler = DofHandler(mesh, Q1)
        dofhandler.distribute_dofs()

        phi = Basis(dofhandler, 'u')

        k = Explicit(lambda x, y: x * y, n_variables=2, dim=1)
        kernel = Kernel(k)
        form = IPForm(kernel, test=phi, trial=phi)

        assembler = Assembler(form, mesh)
        assembler.assemble()

        #af = assembler.af[0]['bilinear']
        M = assembler.get_matrix().toarray()

        u = Nodal(lambda x: x, basis=phi)
        v = Nodal(lambda x: 1 - x, basis=phi)

        u_vec = u.data()
        v_vec = v.data()

        I = v_vec.T.dot(M.dot(u_vec))
        self.assertAlmostEqual(I[0, 0], 1 / 18)
예제 #3
0
    def test02_1d_dirichlet_higher_order(self):
        mesh = Mesh1D()
        for etype in ['Q2', 'Q3']:
            element = QuadFE(1, etype)
            dofhandler = DofHandler(mesh, element)
            dofhandler.distribute_dofs()

            # Basis functions
            ux = Basis(dofhandler, 'ux')
            u = Basis(dofhandler, 'u')

            # Exact solution
            ue = Nodal(f=lambda x: x * (1 - x), basis=u)

            # Define coefficient functions
            one = Constant(1)
            two = Constant(2)

            # Define forms
            a = Form(kernel=Kernel(one), trial=ux, test=ux)
            L = Form(kernel=Kernel(two), test=u)
            problem = [a, L]

            # Assemble problem
            assembler = Assembler(problem, mesh)
            assembler.assemble()

            A = assembler.get_matrix()
            b = assembler.get_vector()

            # Set up linear system
            system = LinearSystem(u, A=A, b=b)

            # Boundary functions
            bnd_left = lambda x: np.abs(x) < 1e-9
            bnd_right = lambda x: np.abs(1 - x) < 1e-9

            # Mark mesh
            mesh.mark_region('left', bnd_left, entity_type='vertex')
            mesh.mark_region('right', bnd_right, entity_type='vertex')

            # Add Dirichlet constraints to system
            system.add_dirichlet_constraint('left', 0)
            system.add_dirichlet_constraint('right', 0)

            # Solve system
            system.solve_system()
            system.resolve_constraints()

            # Compare solution with the exact solution
            ua = system.get_solution(as_function=True)
            self.assertTrue(np.allclose(ua.data(), ue.data()))
예제 #4
0
    def test01_solve_2d(self):
        """
        Solve a simple 2D problem with no hanging nodes
        """
        mesh = QuadMesh(resolution=(5, 5))

        # Mark dirichlet boundaries
        mesh.mark_region('left',
                         lambda x, dummy: np.abs(x) < 1e-9,
                         entity_type='half_edge')

        mesh.mark_region('right',
                         lambda x, dummy: np.abs(x - 1) < 1e-9,
                         entity_type='half_edge')

        Q1 = QuadFE(mesh.dim(), 'Q1')
        dQ1 = DofHandler(mesh, Q1)
        dQ1.distribute_dofs()

        phi = Basis(dQ1, 'u')
        phi_x = Basis(dQ1, 'ux')
        phi_y = Basis(dQ1, 'uy')

        problem = [
            Form(1, test=phi_x, trial=phi_x),
            Form(1, test=phi_y, trial=phi_y),
            Form(0, test=phi)
        ]

        assembler = Assembler(problem, mesh)
        assembler.add_dirichlet('left', dir_fn=0)
        assembler.add_dirichlet('right', dir_fn=1)
        assembler.assemble()

        # Get matrix dirichlet correction and right hand side
        A = assembler.get_matrix().toarray()
        x0 = assembler.assembled_bnd()
        b = assembler.get_vector()

        ua = np.zeros((phi.n_dofs(), 1))
        int_dofs = assembler.get_dofs('interior')
        ua[int_dofs, 0] = np.linalg.solve(A, b - x0)

        dir_bc = assembler.get_dirichlet()
        dir_vals = np.array([dir_bc[dof] for dof in dir_bc])
        dir_dofs = [dof for dof in dir_bc]
        ua[dir_dofs] = dir_vals

        ue_fn = Nodal(f=lambda x: x[:, 0], basis=phi)
        ue = ue_fn.data()
        self.assertTrue(np.allclose(ue, ua))
        self.assertTrue(np.allclose(x0 + A.dot(ua[int_dofs, 0]), b))
예제 #5
0
    def test01_solve_1d(self):
        """
        Test solving 1D systems
        """
        mesh = Mesh1D(resolution=(20, ))
        mesh.mark_region('left', lambda x: np.abs(x) < 1e-9)
        mesh.mark_region('right', lambda x: np.abs(x - 1) < 1e-9)

        Q1 = QuadFE(1, 'Q1')
        dQ1 = DofHandler(mesh, Q1)
        dQ1.distribute_dofs()

        phi = Basis(dQ1, 'u')
        phi_x = Basis(dQ1, 'ux')

        problem = [Form(1, test=phi_x, trial=phi_x), Form(0, test=phi)]
        assembler = Assembler(problem, mesh)
        assembler.add_dirichlet('left', dir_fn=0)
        assembler.add_dirichlet('right', dir_fn=1)
        assembler.assemble()

        # Get matrix dirichlet correction and right hand side
        A = assembler.get_matrix().toarray()
        x0 = assembler.assembled_bnd()
        b = assembler.get_vector()

        ua = np.zeros((phi.n_dofs(), 1))
        int_dofs = assembler.get_dofs('interior')
        ua[int_dofs, 0] = np.linalg.solve(A, b - x0)

        dir_bc = assembler.get_dirichlet()
        dir_vals = np.array([dir_bc[dof] for dof in dir_bc])
        dir_dofs = [dof for dof in dir_bc]
        ua[dir_dofs] = dir_vals

        ue_fn = Nodal(f=lambda x: x[:, 0], basis=phi)
        ue = ue_fn.data()
        self.assertTrue(np.allclose(ue, ua))
        self.assertTrue(np.allclose(x0 + A.dot(ua[int_dofs, 0]), b))
예제 #6
0
    def test08_1d_sampled_rhs(self):
        #
        # Mesh
        #
        mesh = Mesh1D(resolution=(1, ))
        mesh.mark_region('left', lambda x: np.abs(x) < 1e-9, on_boundary=True)
        mesh.mark_region('right',
                         lambda x: np.abs(1 - x) < 1e-9,
                         on_boundary=True)

        #
        # Elements
        #
        Q3 = QuadFE(1, 'Q3')
        dofhandler = DofHandler(mesh, Q3)
        dofhandler.distribute_dofs()

        #
        # Basis
        #
        v = Basis(dofhandler, 'u')
        vx = Basis(dofhandler, 'ux')

        #
        # Define sampled right hand side and exact solution
        #
        xv = dofhandler.get_dof_vertices()
        n_points = dofhandler.n_dofs()

        n_samples = 6
        a = np.arange(n_samples)

        f = lambda x, a: a * x
        u = lambda x, a: a / 6 * (x - x**3) + x
        fdata = np.zeros((n_points, n_samples))
        udata = np.zeros((n_points, n_samples))
        for i in range(n_samples):
            fdata[:, i] = f(xv, a[i]).ravel()
            udata[:, i] = u(xv, a[i]).ravel()

        # Define sampled function
        fn = Nodal(data=fdata, basis=v)
        ue = Nodal(data=udata, basis=v)

        #
        # Forms
        #
        one = Constant(1)
        a = Form(Kernel(one), test=vx, trial=vx)
        L = Form(Kernel(fn), test=v)
        problem = [a, L]

        #
        # Assembler
        #
        assembler = Assembler(problem, mesh)
        assembler.assemble()
        A = assembler.get_matrix()
        b = assembler.get_vector()
        #
        # Linear System
        #
        system = LinearSystem(v, A=A, b=b)

        # Set constraints
        system.add_dirichlet_constraint('left', 0)
        system.add_dirichlet_constraint('right', 1)
        #system.set_constraint_relation()
        #system.incorporate_constraints()

        # Solve and resolve constraints
        system.solve_system()
        #system.resolve_constraints()

        # Extract finite element solution
        ua = system.get_solution(as_function=True)

        # Check that the solution is close
        print(ue.data()[:, [0]])
        print(ua.data())
        self.assertTrue(np.allclose(ue.data()[:, [0]], ua.data()))
예제 #7
0
    def test05_2d_dirichlet(self):
        """
        Two dimensional Dirichlet problem with hanging nodes
        """
        #
        # Define mesh
        #
        mesh = QuadMesh(resolution=(1, 2))
        mesh.cells.get_child(1).mark(1)
        mesh.cells.refine(refinement_flag=1)
        mesh.cells.refine()

        #
        # Mark left and right boundaries
        #
        bm_left = lambda x, dummy: np.abs(x) < 1e-9
        bm_right = lambda x, dummy: np.abs(1 - x) < 1e-9
        mesh.mark_region('left', bm_left, entity_type='half_edge')
        mesh.mark_region('right', bm_right, entity_type='half_edge')

        for etype in ['Q1', 'Q2', 'Q3']:
            #
            # Element
            #
            element = QuadFE(2, etype)
            dofhandler = DofHandler(mesh, element)
            dofhandler.distribute_dofs()

            #
            # Basis
            #
            u = Basis(dofhandler, 'u')
            ux = Basis(dofhandler, 'ux')
            uy = Basis(dofhandler, 'uy')

            #
            # Construct forms
            #
            ue = Nodal(f=lambda x: x[:, 0], basis=u)
            ax = Form(kernel=Kernel(Constant(1)), trial=ux, test=ux)
            ay = Form(kernel=Kernel(Constant(1)), trial=uy, test=uy)
            L = Form(kernel=Kernel(Constant(0)), test=u)
            problem = [ax, ay, L]

            #
            # Assemble
            #
            assembler = Assembler(problem, mesh)
            assembler.assemble()

            #
            # Get system matrices
            #
            A = assembler.get_matrix()
            b = assembler.get_vector()

            #
            # Linear System
            #
            system = LinearSystem(u, A=A, b=b)

            #
            # Constraints
            #
            # Add dirichlet conditions
            system.add_dirichlet_constraint('left', ue)
            system.add_dirichlet_constraint('right', ue)

            #
            # Solve
            #
            system.solve_system()
            #system.resolve_constraints()

            #
            # Check solution
            #
            ua = system.get_solution(as_function=True)
            self.assertTrue(np.allclose(ua.data(), ue.data()))
예제 #8
0
    def test01_1d_dirichlet_linear(self):
        """
        Solve one dimensional boundary value problem with dirichlet 
        conditions on left and right
        """
        #
        # Define mesh
        #
        mesh = Mesh1D(resolution=(10, ))

        for etype in ['Q1', 'Q2', 'Q3']:
            element = QuadFE(1, etype)
            dofhandler = DofHandler(mesh, element)
            dofhandler.distribute_dofs()
            phi = Basis(dofhandler)
            #
            # Exact solution
            #
            ue = Nodal(f=lambda x: x, basis=phi)

            #
            # Define Basis functions
            #
            u = Basis(dofhandler, 'u')
            ux = Basis(dofhandler, 'ux')

            #
            # Define bilinear form
            #
            one = Constant(1)
            zero = Constant(0)
            a = Form(kernel=Kernel(one), trial=ux, test=ux)
            L = Form(kernel=Kernel(zero), test=u)
            problem = [a, L]

            #
            # Assemble
            #
            assembler = Assembler(problem, mesh)
            assembler.assemble()

            #
            # Form linear system
            #

            A = assembler.get_matrix()
            b = assembler.get_vector()

            system = LinearSystem(u, A=A, b=b)

            #
            # Dirichlet conditions
            #

            # Boundary functions
            bm_left = lambda x: np.abs(x) < 1e-9
            bm_rght = lambda x: np.abs(x - 1) < 1e-9

            # Mark boundary regions
            mesh.mark_region('left', bm_left, on_boundary=True)
            mesh.mark_region('right', bm_rght, on_boundary=True)

            # Add Dirichlet constraints
            system.add_dirichlet_constraint('left', ue)
            system.add_dirichlet_constraint('right', ue)

            #
            # Solve system
            #
            #system.solve_system()
            system.solve_system()

            #
            # Get solution
            #
            #ua = system.get_solution(as_function=True)
            uaa = system.get_solution(as_function=True)
            #uaa = uaa.data().ravel()

            # Compare with exact solution
            #self.assertTrue(np.allclose(ua.data(), ue.data()))
            self.assertTrue(np.allclose(uaa.data(), ue.data()))
예제 #9
0
    def test04_1d_periodic(self):
        #
        # Dirichlet Problem on a Periodic Mesh
        #

        # Define mesh, element
        mesh = Mesh1D(resolution=(100, ), periodic=True)
        element = QuadFE(1, 'Q3')
        dofhandler = DofHandler(mesh, element)
        dofhandler.distribute_dofs()

        # Basis functions
        u = Basis(dofhandler, 'u')
        ux = Basis(dofhandler, 'ux')

        # Exact solution
        ue = Nodal(f=lambda x: np.sin(2 * np.pi * x), basis=u)

        #
        # Mark dirichlet regions
        #
        bnd_left = lambda x: np.abs(x) < 1e-9
        mesh.mark_region('left', bnd_left, entity_type='vertex')

        #
        # Set up forms
        #

        # Bilinear form
        a = Form(kernel=Kernel(Constant(1)), trial=ux, test=ux)

        # Linear form
        f = Explicit(lambda x: 4 * np.pi**2 * np.sin(2 * np.pi * x), dim=1)
        L = Form(kernel=Kernel(f), test=u)

        #
        # Assemble
        #
        problem = [a, L]
        assembler = Assembler(problem, mesh)
        assembler.assemble()
        A = assembler.get_matrix()
        b = assembler.get_vector()

        #
        # Linear System
        #
        system = LinearSystem(u, A=A, b=b)

        # Add dirichlet constraint
        system.add_dirichlet_constraint('left', 0, on_boundary=False)

        # Assemble constraints
        #system.set_constraint_relation()
        #system.incorporate_constraints()
        system.solve_system()
        #system.resolve_constraints()

        # Compare with interpolant of exact solution
        ua = system.get_solution(as_function=True)

        #plot = Plot(2)
        #plot.line(ua)
        #plot.line(ue)
        self.assertTrue(np.allclose(ua.data(), ue.data()))
예제 #10
0
def test_ft():
    plot = Plot()
    vb = Verbose()

    # =============================================================================
    # Parameters
    # =============================================================================
    #
    # Flow
    #

    # permeability field
    phi = Constant(1)  # porosity
    D = Constant(0.0252)  # dispersivity
    K = Constant(1)  # permeability

    # =============================================================================
    # Mesh and Elements
    # =============================================================================
    # Mesh
    mesh = QuadMesh(resolution=(30, 30))

    # Mark left and right regions
    mesh.mark_region('left',
                     lambda x, y: np.abs(x) < 1e-9,
                     entity_type='half_edge')
    mesh.mark_region('right',
                     lambda x, y: np.abs(x - 1) < 1e-9,
                     entity_type='half_edge')

    # Elements
    p_element = QuadFE(2, 'Q1')  # element for pressure
    c_element = QuadFE(2, 'Q1')  # element for concentration

    # Dofhandlers
    p_dofhandler = DofHandler(mesh, p_element)
    c_dofhandler = DofHandler(mesh, c_element)

    p_dofhandler.distribute_dofs()
    c_dofhandler.distribute_dofs()

    # Basis functions
    p_ux = Basis(p_dofhandler, 'ux')
    p_uy = Basis(p_dofhandler, 'uy')
    p_u = Basis(p_dofhandler, 'u')

    p_inflow = lambda x, y: np.ones(shape=x.shape)
    p_outflow = lambda x, y: np.zeros(shape=x.shape)
    c_inflow = lambda x, y: np.zeros(shape=x.shape)

    # =============================================================================
    # Solve the steady state flow equations
    # =============================================================================
    vb.comment('Solving flow equations')

    # Define problem
    flow_problem = [
        Form(1, test=p_ux, trial=p_ux),
        Form(1, test=p_uy, trial=p_uy),
        Form(0, test=p_u)
    ]

    # Assemble
    vb.tic('assembly')
    assembler = Assembler(flow_problem)
    assembler.add_dirichlet('left', 1)
    assembler.add_dirichlet('right', 0)
    assembler.assemble()
    vb.toc()

    # Solve linear system
    vb.tic('solve')
    A = assembler.get_matrix().tocsr()
    b = assembler.get_vector()
    x0 = assembler.assembled_bnd()

    # Interior nodes
    pa = np.zeros((p_u.n_dofs(), 1))
    int_dofs = assembler.get_dofs('interior')
    pa[int_dofs, 0] = spla.spsolve(A, b - x0)

    # Resolve Dirichlet conditions
    dir_dofs, dir_vals = assembler.get_dirichlet(asdict=False)
    pa[dir_dofs] = dir_vals
    vb.toc()

    # Pressure function
    pfn = Nodal(data=pa, basis=p_u)

    px = pfn.differentiate((1, 0))
    py = pfn.differentiate((1, 1))

    #plot.contour(px)
    #plt.show()

    # =============================================================================
    # Transport Equations
    # =============================================================================
    # Specify initial condition
    c0 = Constant(1)
    dt = 1e-1
    T = 6
    N = int(np.ceil(T / dt))

    c = Basis(c_dofhandler, 'c')
    cx = Basis(c_dofhandler, 'cx')
    cy = Basis(c_dofhandler, 'cy')

    print('assembling transport equations')
    k_phi = Kernel(f=phi)
    k_advx = Kernel(f=[K, px], F=lambda K, px: -K * px)
    k_advy = Kernel(f=[K, py], F=lambda K, py: -K * py)
    tht = 1
    m = [Form(kernel=k_phi, test=c, trial=c)]
    s = [
        Form(kernel=k_advx, test=c, trial=cx),
        Form(kernel=k_advy, test=c, trial=cy),
        Form(kernel=Kernel(D), test=cx, trial=cx),
        Form(kernel=Kernel(D), test=cy, trial=cy)
    ]

    problems = [m, s]
    assembler = Assembler(problems)
    assembler.add_dirichlet('left', 0, i_problem=0)
    assembler.add_dirichlet('left', 0, i_problem=1)
    assembler.assemble()

    x0 = assembler.assembled_bnd()

    # Interior nodes
    int_dofs = assembler.get_dofs('interior')

    # Dirichlet conditions
    dir_dofs, dir_vals = assembler.get_dirichlet(asdict=False)

    # System matrices
    M = assembler.get_matrix(i_problem=0)
    S = assembler.get_matrix(i_problem=1)

    # Initialize c0 and cp
    c0 = np.ones((c.n_dofs(), 1))
    cp = np.zeros((c.n_dofs(), 1))
    c_fn = Nodal(data=c0, basis=c)

    #
    # Compute solution
    #
    print('time stepping')
    for i in range(N):

        # Build system
        A = M + tht * dt * S
        b = M.dot(c0[int_dofs]) - (1 - tht) * dt * S.dot(c0[int_dofs])

        # Solve linear system
        cp[int_dofs, 0] = spla.spsolve(A, b)

        # Add Dirichlet conditions
        cp[dir_dofs] = dir_vals

        # Record current iterate
        c_fn.add_samples(data=cp)

        # Update c0
        c0 = cp.copy()

        #plot.contour(c_fn, n_sample=i)

    #
    # Quantity of interest
    #
    def F(c, px, py, entity=None):
        """
        Compute c(x,y,t)*(grad p * n)
        """
        n = entity.unit_normal()
        return c * (px * n[0] + py * n[1])

    px.set_subsample(i=np.arange(41))
    py.set_subsample(i=np.arange(41))

    #kernel = Kernel(f=[c_fn,px,py], F=F)
    kernel = Kernel(c_fn)

    #print(kernel.n_subsample())
    form = Form(kernel, flag='right', dmu='ds')
    assembler = Assembler(form, mesh=mesh)
    assembler.assemble()
    QQ = assembler.assembled_forms()[0].aggregate_data()['array']

    Q = np.array([assembler.get_scalar(i_sample=i) for i in np.arange(N + 1)])
    t = np.linspace(0, T, N + 1)
    plt.plot(t, Q)
    plt.show()
    print(Q)
예제 #11
0
    def test03_solve_2d(self):
        """
        Test problem with Neumann conditions
        """
        #
        # Define Mesh
        #
        mesh = QuadMesh(resolution=(2, 1))
        mesh.cells.get_child(1).mark(1)
        mesh.cells.refine(refinement_flag=1)

        # Mark left and right boundaries
        bm_left = lambda x, dummy: np.abs(x) < 1e-9
        bm_right = lambda x, dummy: np.abs(1 - x) < 1e-9
        mesh.mark_region('left', bm_left, entity_type='half_edge')
        mesh.mark_region('right', bm_right, entity_type='half_edge')

        for etype in ['Q1', 'Q2', 'Q3']:
            #
            # Define element and basis type
            #
            element = QuadFE(2, etype)
            dofhandler = DofHandler(mesh, element)
            dofhandler.distribute_dofs()

            u = Basis(dofhandler, 'u')
            ux = Basis(dofhandler, 'ux')
            uy = Basis(dofhandler, 'uy')

            #
            # Exact solution
            #
            ue = Nodal(f=lambda x: x[:, 0], basis=u)

            #
            # Set up forms
            #
            one = Constant(1)
            ax = Form(kernel=Kernel(one), trial=ux, test=ux)
            ay = Form(kernel=Kernel(one), trial=uy, test=uy)
            L = Form(kernel=Kernel(Constant(0)), test=u)
            Ln = Form(kernel=Kernel(one), test=u, dmu='ds', flag='right')

            problem = [ax, ay, L, Ln]

            assembler = Assembler(problem, mesh)
            assembler.add_dirichlet('left', dir_fn=0)
            assembler.add_hanging_nodes()
            assembler.assemble()

            #
            # Automatic solve
            #
            ya = assembler.solve()
            self.assertTrue(np.allclose(ue.data()[:, 0], ya))

            #
            # Explicit solve
            #

            # System Matrices
            A = assembler.get_matrix().toarray()
            b = assembler.get_vector()
            x0 = assembler.assembled_bnd()

            # Solve linear system
            xa = np.zeros(u.n_dofs())
            int_dofs = assembler.get_dofs('interior')
            xa[int_dofs] = np.linalg.solve(A, b - x0)

            # Resolve Dirichlet conditions
            dir_dofs, dir_vals = assembler.get_dirichlet(asdict=False)
            xa[dir_dofs] = dir_vals[:, 0]

            # Resolve hanging nodes
            C = assembler.hanging_node_matrix()
            xa += C.dot(xa)

            self.assertTrue(np.allclose(ue.data()[:, 0], xa))
예제 #12
0
    def test02_solve_2d(self):
        """
        Solve 2D problem with hanging nodes
        """
        # Mesh
        mesh = QuadMesh(resolution=(2, 2))
        mesh.cells.get_leaves()[0].mark(0)
        mesh.cells.refine(refinement_flag=0)

        mesh.mark_region('left',
                         lambda x, y: abs(x) < 1e-9,
                         entity_type='half_edge')
        mesh.mark_region('right',
                         lambda x, y: abs(x - 1) < 1e-9,
                         entity_type='half_edge')

        # Element
        Q1 = QuadFE(2, 'Q1')
        dofhandler = DofHandler(mesh, Q1)
        dofhandler.distribute_dofs()
        dofhandler.set_hanging_nodes()

        # Basis functions
        phi = Basis(dofhandler, 'u')
        phi_x = Basis(dofhandler, 'ux')
        phi_y = Basis(dofhandler, 'uy')

        #
        # Define problem
        #
        problem = [
            Form(1, trial=phi_x, test=phi_x),
            Form(1, trial=phi_y, test=phi_y),
            Form(0, test=phi)
        ]

        ue = Nodal(f=lambda x: x[:, 0], basis=phi)
        xe = ue.data().ravel()

        #
        # Assemble without Dirichlet and without Hanging Nodes
        #
        assembler = Assembler(problem, mesh)
        assembler.add_dirichlet('left', dir_fn=0)
        assembler.add_dirichlet('right', dir_fn=1)
        assembler.add_hanging_nodes()
        assembler.assemble()

        # Get dofs for different regions
        int_dofs = assembler.get_dofs('interior')

        # Get matrix and vector
        A = assembler.get_matrix().toarray()
        b = assembler.get_vector()
        x0 = assembler.assembled_bnd()

        # Solve linear system
        xa = np.zeros(phi.n_dofs())
        xa[int_dofs] = np.linalg.solve(A, b - x0)

        # Resolve Dirichlet conditions
        dir_dofs, dir_vals = assembler.get_dirichlet(asdict=False)
        xa[dir_dofs] = dir_vals[:, 0]

        # Resolve hanging nodes
        C = assembler.hanging_node_matrix()
        xa += C.dot(xa)

        self.assertTrue(np.allclose(xa, xe))
예제 #13
0
    def test_integrals_2d(self):
        """
        Test Assembly of some 2D systems
        """
        mesh = QuadMesh(box=[1, 2, 1, 2], resolution=(2, 2))
        mesh.cells.get_leaves()[0].mark(0)
        mesh.cells.refine(refinement_flag=0)

        # Kernel
        kernel = Kernel(Explicit(f=lambda x: x[:, 0] * x[:, 1], dim=2))

        problem = Form(kernel)
        assembler = Assembler(problem, mesh=mesh)
        assembler.assemble()
        self.assertAlmostEqual(assembler.get_scalar(), 9 / 4)

        #
        # Linear forms (x,x) and (x,x') over [1,2]^2 = 7/3, 3/2
        #

        # Elements
        Q1 = QuadFE(mesh.dim(), 'Q1')
        Q2 = QuadFE(mesh.dim(), 'Q2')
        Q3 = QuadFE(mesh.dim(), 'Q3')

        # Dofhandlers
        dQ1 = DofHandler(mesh, Q1)
        dQ2 = DofHandler(mesh, Q2)
        dQ3 = DofHandler(mesh, Q3)

        # Distribute dofs
        [d.distribute_dofs() for d in [dQ1, dQ2, dQ3]]

        for dQ in [dQ1, dQ2, dQ3]:
            # Basis
            phi = Basis(dQ, 'u')
            phi_x = Basis(dQ, 'ux')

            # Kernel function
            xfn = Nodal(f=lambda x: x[:, 0], basis=phi)
            yfn = Nodal(f=lambda x: x[:, 1], basis=phi)

            # Kernel
            kernel = Kernel(xfn)

            # Form
            problem = [[Form(kernel, test=phi)], [Form(kernel, test=phi_x)]]

            # Assembly
            assembler = Assembler(problem, mesh)
            assembler.assemble()

            # Check b^Tx = (x,y)
            b0 = assembler.get_vector(0)
            self.assertAlmostEqual(np.sum(b0 * yfn.data()[:, 0]), 9 / 4)

            b1 = assembler.get_vector(1)
            self.assertAlmostEqual(np.sum(b1 * xfn.data()[:, 0]), 3 / 2)
            self.assertAlmostEqual(np.sum(b1 * yfn.data()[:, 0]), 0)

        #
        # Bilinear forms
        #
        # Compute (1,x,y) = 9/4, or (xy, 1, 1) = 9/4

        for dQ in [dQ1, dQ2, dQ3]:
            # Basis
            phi = Basis(dQ, 'u')
            phi_x = Basis(dQ, 'ux')
            phi_y = Basis(dQ, 'uy')

            # Kernel function
            xyfn = Explicit(f=lambda x: x[:, 0] * x[:, 1], dim=2)
            xfn = Nodal(f=lambda x: x[:, 0], basis=phi)
            yfn = Nodal(f=lambda x: x[:, 1], basis=phi)

            # Form
            problems = [[Form(1, test=phi, trial=phi)],
                        [Form(Kernel(xfn), test=phi, trial=phi_x)],
                        [Form(Kernel(xyfn), test=phi_y, trial=phi_x)]]

            # Assemble
            assembler = Assembler(problems, mesh)
            assembler.assemble()

            x = xfn.data()[:, 0]
            y = yfn.data()[:, 0]
            for i_problem in range(3):
                A = assembler.get_matrix(i_problem)
                self.assertAlmostEqual(y.T.dot(A.dot(x)), 9 / 4)
예제 #14
0
    def test09_1d_inverse(self):
        """
        Compute the inverse of a matrix and apply it to a vector/matrix.
        """
        #
        # Mesh
        #
        mesh = Mesh1D(resolution=(1, ))
        mesh.mark_region('left', lambda x: np.abs(x) < 1e-9, on_boundary=True)
        mesh.mark_region('right',
                         lambda x: np.abs(1 - x) < 1e-9,
                         on_boundary=True)

        #
        # Elements
        #
        Q3 = QuadFE(1, 'Q3')
        dofhandler = DofHandler(mesh, Q3)
        dofhandler.distribute_dofs()

        #
        # Basis
        #
        u = Basis(dofhandler, 'u')
        ux = Basis(dofhandler, 'ux')

        #
        # Define sampled right hand side and exact solution
        #
        xv = dofhandler.get_dof_vertices()
        n_points = dofhandler.n_dofs()

        n_samples = 6
        a = np.arange(n_samples)

        ffn = lambda x, a: a * x
        ufn = lambda x, a: a / 6 * (x - x**3) + x
        fdata = np.zeros((n_points, n_samples))
        udata = np.zeros((n_points, n_samples))
        for i in range(n_samples):
            fdata[:, i] = ffn(xv, a[i]).ravel()
            udata[:, i] = ufn(xv, a[i]).ravel()

        # Define sampled function
        fn = Nodal(data=fdata, basis=u)
        ue = Nodal(data=udata, basis=u)

        #
        # Forms
        #
        one = Constant(1)
        a = Form(Kernel(one), test=ux, trial=ux)
        L = Form(Kernel(fn), test=u)
        problem = [[a], [L]]

        #
        # Assembler
        #
        assembler = Assembler(problem, mesh)
        assembler.assemble()

        A = assembler.get_matrix()
        b = assembler.get_vector(i_problem=1)

        #
        # Linear System
        #
        system = LinearSystem(u, A=A)

        # Set constraints
        system.add_dirichlet_constraint('left', 0)
        system.add_dirichlet_constraint('right', 1)
        system.solve_system(b)

        # Extract finite element solution
        ua = system.get_solution(as_function=True)

        system2 = LinearSystem(u, A=A, b=b)

        # Set constraints
        system2.add_dirichlet_constraint('left', 0)
        system2.add_dirichlet_constraint('right', 1)
        system2.solve_system()
        u2 = system2.get_solution(as_function=True)

        # Check that the solution is close
        self.assertTrue(np.allclose(ue.data()[:, 0], ua.data()[:, 0]))
        self.assertTrue(np.allclose(ue.data()[:, [0]], u2.data()))
예제 #15
0
def test01_finite_elements():
    """
    Test accuracy of the finite element approximation
    """
    #
    # Construct reference solution
    #
    plot = Plot(quickview=False)

    # Mesh
    mesh = Mesh1D(resolution=(2**11, ))
    mesh.mark_region('left', lambda x: np.abs(x) < 1e-10)
    mesh.mark_region('right', lambda x: np.abs(x - 1) < 1e-10)

    # Element
    Q1 = QuadFE(mesh.dim(), 'Q1')
    dQ1 = DofHandler(mesh, Q1)
    dQ1.distribute_dofs()

    # Basis
    phi = Basis(dQ1, 'v')
    phi_x = Basis(dQ1, 'vx')

    #
    # Covariance
    #
    cov = Covariance(dQ1, name='gaussian', parameters={'l': 0.05})
    cov.compute_eig_decomp()
    lmd, V = cov.get_eig_decomp()
    d = len(lmd)

    #
    # Sample and plot full dimensional parameter and solution
    #
    n_samples = 1
    z = np.random.randn(d, n_samples)
    q_ref = sample_q0(V, lmd, d, z)

    print(q_ref.shape)

    # Define finite element function
    q_ref_fn = Nodal(data=q_ref, basis=phi)
    problem = [[Form(q_ref_fn, test=phi_x, trial=phi_x),
                Form(1, test=phi)],
               [Form(q_ref_fn, test=phi_x, dmu='dv', flag='right')]]

    # Define assembler
    assembler = Assembler(problem)

    # Incorporate Dirichlet conditions
    assembler.add_dirichlet('left', 0)
    assembler.add_dirichlet('right', 1)

    # Assemble system
    assembler.assemble()

    # Solve system
    u_ref = assembler.solve()

    # Compute quantity of interest
    J_ref = u_ref.dot(assembler.get_vector(1))

    # Plot
    fig = plt.figure(figsize=(6, 4))
    ax = fig.add_subplot(111)
    u_ref_fn = Nodal(basis=phi, data=u_ref)

    ax = plot.line(u_ref_fn, axis=ax)

    n_levels = 10
    J = np.zeros(n_levels)
    for l in range(10):
        comment.comment('level: %d' % (l))

        #
        # Mesh
        #
        mesh = Mesh1D(resolution=(2**l, ))
        mesh.mark_region('left', lambda x: np.abs(x) < 1e-10)
        mesh.mark_region('right', lambda x: np.abs(x - 1) < 1e-10)

        #
        # Element
        #
        Q1 = QuadFE(mesh.dim(), 'Q1')
        dQ1 = DofHandler(mesh, Q1)
        dQ1.distribute_dofs()

        #
        # Basis
        #
        phi = Basis(dQ1, 'v')
        phi_x = Basis(dQ1, 'vx')

        # Define problem
        problem = [[
            Form(q_ref_fn, test=phi_x, trial=phi_x),
            Form(1, test=phi)
        ], [Form(q_ref_fn, test=phi_x, dmu='dv', flag='right')]]

        assembler = Assembler(problem)

        # Incorporate Dirichlet conditions
        assembler.add_dirichlet('left', 0)
        assembler.add_dirichlet('right', 1)

        assembler.assemble()
        A = assembler.get_matrix()
        print('A shape', A.shape)

        u = assembler.solve()
        J[l] = u.dot(assembler.get_vector(1))

        print(u.shape)
        print(phi.n_dofs())
        ufn = Nodal(basis=phi, data=u)
        ax = plot.line(ufn, axis=ax)

    plt.show()
    #
    # Plots
    #
    # Formatting
    plt.rc('text', usetex=True)

    # Figure sizes
    fs2 = (3, 2)
    fs1 = (4, 3)

    print(J_ref)
    print(J)

    #
    # Plot truncation error for mean and variance of J
    #

    fig = plt.figure(figsize=fs2)
    ax = fig.add_subplot(111)

    err = np.array([np.abs(J[i] - J_ref) for i in range(n_levels)])
    h = np.array([2**(-l) for l in range(n_levels)])
    plt.loglog(h, err, '.-')

    ax.set_xlabel(r'$h$')
    ax.set_ylabel(r'$|J-J^h|$')
    plt.tight_layout()
    fig.savefig('fig/ex02_gauss_fem_error.eps')
예제 #16
0
vx = Explicit(f=lambda x: -x[:, 1], dim=2)
vy = Explicit(f=lambda x: x[:, 0], dim=2)

uB = Explicit(f=lambda x: np.cos(2 * np.pi * (x[:, 1] + 0.25)), dim=2)
problem = [
    Form(epsilon, trial=ux, test=ux),
    Form(epsilon, trial=uy, test=uy),
    Form(vx, trial=ux, test=u),
    Form(vy, trial=uy, test=u),
    Form(0, test=u)
]

print('assembling', end=' ')
assembler = Assembler(problem, mesh)
assembler.assemble()
print('done')

print('solving', end=' ')
A = assembler.get_matrix()
b = np.zeros(u.n_dofs())
system = LS(u, A=A, b=b)
system.add_dirichlet_constraint('B', uB)
system.add_dirichlet_constraint('perimeter', 0)

system.solve_system()
ua = system.get_solution()
print('done')

plot = Plot()
plot.wire(ua)
예제 #17
0
    def test_integrals_1d(self):
        """
        Test system assembly
        """
        #
        # Constant form
        #

        # Mesh
        mesh = Mesh1D(box=[1, 2], resolution=(1, ))

        # Kernel
        kernel = Kernel(Explicit(f=lambda x: x[:, 0], dim=1))

        problem = Form(kernel)
        assembler = Assembler(problem, mesh=mesh)
        assembler.assemble()
        self.assertAlmostEqual(assembler.get_scalar(), 3 / 2)

        #
        # Linear forms (x,x) and (x,x') over [1,2] = 7/3, 3/2
        #

        # Elements
        Q1 = QuadFE(mesh.dim(), 'Q1')
        Q2 = QuadFE(mesh.dim(), 'Q2')
        Q3 = QuadFE(mesh.dim(), 'Q3')

        # Dofhandlers
        dQ1 = DofHandler(mesh, Q1)
        dQ2 = DofHandler(mesh, Q2)
        dQ3 = DofHandler(mesh, Q3)

        # Distribute dofs
        [d.distribute_dofs() for d in [dQ1, dQ2, dQ3]]

        for dQ in [dQ1, dQ2, dQ3]:
            # Basis
            phi = Basis(dQ, 'u')
            phi_x = Basis(dQ, 'ux')

            # Kernel function
            xfn = Nodal(f=lambda x: x[:, 0], basis=phi)

            # Kernel
            kernel = Kernel(xfn)

            # Form
            problem = [[Form(kernel, test=phi)], [Form(kernel, test=phi_x)]]

            # Assembly
            assembler = Assembler(problem, mesh)
            assembler.assemble()

            # Check b^Tx = (x,x)
            b0 = assembler.get_vector(0)
            self.assertAlmostEqual(np.sum(b0 * xfn.data()[:, 0]), 7 / 3)

            b1 = assembler.get_vector(1)
            self.assertAlmostEqual(np.sum(b1 * xfn.data()[:, 0]), 3 / 2)

        #
        # Bilinear forms
        #
        # Compute (1,x,x) = 7/3, or (x^2, 1, 1) = 7/3

        for dQ in [dQ1, dQ2, dQ3]:
            # Basis
            phi = Basis(dQ, 'u')
            phi_x = Basis(dQ, 'ux')

            # Kernel function
            x2fn = Explicit(f=lambda x: x[:, 0]**2, dim=1)
            xfn = Nodal(f=lambda x: x[:, 0], basis=phi)

            # Form
            problems = [[Form(1, test=phi, trial=phi)],
                        [Form(Kernel(xfn), test=phi, trial=phi_x)],
                        [Form(Kernel(x2fn), test=phi_x, trial=phi_x)]]

            # Assemble
            assembler = Assembler(problems, mesh)
            assembler.assemble()

            x = xfn.data()[:, 0]
            for i_problem in range(3):
                A = assembler.get_matrix(i_problem)
                self.assertAlmostEqual(x.T.dot(A.dot(x)), 7 / 3)

        # ======================================================================
        # Test 1: Assemble simple bilinear form (u,v) on Mesh1D
        # ======================================================================
        # Mesh
        mesh = Mesh1D(resolution=(1, ))
        Q1 = QuadFE(mesh.dim(), 'Q1')
        Q2 = QuadFE(mesh.dim(), 'Q2')
        Q3 = QuadFE(mesh.dim(), 'Q3')

        # Test and trial functions
        dhQ1 = DofHandler(mesh, QuadFE(1, 'Q1'))
        dhQ1.distribute_dofs()

        u = Basis(dhQ1, 'u')
        v = Basis(dhQ1, 'v')

        # Form
        form = Form(trial=u, test=v)

        # Define system
        system = Assembler(form, mesh)

        # Get local information
        cell = mesh.cells.get_child(0)
        si = system.shape_info(cell)

        # Compute local Gauss nodes
        xg, wg, phi, dofs = system.shape_eval(cell)
        self.assertTrue(cell in xg)
        self.assertTrue(cell in wg)

        # Compute local shape functions
        self.assertTrue(cell in phi)
        self.assertTrue(u in phi[cell])
        self.assertTrue(v in phi[cell])
        self.assertTrue(u in dofs[cell])

        # Assemble system
        system.assemble()

        # Extract system bilinear form
        A = system.get_matrix()

        # Use bilinear form to integrate x^2 over [0,1]
        f = Nodal(lambda x: x, basis=u)
        fv = f.data()[:, 0]
        self.assertAlmostEqual(np.sum(fv * A.dot(fv)), 1 / 3)

        # ======================================================================
        # Test 3: Constant form (x^2,.,.) over 1D mesh
        # ======================================================================

        # Mesh
        mesh = Mesh1D(resolution=(10, ))

        # Nodal kernel function
        Q2 = QuadFE(1, 'Q2')
        dhQ2 = DofHandler(mesh, Q2)
        dhQ2.distribute_dofs()
        phiQ2 = Basis(dhQ2)

        f = Nodal(lambda x: x**2, basis=phiQ2)
        kernel = Kernel(f=f)

        # Form
        form = Form(kernel=kernel)

        # Generate and assemble the system
        system = Assembler(form, mesh)
        system.assemble()

        # Check
        self.assertAlmostEqual(system.get_scalar(), 1 / 3)

        # =====================================================================
        # Test 4: Periodic Mesh
        # =====================================================================
        #
        # TODO: NO checks yet
        #

        mesh = Mesh1D(resolution=(2, ), periodic=True)

        #
        Q1 = QuadFE(1, 'Q1')
        dhQ1 = DofHandler(mesh, Q1)
        dhQ1.distribute_dofs()
        u = Basis(dhQ1, 'u')

        form = Form(trial=u, test=u)

        system = Assembler(form, mesh)
        system.assemble()

        # =====================================================================
        # Test 5: Assemble simple sampled form
        # ======================================================================
        mesh = Mesh1D(resolution=(3, ))

        Q1 = QuadFE(1, 'Q1')
        dofhandler = DofHandler(mesh, Q1)
        dofhandler.distribute_dofs()
        phi = Basis(dofhandler)

        xv = dofhandler.get_dof_vertices()
        n_points = dofhandler.n_dofs()

        n_samples = 6
        a = np.arange(n_samples)

        f = lambda x, a: a * x

        fdata = np.zeros((n_points, n_samples))
        for i in range(n_samples):
            fdata[:, i] = f(xv, a[i]).ravel()

        # Define sampled function
        fn = Nodal(data=fdata, basis=phi)
        kernel = Kernel(fn)
        #
        # Integrate I[0,1] ax^2 dx by using the linear form (ax,x)
        #
        v = Basis(dofhandler, 'v')
        form = Form(kernel=kernel, test=v)
        system = Assembler(form, mesh)
        system.assemble()

        one = np.ones(n_points)
        for i in range(n_samples):
            b = system.get_vector(i_sample=i)
            self.assertAlmostEqual(one.dot(b), 0.5 * a[i])

        #
        # Integrate I[0,1] ax^4 dx using bilinear form (ax, x^2, x)
        #
        Q2 = QuadFE(1, 'Q2')
        dhQ2 = DofHandler(mesh, Q2)
        dhQ2.distribute_dofs()
        u = Basis(dhQ2, 'u')

        # Define form
        form = Form(kernel=kernel, test=v, trial=u)

        # Define and assemble system
        system = Assembler(form, mesh)
        system.assemble()

        # Express x^2 in terms of trial function basis
        dhQ2.distribute_dofs()
        xvQ2 = dhQ2.get_dof_vertices()
        xv_squared = xvQ2**2

        for i in range(n_samples):
            #
            # Iterate over samples
            #

            # Form sparse matrix
            A = system.get_matrix(i_sample=i)

            # Evaluate the integral
            I = np.sum(xv * A.dot(xv_squared))

            # Compare with expected result
            self.assertAlmostEqual(I, 0.2 * a[i])

        # =====================================================================
        # Test 6: Working with submeshes
        # =====================================================================
        mesh = Mesh1D(resolution=(2, ))