Exemple #1
0
def sensitivity_sample_qoi(exp_q, dofhandler):
    """
    Sample QoI by means of Taylor expansion
    
        J(q+dq) ~= J(q) + dJdq(q)dq
    """
    # Basis
    phi = Basis(dofhandler, 'v')
    phi_x = Basis(dofhandler, 'vx')

    # Define problem
    exp_q_fn = Nodal(data=exp_q, basis=phi)

    primal = [Form(exp_q_fn, test=phi_x, trial=phi_x), Form(1, test=phi)]
    adjoint = [Form(exp_q_fn, test=phi_x, trial=phi_x), Form(0, test=phi)]
    qoi = [Form(exp_q_fn, test=phi_x)]
    problems = [primal, adjoint, qoi]

    # Define assembler
    assembler = Assembler(problems)

    #
    # Dirichlet conditions for primal problem
    #
    assembler.add_dirichlet('left', 0, i_problem=0)
    assembler.add_dirichlet('right', 1, i_problem=0)

    # Dirichlet conditions for adjoint problem
    assembler.add_dirichlet('left', 0, i_problem=1)
    assembler.add_dirichlet('right', -1, i_problem=1)

    # Assemble system
    assembler.assemble()

    # Compute solution and qoi at q (primal)
    u = assembler.solve(i_problem=0)

    # Compute solution of the adjoint problem
    v = assembler.solve(i_problem=1)

    # Evaluate J
    J = u.dot(assembler.get_vector(2))

    #
    # Assemble gradient
    #
    ux_fn = Nodal(data=u, basis=phi_x)
    vx_fn = Nodal(data=v, basis=phi_x)

    k_int = Kernel(f=[exp_q_fn, ux_fn, vx_fn],
                   F=lambda exp_q, ux, vx: exp_q * ux * vx)

    problem = [Form(k_int, test=phi)]

    assembler = Assembler(problem)
    assembler.assemble()
    dJ = -assembler.get_vector()
    return dJ
Exemple #2
0
def experiment01():
    """
    Compute the quantity of interest, it's expectation and variance
    """
    #
    # FE Discretization
    #

    # Computational mesh
    mesh = Mesh1D(resolution=(64, ))

    # Element
    element = QuadFE(mesh.dim(), 'DQ0')
    dofhandler = DofHandler(mesh, element)
    dofhandler.distribute_dofs()

    # Linear Functional
    mesh.mark_region('integrate',
                     lambda x: x > 0.75,
                     entity_type='cell',
                     strict_containment=False)
    phi = Basis(dofhandler)
    assembler = Assembler(Form(1, test=phi, flag='integrate'))
    assembler.assemble()
    L = assembler.get_vector()
    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()))
Exemple #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))
Exemple #5
0
def test02_variance():
    """
    Compute the variance of J(q) for different mesh refinement levels
    and compare with MC estimates. 
    """
    l_max = 8
    for i_res in np.arange(2, l_max):

        # Computational mesh
        mesh = Mesh1D(resolution=(2**i_res, ))

        # Element
        element = QuadFE(mesh.dim(), 'DQ0')
        dofhandler = DofHandler(mesh, element)
        dofhandler.distribute_dofs()

        # Linear Functional
        mesh.mark_region('integrate',
                         lambda x: x >= 0.75,
                         entity_type='cell',
                         strict_containment=False)
        phi = Basis(dofhandler)
        assembler = Assembler(Form(4, test=phi, flag='integrate'))
        assembler.assemble()
        L = assembler.get_vector()

        # Define Gaussian random field
        C = Covariance(dofhandler, name='gaussian', parameters={'l': 0.05})
        C.compute_eig_decomp()

        eta = GaussianField(dofhandler.n_dofs(), K=C)
        eta.update_support()

        n_samples = 100000
        J_paths = L.dot(eta.sample(n_samples=n_samples))
        var_mc = np.var(J_paths)
        lmd, V = C.get_eig_decomp()
        LV = L.dot(V)
        var_an = LV.dot(np.diag(lmd).dot(LV.transpose()))

        print(var_mc, var_an)
Exemple #6
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))
Exemple #7
0
    ax.set_ylim([-3, 3])
    plt.tight_layout()
    plt.show()

    #
    # Define linear functional
    #
    mesh.mark_region('integrate',
                     lambda x: x > 0.75,
                     entity_type='cell',
                     strict_containment=False)
    phi = Basis(dofhandler)
    assembler = Assembler(Form(1, test=phi, flag='integrate'))
    assembler.assemble()
    L = assembler.get_vector()

    n_samples = 1000
    J = {}
    for l in range(l_max + 1):
        P = projection_matrix(dofhandler, None, l)
        J[l] = L.dot(P.T.dot(P.dot(eta.sample(n_samples=n_samples))))
        plt.hist(J[l], bins=40, density=False, alpha=0.5, label=l)
    plt.legend()
    plt.show()

    # Compute variance
    var = np.zeros(l_max + 1)
    h = np.zeros(l_max + 1)
    for i in range(l_max + 1):
        var[i] = compute_variance(dofhandler, eta, L, submesh_flag=i)
Exemple #8
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)
    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()))
    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()))
Exemple #11
0
def dJdq_adj(q, u, dq=None):
    """
    Compute the directional derivative dJ(q,dq) by solving the adjoint equation 
    
        -(exp(q)v')' = 0, 
        v(0)=0, v(1)=1 
        
    and computing
    
        ( v, (exp(q)*dq(1)*u')' ) + exp(q(1))*dq(1)*u'(1) = -(exp(q)*dq u', v')
        
        
    Inputs: 
    
        q: Nodal, single reference log diffusitivity 
        
        u: Nodal, single reference system response
        
        dq: Nodal/None, sampled perturbation vector (or None) 
        
    
    Output:
    
        dJdq: Derivative of J wrt q
        
            If dq = Nodal, return directional derivative in direction dq
            
            If dq = None, return gradient
    """
    #
    # Finite Element Specification
    #

    # Reference solution
    u_dh = u.basis().dofhandler()
    phi = Basis(u_dh, 'u')
    phi_x = Basis(u_dh, 'ux')
    ux = Nodal(data=u.data(), basis=phi_x)

    # Reference diffusivity
    q_dh = q.basis().dofhandler()
    psi = Basis(q_dh, 'q')
    exp_q = Nodal(data=np.exp(q.data()), basis=psi)

    # Define adjoint equations
    adjoint_eqn = [Form(exp_q, test=phi_x, trial=phi_x), Form(0, test=phi)]

    # Assembler
    assembler = Assembler(adjoint_eqn)

    # Apply Dirichlet BC
    assembler.add_dirichlet('left', 0)
    assembler.add_dirichlet('right', 1)

    # Assemble
    assembler.assemble()

    # Solve for adjoint
    v = assembler.solve()

    # Get derivative
    vx = Nodal(data=v, basis=phi_x)

    # Assemble

    if dq is None:
        #
        # Compute the gradient
        #

        # Kernel
        k_adj = Kernel(f=[exp_q, ux, vx], F=lambda eq, ux, vx: -eq * ux * vx)

        # Linear form
        adj_qoi = [Form(k_adj, test=psi)]

        # Assemble
        assembler = Assembler(adj_qoi)
        assembler.assemble()

        # Get gradient vector
        dJdq = assembler.get_vector()
    else:
        #
        # Compute the directional derivative
        #

        # Kernel
        k_adj = Kernel(f=[exp_q, dq, ux, vx],
                       F=lambda eq, dq, ux, vx: -eq * dq * ux * vx)

        # Constant form
        adj_qoi = [Form(k_adj)]

        # Assemble
        assembler = Assembler(adj_qoi, mesh=u_dh.mesh)
        assembler.assemble()

        # Get directional derivatives for each direction
        dJdq = np.array(
            [assembler.get_scalar(i_sample=i) for i in range(dq.n_samples())])
    # Return
    return dJdq
Exemple #12
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))
Exemple #13
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))
Exemple #14
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)
Exemple #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')
Exemple #16
0
# Compute state
#

# Define weak form
state = [[
    Form(eq, test=phix_1, trial=phix_1),
    Form(eq, test=phiy_1, trial=phiy_1),
    Form(1, test=phi_1)
], [Form(1, test=phi_1, flag='dmn')]]

# Assemble system
assembler = Assembler(state)
assembler.add_dirichlet('bnd')
assembler.assemble()

J = assembler.get_vector(1)

# Solve system
u_vec = assembler.solve()
u = Nodal(basis=phi_1, data=u_vec)

plot.contour(u)
plt.title('Sample Path')

# Solve the adjoint system
adjoint = [
    Form(eq, test=phix_2, trial=phix_2),
    Form(eq, test=phiy_2, trial=phiy_2),
    Form(1, test=phi_2, flag='dmn')
]
Exemple #17
0
def test02_sensitivity():
    """
    Check that the sensitivity calculation works. Compare 
    
        J(q+eps*dq) - J(q) ~= eps*dJ^T dq
    """
    #
    # Mesh
    #
    mesh = Mesh1D(resolution=(20, ))
    mesh.mark_region('left', lambda x: np.abs(x) < 1e-10)
    mesh.mark_region('right', lambda x: np.abs(x - 1) < 1e-10)

    #
    # Element
    #
    Q = QuadFE(mesh.dim(), 'Q3')
    dQ = DofHandler(mesh, Q)
    dQ.distribute_dofs()
    nx = dQ.n_dofs()
    x = dQ.get_dof_vertices()

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

    #
    # Parameters
    #

    # Reference q
    q_ref = np.zeros(nx)

    # Perturbation
    dq = np.ones(nx)

    # Perturbed q
    n_eps = 10  # Number of refinements
    epsilons = [10**(-l) for l in range(n_eps)]
    q_per = np.empty((nx, n_eps))
    for i in range(n_eps):
        q_per[:, i] = q_ref + epsilons[i] * dq

    # Define finite element function
    exp_qref = Nodal(data=np.exp(q_ref), basis=phi)
    exp_qper = Nodal(data=np.exp(q_per), basis=phi)

    #
    # PDEs
    #

    # 1. State Equation
    state_eqn = [Form(exp_qref, test=phi_x, trial=phi_x), Form(1, test=phi)]
    state_dbc = {'left': 0, 'right': 1}

    # 2. Perturbed Equation
    perturbed_eqn = [
        Form(exp_qper, test=phi_x, trial=phi_x),
        Form(1, test=phi)
    ]
    perturbed_dbc = {'left': 0, 'right': 1}

    # 3. Adjoint Equation
    adjoint_eqn = [Form(exp_qref, test=phi_x, trial=phi_x), Form(0, test=phi)]
    adjoint_dbc = {'left': 0, 'right': -1}

    # Combine
    eqns = [state_eqn, perturbed_eqn, adjoint_eqn]
    bcs = [state_dbc, perturbed_dbc, adjoint_dbc]

    #
    # Assembly
    #
    assembler = Assembler(eqns)

    # Boundary conditions
    for i, bc in zip(range(3), bcs):
        for loc, val in bc.items():
            assembler.add_dirichlet(loc, val, i_problem=i)

    # Assemble
    assembler.assemble()

    #
    # Solve
    #

    # Solve state
    ur = assembler.solve(i_problem=0)
    u_ref = Nodal(data=ur, basis=phi)
    ux_ref = Nodal(data=ur, basis=phi_x)

    # Solve perturbed state
    u_per = Nodal(basis=phi)
    ue_per = Nodal(basis=phi)
    for i in range(n_eps):
        # FEM solution
        up = assembler.solve(i_problem=1, i_matrix=i)
        u_per.add_samples(up)

        # Exact perturbed solution
        eps = epsilons[i]
        ue_per.add_samples(0.5 * np.exp(-eps) * (x - x**2) + x)

    ux_per = Nodal(data=u_per.data(), basis=phi_x)

    # Solve adjoint equation
    v = assembler.solve(i_problem=2)
    v_adj = Nodal(data=v, basis=phi)
    vx_adj = Nodal(data=v, basis=phi_x)

    #
    # Check against exact solution
    #
    ue = -0.5 * x**2 + 1.5 * x
    ve = -x

    assert np.allclose(ue, u_ref.data())
    assert np.allclose(ve, v_adj.data())
    assert np.allclose(ue_per.data(), u_per.data())

    #
    # Quantities of Interest
    #

    # Reference
    k_ref = Kernel(f=[exp_qref, ux_ref], F=lambda eq, ux: eq * ux)
    ref_qoi = [Form(k_ref, dmu='dv', flag='right')]

    # Perturbed
    k_per = Kernel(f=[exp_qper, ux_per], F=lambda eq, ux: eq * ux)
    per_qoi = [Form(k_per, dmu='dv', flag='right')]

    # Adjoint
    k_adj = Kernel(f=[exp_qref, ux_ref, vx_adj],
                   F=lambda eq, ux, vx: -eq * ux * vx)
    adj_qoi = [Form(k_adj, test=phi)]

    qois = [ref_qoi, per_qoi, adj_qoi]

    # Assemble
    assembler = Assembler(qois)
    assembler.assemble()

    # Evaluate
    J_ref = assembler.get_scalar(0)
    J_per = []
    for i in range(n_eps):
        J_per.append(assembler.get_scalar(1, i))

    # Finite difference approximation
    dJ = []
    for eps, J_p in zip(epsilons, J_per):
        dJ.append((J_p - J_ref) / eps)

    # Adjoint differential
    dJ_adj = assembler.get_vector(2).dot(dq)

    #
    # Check against exact qois
    #

    # Check reference sol
    Je_ref = 0.5
    assert np.allclose(Je_ref, J_ref)

    # Check perturbed cost
    Je_per = -0.5 + np.exp(np.array(epsilons))
    assert np.allclose(Je_per, J_per)

    # Check derivative by the adjoint equation
    dJdq = 1
    assert np.allclose(dJ_adj, dJdq)
    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()))
Exemple #19
0
def experiment01_problem():
    """
    Illustrate the problem:  Plot sample paths of the input q, of the output, 
        and histogram of the QoI.
    """

    #
    # Computational Mesh
    #
    mesh = Mesh1D(resolution=(100, ))
    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 = 20000
    z = np.random.randn(d, n_samples)
    q = sample_q0(V, lmd, d, z)

    # Define finite element function
    qfn = Nodal(data=q, basis=phi)
    problem = [[Form(qfn, test=phi_x, trial=phi_x),
                Form(1, test=phi)],
               [Form(qfn, 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)

    comment.tic('assembly')
    # Assemble system
    assembler.assemble()
    comment.toc()

    comment.tic('solver')
    ufn = Nodal(basis=phi, data=None)
    J = np.zeros(n_samples)
    for i in range(n_samples):
        # Solve system
        u = assembler.solve(i_problem=0, i_matrix=i, i_vector=0)

        # Compute quantity of interest
        J[i] = u.dot(assembler.get_vector(1, i))

        # Update sample paths
        ufn.add_samples(u)
    comment.toc()

    #
    # Plots
    #
    """
    # Formatting
    plt.rc('text', usetex=True)
    
    # Figure sizes
    fs2 = (3,2)
    fs1 = (4,3)
    
    plot = Plot(quickview=False)
    plot_kwargs = {'color':'k', 'linewidth':0.05}
    
    #
    # Plot qfn
    # 
    
    # Figure 
    fig = plt.figure(figsize=fs2)
    ax = fig.add_subplot(111)
    ax = plot.line(qfn, axis=ax, 
                   i_sample=np.arange(100), 
                   plot_kwargs=plot_kwargs)
    ax.set_xlabel(r'$x$')
    ax.set_ylabel(r'$q$')
    plt.tight_layout()
    fig.savefig('fig/ex02_gauss_qfn.eps')
    plt.close()
    
    #
    # Plot ufn
    # 
    fig = plt.figure(figsize=fs2)
    ax = fig.add_subplot(111)
    ax = plot.line(ufn, axis=ax, 
                   i_sample=np.arange(100), 
                   plot_kwargs=plot_kwargs)
    ax.set_xlabel(r'$x$')
    ax.set_ylabel(r'$u$')
    plt.tight_layout()
    fig.savefig('fig/ex02_gauss_ufn.eps')
    plt.close()
    """

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

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

    fig = plt.figure(figsize=fs2)
    ax = fig.add_subplot(111)
    plt.hist(J, bins=100, density=True)
    ax.set_xlabel(r'$J(u)$')
    plt.tight_layout()
    fig.savefig('fig/ex02_gauss_jhist.eps')
    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()))
Exemple #21
0
def sample_qoi(q, dofhandler, return_state=False):
    """
    Compute the Quantity of Interest 
    
        J(u) = -exp(q(1))*u'(1),
        
    where u solves 
    
        -d/dx ( exp(q)* du/dx) = 1
        u(0) = 0,  u(1) = 1
        
    for a sample of q's. 
    
    Inputs:
    
        q: Nodal, (n_dofs, n_samples) function representing the log porosity
        
        dofhandler: DofHandler
        
    """
    # Basis
    phi = Basis(dofhandler, 'v')
    phi_x = Basis(dofhandler, 'vx')
    n_dofs = phi.n_dofs()

    # Define problem
    expq_fn = Nodal(data=np.exp(q), basis=phi)

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

    # Define assembler
    assembler = Assembler(problem, dofhandler.mesh)

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

    n_samples = expq_fn.n_subsample()

    # Assemble system
    assembler.assemble()

    if return_state:
        U = np.empty((n_dofs, n_samples))

    J = np.zeros(n_samples)
    for i in range(n_samples):
        # Solve system
        u = assembler.solve(i_problem=0, i_matrix=i, i_vector=0)

        # Compute quantity of interest
        J[i] = -u.dot(assembler.get_vector(1, i))

        if return_state:
            U[:, i] = u

    if return_state:
        return J, U
    else:
        return J
    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()))
Exemple #23
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, ))