Exemplo n.º 1
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))
Exemplo n.º 2
0
 def test_mark_region(self):
     """
     This is a method in Mesh2D, but 
     """
     #
     # Define Mesh
     # 
     mesh = QuadMesh(resolution=(2,2))
     mesh.cells.get_child(2).mark('1')
     mesh.cells.refine(refinement_flag='1')
     
     #
     # Mark left boundary vertices 
     #  
     f_left = lambda x,dummy: np.abs(x)<1e-9
     mesh.mark_region('left', f_left, on_boundary=True)
     
     #
     # Check that left boundary vertices are the only  
     # 
     count = 0
     for segment in mesh.get_boundary_segments():
         for he in segment:
             # Half-edge should not be marked 
             self.assertFalse(he.is_marked('left'))
             
             # Cell should not be marked
             self.assertFalse(he.cell().is_marked('left'))
             
             for v in he.get_vertices():
                 if f_left(*v.coordinates()):
                     #
                     # Left boundary vertices should be marked
                     # 
                     self.assertTrue(v.is_marked('left'))
                     count += 1
                 else:
                     #
                     # No other boundary vertices should be marked
                     # 
                     self.assertFalse(v.is_marked('left'))
     self.assertEqual(count, 8)
Exemplo n.º 3
0
 def test_get_region(self):
     #
     # Define Mesh
     # 
     mesh = QuadMesh(resolution=(2,2))
     mesh.cells.get_child(2).mark('1')
     mesh.cells.refine(refinement_flag='1')
     
     #
     # Mark left boundary vertices 
     #  
     f_left = lambda x,dummy: np.abs(x)<1e-9
     mesh.mark_region('left', f_left, on_boundary=True)
     
     
     
     
     for v,cell in mesh.get_region('left', entity_type='vertex', 
                                   return_cells=True, on_boundary=True):
         self.assertTrue(v.is_marked('left'))
Exemplo n.º 4
0
 def test_get_region_dofs(self):
     """
     Test the function for returning the dofs associated with a region.
     """   
     # 
     # 2D
     #
     mesh = QuadMesh()
     for etype in ['Q1','Q2','Q3']:
         element = QuadFE(2, etype)
         dofhandler = DofHandler(mesh, element)
         dofhandler.distribute_dofs()
         
         # 
         # Mark half-edges 
         #  
         bnd_right = lambda x,dummy: np.abs(x-1)<1e-9
         mesh.mark_region('right', bnd_right, \
                          entity_type='half_edge', \
                          on_boundary=True)
         
         # Check that mesh.mark_region is doing the right thing. 
         cell = mesh.cells.get_child(0)
         marked_edge = False
         for he in cell.get_half_edges():
             if he.is_marked('right'):
                 #
                 # All vertices should be on the boundary
                 # 
                 marked_edge = True
                 for v in he.get_vertices():
                     x,y = v.coordinates()
                 self.assertTrue(bnd_right(x,y))
             else:
                 #
                 # Not all vertices on should be on the boundary
                 # 
                 on_right = True
                 for v in he.get_vertices():
                     x,y = v.coordinates()
                     if not bnd_right(x,y):
                         on_right = False
                 self.assertFalse(on_right)
         #
         # Some half-edge should be marked
         # 
         self.assertTrue(marked_edge)
         
         #
         # Check that we get the right number of dofs
         #
         n_dofs = {True: {'Q1': 0, 'Q2': 1, 'Q3': 2}, 
                   False: {'Q1': 2, 'Q2': 3, 'Q3': 4}}
         for interior in [True, False]:
             dofs = dofhandler.get_region_dofs(entity_type='half_edge', \
                                               entity_flag='right', \
                                               interior=interior, \
                                               on_boundary=True)
             #
             # Check that we get the right number of dofs
             # 
             self.assertEqual(len(dofs), n_dofs[interior][etype])
Exemplo n.º 5
0
from mesh import QuadMesh
from mesh import Vertex
from mesh import HalfEdge
from solver import LinearSystem as LS
from plot import Plot
import numpy as np

# =============================================================================
# Computational mesh
# =============================================================================
mesh = QuadMesh(box=[-0.5, 0.5, -0.5, 0.5], resolution=(20, 20))

# Mark slit region
slit = HalfEdge(Vertex((0, 0)), Vertex((0, -0.5)))
sf = lambda x, y: slit.contains_points(np.array([x, y]))[0]
mesh.mark_region('slit', sf, entity_type='half_edge')

# Mark perimeter
tol = 1e-9
pf = lambda x,y: np.abs(x+0.5)<tol or np.abs(x-0.5)<tol or \
                 np.abs(y+0.5)<tol or np.abs(y-0.5)<tol
mesh.mark_region('perimeter', pf, entity_type='half_edge')

# Get rid of neighbors of half-edges on slit
for he in mesh.half_edges.get_leaves('slit'):
    if he.unit_normal()[0] < 0:
        he.mark('B')
mesh.tear_region('B')

# =============================================================================
# Functions
Exemplo n.º 6
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()))
Exemplo n.º 7
0
import matplotlib.pyplot as plt
"""
Investigate local error estimates on the resolution of a random field
"""

plot = Plot()

#
# Computational mesh
#
mesh = QuadMesh(resolution=(4, 4))

# Mark boundary
bnd_fn = lambda x, y: abs(x) < 1e-6 or abs(1 - x) < 1e-6 or abs(
    y) < 1e-6 or abs(1 - y) < 1e-6
mesh.mark_region('bnd', bnd_fn, entity_type='half_edge', on_boundary=True)

# Mark averaging region
dmn_fn = lambda x, y: x >= 0.75 and x <= 1 and y >= 0.75 and y <= 1
mesh.mark_region('dmn',
                 dmn_fn,
                 entity_type='cell',
                 strict_containment=True,
                 on_boundary=False)
#cells = mesh.get_region(flag='dmn', entity_type='cell', on_boundary=False, subforest_flag=None)
plot.mesh(mesh, regions=[('bnd', 'edge'), ('dmn', 'cell')])

#
# Elements
#
Q0 = QuadFE(mesh.dim(), 'DQ0')  # Constants for parameter
Exemplo n.º 8
0
"""

from mesh import QuadMesh
from fem import DofHandler, Basis, QuadFE
from function import Nodal
from gmrf import GaussianField, SPDMatrix, Covariance
from plot import Plot
from assembler import Assembler, Form, Kernel
import numpy as np

# Computational mesh
mesh = QuadMesh(resolution=(50, 50))

# Mark Dirichlet boundary regions
out_fn = lambda x, y: abs(x - 1) < 1e-8 and 0.8 <= y and y <= 1
mesh.mark_region('out', out_fn, entity_type='half_edge', on_boundary=True)

in_fn = lambda x, y: abs(x) < 1e-8 and 0 <= y and y <= 0.2
mesh.mark_region('in', in_fn, entity_type='half_edge', on_boundary=True)

x_min, x_max = 0.7, 0.8
y_min, y_max = 0.4, 0.5
reg_fn = lambda x, y: x >= x_min and x <= x_max and y >= y_min and y <= y_max
mesh.mark_region('reg', reg_fn, entity_type='cell')

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

phi = Basis(dQ1)
Exemplo n.º 9
0
def reference_solution():
    """
    Use sparse grid method to compute a benchmark solution
    """
    
    mesh = QuadMesh(resolution=(10,10))
    mesh.mark_region('boundary', lambda x,y:True, 
                     entity_type='half_edge', on_boundary=True)
    element = QuadFE(mesh.dim(), 'Q1')
    dofhandler = DofHandler(mesh, element)
    dofhandler.distribute_dofs()
    n = dofhandler.n_dofs()
    phi = Basis(dofhandler, 'u')
    phi_x = Basis(dofhandler, 'ux')
    phi_y = Basis(dofhandler, 'uy')
    yd_fn = Explicit(lambda x: np.sin(2*np.pi*x[:,0])*np.sin(2*np.pi*x[:,1]),dim=2)
    g = np.ones((n,1))
    
    #
    # Random diffusion coefficient
    # 
    
    # Sparse grid
    tasmanian_library="/home/hans-werner/bin/TASMANIAN-6.0/libtasmaniansparsegrid.so"
    grid = TasmanianSG.TasmanianSparseGrid(tasmanian_library=tasmanian_library)
    dimensions = 4
    outputs = 1
    depth = 4
    type = 'tensor'
    rule = 'gauss-legendre'
    grid.makeGlobalGrid(dimensions, outputs, depth, type, rule)
    Y = grid.getPoints()
    w = grid.getQuadratureWeights()
    n_samples = grid.getNumPoints()
    
    
    x = dofhandler.get_dof_vertices()
    a_nodal = 1 + 0.1*(np.outer(np.cos(np.pi*x[:,1]),Y[:,0])+\
                       np.outer(np.cos(np.pi*x[:,0]),Y[:,1])+\
                       np.outer(np.sin(2*np.pi*x[:,1]),Y[:,2])+\
                       np.outer(np.sin(2*np.pi*x[:,0]),Y[:,3]))
    a = Nodal(data=a_nodal, dofhandler=dofhandler)
    yd_vec = yd_fn.eval(x)
    
    problems = [[Form(a, test=phi_x, trial=phi_x), 
                Form(a, test=phi_y, trial=phi_y)],
                [Form(1, test=phi, trial=phi)]]
    
    assembler = Assembler(problems, mesh)
    assembler.assemble()
    
    A = assembler.af[0]['bilinear'].get_matrix()
    M = assembler.af[1]['bilinear'].get_matrix()
    
    state = LS(phi)
    state.add_dirichlet_constraint('boundary')
    
    adjoint = LS(phi)
    adjoint.add_dirichlet_constraint('boundary')
    
    tau = 10
    k_max = 20
    alpha = 0.1
    u = np.zeros((n,1))
    norm_dJ_iter = []
    J_iter = []
    u_iter = []
    for k in range(k_max):
        print('iteration', k)
        # 
        # Compute average cost and gradient
        # 
        dJ = np.zeros((n,1))
        J = 0
        print('sampling')
        for n in range(n_samples):
            print(n)
            yn, pn, Jn, dJn = cost_gradient(state,adjoint,A[n],M,
                                            g,u,yd_vec,alpha)
            
            J += w[n]*Jn
            dJ += w[n]*dJn
        print('')
        norm_dJ = np.sqrt(dJ.T.dot(M.dot(dJ)))
        
        #
        # Store current iterates
        # 
        norm_dJ_iter.append(norm_dJ)
        J_iter.append(J)
        u_iter.append(u)
        
        #
        # Check for convergence
        # 
        if norm_dJ<1e-8:
            break
        #
        # Update iterate
        # 
        u -= tau*dJ
Exemplo n.º 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)
Exemplo n.º 11
0
from solver import LinearSystem
from diagnostics import Verbose
import numpy as np
"""
Simulate the time dependent advection-diffusion-reaction system 

    u_t - div*(D*grad(u)) + div(v*u) + R(u) = 0
    
subject to the appropriate initial and boundary conditions, using
SUPG and 
 
"""
comment = Verbose()
# Computational mesh
mesh = QuadMesh(box=[0, 10, 0, 10], resolution=(100, 100))
left = mesh.mark_region('left', lambda x, y: abs(x) < 1e-10)

# Finite elements

# Piecewise constants
E0 = QuadFE(mesh.dim(), 'DQ0')
V0 = DofHandler(mesh, E0)
V0.distribute_dofs()

# Piecewise linears
E1 = QuadFE(mesh.dim(), 'Q1')
V1 = DofHandler(mesh, E1)
V1.distribute_dofs()

v = Basis(V1, 'v')
v_x = Basis(V1, 'vx')
Exemplo n.º 12
0
# =============================================================================
# Mesh and Elements
# =============================================================================
# Finite element mesh

x_min = 0
x_max = 2
y_min = 0
y_max = 1

mesh = QuadMesh(box=[x_min, x_max, y_min, y_max], resolution=(20, 10))

# Mark Dirichlet Edges
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 - 2) < 1e-9,
                 entity_type='half_edge')

# Element
element_Q0 = QuadFE(mesh.dim(), 'DQ0')
element_Q1 = QuadFE(mesh.dim(), 'Q1')

dh_Q0 = DofHandler(mesh, element_Q0)
dh_Q0.distribute_dofs()
n_Q0 = dh_Q0.n_dofs()

dh_Q1 = DofHandler(mesh, element_Q1)
dh_Q1.distribute_dofs()
Exemplo n.º 13
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))
Exemplo n.º 14
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))